feat(aula-10): migrar para Hetzner Object Storage + melhorias

Mudanças principais:
- Substituir MinIO bundled por Hetzner Object Storage (S3)
- Secrets YAML com envsubst para credenciais S3
- Anti-affinity preferencial (adapta a qualquer topologia)
- Detecção automática de cert-manager existente
- Menu TLS simplificado (Let's Encrypt/CloudFlare/HTTP)
- Perguntar hostname do registry separadamente
- Exibição unificada de TLS (não mais CloudFlare: true/false)
This commit is contained in:
ArgoCD Setup
2026-01-23 22:52:43 -03:00
parent 420fce0eb9
commit 12f6f48c64
6 changed files with 334 additions and 114 deletions

View File

@@ -29,11 +29,21 @@ Deploy do GitLab em Kubernetes usando Helm chart oficial, com Container Registry
│ │ (Git Storage) │ │
│ └──────────────────────┘ │
│ │
│ ┌──────────┐ ┌───────┐ ┌──────────┐
│ │PostgreSQL│ │ Redis │ MinIO │
│ │ (10Gi) │ │(10Gi) │ (10Gi) │
│ └──────────┘ └───────┘ └──────────┘
└────────────────────────────────────────┘
│ ┌──────────┐ ┌───────┐
│ │PostgreSQL│ │ Redis │
│ │ (10Gi) │ │(10Gi) │
│ └──────────┘ └───────┘
└────────────────────────────────────────┘
┌─────────────────────┐
│ Hetzner Object │
│ Storage (S3) │
│ - uploads │
│ - artifacts │
│ - registry images │
│ - lfs objects │
└─────────────────────┘
```
## Pré-requisitos
@@ -41,8 +51,11 @@ Deploy do GitLab em Kubernetes usando Helm chart oficial, com Container Registry
1. **Cluster Talos na Hetzner** (aula-08) com:
- Hetzner CSI Driver (StorageClass: hcloud-volumes)
- NGINX Ingress Controller com LoadBalancer
2. **kubectl** instalado
3. **Helm** 3.x instalado
2. **Hetzner Object Storage** (bucket + credenciais):
- Criar bucket em: https://console.hetzner.cloud → Object Storage
- Gerar Access Key e Secret Key
3. **kubectl** instalado
4. **Helm** 3.x instalado
## Contexto do Cluster
@@ -71,6 +84,7 @@ O script é interativo e pergunta:
1. **Hostname do GitLab** (ex: `git.kube.quest`) - FQDN completo
2. **Usa CloudFlare?** (com proxy/CDN) - pode herdar da aula-09
3. **Ativar Let's Encrypt?** (se não usar CloudFlare)
4. **Hetzner Object Storage** - endpoint, bucket e credenciais
### Opções de TLS
@@ -128,43 +142,51 @@ Com isso, o Workhorse confia nos headers `X-Forwarded-*` vindos do CloudFlare e
| Gitaly | 512Mi | 1Gi | 10Gi |
| PostgreSQL | 512Mi | 1Gi | 10Gi |
| Redis | 256Mi | 512Mi | 10Gi |
| MinIO | 128Mi | 256Mi | 10Gi |
| Shell | 64Mi | 128Mi | - |
| Toolbox | 256Mi | 512Mi | - |
| **Total** | ~5Gi | ~8Gi | 40Gi |
| **Total** | ~5Gi | ~8Gi | 30Gi |
## Pod Anti-Affinity (Distribuicao Inteligente)
**Object Storage (externo):**
- Hetzner Object Storage (S3-compatible)
- Uploads, artifacts, LFS, registry images
- Custo: €0.006/GB/mês (paga por uso)
O GitLab configura **antiAffinity** para garantir que webservice e sidekiq rodem em nos diferentes:
## Distribuição Inteligente de Pods
O GitLab usa **anti-affinity preferencial** para se adaptar automaticamente ao cluster:
```yaml
gitlab:
webservice:
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchLabels:
app: sidekiq
topologyKey: kubernetes.io/hostname
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchLabels:
app: sidekiq
topologyKey: kubernetes.io/hostname
```
### Por que isso importa?
### Comportamento Adaptativo
Sem antiAffinity, webservice (~2.5Gi) + sidekiq (~2Gi) = 4.5Gi no mesmo no CAX11 (4GB):
- **Resultado**: OOMKilled constantes, servico instavel
| Cenário | Comportamento |
|---------|---------------|
| 1 nó grande (8GB+) | Tudo roda junto no mesmo nó |
| Múltiplos nós pequenos | Distribui automaticamente |
| Sem recursos suficientes | Cluster Autoscaler cria nós novos |
Com antiAffinity:
- Kubernetes detecta que nao pode agendar no mesmo no
- Pod fica **Pending**
- Cluster Autoscaler cria um novo no automaticamente
- Pods distribuidos = servico estavel
### Por que preferencial ao invés de obrigatório?
### Licao do Workshop
- **Obrigatório** (`required`): pods ficam Pending se não houver nós separados
- **Preferencial** (`preferred`): funciona com qualquer topologia, otimiza quando possível
> "Kubernetes nao e so rodar containers - e **orquestracao inteligente**.
> Quando configuramos antiAffinity, o scheduler entendeu que precisava de mais
> recursos e o autoscaler provisionou automaticamente."
### Lição do Workshop
> "Configurações adaptativas são melhores que rígidas. O anti-affinity preferencial
> permite que o GitLab funcione em um nó grande ou distribua em vários pequenos,
> sem intervenção manual."
## Padrão de Domínios
@@ -191,6 +213,13 @@ DOMAIN=kube.quest
USE_CLOUDFLARE=true
USE_LETSENCRYPT=false
LETSENCRYPT_EMAIL=
# Hetzner Object Storage (use a mesma região do cluster)
S3_ENDPOINT=nbg1.your-objectstorage.com
S3_ACCESS_KEY=xxxxx
S3_SECRET_KEY=xxxxx
S3_BUCKET=gitlab-workshop
S3_REGION=nbg1
```
## Acesso
@@ -321,15 +350,21 @@ kubectl run test --rm -it --image=busybox -- wget -qO- http://gitlab-registry:50
## Custos
| Cenário | Workers | Custo/mês |
|---------|---------|-----------|
| 1x CAX21 (8GB) | 1 nó | ~$8.49 |
| 2x CAX11 (4GB) | 2 nós (distribuído) | ~$9.18 |
| Recurso | Custo/mês |
|---------|-----------|
| Workers (2x CAX11 - antiAffinity) | ~$9.18 |
| Volumes (4x 10Gi = 40Gi) | ~$1.94 |
| Volumes (3x 10Gi = 30Gi) | ~$1.45 |
| Object Storage (~10GB uso) | ~€0.06 |
| LoadBalancer (compartilhado) | ~$1.80 (1/3) |
| **Total GitLab** | ~$12.92 |
**Nota:** O antiAffinity requer 2 workers minimos (webservice e sidekiq em nos separados).
O Cluster Autoscaler provisiona automaticamente quando necessario.
**Nota:** O anti-affinity preferencial permite ambos os cenários.
O Cluster Autoscaler provisiona nós automaticamente quando necessário.
**Vantagem Object Storage:** Sem volume MinIO (economia de ~$0.50/mês) + storage ilimitado.
## Referências