Como Realizar Atualizações Rolling com Zero Downtime em Deployments Kubernetes
Configure atualizações rolling no Kubernetes com probes de prontidão, maxSurge, maxUnavailable e desligamento gracioso.
Como Realizar Atualizações Rolling com Zero Downtime em Deployments Kubernetes
As atualizações rolling do Kubernetes podem substituir Pods sem uma interrupção visível, mas apenas se seu Deployment e sua aplicação concordarem sobre quando um Pod está pronto e como ele deve ser desligado. A estratégia padrão ajuda, mas não o salva de probes de prontidão ruins, versões incompatíveis ou requisições em andamento perdidas.
Alcançar verdadeiro zero downtime, no entanto, requer mais do que apenas a configuração padrão do Kubernetes. Exige coordenação cuidadosa entre o manifesto do Deployment, os endpoints de saúde da aplicação e o processo de terminação graciosa. Este guia fornece uma abordagem abrangente e passo a passo para configurar Deployments Kubernetes para garantir que as atualizações de aplicação sejam contínuas e invisíveis para o usuário final.
Este guia aborda probes de prontidão, maxSurge, maxUnavailable e terminação graciosa para que seu serviço mantenha a capacidade durante uma implantação.
Pré-requisitos para Zero Downtime
Antes de configurar o manifesto Kubernetes, a aplicação subjacente deve aderir a certos princípios para suportar implantações com zero downtime:
- Compatibilidade Retroativa da Aplicação: Durante o curto período em que as versões antiga e nova da aplicação estão rodando simultaneamente, elas devem ser compatíveis com recursos compartilhados (bancos de dados, filas, caches).
- Idempotência: Operações que podem ser tratadas por ambas as versões devem ser repetíveis sem efeitos colaterais negativos.
- Terminação Graciosa: A aplicação deve ser programada para reconhecer o sinal
SIGTERMenviado pelo Kubernetes e parar graciosamente de aceitar novas conexões enquanto finaliza as requisições em andamento antes de sair.
Entendendo a Estratégia de Atualização Rolling do Kubernetes
Os Deployments do Kubernetes usam por padrão a estratégia RollingUpdate. Este método garante que a versão antiga da aplicação não seja completamente removida antes que a nova versão esteja operacional, gerenciando a transição usando dois parâmetros principais:
| Parâmetro | Descrição | Impacto no Zero Downtime |
|---|---|---|
maxSurge |
Define o número máximo de Pods que podem ser criados acima do número desejado de réplicas. Pode ser um número absoluto ou uma porcentagem (padrão: 25%). | Controla a velocidade da implantação e garante que a capacidade aumente temporariamente. |
maxUnavailable |
Define o número máximo de Pods que podem ficar indisponíveis durante a atualização. Pode ser um número absoluto ou uma porcentagem (padrão: 25%). | Crucial para zero downtime. Definir isso como 0% significa que nenhum Pod em serviço é terminado até que os novos Pods estejam totalmente Prontos. |
Estratégia Recomendada para Zero Downtime
Para a mais alta disponibilidade, a melhor configuração é frequentemente garantir zero perda de capacidade durante o downtime:
maxUnavailable: 0(Garante que a capacidade nunca caia).maxSurge: 1ou25%(Permite que a capacidade exceda brevemente o alvo, garantindo que um novo Pod esteja pronto antes que um antigo seja morto).
Passo 1: Implementando Probes de Prontidão
A Probe de Prontidão é o mecanismo mais importante para garantir atualizações com zero downtime. O Kubernetes depende desta probe para determinar se um novo Pod está pronto para receber tráfego de usuário e se um Pod antigo ainda está ativamente servindo tráfego.
Probes de Vitalidade vs. Prontidão
- Probe de Vitalidade: Diz ao Kubernetes se o contêiner está saudável e funcional. Se falhar, o contêiner é reiniciado.
- Probe de Prontidão: Diz ao Kubernetes se o contêiner está pronto para servir requisições. Se falhar, o Pod é removido dos endpoints do Service associado, desviando o tráfego dele até que se torne pronto.
Para atualizações rolling, a Probe de Prontidão é usada para controlar a transição. O Kubernetes não prosseguirá para terminar um Pod antigo até que um Pod recém-criado passe com sucesso em sua verificação de prontidão.
# trecho de deployment.yaml
spec:
containers:
- name: my-app
image: myregistry/my-app:v2.0
ports:
- containerPort: 8080
# --- Configuração da Probe de Prontidão ---
readinessProbe:
httpGet:
path: /health/ready
port: 8080
initialDelaySeconds: 15 # Tempo de espera antes da primeira tentativa de probe
periodSeconds: 5 # Com que frequência realizar a verificação
timeoutSeconds: 3
failureThreshold: 3 # Número de falhas consecutivas para marcar o Pod como não pronto
# --- Configuração da Probe de Vitalidade (Verificação de Saúde Padrão) ---
livenessProbe:
httpGet:
path: /health/live
port: 8080
initialDelaySeconds: 60
periodSeconds: 10
Dica: Certifique-se de que o endpoint
/health/readyda sua aplicação retorne um código de sucesso (HTTP 200-299) apenas quando a inicialização, conexões de banco de dados e outras dependências externas estiverem totalmente operacionais.
Passo 2: Configurando a Estratégia do Deployment
Para exigir verdadeiro zero downtime, configuramos explicitamente a estratégia de atualização rolling para evitar qualquer queda no número de réplicas disponíveis.
Nesta configuração, o Kubernetes primeiro criará um novo Pod (maxSurge: 1). Assim que o novo Pod passar em sua probe de prontidão, só então o Kubernetes terminará um Pod antigo. Como maxUnavailable é 0, a capacidade do serviço nunca cai abaixo da contagem alvo de réplicas.
# trecho de deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-web-deployment
spec:
replicas: 4
strategy:
type: RollingUpdate
rollingUpdate:
# Garante que a capacidade nunca caia abaixo da contagem desejada de réplicas (4)
maxUnavailable: 0
# Permite que um Pod extra seja criado durante a implantação
maxSurge: 1
template:
# ... especificação do contêiner ...
Passo 3: Garantindo a Terminação Graciosa
Mesmo com probes de prontidão robustas, se a aplicação desligar instantaneamente ao receber o sinal de terminação, corre o risco de perder requisições em andamento.
O Kubernetes segue uma sequência de terminação específica:
- O Pod é marcado como Terminando.
- O Pod é removido dos endpoints do Service (o tráfego para de ser roteado para ele).
- O hook pré-parada (se definido) é executado.
- O contêiner recebe o sinal
SIGTERM. - O Kubernetes aguarda pela duração definida em
terminationGracePeriodSeconds(padrão: 30 segundos). - Se o contêiner ainda estiver rodando, ele recebe um
SIGKILLinegociável.
Para garantir um desligamento gracioso, a aplicação deve lidar com SIGTERM, e o terminationGracePeriodSeconds deve ser longo o suficiente para a aplicação finalizar as requisições existentes.
# trecho de deployment.yaml, dentro do spec do template do Pod
spec:
terminationGracePeriodSeconds: 45 # Configuração a nível de Pod
containers:
- name: my-app
image: myregistry/my-app:v2.0
lifecycle:
preStop:
exec:
# Dá tempo para atualizações de endpoint e balanceadores de carga externos drenarem.
command: ["/bin/sh", "-c", "sleep 10"]
Melhor Prática: Sua aplicação deve parar de aceitar novo trabalho quando receber
SIGTERM, depois finalizar as requisições em andamento antes de sair. UmterminationGracePeriodSecondsligeiramente mais longo, como 45 ou 60 segundos, ajuda a prevenir mortes forçadas para requisições mais lentas.
Passo 4: Realizando e Monitorando a Atualização
Assim que seu manifesto do Deployment incluir a estratégia otimizada e probes robustas, realizar a atualização é direto.
Atualize a Tag da Imagem: Modifique seu manifesto de deployment para refletir a nova versão da imagem (ex:
v2.0parav2.1).Aplique a Configuração:
kubectl apply -f deployment.yamlAlternativamente, você pode corrigir a imagem diretamente:
kubectl set image deployment/my-web-deployment my-app=myregistry/my-app:v2.1Monitore o Status da Implantação: Observe o Kubernetes progredir através dos estágios, verificando se o número de Pods prontos nunca cai abaixo da contagem desejada.
kubectl rollout status deployment/my-web-deploymentVerifique a Disponibilidade dos Pods: Observe o status dos Pods para confirmar que os Pods antigos (v2.0) são terminados graciosamente apenas após os novos Pods (v2.1) estarem totalmente prontos.
kubectl get pods -l app=my-web-deployment -w
Considerações Avançadas
Usando Orçamentos de Interrupção de Pods (PDBs)
Enquanto uma estratégia de deployment gerencia implantações, um Orçamento de Interrupção de Pods (PDB) limita interrupções voluntárias, como drenagem de nós e algumas operações de manutenção do cluster. Ele não impede todas as falhas não planejadas, mas dá ao Kubernetes e ferramentas de automação um alvo mínimo de disponibilidade a ser respeitado.
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: my-app-pdb
spec:
minAvailable: 75% # Garante que pelo menos 75% das réplicas estejam sempre disponíveis
selector:
matchLabels:
app: my-web-deployment
A Importância do Atraso Inicial
Se sua aplicação leva tempo para aquecer, ajuste initialDelaySeconds, periodSeconds e failureThreshold para que a prontidão reflita o comportamento real de inicialização. Uma probe de prontidão com falha mantém o Pod fora dos endpoints do Service; uma probe de vitalidade com falha é o que pode reiniciar o contêiner e criar um loop de falhas.
Implante com Segurança
Alcançar verdadeiras atualizações rolling com zero downtime no Kubernetes é uma combinação de configuração robusta da plataforma e desenvolvimento disciplinado de aplicações. Ao aproveitar corretamente as Probes de Prontidão para sinalizar o status operacional, ajustar a estratégia do Deployment (maxUnavailable: 0) para manter a capacidade e implementar manipuladores de terminação graciosa, você pode garantir que as atualizações de aplicação sejam realizadas de forma confiável sem interromper o serviço aos seus usuários. Sempre teste seu processo de atualização minuciosamente em um ambiente de staging para validar o período de graça de terminação e a lógica da probe.