Kubernetes Self-Hosted: Hetzner vs AKS vs K3s para PME
Escolher onde correr Kubernetes é uma das decisões mais importantes — e mais caras — para uma PME. Azure AKS oferece comodidade mas custa premium. Hetzner Cloud oferece VMs a preços agressivos. K3s on-prem reduz dependência de cloud. Esta comparação ajuda sysadmins a decidir com base em custos reais, complexidade operacional e cenários concretos.
TL;DR: Para uma PME com 2-5 serviços, K3s no Hetzner Cloud custa ~40€/mês vs ~180€/mês no AKS. Se tens hardware próprio, K3s on-prem fica a 0€/mês (apenas electricidade). Não uses Kubernetes se tens um único serviço monolítico — Docker Compose chega.
Neste artigo
- Comparação de Custos: Hetzner vs AKS vs On-prem K3s
- AKS em 2026: O que pagas pelo gerido
- Configurar K3s no Hetzner Cloud
- Traefik e Ingress no K3s
- Trade-offs: Gerido vs Self-hosted vs On-prem
- Erros Comuns
- Checklist de Implantação K3s
- Quando NÃO Usar Kubernetes
- Artigos Relacionados
Comparação de Custos: Hetzner vs AKS vs On-prem K3s
Os valores abaixo refletem um cenário típico de PME: cluster de 2-3 nós, 8GB RAM cada, 4 vCPU, 160GB armazenamento. Preços recolhidos em julho 2026.
| Componente | Hetzner + K3s | Azure AKS | On-prem K3s |
|---|---|---|---|
| Nós (3x 4vCPU/8GB) | ~30€/mês (CX32) | ~120€/mês (D4s v3) | 0€ (hardware existente) |
| Load Balancer | ~5€/mês (Hetzner LB) | ~20€/mês (Standard LB) | 0€ (MetalLB / Traefik) |
| Gestão do plano de controlo | 0€ (K3s embedded) | 0€ (gerido pela Azure) | 0€ (K3s embedded) |
| Tráfego de saída | Incluído (20TB) | ~5€/mês (100GB grátis) | Variável (ISP) |
| Storage persistente | ~5€/mês (50GB) | ~10€/mês (50GB SSD) | 0€ (discos locais) |
| Total mensal estimado | ~40€ | ~155-180€ | ~0€ (custo eléctrico) |
| Horas de setup inicial | 2-4h | 1-2h | 4-8h |
| Manutenção mensal | 2-4h | 1h | 4-8h |
Nota: AKS cobra apenas os nós (VMs), não o plano de controlo. No entanto, a Azure cobra por Load Balancer, IPs públicos, discos geridos e tráfego de saída separadamente. O custo real é quase sempre 30-50% superior ao estimado inicial.
AKS em 2026: O que pagas pelo gerido
Azure Kubernetes Service elimina a gestão do plano de controlo (etcd, API server, scheduler). Recebes patches automáticos de versão K8s, integração nativa com Azure Monitor, Key Vault e Entra ID. Para equipas já invested no ecossistema Azure, o AKS é o caminho de menor resistência.
O que tens gratuitamente:
- Plano de controlo gerido (sem etcd para gerir)
- Auto-scaling de nós (cluster autoscaler)
- Upgrade de versão K8s com um clique
- Integração com Azure Monitor e Log Analytics
O que pagas extra (e dói):
- Standard Load Balancer: ~20€/mês por LB
- IP público: ~4€/mês por IP
- Discos geridos Premium: 2x mais caros que Hetzner
- Tráfego de saída: 0,087€/GB após 100GB grátis
- Application Gateway WAF: ~25€/mês mínimo
# Criar cluster AKS básico (1 nó)
az aks create \
--resource-group rg-pme \
--name aks-pme-prod \
--node-count 2 \
--node-vm-size Standard_D4s_v3 \
--enable-managed-identity \
--auto-upgrade-channel stable \
--no-ssh-key
# Custo estimado: ~120€/mês nós + ~25€ LB/IP = ~145€/mês
Configurar K3s no Hetzner Cloud
K3s é uma distribuição Kubernetes leve (single binary, ~70MB) desenvolvida pela Rancher/SUSE. Remove componentes opcionais (alpha features, cloud providers legacy) e usa SQLite ou etcd embedded. Ideal para clusters pequenos e edge computing.
Vantagens do K3s no Hetzner:
- Binary único — sem dependências externas
- Traefik e ServiceLB incluídos por defeito
- Instala em 60 segundos por nó
- Hetzner Cloud API para provisionar VMs rapidamente
- Custos 4-5x inferiores ao AKS equivalente
Passo 1: Provisionar VMs no Hetzner
# Instalar hcloud CLI
curl -fsSL https://github.com/hetznercloud/cli/releases/download/v1.45.0/hcloud-linux-amd64.tar.gz | tar xz
sudo mv hcloud /usr/local/bin/
# Configurar token (Hetzner Cloud Console > API Tokens)
hcloud context create kbase-pme
# Criar rede privada
hcloud network create --name k8s-net --ip-range 10.0.0.0/16
hcloud network add-subnet k8s-net --network-zone eu-central --type server --ip-range 10.0.0.0/24
# Criar master node (CX32: 4 vCPU, 8GB RAM, 160GB disk)
hcloud server create --name k8s-master --type cx32 --image ubuntu-24.04 --network k8s-net --ssh-key your-key
# Criar 2 worker nodes
hcloud server create --name k8s-worker1 --type cx32 --image ubuntu-24.04 --network k8s-net --ssh-key your-key
hcloud server create --name k8s-worker2 --type cx32 --image ubuntu-24.04 --network k8s-net --ssh-key your-key
Passo 2: Instalar K3s no master
# No master node (10.0.0.2):
curl -sfL https://get.k3s.io | INSTALL_K3S_EXEC="server \
--cluster-init \
--tls-san $(hostname -I | awk '{print $1}') \
--node-external-ip $(curl -s ifconfig.me) \
--disable traefik" sh -
# Guardar o token para os workers juntarem ao cluster
cat /var/lib/rancher/k3s/server/node-token
# Ex: K107...EXTRACTION_TOKEN...
Atenção: O comando acima desactiva o Traefik nativo do K3s (--disable traefik). Se preferes usar o Traefik incluído, remove essa flag. Para PME que já usam Traefik como Ingress Controller externo, é melhor gerir a versão manualmente.
Passo 3: Juntar workers ao cluster
# Em cada worker node:
curl -sfL https://get.k3s.io | K3S_URL="https://10.0.0.2:6443" \
K3S_TOKEN="K107...EXTRACTION_TOKEN..." sh -
# Verificar no master:
kubectl get nodes
# NAME STATUS ROLES AGE VERSION
# k8s-master Ready control-plane,master 2m v1.30.4+k3s1
# k8s-worker1 Ready <none> 1m v1.30.4+k3s1
# k8s-worker2 Ready <none> 1m v1.30.4+k3s1
Passo 4: Configurar Hetzner Cloud Controller Manager
# Criar secret com token da Hetzner API
kubectl create secret generic hcloud \
--from-literal=token=SEU_HETZNER_API_TOKEN \
--from-literal=network=k8s-net \
-n kube-system
# Aplicar Cloud Controller Manager
kubectl apply -f https://github.com/hetznercloud/hcloud-cloud-controller-manager/releases/latest/download/ccm-networks.yaml
# Agora pods recebem IPs privados da rede Hetzner
# e LoadBalancers são criados automaticamente
Passo 5: CSI Driver para volumes persistentes
# Instalar Hetzner CSI driver
kubectl apply -f https://github.com/hetznercloud/csi-driver/releases/latest/download/csi.yaml
# Criar StorageClass que usa volumes Hetzner
cat <<EOF | kubectl apply -f -
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: hcloud-volumes
provisioner:csi.hetzner.cloud
parameters:
type: cx_vol
reclaimPolicy: Delete
EOF
# PVC exemplo
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: postgres-data
spec:
accessModes: [ReadWriteOnce]
storageClassName: hcloud-volumes
resources:
requests:
storage: 20Gi
EOF
Traefik e Ingress no K3s
K3s inclui Traefik v2 por defeito como Ingress Controller. Para PME que precisam de TLS automático e routing por hostname, o Traefik integrado é suficiente. Para setups mais avançados (WAF, rate limiting complexo), considera instalar Traefik manualmente com Helm.
# Ingress simples com TLS automático (cert-manager necessário)
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: app-ingress
annotations:
cert-manager.io/cluster-issuer: letsencrypt-prod
spec:
tls:
- hosts: [app.exemplo.pt]
secretName: app-tls
rules:
- host: app.exemplo.pt
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: app-service
port:
number: 8080
Ver também: Para uma análise detalhada de Traefik vs Nginx como Ingress Controller, consulta o nosso artigo Traefik vs Nginx: Ingress Controller para Kubernetes em 2026.
Trade-offs: Gerido vs Self-hosted vs On-prem
| Critério | AKS (Gerido) | Hetzner + K3s | On-prem K3s |
|---|---|---|---|
| Custo mensal | Alto (~180€) | Baixo (~40€) | Mínimo (electricidade) |
| Setup inicial | Rápido (1h) | Médio (2-4h) | Lento (4-8h) |
| Patches de segurança K8s | Automático | Manual (k3s upgrade) | Manual |
| Backup do etcd | Gerido pela Azure | Manual (snapshot) | Manual |
| Auto-scaling de nós | Nativo | Cluster Autoscaler + Hetzner API | Limitado ao hardware |
| Latência de rede | Baixa (Azure backbone) | Baixa (Hetzner Nuremberg) | Mínima (LAN) |
| Vendor lock-in | Alto | Baixo | Nenhum |
| Integração IAM/RBAC | Entra ID nativo | OIDC manual | OIDC manual |
| SLA | 99.9% (plano controlo) | 99.9% (VMs) | Depende de ti |
| Monitoring | Azure Monitor incluído | Prometheus + Grafana | Prometheus + Grafana |
Erros Comuns
| Erro | Sintoma | Solução |
|---|---|---|
| K3s sem –tls-san | kubectl dá cert error ao conectar por IP | Reinstalar com --tls-san IP_PUBLICO |
| Firewall bloqueia 6443 | Workers não conseguem juntar-se ao cluster | Abrir porta 6443 apenas na rede privada |
| Node token expirado | k3s agent falha após reinstall do master | Re-obter token de /var/lib/rancher/k3s/server/node-token |
| Sem Cloud Controller | Services LoadBalancer ficam em Pending | Instalar hcloud-cloud-controller-manager |
| etcd sem backup | Perda total do cluster se master morre | Cron job para k3s etcd-snapshot diário |
| Upgrades sem drain | Pods terminam abruptamente, downtime | Sempre kubectl drain antes de upgrade |
| AKS sem budget alerts | Factura surpresa por auto-scaling descontrolado | Configurar Azure Cost Alerts e limites de nós |
| Single master sem HA | Master down = cluster down | Para produção: 3 masters com --cluster-init |
Checklist de Implantação K3s
- Provisionar infraestrutura: 3 VMs no Hetzner (1 master + 2 workers), rede privada configurada, firewall com porta 6443 aberta apenas intra-rede.
- Instalar K3s no master:
curl -sfL https://get.k3s.io | INSTALL_K3S_EXEC="server --cluster-init --tls-san <IP>" sh - - Guardar node token: Copiar conteúdo de
/var/lib/rancher/k3s/server/node-tokenpara local seguro (password manager). - Juntar workers: Em cada worker, executar
curl -sfL https://get.k3s.io | K3S_URL=https://<master-ip>:6443 K3S_TOKEN=<token> sh - - Verificar cluster:
kubectl get nodes— todos em estado Ready. - Instalar Cloud Controller Manager: Criar secret com token Hetzner e aplicar manifesto CCM.
- Instalar CSI Driver: Aplicar manifesto do Hetzner CSI driver e criar StorageClass.
- Configurar cert-manager:
kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.15.0/cert-manager.yaml - Criar ClusterIssuer Let’s Encrypt: Configurar email e solver HTTP-01.
- Configurar backup etcd: Cron job diário:
k3s etcd-snapshot save --name daily-$(date +%Y%m%d) - Instalar monitoring: Prometheus + Grafana via Helm (kube-prometheus-stack).
- Configurar alertas: Alertmanager com notificação por email/Slack para nós down, disk full, pod restarts.
- Testar disaster recovery: Simular falha do master e restaurar do snapshot mais recente.
- Documentar runbooks: Procedimentos para upgrade, rollback, node replacement e certificate renewal.
Quando NÃO Usar Kubernetes
Kubernetes tornou-se o default answer para tudo que envolva containers, mas nem tudo precisa de um orquestrador distribuído. Eis cenários onde Kubernetes é overkill:
Red flag: Se a tua equipa não tem ninguém que saiba debugar crictl, kubectl logs e etcdctl, não uses Kubernetes em produção. A curva de aprendizagem vai custar mais que a poupança de infraestrutura.
Cenários onde Docker Compose (ou similar) chega:
- Aplicação monolítica single-host: Um web app + base de dados num só servidor. Compose com 20 linhas resolve.
- 2-3 serviços sem necessidade de auto-scaling: Se nunca precisaste de escalar horizontalmente, K8s é peso morto.
- Equipas sem dedicação DevOps: K8s requer manutenção contínua. Sem alguém responsável, degrada rapidamente.
- Orçamento < 50€/mês e sem hardware: Um VPS com Compose é mais simples e barato.
- Latência crítica single-region: K8s adiciona overhead de rede entre componentes. Para serviços ultra-low-latency, VM directa é melhor.
Cenários onde Kubernetes vale a pena:
- Múltiplas equipas a deployar serviços independentes (multi-tenant)
- Necessidade de auto-scaling baseado em carga variável
- Zero-downtime deployments obrigatórios (blue/green, canary)
- Microserviços com 10+ componentes que precisam de service discovery
- Múltiplos ambientes (dev/staging/prod) no mesmo cluster com isolação
Artigos Relacionados
- K3s: Kubernetes Leve para PME em Edge Computing 2026 — Análise detalhada do K3s em cenários edge e IoT.
- Traefik vs Nginx: Ingress Controller para Kubernetes em 2026 — Qual escolher para routing e TLS no teu cluster.