- Aula 08: nginx-ingress TCP passthrough gitlab→gitea, comments
- Aula 09: add-client.sh API GitLab→Gitea
- Aula 11: node-bugado deployment image registry.kube.quest→gitea.kube.quest
- Aula 12: setup.sh/cleanup.sh API GitLab→Gitea, ArgoCD repoURL
- Aula 13: k8s manifests, benchmarks: registry.kube.quest→gitea.kube.quest,
gitlab-registry→gitea-registry, GITLAB_TOKEN→GITEA_TOKEN
- Aula 14: comments GitLab→Gitea
- README raiz: arquitetura, tabela, DNS
6.9 KiB
6.9 KiB
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 (Gitea) |
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
→ gitea.kube.quest → gitea pods
→ argocd.kube.quest → argocd pods
→ registry.git... → registry pods
Custos Estimados
Precos baseados em Hetzner 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
# 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
# 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
export KUBECONFIG=$PWD/kubeconfig
kubectl get nodes
Configurar talosctl
export TALOSCONFIG=$PWD/talosconfig
talosctl -n <IP> health
Ver logs do Autoscaler
kubectl logs -n cluster-autoscaler -l app=cluster-autoscaler -f
Ver IP do LoadBalancer
kubectl get svc -n ingress-nginx ingress-nginx-controller -o jsonpath='{.status.loadBalancer.ingress[0].ip}'
Ver StorageClass
kubectl get storageclass
# Esperado: hcloud-volumes (default)
Ver uso de recursos
kubectl top nodes # Uso de CPU/memoria por no
kubectl top pods -A # Uso de CPU/memoria por pod
Testar Autoscaler
# 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
- Configurar DNS - Apontar dominio para o IP do LoadBalancer
- Deploy n8n (aula-09) - Workflow automation com PostgreSQL e Redis
- Deploy Gitea (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
kubectl get volumeattachments
kubectl describe volumeattachment <name>
2. Se o node de origem nao existe mais
# Deletar o VolumeAttachment orfao (seguro pois node nao existe)
kubectl delete volumeattachment <name>
3. Se o node existe mas pod morreu
# Aguardar - Kubernetes vai liberar automaticamente
# Timeout padrao: 6 minutos
4. Verificar no Hetzner
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)