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

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

  1. Provisionar infraestrutura: 3 VMs no Hetzner (1 master + 2 workers), rede privada configurada, firewall com porta 6443 aberta apenas intra-rede.
  2. Instalar K3s no master: curl -sfL https://get.k3s.io | INSTALL_K3S_EXEC="server --cluster-init --tls-san <IP>" sh -
  3. Guardar node token: Copiar conteúdo de /var/lib/rancher/k3s/server/node-token para local seguro (password manager).
  4. Juntar workers: Em cada worker, executar curl -sfL https://get.k3s.io | K3S_URL=https://<master-ip>:6443 K3S_TOKEN=<token> sh -
  5. Verificar cluster: kubectl get nodes — todos em estado Ready.
  6. Instalar Cloud Controller Manager: Criar secret com token Hetzner e aplicar manifesto CCM.
  7. Instalar CSI Driver: Aplicar manifesto do Hetzner CSI driver e criar StorageClass.
  8. Configurar cert-manager: kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.15.0/cert-manager.yaml
  9. Criar ClusterIssuer Let’s Encrypt: Configurar email e solver HTTP-01.
  10. Configurar backup etcd: Cron job diário: k3s etcd-snapshot save --name daily-$(date +%Y%m%d)
  11. Instalar monitoring: Prometheus + Grafana via Helm (kube-prometheus-stack).
  12. Configurar alertas: Alertmanager com notificação por email/Slack para nós down, disk full, pod restarts.
  13. Testar disaster recovery: Simular falha do master e restaurar do snapshot mais recente.
  14. 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