Files
workshop/aula-13/README.md
ArgoCD Setup d380cd8585 refactor: migrar GitLab → Gitea (aulas 10, 11, 13)
- Aula 10: Gitea + Registry + Actions + Runner (substituiu GitLab)
  - gitea-values.yaml: PostgreSQL standalone, Valkey standalone, ~800Mi RAM
  - setup.sh/cleanup.sh: namespace gitea, Helm gitea-charts/gitea + actions
  - README.md: documentação completa com de→para (GitLab/Harbor/Tekton vs Gitea)

- Aula 11: ArgoCD (GitOps) — removido GitLab Runner (runner vive na aula-10)
  - setup.sh: só ArgoCD, integração SSH com Gitea
  - node-bugado/.gitea/workflows/ci.yml: pipeline convertida

- Aula 13: Container Factory — atualizado para Gitea
  - setup.sh/cleanup.sh: referências GitLab → Gitea
  - pipelines/postgresql/ci.yml: Gitea Actions workflow
  - README.md: conexão com act_runner explicada

- CLAUDE.md: tabela de aulas atualizada
2026-03-14 01:44:30 -03:00

410 lines
14 KiB
Markdown

# Aula 13 - Container Factory + Lazy Pulling (eStargz)
Crie suas próprias imagens Docker e aprenda **quando** usar eStargz para lazy pulling.
## Conexão com as aulas anteriores
```
┌────────────────────────────────────────────────────────────────┐
│ Aula 10: Gitea │
│ Git server + Container Registry + Gitea Actions (habilitado) │
│ Chart: gitea-charts/gitea │ Chart: gitea-charts/actions │
│ Pods: gitea, postgresql, │ Pod: act-runner + DinD │
│ valkey │ (executa os workflows) │
└────────────────────┬───────────────────────┬──────────────────┘
│ │
│ push código │ roda workflow
│ │ (.gitea/workflows/)
▼ ▼
┌────────────────────────────────────────────────────────────────┐
│ Aula 13: Container Factory │
│ │
│ 1. git push → Gitea recebe o código │
│ 2. act_runner detecta .gitea/workflows/ci.yml │
│ 3. Runner executa: docker buildx build --compression=estargz │
│ 4. Runner faz push da imagem pro Gitea Container Registry │
│ 5. kubectl apply → Kubernetes puxa do registry │
└────────────────────────────────────────────────────────────────┘
```
O **act_runner** (Gitea Actions Runner) é a peça que conecta o `git push` ao build da imagem.
Ele foi instalado na aula-10 via `gitea-charts/actions` — um StatefulSet com dois containers:
| Container | Função |
|-----------|--------|
| `act-runner` | Escuta o Gitea por jobs, executa workflows (sintaxe GitHub Actions) |
| `dind` (Docker-in-Docker) | Daemon Docker privilegiado que o runner usa para `docker build`, `docker push` |
Sem o runner, os arquivos `.gitea/workflows/*.yml` existem no repo mas nunca executam.
Nesta aula usamos o runner para **build automatizado de imagens eStargz** — o ciclo completo de Container Factory.
## Visão Geral
| Parte | Tema | Valor |
|-------|------|-------|
| **1** | Container Factory | Prático - criar imagens independentes |
| **2** | eStargz e Lazy Pulling | Educacional - quando usar e quando NÃO usar |
| **3** | Alternativas para Cold Start | Prático - soluções para KEDA/auto-scaling |
---
# Parte 1: Container Factory
## Por que criar suas próprias imagens?
### O Problema Bitnami
A partir de **28 de agosto de 2025**, a Broadcom descontinuou imagens gratuitas:
- Imagens movidas para repositório **legacy** (sem atualizações de segurança)
- Tags estáveis (`postgresql:13.7.0`) não disponíveis no tier gratuito
- Imagens atualizadas só via **Bitnami Secure** (~$72k/ano)
Referência: [Bitnami Issue #83267](https://github.com/bitnami/containers/issues/83267)
### A Solução: Container Factory
Criar imagens próprias baseadas nas imagens oficiais:
- Gratuitas e mantidas pela comunidade
- Menores e mais seguras
- Totalmente customizáveis
## Estrutura do Projeto
```
aula-13/
├── README.md
├── setup.sh
├── cleanup.sh
├── images/
│ ├── postgresql/ # Exemplo principal
│ │ ├── Dockerfile
│ │ └── postgresql.conf
│ └── devops-toolbox/ # Demonstração eStargz
│ ├── Dockerfile
│ └── entrypoint.sh
├── pipelines/
│ └── postgresql/
│ ├── ci.yml # Gitea Actions workflow
│ └── .gitlab-ci.yml # (legado - referência)
├── k8s/
│ ├── postgresql/
│ │ ├── deployment.yaml
│ │ ├── service.yaml
│ │ └── pvc.yaml
│ └── prepull-daemonset.yaml # Alternativa para cold start
└── benchmarks/
├── benchmark-postgresql.sh
└── benchmark-toolbox.sh
```
## Instalação
### 1. Executar Setup
```bash
cd aula-13
./setup.sh
```
### 2. Criar Projeto no Gitea
1. Criar org `factory` em `https://gitea.kube.quest/-/admin/orgs`
2. Criar repositório `postgresql` na org
3. Push dos arquivos:
```bash
git clone git@gitea.kube.quest:factory/postgresql.git
cd postgresql
cp /path/to/aula-13/images/postgresql/* .
mkdir -p .gitea/workflows
cp /path/to/aula-13/pipelines/postgresql/ci.yml .gitea/workflows/ci.yml
git add . && git commit -m "Initial commit" && git push
```
### 3. Deploy
```bash
kubectl apply -f k8s/postgresql/ -n factory
kubectl get pods -n factory -w
```
---
# Parte 2: eStargz e Lazy Pulling
## O que é eStargz?
**eStargz** (Externally Seekable Stargz) permite **lazy pulling** - o container inicia ANTES de baixar a imagem completa:
```
Imagem Tradicional:
Download 100% (30s) → Extract (10s) → Start (1s) = 41s total
Imagem eStargz:
Download 5% (1s) → Start (1s) → Download resto em background = 2s para iniciar
```
## Quando eStargz FUNCIONA (casos reais)
| Empresa | Melhoria | Cenário |
|---------|----------|---------|
| **CERN** | 13x mais rápido | Pipelines de análise nuclear |
| **BuildBuddy** | 10x redução latência | Executor images |
| **AWS (SOCI)** | 10-15x melhoria | ML containers |
**Condições para sucesso:**
- Imagem > 250MB (comprimida)
- < 10% dos dados necessários no boot
- Container que NÃO precisa de todos os arquivos para iniciar
## Quando eStargz NÃO ajuda
### Aplicações que NÃO se beneficiam:
| Aplicação | Tamanho | Por que NÃO funciona |
|-----------|---------|---------------------|
| PostgreSQL | ~100MB | Database precisa de 100% dos arquivos |
| MongoDB | ~500MB | Database precisa de 100% dos arquivos |
| CockroachDB | ~400MB | Database precisa de 100% dos arquivos |
| n8n | ~500MB | Carrega TODAS as 400+ integrações no boot |
| Laravel Octane | ~400MB | Precarrega TODA a aplicação na RAM |
### Por que não funcionou nos testes?
Benchmark com PostgreSQL mostrou **performance idêntica** entre eStargz e GZIP:
| Imagem | Tempo (cold start) |
|--------|-------------------|
| PostgreSQL eStargz | ~10s |
| PostgreSQL GZIP | ~10s |
**Razões:**
1. Imagem pequena (~100MB) - overhead do lazy pull > benefício
2. PostgreSQL precisa de TODOS os arquivos para iniciar
3. Não há arquivos "opcionais" para lazy load
## Matriz de Decisão
| Cenário | Usar eStargz? | Motivo |
|---------|---------------|--------|
| Imagem < 250MB | ❌ **Não** | Overhead > benefício |
| Database (PostgreSQL, MySQL, MongoDB) | ❌ **Não** | Precisa de ~100% dos arquivos |
| Apps que precarregam (Laravel Octane, n8n) | ❌ **Não** | Carrega tudo no boot |
| Imagem > 1GB com uso parcial | ✅ **Sim** | Lazy pulling efetivo |
| ML/AI com múltiplos modelos | ✅ **Sim** | Só baixa modelo usado |
| DevOps toolbox (terraform, kubectl) | ✅ **Sim** | Só baixa ferramenta usada |
| Serverless/FaaS | ✅ **Sim** | Cold start crítico |
## Demonstração: DevOps Toolbox (eStargz vantajoso)
Para demonstrar quando eStargz **realmente funciona**, criamos uma imagem grande com uso parcial:
```dockerfile
# images/devops-toolbox/Dockerfile
FROM alpine:3.21
# Camada 1: Base (~50MB)
RUN apk add --no-cache bash curl wget jq git
# Camada 2: Terraform (~100MB)
RUN wget -q https://releases.hashicorp.com/terraform/1.9.0/terraform_1.9.0_linux_arm64.zip && \
unzip terraform_*.zip && mv terraform /usr/local/bin/ && rm terraform_*.zip
# Camada 3: Kubectl + Helm (~150MB)
RUN curl -sLO "https://dl.k8s.io/release/v1.31.0/bin/linux/arm64/kubectl" && \
chmod +x kubectl && mv kubectl /usr/local/bin/
# Camada 4: AWS CLI (~200MB)
RUN apk add --no-cache aws-cli
# Camada 5: Ansible (~150MB)
RUN apk add --no-cache python3 py3-pip && \
pip3 install ansible --break-system-packages --quiet
# Total: ~650MB - mas você só usa UMA ferramenta por vez!
```
**Resultado esperado:**
- GZIP: Baixa 650MB inteiro → ~60s
- eStargz: Baixa só camada necessária (~100MB) → ~10s
- **Melhoria: 6x mais rápido**
---
# Parte 3: Alternativas para Cold Start
Se suas aplicações são databases ou apps que precarregam, use estas alternativas:
## Opção 1: Pre-pull DaemonSet (Recomendado)
Garante que imagens já estão em TODOS os nodes antes do KEDA escalar:
```yaml
# k8s/prepull-daemonset.yaml
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: image-prepuller
namespace: kube-system
spec:
selector:
matchLabels:
app: image-prepuller
template:
metadata:
labels:
app: image-prepuller
spec:
initContainers:
- name: prepull-postgres
image: gitea.kube.quest/factory/postgresql:17
command: ["echo", "Image pulled"]
imagePullPolicy: Always
- name: prepull-n8n
image: docker.n8n.io/n8nio/n8n:latest
command: ["echo", "Image pulled"]
imagePullPolicy: Always
containers:
- name: pause
image: gcr.io/google_containers/pause:3.2
imagePullSecrets:
- name: gitea-registry
```
**Resultado:** Quando KEDA escalar, imagens já estão em cache em todos os nodes.
## Opção 2: Over-provisioning
Manter `minReplicas > 0` para evitar cold starts:
```yaml
# ScaledObject com mínimo de 1 réplica
apiVersion: keda.sh/v1alpha1
kind: ScaledObject
spec:
minReplicaCount: 1 # Sempre tem pelo menos 1 pod rodando
maxReplicaCount: 10
```
## Opção 3: Imagens menores
Reduzir tamanho da imagem para downloads mais rápidos:
| Base | Tamanho típico | Uso |
|------|----------------|-----|
| `alpine` | ~5MB | Apps Go, binários estáticos |
| `distroless` | ~20MB | Java, Node.js |
| `debian-slim` | ~80MB | Quando Alpine não funciona |
## Comparação de Soluções
| Solução | Cold Start | Complexidade | Custo |
|---------|------------|--------------|-------|
| Pre-pull DaemonSet | ⭐⭐⭐⭐⭐ | Baixa | Nenhum |
| Over-provisioning | ⭐⭐⭐⭐ | Baixa | $$ (pods sempre rodando) |
| Imagens menores | ⭐⭐⭐ | Média | Nenhum |
| eStargz | ⭐⭐ (só imagens grandes) | Alta | Nenhum |
---
# Apêndice: Configuração Técnica
## Pipeline CI com eStargz (Gitea Actions)
```yaml
# .gitea/workflows/ci.yml
name: Build PostgreSQL
on:
push:
branches: [main]
env:
REGISTRY: gitea.kube.quest
IMAGE_NAME: factory/postgresql
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: docker/setup-buildx-action@v3
- run: echo "${{ secrets.REGISTRY_TOKEN }}" | docker login ${{ env.REGISTRY }} -u ${{ gitea.actor }} --password-stdin
- run: |
docker buildx build \
--output type=image,name=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest,push=true,compression=estargz,force-compression=true,oci-mediatypes=true \
.
```
| Parâmetro | Descrição |
|-----------|-----------|
| `compression=estargz` | Formato para lazy pulling |
| `force-compression=true` | Recomprime camadas da base |
| `oci-mediatypes=true` | Media types OCI (requerido) |
## Verificar stargz-snapshotter no Talos
```bash
# Extensão instalada
talosctl get extensionstatuses | grep stargz
# Configuração
talosctl read /etc/cri/conf.d/10-stargz-snapshotter.part
# Output: snapshotter = "stargz"
```
## Testar PostgreSQL
```bash
# Obter senha
PGPASSWORD=$(kubectl get secret postgresql-secret -n factory -o jsonpath='{.data.password}' | base64 -d)
# Conectar
kubectl run pg-client --rm -it --restart=Never \
--image=postgres:17-alpine \
--env=PGPASSWORD=$PGPASSWORD \
-- psql -h postgresql.factory.svc.cluster.local -U postgres -d app
```
---
# Conclusão
## Resumo
| Tema | Aprendizado |
|------|-------------|
| **Container Factory** | Crie imagens próprias para independência de terceiros |
| **eStargz** | Só vale para imagens > 250MB com uso parcial |
| **Cold Start** | Para databases, use pre-pull DaemonSet |
## Regra de Ouro
```
┌─────────────────────────────────────────────────────────────────┐
│ eStargz funciona quando: │
│ - Imagem > 250MB │
│ - < 10% dos dados necessários no boot │
│ - Container NÃO precisa de todos os arquivos para iniciar │
│ │
│ Para databases e apps que precarregam: │
│ → Use Pre-pull DaemonSet │
└─────────────────────────────────────────────────────────────────┘
```
## Referências
- [CERN: Lazy Pulling](https://indico.cern.ch/event/1338689/) - 13x mais rápido
- [BuildBuddy: SOCI](https://www.buildbuddy.io/blog/image-streaming/) - 10x redução latência
- [AWS: SOCI Snapshotter](https://aws.amazon.com/blogs/containers/under-the-hood-lazy-loading-container-images-with-seekable-oci-and-aws-fargate/)
- [NTT Labs: eStargz](https://medium.com/nttlabs/startup-containers-in-lightning-speed-with-lazy-image-distribution-on-containerd-243d94522361)
- [stargz-snapshotter](https://github.com/containerd/stargz-snapshotter)
## Cleanup
```bash
./cleanup.sh
```