Files
workshop/aula-08/README.md
ArgoCD Setup 2480c82944 fix(aula-08): prevenir volume stalling com CSI tolerations e PDB
- Adicionar hcloud-csi-values.yaml com tolerations para node failures
- Configurar 2 replicas do CSI controller para HA
- Criar statefulset-pdb.yaml para proteger StatefulSets durante drain
- Documentar troubleshooting de volumes stuck no README
2026-01-23 18:45:24 -03:00

249 lines
6.9 KiB
Markdown

# Aula 08 - Cluster Kubernetes HA na Hetzner Cloud
## Objetivo
Provisionar um cluster Kubernetes Talos de producao na Hetzner Cloud usando OpenTofu, com opcoes de Alta Disponibilidade (HA) e LoadBalancer.
## Arquitetura
### Modo HA com LoadBalancer (Recomendado)
```
Internet
┌───────────────────────┐
│ Hetzner Load │
│ Balancer (LB11) │
│ IP: 1.2.3.4 │
└───────────────────────┘
┌───────────────┼───────────────┐
│ │ │
▼ ▼ ▼
┌─────────┐ ┌─────────┐ ┌─────────┐
│ CP-0 │ │ CP-1 │ │ CP-2 │
│ CAX11 │ │ CAX11 │ │ CAX11 │
│10.0.1.10│ │10.0.1.11│ │10.0.1.12│
└─────────┘ └─────────┘ └─────────┘
│ │ │
└───────────────┼───────────────┘
┌──────────┐
│ Worker-0 │
│ CAX11 │
│10.0.1.20 │
└──────────┘
```
### Servicos do LoadBalancer
O LoadBalancer centraliza todo o trafego externo:
| Porta | Destino | Uso |
|:-----:|---------|-----|
| 6443 | Control Planes | Kubernetes API |
| 50000 | Control Planes | Talos API |
| 80 | Workers | HTTP (NGINX Ingress) |
| 443 | Workers | HTTPS (NGINX Ingress) |
| 22 | Workers | SSH (GitLab) |
### Roteamento L7 (por dominio)
O LoadBalancer faz apenas roteamento L4 (por porta). O roteamento por dominio e feito pelo NGINX Ingress:
```
LB :443 → NGINX Ingress → n8n.kube.quest → n8n pods
→ git.kube.quest → gitlab pods
→ argocd.kube.quest → argocd pods
→ registry.git... → registry pods
```
## Custos Estimados
Precos baseados em [Hetzner Cloud](https://www.hetzner.com/cloud/) (NBG1 - Nuremberg):
| Configuracao | CPs | LB | Custo/mes |
|--------------|:---:|:--:|----------:|
| Single | 1 | Floating IP | ~$13 |
| HA | 3 | Floating IP | ~$22 |
| HA + LB | 3 | LB11 | ~$24 |
| HA + LB + Autoscaler (max 5 workers) | 3 | LB11 | ~$43 |
Recursos: CAX11 $4.59, LB11 $5.99, Floating IP $3.29
## Pre-requisitos
```bash
# macOS
brew install opentofu
brew install siderolabs/tap/talosctl
brew install kubectl
brew install helm
# Criar imagem Talos (aula-07)
# Obter ID: hcloud image list --type snapshot
```
## Comandos
```bash
# Provisionar cluster (interativo)
./setup.sh
# Destruir infraestrutura
./cleanup.sh
```
## Fluxo do Setup
```
1. Verifica pre-requisitos
2. Coleta credenciais:
- Token Hetzner Cloud
- Chave SSH
- ID da imagem Talos
3. Pergunta configuracao:
- Cluster HA? (S/n)
- LoadBalancer? (S/n) [se HA]
4. Cria terraform.tfvars
5. Executa tofu init/plan/apply
6. Aguarda cluster ficar pronto
7. Instala CCM (Cloud Controller Manager)
8. Instala Cluster Autoscaler
9. Instala Hetzner CSI Driver
10. Instala Metrics Server
11. Instala NGINX Ingress Controller
```
## Componentes Instalados
| Componente | Funcao |
|------------|--------|
| Hetzner CCM | Remove taints dos workers, provisiona LoadBalancers |
| Cluster Autoscaler | Escala workers de 1 a 5 automaticamente |
| Hetzner CSI Driver | Provisiona volumes persistentes (StorageClass: hcloud-volumes) |
| Metrics Server | Habilita kubectl top e HPA baseado em CPU/memoria |
| NGINX Ingress | Expoe servicos HTTP/HTTPS/SSH via LoadBalancer |
## Apos o Setup
### Configurar kubectl
```bash
export KUBECONFIG=$PWD/kubeconfig
kubectl get nodes
```
### Configurar talosctl
```bash
export TALOSCONFIG=$PWD/talosconfig
talosctl -n <IP> health
```
### Ver logs do Autoscaler
```bash
kubectl logs -n cluster-autoscaler -l app=cluster-autoscaler -f
```
### Ver IP do LoadBalancer
```bash
kubectl get svc -n ingress-nginx ingress-nginx-controller -o jsonpath='{.status.loadBalancer.ingress[0].ip}'
```
### Ver StorageClass
```bash
kubectl get storageclass
# Esperado: hcloud-volumes (default)
```
### Ver uso de recursos
```bash
kubectl top nodes # Uso de CPU/memoria por no
kubectl top pods -A # Uso de CPU/memoria por pod
```
### Testar Autoscaler
```bash
# Criar pods pending (vai escalar workers)
kubectl create deployment test --image=nginx --replicas=20
# Acompanhar
kubectl get nodes -w
# Limpar
kubectl delete deployment test
```
## Proximos Passos
1. **Configurar DNS** - Apontar dominio para o IP do LoadBalancer
2. **Deploy n8n** (aula-09) - Workflow automation com PostgreSQL e Redis
3. **Deploy GitLab** (aula-10) - Git + Container Registry + SSH
## Arquivos
```
aula-08/
├── main.tf # Recursos principais (servers, LB, Talos)
├── variables.tf # Variaveis de entrada
├── outputs.tf # Outputs do cluster
├── versions.tf # Versoes dos providers
├── setup.sh # Script de setup interativo
├── cleanup.sh # Script de destruicao
├── cluster-autoscaler.yaml # Manifesto do autoscaler
├── install-nginx-ingress.sh # Instala NGINX Ingress com LB
├── install-metrics-server.sh # Instala Metrics Server (kubectl top, HPA)
├── nginx-ingress-values.yaml # Configuracao do NGINX Ingress
├── talos-patches/ # Patches de configuracao Talos
│ ├── control-plane.yaml
│ └── worker.yaml
├── hcloud-csi-values.yaml # Configuracao do CSI Driver
└── statefulset-pdb.yaml # PDB para proteger StatefulSets
```
## Troubleshooting: Volume Stuck
Se um pod ficar `Pending` aguardando volume:
### 1. Verificar VolumeAttachment
```bash
kubectl get volumeattachments
kubectl describe volumeattachment <name>
```
### 2. Se o node de origem nao existe mais
```bash
# Deletar o VolumeAttachment orfao (seguro pois node nao existe)
kubectl delete volumeattachment <name>
```
### 3. Se o node existe mas pod morreu
```bash
# Aguardar - Kubernetes vai liberar automaticamente
# Timeout padrao: 6 minutos
```
### 4. Verificar no Hetzner
```bash
hcloud volume list
# Se volume mostra attached a server que nao existe, abrir ticket
```
### Limitacoes do Block Storage
- Volumes Hetzner sao **RWO** (ReadWriteOnce) - single-attach por design
- Podem ficar stuck por ate 6 min (timeout do Kubernetes)
- Se node morrer abruptamente, recuperacao pode ser manual (deletar VolumeAttachment)