Kubernetes em vários continentes: k3s e k8s em alta disponibilidade entre centros de dados de todo o mundo

Publicado a 16 min de leitura

Kubernetes nos EUA, na Europa e na Ásia, capaz de aguentar a falha de um continente inteiro: porque é que o etcd não tolera longas distâncias, um cluster k3s por região, GitOps com Flux, failover por Geo-DNS, dados entre regiões e as diferenças face ao kubeadm.

O Kubernetes é o padrão quando as aplicações têm de funcionar de forma tolerante a falhas e escalar automaticamente. A ideia óbvia de estender um único cluster Kubernetes por servidores nos EUA, na Europa e na Ásia esbarra, no entanto, num pormenor: no etcd, a base de dados onde o Kubernetes guarda todo o seu estado. Este artigo mostra como o Kubernetes em vários continentes funciona mesmo assim, e de forma a aguentar a falha de um continente inteiro: com um cluster por região, um deploy comum via GitOps e um Geo-DNS que envia os utilizadores para a região saudável mais próxima.

Montamos a arquitetura com o k3s, a distribuição Kubernetes leve e totalmente certificada que se instala em minutos, e no fim mostramos o que muda com um Kubernetes clássico instalado com o kubeadm. As bases sobre disponibilidade, quorum e failover em várias localizações estão explicadas em pormenor no artigo Docker Swarm em três continentes; aqui tratamos do que é diferente no Kubernetes.

Um cluster para todos os continentes ou um cluster por região?

Para o Kubernetes em vários continentes, a arquitetura certa é um cluster por região, e não um único cluster para todos os continentes. Cada cluster funciona de forma independente, todos são implementados a partir do mesmo repositório Git, e um Geo-DNS com health checks distribui os utilizadores. Se uma região falhar, as outras assumem o serviço, sem que seja preciso coordenar um estado comum do cluster através do oceano.

Porque é que o etcd não tolera longas distâncias

O Kubernetes guarda cada estado, cada configuração e cada alteração no etcd, um armazenamento chave-valor com consenso Raft. Cada escrita precisa da confirmação da maioria de todos os membros do etcd. Por predefinição, o etcd trabalha com um heartbeat de 100 milissegundos e um timeout de eleição de um segundo; entre a Europa, a América do Norte e a Ásia, os tempos de trânsito dos pacotes situam-se entre 80 e 250 milissegundos. É possível aumentar estes tempos, mas então todas as escritas no cluster ficam lentas, desde o agendamento de um pod até à gravação de um Secret. A documentação do k3s é clara neste ponto: o etcd integrado não é suportado em clusters distribuídos por várias redes, e todos os servidores devem estar na mesma localização. Também o próprio Kubernetes foi concebido para que um cluster abranja várias zonas dentro de uma região, e não vários continentes.

Os três padrões comparados

PadrãoComo funcionaAvaliação
Um cluster para todos os continentesPlano de controlo e etcd distribuídos por vários continentesNão recomendado: escritas lentas, etcd instável, não suportado no k3s com etcd integrado
Plano de controlo numa região, workers em todo o mundoServidores numa localização, agents noutros continentesFunciona tecnicamente, mas se a região do plano de controlo falhar, deixa de ser possível reagendar o que quer que seja em todo o mundo
Um cluster por regiãoTrês clusters independentes, implementados em conjunto via GitOps, com Geo-DNS à frenteRecomendado: cada região sobrevive à falha das outras, e os erros ficam limitados a uma região

A abordagem «um cluster por região» tem uma segunda vantagem, muitas vezes subestimada: um erro no plano de controlo, uma alteração errada no cluster ou um upgrade que corre mal afeta sempre apenas uma região. Os utilizadores das outras regiões nem dão por isso.

k3s ou k8s?

Ambos são Kubernetes a sério, com a mesma API, os mesmos manifestos e as mesmas ferramentas. A diferença está na estrutura e no esforço:

Característicak3sk8s com kubeadm
InstalaçãoUm comando, um binárioConfigurar separadamente o runtime de containers, o kubeadm, o kubelet e o plugin de rede
Recursos para um nó servidorPelo menos 2 núcleos e 2 GB de RAMBastante mais, consoante os componentes
IncluídoControlador de Ingress (Traefik), rede (Flannel), provisionador de armazenamento, load balancer de serviçosApenas o núcleo, tudo o resto fica à sua escolha
Alta disponibilidadeetcd integrado com três servidoresTrês nós do plano de controlo com um load balancer à frente da API
Indicado paraA maioria das aplicações, equipas pequenas, um único nó por regiãoEquipas que querem escolher cada componente por si próprias

Para a arquitetura com um cluster por região, recomendamos o k3s: operar três clusters só é confortável se cada um deles for simples. Quem já tem experiência com o kubeadm pode adotar a arquitetura sem alterações; a secção sobre o kubeadm, mais abaixo, mostra as diferenças.

A arquitetura: três regiões, três clusters, um ponto de entrada

ComponenteFunçãoQue falha fica coberta
Um cluster k3s por regiãoExecuta a aplicação perto dos utilizadoresFalha de uma região inteira
Três servidores por região (fase de expansão)Mantém o etcd e o plano de controlo em alta disponibilidade dentro da regiãoFalha de servidores individuais numa região
Repositório Git e Flux em cada clusterCada cluster vai buscar ele próprio o seu estado desejado ao GitNenhum servidor central de deploy como ponto de falha
Ingress com certificados por validação DNSRecebe os pedidos dos utilizadoresOs certificados funcionam independentemente da comutação de DNS
Geo-DNS com health checksEnvia os utilizadores para a região saudável mais próximaRegiões inacessíveis
Armazenamento de dados replicado e backupsMantém os dados em várias regiõesPerda de dados na falha de uma região

Configuração inicial e expansão

A configuração inicial consiste em três servidores, um nos EUA, um na Europa e um na Ásia, cada um como cluster independente de nó único. Se um servidor falhar, a sua região falha, e o Geo-DNS envia os respetivos utilizadores para a região vizinha. Esta fase já está concebida para a falha de um continente inteiro. Na expansão, cada região recebe três servidores na mesma localização; assim, cada região sobrevive também, por si só, à falha de um servidor, sem que os utilizadores tenham de ser redirecionados.

Que localizações da KernelHost são adequadas

A KernelHost opera servidores no centro de dados maincubes em Frankfurt am Main e oferece servidores virtuais noutras localizações na Europa, na América do Norte e na Ásia-Pacífico, entre elas três localizações nos EUA, o Canadá, Londres, Estrasburgo, Varsóvia, Helsínquia, Singapura, o Japão, Sydney e Mumbai. A lista completa está na página Localizações de servidores. O exemplo deste artigo usa Frankfurt am Main para a Europa, a costa leste dos EUA para a América do Norte e Singapura para a Ásia.

Guia: Kubernetes com k3s em três regiões

O exemplo usa três servidores com Debian 12 ou 13: k3s-eu, k3s-us e k3s-asia. Os endereços públicos vêm da rede de documentação 203.0.113.0/24, e o domínio é example.com. Substitua ambos pelos seus valores.

Passo 1: disponibilizar servidores em três regiões

Encomende três servidores em três regiões, com pelo menos 2 vCPU e 4 GB de RAM, para que, além do k3s, também a sua aplicação tenha espaço. Aplique a proteção básica da checklist para novos servidores root e atribua nomes de host descritivos. O etcd beneficia claramente de SSD rápidos, e o armazenamento NVMe dos servidores da KernelHost cumpre esse requisito.

Passo 2: instalar o k3s

Em cada um dos três servidores, instale o k3s com um único comando. Cada servidor passa assim a ser um cluster Kubernetes completo com um nó:

curl -sfL https://get.k3s.io | sh -
kubectl get nodes

Após cerca de um minuto, o kubectl get nodes mostra o nó como Ready. Vêm incluídos o Traefik como controlador de Ingress, o Flannel como rede e um provisionador para volumes locais.

Passo 3: expandir para três servidores por região

Se quiser que a própria região fique em alta disponibilidade, coloque três servidores na mesma localização. O primeiro servidor inicia o etcd integrado, e os outros dois juntam-se ao cluster com um token comum. O etcd exige um número ímpar de servidores; com três servidores, a região aguenta a falha de um servidor:

curl -sfL https://get.k3s.io | K3S_TOKEN=TOKEN_SECRETO sh -s - server \
    --cluster-init \
    --tls-san=api.eu.example.com
curl -sfL https://get.k3s.io | K3S_TOKEN=TOKEN_SECRETO sh -s - server \
    --server https://203.0.113.21:6443 \
    --tls-san=api.eu.example.com

Todos os servidores de uma região precisam das mesmas definições para os intervalos de rede e para as funcionalidades. Entre eles, têm de estar abertas as portas 2379 a 2380/TCP para o etcd, 6443/TCP para a API, 10250/TCP para o Kubelet e 8472/UDP para a rede Flannel; para o exterior, ficam bloqueadas. O token é um segredo: quem o conhecer pode acrescentar servidores seus ao cluster.

Passo 4: configurar o acesso aos três clusters

O k3s guarda as credenciais de acesso em /etc/rancher/k3s/k3s.yaml. Copie o ficheiro de cada cluster para o seu computador de trabalho, substitua nele 127.0.0.1 pelo endereço do servidor e dê aos contextos o nome da respetiva região:

kubectl config rename-context default eu
kubectl config use-context eu
kubectl --context us get nodes

A API na porta 6443 é o acesso mais poderoso ao cluster. Permita esse acesso na firewall apenas a partir do seu próprio endereço ou de uma VPN, nunca para toda a internet. O ficheiro k3s.yaml contém um certificado de administrador e deve ser guardado com o mesmo cuidado que uma palavra-passe de root.

Passo 5: GitOps com o Flux em cada cluster

Para que as três regiões operem a mesma aplicação na mesma versão, o estado desejado fica num repositório Git e, em cada cluster, corre o Flux, que estabelece esse estado de forma autónoma. Cada cluster vai, portanto, buscar a sua configuração por si próprio; não existe um servidor central de deploy que possa falhar. Uma estrutura de repositório comprovada:

apps/
  web/            manifestos comuns da aplicação
clusters/
  eu/             definições e versão para a Europa
  us/             definições e versão para a América do Norte
  asia/           definições e versão para a Ásia
flux bootstrap git --url=ssh://git@git.example.com/infra/fleet.git --branch=main --path=clusters/eu

Execute o mesmo comando com --path=clusters/us e --path=clusters/asia no respetivo contexto. Como cada região tem o seu próprio diretório, pode implementar uma nova versão primeiro numa região e só depois nas outras.

Passo 6: descrever a aplicação de forma tolerante a falhas

Dentro de uma região, há três elementos que garantem que a aplicação sobrevive a manutenções e a falhas de servidores: várias réplicas distribuídas por nós diferentes, verificações que detetam pods não saudáveis e um orçamento de interrupções que impede que uma manutenção remova todos os pods ao mesmo tempo:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: web
spec:
  replicas: 3
  selector:
    matchLabels:
      app: web
  template:
    metadata:
      labels:
        app: web
    spec:
      topologySpreadConstraints:
        - maxSkew: 1
          topologyKey: kubernetes.io/hostname
          whenUnsatisfiable: ScheduleAnyway
          labelSelector:
            matchLabels:
              app: web
      containers:
        - name: web
          image: registry.example.com/web:1.0
          ports:
            - containerPort: 8080
          readinessProbe:
            httpGet:
              path: /health
              port: 8080
            periodSeconds: 5
          livenessProbe:
            httpGet:
              path: /health
              port: 8080
            periodSeconds: 10
---
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
  name: web
spec:
  minAvailable: 1
  selector:
    matchLabels:
      app: web

A verificação de readiness retira um pod do tráfego enquanto ele não responder, e a verificação de liveness reinicia-o quando fica bloqueado. Num cluster de nó único, a distribuição por vários nós ainda não tem efeito; passa a aplicar-se automaticamente assim que a região tiver três servidores.

Passo 7: Ingress e certificados

A entrada fica a cargo do Traefik incluído. Como as três regiões servem o mesmo domínio, obtenha os certificados TLS com o cert-manager através da validação DNS: esta funciona em todas as regiões, independentemente do sítio para onde o registo DNS aponta nesse momento. A validação HTTP, pelo contrário, falha em todas as regiões para as quais o registo não aponta nesse momento. Quem trabalha sem Ingress do Kubernetes encontra as bases no artigo Configurar o nginx como reverse proxy.

Passo 8: configurar o Geo-DNS com failover

Um serviço de DNS com encaminhamento geográfico e health checks envia os utilizadores da Europa para Frankfurt am Main, os da América para a costa leste dos EUA e os da Ásia para Singapura, e verifica a cada 30 a 60 segundos se a entrada de cada região responde. Se uma região falhar, deixa de devolver o respetivo endereço. Defina o TTL dos registos para 60 segundos; assim, uma comutação fica normalmente concluída ao fim de um a dois minutos. Quem quiser gerir os registos a partir do próprio cluster pode usar o external-dns para isso.

Passo 9: implementar região a região e testar a falha

Introduza uma nova versão primeiro no diretório de uma região, observe essa região durante alguns minutos e só depois adote a versão nas outras. Assim, um erro que nenhuma verificação deteta atinge no máximo uma região. Para ensaiar a falha de uma região, pare o k3s no respetivo servidor e verifique se o Geo-DNS retira a região das respostas e se a região vizinha aguenta a carga:

systemctl stop k3s
systemctl start k3s

Numa região com três servidores, ensaie também a manutenção de um único servidor. O kubectl drain desloca os pods respeitando o orçamento de interrupções do passo 6, e o kubectl uncordon volta a colocar o servidor em serviço:

kubectl drain k3s-eu-2 --ignore-daemonsets --delete-emptydir-data
kubectl uncordon k3s-eu-2

Dados entre regiões

O Kubernetes distribui pods, não dados. Um PersistentVolume do provisionador incluído fica em exatamente um nó, e entre os clusters não existe, de origem, qualquer armazenamento de dados comum. Por isso, para tudo o que envolve dados, aplica-se o mesmo que em qualquer cluster distribuído por várias localizações:

  • As bases de dados tratam da sua própria replicação. Uma solução comprovada é uma instância primária numa região com réplicas nas outras; operadores de bases de dados como o CloudNativePG para PostgreSQL suportam essas réplicas também entre clusters diferentes. Entre continentes, a replicação é assíncrona, e numa emergência podem faltar os últimos segundos de escritas. Para escrita sem perdas em todo o mundo, existem bases de dados multirregião como o CockroachDB ou o YugabyteDB.
  • Os ficheiros e os uploads devem ficar num armazenamento de objetos compatível com S3, com replicação para uma segunda região.
  • As sessões ficam numa base de dados replicada ou numa cache replicada, ou então a aplicação usa tokens assinados.
  • Os backups continuam a ser obrigatórios, porque a replicação distribui os erros tal como distribui os dados bons. Para objetos e volumes do Kubernetes, o Velero é adequado; para as bases, consulte a estratégia de backup para servidores.

Kubernetes com kubeadm em vez de k3s

Com o kubeadm, a arquitetura mantém-se a mesma: um cluster por região, GitOps, Geo-DNS. O que muda é a construção de cada cluster. Instale em todos os nós um runtime de containers como o containerd, bem como o kubeadm, o kubelet e o kubectl, coloque à frente da API da região um load balancer ou um endereço virtual, por exemplo com o kube-vip, e inicialize o primeiro nó do plano de controlo:

kubeadm init --control-plane-endpoint "api.eu.example.com:6443" --upload-certs

A saída contém dois comandos de adesão: um com --control-plane --certificate-key para os outros dois nós do plano de controlo e um para os workers. Depois, instale um plugin de rede como o Calico ou o Cilium e um controlador de Ingress, que o k3s já traz de origem. O esforço adicional compensa quando precisa de escolher componentes específicos de forma deliberada ou de se manter próximo da versão upstream.

Porquê a KernelHost para Kubernetes em vários continentes

RequisitoPorque é importanteNa KernelHost
Localizações em vários continentesUm cluster por região precisa de servidores em cada regiãoFrankfurt am Main e ainda localizações na Europa, na América do Norte e na Ásia-Pacífico, tudo do mesmo fornecedor
Tráfego ilimitadoOs downloads de imagens, a replicação de bases de dados e os backups geram tráfego permanenteVPS com tráfego ilimitado sem limite de volume
Armazenamento rápidoO etcd é sensível a discos lentosSSD NVMe em RAID
Proteção DDoSCada Ingress está acessível publicamenteIncluída em todas as localizações; na localização principal, Frankfurt am Main, com 3,2 Tbps de filtragem Arbor em tempo real, sem null-routing
Acesso root completoO k3s, a firewall e as definições do kernel precisam de controlo totalEm todos os servidores root KVM e servidores dedicados
Sem fidelizaçãoOs nós e os clusters de teste vêm e vãoPrePaid, sem prazo mínimo, sem taxa de instalação
AutomatizaçãoOs novos nós devem poder ser criados por scriptEncomenda e gestão através da KernelHost API

Na página Alugar servidor cloud encontra uma visão geral de todos os planos cloud e uma comparação de custos com os grandes fornecedores de cloud.

Erros frequentes e como evitá-los

  • etcd estendido entre continentes. O resultado são escritas lentas e eleições instáveis, e no k3s com etcd integrado isto não é suportado. Solução: um cluster por região.
  • Dois servidores numa região. O etcd precisa de uma maioria, e dois servidores não aguentam nenhuma falha. Solução: um ou três.
  • API aberta a toda a internet. A porta 6443 é a chave mestra do cluster. Solução: apenas a partir do seu próprio endereço ou por VPN.
  • Servidor central de deploy. Se falhar, deixa de ser possível implementar o que quer que seja. Solução: o Flux em cada cluster, que se serve diretamente do Git.
  • Atualização em todas as regiões ao mesmo tempo. Nesse caso, um erro afeta todos os utilizadores. Solução: região a região, através dos diretórios no repositório.
  • Certificados por validação HTTP. Nas regiões para as quais o registo DNS não aponta nesse momento, a renovação falha. Solução: validação DNS.
  • Base de dados num volume local sem replicação. Se o nó falhar, os dados ficam inacessíveis. Solução: replicação através de um operador de bases de dados.
  • Sem probes e sem orçamento de interrupções. Os pods não saudáveis continuam a receber tráfego, e as manutenções tiram todos os pods da rede ao mesmo tempo. Solução: verificações de readiness e liveness, mais um PodDisruptionBudget.

Em resumo

  • Para o Kubernetes em vários continentes, o correto é um cluster por região; um único cluster para todos os continentes falha por causa da latência do etcd.
  • A configuração inicial consiste em três servidores, um nos EUA, um na Europa e um na Ásia; esta fase já sobrevive à falha de um continente inteiro.
  • Na expansão, cada região recebe três servidores na mesma localização, e assim cada região sobrevive também a falhas de servidores individuais.
  • O Flux em cada cluster implementa a aplicação a partir do mesmo repositório Git, região a região.
  • Um Geo-DNS com health checks e um TTL curto envia os utilizadores para a região saudável mais próxima, e os certificados são obtidos por validação DNS.
  • O Kubernetes distribui pods, não dados: as bases de dados precisam de replicação própria e os backups continuam a ser obrigatórios.
  • Para esta arquitetura, o k3s é normalmente uma escolha melhor do que o kubeadm, porque três clusters simples são mais fáceis de operar do que três complexos.

Perguntas frequentes

Um cluster Kubernetes pode abranger vários continentes?
Tecnicamente, é possível distribuir o plano de controlo, mas não é recomendável. O Kubernetes guarda o seu estado no etcd, e cada escrita precisa da confirmação de uma maioria de todos os membros do etcd. Entre continentes, o tempo de trânsito é de 80 a 250 milissegundos, e o etcd trabalha por predefinição com um heartbeat de 100 milissegundos. Segundo a documentação do k3s, o etcd integrado não é suportado em redes distribuídas. O correto é um cluster por região.
Como se monta o Kubernetes em alta disponibilidade em várias regiões?
Com um cluster próprio por região, por exemplo um cluster k3s nos EUA, outro na Europa e outro na Ásia. Todos os clusters são implementados via GitOps a partir do mesmo repositório Git, por exemplo com o Flux em cada cluster, e um Geo-DNS com health checks envia os utilizadores para a região saudável mais próxima. Se uma região falhar, as outras assumem o serviço, sem que seja preciso coordenar um estado comum através do oceano.
Qual é a diferença entre k3s e k8s?
Ambos são Kubernetes completo, com a mesma API e os mesmos manifestos. O k3s é uma distribuição leve e certificada num único binário, que se instala com um comando e já traz controlador de Ingress, rede e provisionador de armazenamento; um servidor precisa de pelo menos 2 núcleos e 2 GB de RAM. Um cluster k8s com kubeadm é montado a partir de componentes individuais, oferece mais liberdade de escolha e exige mais esforço.
De quantos servidores precisa um cluster k3s de alta disponibilidade?
De três nós servidor com etcd integrado, na mesma localização. O etcd precisa de uma maioria, pelo que três servidores aguentam a falha de um servidor. Dois servidores não trazem qualquer ganho, porque a falha de um dos dois faz perder a maioria. Para o Kubernetes em vários continentes, bastam, para começar, três clusters de nó único, um por região, porque o Geo-DNS absorve a falha de uma região inteira.
De que portas precisa o k3s?
A API do Kubernetes e o supervisor do k3s usam a porta 6443/TCP, o Kubelet a 10250/TCP e a rede Flannel a 8472/UDP com VXLAN ou a 51820/UDP com WireGuard. Com vários servidores e etcd integrado, juntam-se as portas 2379 a 2380/TCP entre os servidores. Nenhuma destas portas deve ficar aberta para a internet; permita a API apenas a partir do seu próprio endereço ou por VPN.
Como se implementam aplicações em vários clusters Kubernetes?
Via GitOps: o estado desejado de todos os clusters fica num repositório Git, e em cada cluster corre uma ferramenta como o Flux, que estabelece esse estado de forma autónoma. Cada região tem o seu próprio diretório, pelo que uma nova versão pode ser implementada primeiro numa região e, após um período de observação, nas outras. Deste modo, não existe um servidor central de deploy que possa falhar.
Como funciona o failover entre as regiões Kubernetes?
Através de um serviço de DNS com encaminhamento geográfico e health checks. Esse serviço envia os utilizadores para a região mais próxima e verifica a cada 30 a 60 segundos se o respetivo Ingress responde. Se uma região falhar, deixa de devolver o seu endereço e encaminha os utilizadores para a região saudável mais próxima. Com um TTL de 60 segundos, a comutação fica normalmente concluída ao fim de um a dois minutos.
Como se preservam os dados quando uma região falha?
O Kubernetes distribui pods, não dados. Por isso, as bases de dados tratam da sua própria replicação, por exemplo o PostgreSQL com o operador CloudNativePG, que mantém réplicas também entre clusters diferentes. Entre continentes, a replicação é assíncrona, e numa emergência podem faltar os últimos segundos de escritas. Os ficheiros devem ficar num armazenamento de objetos replicado, e os backups regulares, por exemplo com o Velero, continuam a ser obrigatórios.
Kubernetes ou Docker Swarm para vários continentes?
O Docker Swarm pode ser estendido como um único cluster por três continentes e é bastante mais simples de operar. O Kubernetes oferece mais automatização e um ecossistema maior, mas entre continentes é operado como um cluster por região, unificado via GitOps. Para equipas pequenas com aplicações de dimensão gerível, o Swarm é muitas vezes a escolha pragmática; para plataformas complexas, o Kubernetes.
Que localizações da KernelHost são adequadas para Kubernetes em vários continentes?
A KernelHost oferece servidores em Frankfurt am Main e noutras localizações na Europa, na América do Norte e na Ásia-Pacífico, entre elas três localizações nos EUA, o Canadá, Londres, Estrasburgo, Varsóvia, Helsínquia, Singapura, o Japão, Sydney e Mumbai. Uma combinação comprovada é Frankfurt am Main, a costa leste dos EUA e Singapura, com um ou três servidores por região na mesma localização.
Quanto custa o Kubernetes em três continentes?
Na configuração inicial, três servidores, um por região, e na expansão nove, a que se junta um serviço de DNS com health checks. O k3s em si é gratuito. Como a replicação, os backups e os downloads de imagens geram tráfego permanente, os planos com tráfego ilimitado são decisivos. Na KernelHost, os VPS com tráfego ilimitado funcionam sem limite de volume, em PrePaid, sem prazo mínimo e sem taxa de instalação, pelo que os clusters podem ser aumentados ou reduzidos conforme as necessidades.

Kubernetes k3s k8s kubeadm Alta disponibilidade Multirregião GitOps Flux Geo-DNS Cloud