Home Comunidade Eventos YouTube Networks Desafios // produtos Academy News CTI | CVE Contato

01 - Rolling Update

#deploy#health-check#kubernetes#rollback#rolling-update
video explicativo
Video explicativoEspaco reservado para o video desta anotação — adicione video: https://youtu.be/... no frontmatter da nota.

Rolling Update

O Rolling Update é a estratégia de deploy que substitui as instâncias de uma aplicação de forma gradual, em ondas, mantendo parte da frota antiga servindo tráfego enquanto as novas réplicas entram em operação. Ao final do processo, todas as instâncias rodam a versão nova e nenhuma janela de indisponibilidade é aberta em nenhum momento. É a estratégia padrão de orquestradores como Kubernetes e AWS ECS, e a escolha natural para serviços stateless com tráfego contínuo. Sua relevância em produção vem da combinação de custo zero de infraestrutura adicional com simplicidade operacional: não existe ambiente paralelo para manter, apenas a mesma frota sendo reciclada aos poucos. O preço dessa simplicidade é que, durante a transição, duas versões coexistem em produção, o que impõe exigências reais de compatibilidade entre versões, sobretudo no schema do banco de dados.

Conceito e problema que resolve

O problema central que o rolling update ataca é a implantação sem downtime em uma frota única. Antes de orquestradores difundirem essa prática, deploys exigiam janelas de manutenção: o serviço parava, o binário novo entrava e o serviço voltava, com perda de requisições em curso e risco ampliado porque a versão nova só era testada em produção depois de já ter substituído tudo. O rolling update inverte essa lógica ao tratar o deploy como um processo incremental e verificável, em que cada onda só avança se a anterior passar nos critérios de saúde.

Três propriedades definem a estratégia. Primeiro, a substituição é gradual, então a capacidade total nunca cai abaixo de um piso declarado. Segundo, a validação acontece por onda, com health checks entre etapas, e não apenas no final. Terceiro, o rollback é natural, bastando reimplantar a versão anterior pelo mesmo mecanismo, sem troca de ambiente nem manipulação de roteamento.

Funcionamento interno: max surge e max unavailable

Duas margens controlam a dança das réplicas. O max surge define quantos Pods acima do número desejado podem ser criados, garantindo capacidade extra durante a transição. O max unavailable define quantos Pods abaixo do desejado podem estar indisponíveis, permitindo acelerar o processo às custas de capacidade reduzida. Com desejado igual a 4, max surge igual a 1 e max unavailable igual a 0, o controlador cria 1 Pod novo, espera ele ficar saudável, encerra 1 Pod antigo, e repete até completar; a frota nunca fica abaixo de 4 réplicas prontas.

Cada onda segue o mesmo ciclo de verificação. O orquestrador cria a réplica nova, aguarda o readiness probe responder com sucesso, somente então insere a réplica no pool do balanceador e encerra a réplica antiga equivalente, respeitando o grace period para drenar conexões em curso. Se o Pod novo falhar repetidamente no readiness, a onda trava e o deploy fica estagnado, o que é o comportamento desejado: um deploy ruim não deve se propagar silenciosamente pela frota.

# Rolling update em Kubernetes: transição conservadora para um serviço crítico
apiVersion: apps/v1
kind: Deployment
metadata:
  name: pagamentos
spec:
  replicas: 6
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 2          # cria até 2 Pods extras; capacidade nunca falta
      maxUnavailable: 0    # nenhum Pod antigo sai antes do novo ficar pronto
  minReadySeconds: 15      # Pod precisa ficar 15s pronto antes de contar
  selector:
    matchLabels:
      app: pagamentos
  template:
    metadata:
      labels:
        app: pagamentos
    spec:
      terminationGracePeriodSeconds: 30   # tempo para drenar conexões
      containers:
        - name: api
          image: registry.internal/pagamentos:v2.4.1
          readinessProbe:                  # gate de entrada no tráfego
            httpGet:
              path: /healthz/ready
              port: 8080
            periodSeconds: 5
            failureThreshold: 3
          livenessProbe:                   # gate de permanência em execução
            httpGet:
              path: /healthz/live
              port: 8080
            periodSeconds: 10

No ECS o mesmo conceito aparece nos parâmetros minimumHealthyPercent e maximumPercent do serviço, e em grupos de Auto Scaling clássicos aparece nas políticas de substituição de instâncias. A semântica é idêntica em todas as plataformas: surge e unavailable expressam as margens de folga da transição.

# Rolling update no AWS ECS: substituição controlada das tasks do serviço
aws ecs update-service \
  --cluster prod-api \
  --service pagamentos \
  --task-definition pagamentos:42 \
  --deployment-configuration \
    "minimumHealthyPercent=100,maximumPercent=150" \
  --deployment-circuit-breaker "enable=true,rollback=true"
# minimumHealthyPercent=100 mantém a frota cheia; maximumPercent=150
# permite 50% de tasks extras (surge); o circuit breaker reverte
# automaticamente o deploy se as tasks novas falharem repetidamente

O deployment circuit breaker do ECS materializa a lição mais importante da estratégia: um rolling update precisa de um juiz automático. Sem ele, um deploy ruim fica estagnado indefinidamente, com o serviço operando em capacidade reduzida e ninguém agindo. Com o breaker habilitado, a falha repetida das tasks novas dispara o rollback automático, devolvendo o serviço ao estado anterior sem intervenção humana.

Health checks por onda e qualidade do gate

A confiabilidade de um rolling update depende diretamente da qualidade dos health checks. Um endpoint de readiness deve verificar não apenas o processo estar de pé, mas as dependências essenciais estarem prontas: conexão com banco, cache aquecido, filas conectadas e configuração carregada. Um readiness frouxo, que responde 200 logo no boot da aplicação, transforma o rolling update em roleta russa, porque Pods quebrados entram no pool antes de conseguirem servir.

Além do readiness, o minReadySeconds protege contra Pods que ficam prontos e morrem logo depois, um padrão comum em falhas de inicialização lenta, como carregamento de cache ou compilação JIT. Durante esses segundos mínimos, o Pod ainda não conta como disponível para o progresso do deploy. Em plataformas mais sofisticadas, o gate por onda pode incorporar análise de métricas das réplicas novas, aproximando o rolling update de um canary em micro-escala.

Compatibilidade de schema entre versões

Durante a transição, requisições de ambas as versões atingem o mesmo banco de dados, e é aqui que o rolling update cobra seu preço técnico. A regra de ouro é o expand and contract: toda migração de schema é dividida em duas fases reversíveis. Na fase de expansão, a mudança é apenas aditiva, com colunas, tabelas ou índices novos, de modo que o código antigo e o novo operam sem conflito. Na fase de contração, executada só depois de nenhuma instância da versão antiga restar, os elementos obsoletos são removidos.

  • Colunas novas devem aceitar nulo ou ter default, porque o código antigo não as preenche.
  • Colunas renomeadas exigem duplicação temporária, sincronizada pela aplicação ou por trigger.
  • Remoção de coluna só ocorre na fase de contração, jamais junto do deploy que para de usá-la.
  • Índices criados em tabelas grandes usam build concorrente para não bloquear escritas durante o deploy.
  • Mudanças de tipo exigem coluna nova com conversão e backfill gradual, nunca alteração in place.

Esse regime de compatibilidade também vale para contratos de API entre serviços, já que consumidores antigos continuam chamando enquanto a frota nova entra. Versionamento de endpoints e tolerância a campos desconhecidos em payloads são práticas complementares.

Rollback natural e limites

O rollback de um rolling update é apenas um novo rolling update com a imagem anterior, executado pelo mesmo pipeline. Não há troca de tráfego nem ambiente a restaurar, e as réplicas voltam ao estado anterior onda por onda. Em Kubernetes, o comando abaixo reverte para o revision anterior do histórico do Deployment, e a condição Progressing do objeto passa a reportar o regresso.

# Rollback natural: reimplantação da revisão anterior pelo mesmo mecanismo
kubectl rollout undo deployment/pagamentos              # volta uma revisão
kubectl rollout history deployment/pagamentos           # lista revisões disponíveis
kubectl rollout status deployment/pagamentos            # acompanha o progresso
kubectl rollout pause deployment/pagamentos             # congela a onda em andamento

O limite do rollback natural é o schema: se o deploy introduziu uma migração destrutiva, voltar a imagem não volta o dado, e o rollback completo se torna inviável. O segundo limite é a velocidade, porque a reversão leva o mesmo tempo da ida, onda por onda, enquanto estratégias com switch de tráfego revertem em segundos. O terceiro limite é a durabilidade da sessão: instâncias encerradas perdem estado em memória, o que exige sessões externas ou adesão de sticky session com cautela.

O progressDeadlineSeconds complementa o controle do processo: define o prazo máximo para o deploy progredir antes de o controlador marcar a condição Progressing como Degraded. Sem esse prazo, uma onda travada por uma imagem que não baixa ou por um readiness que nunca responde fica em silêncio indefinido. Em pipelines com GitOps, o mesmo papel é cumprido pelo timeout de sincronização do operador, que deve estar configurado para falhar visivelmente em vez de esperar para sempre.

Aplicação prática e comparação

O rolling update é a escolha certa quando a aplicação é stateless, o schema evolui sob expand and contract, e a tolerância a um período de coexistência de versões é alta. Ele domina o dia a dia de microsserviços com deploys frequentes, justamente porque não cobra infraestrutura duplicada nem decisões de roteamento. A tabela abaixo posiciona a estratégia frente às alternativas do mesmo módulo.

Critério Rolling Update Blue-Green Canary
Custo de infra extra Zero, reusa a frota Dobro, ambiente completo Pequeno, réplicas a mais
Tempo de rollback Minutos, onda por onda Segundos, switch de tráfego Minutos, ajuste de peso
Exposição ao risco Gradual e automática Tudo de uma vez no switch Gradual e controlada
Coexistência de versões Sim, durante toda a transição Sim, antes do switch Sim, por tempo estendido
Requisito de schema Compatibilidade obrigatória Compatibilidade no switch Compatibilidade estendida
Complexidade operacional Baixa Média, dois ambientes Alta, análise de métricas

Erros comuns e boas práticas

Os erros clássicos têm um padrão em comum: transformar um deploy seguro em uma propagação de falha.

  • Readiness probe que só testa o processo, e não as dependências, deixando Pods doentes entrarem no pool; o gate deve validar prontidão real de serviço.
  • maxUnavailable alto em frotas pequenas, que derruba a capacidade de resposta justo durante a janela mais sensível do deploy.
  • Migrações destrutivas junto do deploy, inviabilizando o rollback natural; a fase de contração pertence a um deploy futuro.
  • Ausência de minReadySeconds, permitindo que Pods instáveis contabilizem progresso e liberem a onda seguinte.
  • Grace period curto demais no encerramento, cortando requisições em curso; o Pod deve drenar e o balanceador respeitar a desregistro.
  • Deploy estagnado sem alarme, com a condição Progressing travada e ninguém percebendo por horas; todo deploy precisa de timeout e alerta.
  • PDB ausente em Kubernetes, permitindo que a evicção de Pods durante o update reduza a capacidade abaixo do tolerável.

Entre as boas práticas, estabeleça surge e unavailable coerentes com o tamanho da frota, use readiness honesto combinado com minReadySeconds, trate o schema com expand and contract como pré-condição do pipeline, e monitore a condição de progresso com alarme automático. Em serviços de missão crítica onde o tempo de rollback é insuficiente, a evolução natural é adotar canary com análise de métricas, mantendo o rolling update como base mecânica da substituição.