Como Realizar Atualizações Contínuas sem Tempo de Inatividade em Implantações Kubernetes
Introdução
Em arquiteturas de microsserviços modernas, manter a disponibilidade contínua durante as atualizações de aplicativos é um requisito inegociável. As Implantações Kubernetes simplificam esse processo, oferecendo Atualizações Contínuas automatizadas, uma estratégia projetada para substituir versões antigas de Pods por novas de forma incremental.
Alcançar um tempo de inatividade realmente zero, no entanto, exige mais do que apenas a configuração padrão do Kubernetes. Exige uma coordenação cuidadosa entre o manifesto da Implantação, os endpoints de saúde do aplicativo e o processo de encerramento elegante. Este guia fornece uma abordagem abrangente e passo a passo para configurar Implantações Kubernetes para garantir que as atualizações do aplicativo sejam contínuas e invisíveis para o usuário final.
Abordaremos o papel crítico das sondas de prontidão, como ajustar os parâmetros da estratégia de implantação (maxSurge e maxUnavailable) e as melhores práticas para encerramento de aplicativos para eliminar interrupções de serviço durante as transições de implantação.
Pré-requisitos para Tempo de Inatividade Zero
Antes de configurar o manifesto do Kubernetes, o aplicativo subjacente deve aderir a certos princípios para suportar implantações com tempo de inatividade zero:
- Compatibilidade Retroativa do Aplicativo: Pelo curto período em que as versões antiga e nova do aplicativo 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 Elegante: O aplicativo deve ser programado para reconhecer o sinal
SIGTERMenviado pelo Kubernetes e parar elegantemente de aceitar novas conexões enquanto finaliza as solicitações em andamento antes de sair.
Entendendo a Estratégia de Atualização Contínua do Kubernetes
As Implantações Kubernetes padrão usam a estratégia RollingUpdate. Este método garante que a versão antiga do aplicativo não seja totalmente desativada antes que a nova versão esteja operacional, gerenciando a transição usando dois parâmetros principais:
| Parâmetro | Descrição | Impacto no Tempo de Inatividade Zero |
|---|---|---|
maxSurge |
Define o número máximo de Pods que podem ser criados além do número desejado de réplicas. Pode ser um número absoluto ou uma porcentagem (padrão: 25%). | Controla a velocidade do rollout e garante que a capacidade aumente temporariamente. |
maxUnavailable |
Define o número máximo de Pods que podem estar indisponíveis durante a atualização. Pode ser um número absoluto ou uma porcentagem (padrão: 25%). | Crucial para tempo de inatividade zero. Definir isso para 0% significa que nenhum Pod em serviço é encerrado até que os novos Pods estejam totalmente Ready. |
Estratégia Recomendada para Tempo de Inatividade Zero
Para a mais alta disponibilidade, a melhor configuração é muitas vezes garantir a perda zero de capacidade de tempo de inatividade:
maxUnavailable: 0(Garanta que a capacidade nunca caia).maxSurge: 1ou25%(Permita que a capacidade exceda brevemente o alvo, garantindo que um novo Pod esteja pronto antes que um antigo seja eliminado).
Passo 1: Implementando Sondas de Prontidão
A Sonda de Prontidão é o mecanismo mais importante para garantir atualizações sem tempo de inatividade. O Kubernetes depende dessa sonda 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.
Liveness vs. Readiness
- Sonda de Atividade (Liveness Probe): Informa ao Kubernetes se o contêiner está saudável e funcional. Se falhar, o contêiner é reiniciado.
- Sonda de Prontidão (Readiness Probe): Informa ao Kubernetes se o contêiner está pronto para servir solicitações. Se falhar, o Pod é removido dos endpoints do Serviço associado, desviando o tráfego dele até que ele fique pronto.
Para atualizações contínuas, a Sonda de Prontidão é usada para controlar a transição. O Kubernetes não prosseguirá para encerrar 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 Sonda de Prontidão ---
readinessProbe:
httpGet:
path: /health/ready
port: 8080
initialDelaySeconds: 15 # Tempo de espera antes da primeira tentativa de sonda
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 Sonda de Atividade (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/readydo seu aplicativo retorne um código de sucesso (HTTP 200-299) somente quando a inicialização, as conexões de banco de dados e outras dependências externas estiverem totalmente operacionais.
Passo 2: Configurando a Estratégia de Implantação
Para exigir um verdadeiro tempo de inatividade zero, configuramos explicitamente a estratégia de atualização contínua 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 sonda de prontidão, somente então o Kubernetes encerrará um Pod antigo. Como maxUnavailable é 0, a capacidade de serviço nunca cai abaixo da contagem de réplicas alvo.
# 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 de réplicas desejada (4)
maxUnavailable: 0
# Permite que um Pod extra seja criado durante o rollout
maxSurge: 1
template:
# ... especificação do contêiner ...
Passo 3: Garantindo a Terminação Elegante
Mesmo com sondas de prontidão robustas, se o aplicativo for encerrado instantaneamente ao receber o sinal de terminação, ele corre o risco de descartar solicitaçõ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 Serviço (o tráfego para de ser roteado para ele).
- O hook de pré-parada (se definido) é executado.
- O contêiner recebe o sinal
SIGTERM. - O Kubernetes aguarda pela duração definida por
terminationGracePeriodSeconds(padrão: 30 segundos). - Se o contêiner ainda estiver em execução, ele recebe um
SIGKILLnão negociável.
Para garantir o desligamento elegante, o aplicativo deve lidar com SIGTERM, e o terminationGracePeriodSeconds deve ser longo o suficiente para o aplicativo finalizar as solicitações existentes.
# trecho de deployment.yaml, dentro da especificação do contêiner
terminationGracePeriodSeconds: 45 # Tempo aumentado para desligamento elegante
containers:
- name: my-app
image: myregistry/my-app:v2.0
lifecycle:
preStop:
exec:
# Exemplo: Executar um script para drenar conexões imediatamente
command: ["/bin/sh", "-c", "sleep 10"]
Melhor Prática: O tempo entre a falha da Sonda de Prontidão do Pod (Passo 2) e o recebimento de
SIGTERM(Passo 4) é crítico. Se seu aplicativo lida comSIGTERMcorretamente, definir umterminationGracePeriodSecondsum pouco mais longo (por exemplo, 45 ou 60 segundos) evita interrupções abruptas.
Passo 4: Realizando e Monitorando a Atualização
Uma vez que seu manifesto de Implantação inclua a estratégia otimizada e sondas robustas, realizar a atualização é simples.
-
Atualize a Tag da Imagem: Modifique seu manifesto de implantação para refletir a nova versão da imagem (por exemplo,
v2.0parav2.1). -
Aplique a Configuração:
bash kubectl apply -f deployment.yamlAlternativamente, você pode corrigir a imagem diretamente:
bash kubectl set image deployment/my-web-deployment my-app=myregistry/my-app:v2.1 -
Monitore o Status do Rollout: Observe o progresso do Kubernetes através das etapas, verificando se o número de Pods prontos nunca cai abaixo da contagem desejada.
bash kubectl rollout status deployment/my-web-deployment -
Verifique a Disponibilidade do Pod: Observe o status do Pod para confirmar que os Pods antigos (v2.0) são encerrados elegantemente somente depois que os novos Pods (v2.1) estão totalmente prontos.
bash kubectl get pods -l app=my-web-deployment -w
Considerações Avançadas
Usando Orçamentos de Interrupção de Pod (PDBs)
Embora uma estratégia de implantação gerencie atualizações voluntárias, um Orçamento de Interrupção de Pod (PDB) garante que um número mínimo de Pods esteja disponível mesmo durante interrupções não planejadas (por exemplo, manutenção de nós, atualizações de cluster). Embora os PDBs não controlem diretamente a velocidade da atualização contínua, eles atuam como uma rede de segurança.
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 seu aplicativo leva tempo para aquecer (por exemplo, carregar grandes arquivos de configuração ou estabelecer caches), certifique-se de que o initialDelaySeconds em sua Sonda de Prontidão seja suficientemente longo. Se a sonda verificar muito cedo e falhar, o Pod será marcado como não saudável e potencialmente ficará preso em um loop de falhas, interrompendo toda a implantação.
Conclusão
Alcançar atualizações contínuas com tempo de inatividade zero no Kubernetes é uma combinação de configuração robusta da plataforma e desenvolvimento disciplinado de aplicativos. Ao alavancar corretamente as Sondas de Prontidão para sinalizar o status operacional, ajustar a estratégia de Implantação (maxUnavailable: 0) para manter a capacidade e implementar manipuladores de terminação elegante, você pode garantir que as atualizações do aplicativo sejam realizadas de forma confiável sem interromper o serviço aos seus usuários. Sempre teste seu processo de atualização completamente em um ambiente de staging para validar o período de carência de terminação e a lógica da sonda.