Docker & Kubernetes

O que Todo Dev Deve Saber sobre Progressive Delivery com Argo Rollouts: Canary e Blue-Green Automatizados

13 min de leitura

O que Todo Dev Deve Saber sobre Progressive Delivery com Argo Rollouts: Canary e Blue-Green Automatizados

O que é Progressive Delivery? Progressive Delivery é um modelo de implantação que permite liberar alterações de software para produção de forma gradual e controlada, minimizando riscos e permitindo validação em tempo real. Diferente da entrega contínua tradicional (onde você implanta tudo de uma vez), a progressive delivery segmenta o acesso a novas versões, observa comportamento, coleta métricas e decide automaticamente se continua a migração ou faz rollback. A principal vantagem é reduzir o impacto de bugs ou problemas de performance. Se você descobre que a versão nova consome mais memória ou tem latência mais alta, você não perdeu 100% dos seus usuários. Você pode parar a migração, investigar, corrigir e tentar novamente. Isso é especialmente crítico em sistemas de missão crítica onde indisponibilidade ou degradação custa dinheiro em tempo real. Argo Rollouts: Orquestração de Progressive Delivery no Kubernetes O que é Argo Rollouts? Argo Rollouts é uma extensão do Kubernetes mantida pela CNCF que traz estratégias sofisticadas de implantação

<h2>O que é Progressive Delivery?</h2>

<p>Progressive Delivery é um modelo de implantação que permite liberar alterações de software para produção de forma gradual e controlada, minimizando riscos e permitindo validação em tempo real. Diferente da entrega contínua tradicional (onde você implanta tudo de uma vez), a progressive delivery segmenta o acesso a novas versões, observa comportamento, coleta métricas e decide automaticamente se continua a migração ou faz rollback.</p>

<p>A principal vantagem é reduzir o impacto de bugs ou problemas de performance. Se você descobre que a versão nova consome mais memória ou tem latência mais alta, você não perdeu 100% dos seus usuários. Você pode parar a migração, investigar, corrigir e tentar novamente. Isso é especialmente crítico em sistemas de missão crítica onde indisponibilidade ou degradação custa dinheiro em tempo real.</p>

<h2>Argo Rollouts: Orquestração de Progressive Delivery no Kubernetes</h2>

<h3>O que é Argo Rollouts?</h3>

<p>Argo Rollouts é uma extensão do Kubernetes mantida pela CNCF que traz estratégias sofisticadas de implantação além do Deployment padrão. Enquanto o Deployment do Kubernetes oferece apenas Rolling Updates ou Recreate, Argo Rollouts implementa nativamente Canary, Blue-Green, e A/B Testing com suporte automático a análise de métricas.</p>

<p>Argo Rollouts funciona através de um recurso customizado chamado <code>Rollout</code>. Você define seu aplicativo como um Rollout em vez de um Deployment, e o controller do Argo Rollouts gerencia a transição entre versões conforme regras de tráfego e critérios de análise que você especifica. Isso é poderoso porque toda a lógica de decisão (continuar ou reverter) é declarativa, versionável e repetível.</p>

<h3>Instalando Argo Rollouts</h3>

<p>Antes de criar seu primeiro Rollout, você precisa instalar o controller no cluster. Argo Rollouts roda como um deployment no namespace <code>argo-rollouts</code>:</p>

<pre><code class="language-bash">kubectl create namespace argo-rollouts

kubectl apply -n argo-rollouts -f https://github.com/argoproj/argo-rollouts/releases/latest/download/install.yaml</code></pre>

<p>Após a instalação, verifique se o controller está rodando:</p>

<pre><code class="language-bash">kubectl get pods -n argo-rollouts</code></pre>

<p>Você deve ver um pod com nome <code>argo-rollouts-*</code> em estado <code>Running</code>. Se estiver em <code>CrashLoopBackOff</code>, verifique os logs com <code>kubectl logs -n argo-rollouts &lt;pod-name&gt;</code>.</p>

<h2>Estratégia Canary: Implantação Gradual com Validação Automática</h2>

<h3>Conceito e Fluxo</h3>

<p>Canary é uma estratégia onde você envia a nova versão para um pequeno percentual de usuários (por exemplo, 5%) e observa métricas como taxa de erro, latência e uso de recursos. Se tudo estiver bem, você aumenta gradualmente o percentual até que todos os usuários estejam na nova versão. Se algo der errado, você reverte para a versão anterior automaticamente.</p>

<p>O nome &quot;canary&quot; vem da metáfora do canário na mina de carvão: os mineiros levavam canários porque eles morriam quando havia gás tóxico, servindo como alarme. Aqui, o canário é seu pequeno grupo de usuários que &quot;avisa&quot; se a nova versão tem problemas.</p>

<h3>Exemplo Prático: Canary com Análise Automática</h3>

<p>Vamos criar um Rollout que faz implantação canary automática. Suponha que você tem uma API simples em Go:</p>

<pre><code class="language-go">package main

import (

&quot;fmt&quot;

&quot;net/http&quot;

&quot;os&quot;

)

func handler(w http.ResponseWriter, r *http.Request) {

version := os.Getenv(&quot;APP_VERSION&quot;)

if version == &quot;&quot; {

version = &quot;v1&quot;

}

fmt.Fprintf(w, &quot;Hello from %s\n&quot;, version)

}

func main() {

http.HandleFunc(&quot;/&quot;, handler)

http.ListenAndServe(&quot;:8080&quot;, nil)

}</code></pre>

<p>Você conteirizará isso em uma imagem Docker chamada <code>meu-app:v1</code> e depois <code>meu-app:v2</code> com <code>APP_VERSION=v2</code>.</p>

<p>Agora crie um Rollout que faz canary automático:</p>

<pre><code class="language-yaml">apiVersion: argoproj.io/v1alpha1

kind: Rollout

metadata:

name: meu-app

spec:

replicas: 4

selector:

matchLabels:

app: meu-app

template:

metadata:

labels:

app: meu-app

spec:

containers:

  • name: meu-app

image: meu-app:v1

ports:

  • containerPort: 8080

env:

  • name: APP_VERSION

value: &quot;v1&quot;

strategy:

canary:

steps:

  • setWeight: 20
  • pause: {duration: 5m}
  • setWeight: 50
  • pause: {duration: 5m}
  • setWeight: 100

revisionHistoryLimit: 2</code></pre>

<p>Neste exemplo, o Rollout começa com 20% do tráfego na nova versão, aguarda 5 minutos (tempo para coletar métricas), aumenta para 50%, aguarda novamente, e finalmente coloca 100%. Se nenhuma análise falhar nesse tempo, a versão nova é promovida.</p>

<p>Para atualizar para a versão v2, você muda a imagem:</p>

<pre><code class="language-bash">kubectl patch rollout meu-app --type=&#039;json&#039; \

-p=&#039;[{&quot;op&quot;: &quot;replace&quot;, &quot;path&quot;: &quot;/spec/template/spec/containers/0/image&quot;, &quot;value&quot;:&quot;meu-app:v2&quot;}]&#039;</code></pre>

<p>Ou edite o YAML diretamente com <code>kubectl edit rollout meu-app</code>.</p>

<h3>Integração com Análise (Prometheus)</h3>

<p>Para que o Rollout realmente interrompa a migração em caso de problemas, você precisa definir regras de análise. Isso requer um recurso chamado <code>AnalysisTemplate</code>. Vamos supor que você tem Prometheus rodando no cluster:</p>

<pre><code class="language-yaml">apiVersion: argoproj.io/v1alpha1

kind: AnalysisTemplate

metadata:

name: meu-app-analysis

spec:

metrics:

  • name: error-rate

interval: 60s

successCriteria: &quot;{{ result &lt;= 0.05 }}&quot;

provider:

prometheus:

address: http://prometheus:9090

query: |

sum(rate(http_requests_total{job=&quot;meu-app&quot;,status=~&quot;5..&quot;}[5m])) /

sum(rate(http_requests_total{job=&quot;meu-app&quot;}[5m]))

  • name: response-latency

interval: 60s

successCriteria: &quot;{{ result &lt; 500 }}&quot;

provider:

prometheus:

address: http://prometheus:9090

query: |

histogram_quantile(0.95, sum(rate(http_request_duration_seconds_bucket{job=&quot;meu-app&quot;}[5m])) by (le))</code></pre>

<p>Agora modifique seu Rollout para usar essa análise:</p>

<pre><code class="language-yaml">apiVersion: argoproj.io/v1alpha1

kind: Rollout

metadata:

name: meu-app

spec:

replicas: 4

selector:

matchLabels:

app: meu-app

template:

metadata:

labels:

app: meu-app

spec:

containers:

  • name: meu-app

image: meu-app:v1

ports:

  • containerPort: 8080

strategy:

canary:

steps:

  • setWeight: 20
  • pause: {duration: 5m}
  • analysis:

templates:

  • name: meu-app-analysis
  • setWeight: 50
  • pause: {duration: 5m}
  • setWeight: 100</code></pre>

<p>Agora, após 5 minutos na versão canary (20%), o Argo Rollouts executa a análise. Se a taxa de erro estiver acima de 5% ou a latência acima de 500ms, a análise falha e a migração é revertida automaticamente.</p>

<h2>Estratégia Blue-Green: Troca Instantânea com Validação Offline</h2>

<h3>Conceito e Fluxo</h3>

<p>Blue-Green é radicalmente diferente de Canary. Em vez de gradualmente migrar tráfego, você mantém dois ambientes completos: Blue (atual) e Green (nova versão). O Green é preparado completamente em paralelo, testado offline, e depois você faz uma mudança instantânea de tráfego de Blue para Green. Se algo der errado, você volta para Blue imediatamente.</p>

<p>Blue-Green é mais apropriado para aplicações onde você quer validação completa antes de qualquer usuário ver a nova versão, ou quando suas métricas levam tempo para estabilizar (você não quer esperar 30 minutos em Canary). A desvantagem é que você precisa do dobro de recursos durante a transição.</p>

<h3>Exemplo Prático: Blue-Green com Validação Manual</h3>

<pre><code class="language-yaml">apiVersion: argoproj.io/v1alpha1

kind: Rollout

metadata:

name: meu-app-bg

spec:

replicas: 3

selector:

matchLabels:

app: meu-app-bg

template:

metadata:

labels:

app: meu-app-bg

spec:

containers:

  • name: meu-app

image: meu-app:v1

ports:

  • containerPort: 8080

strategy:

blueGreen:

activeSlotSelector: blue

prePromotionAnalysis:

templates:

  • name: meu-app-analysis

autoPromotionEnabled: false

autoPromotionSeconds: 0</code></pre>

<p>Neste Rollout Blue-Green:</p>

<ul>

<li><code>activeSlotSelector: blue</code> significa que atualmente o slot &quot;blue&quot; (v1) está recebendo tráfego.</li>

<li>Quando você atualiza a imagem para <code>meu-app:v2</code>, o Argo cria pods novos no slot &quot;green&quot; sem mudar tráfego.</li>

<li><code>prePromotionAnalysis</code> roda testes antes de promover green para ativo. Você pode fazer chamadas HTTP, verificar logs, etc.</li>

<li><code>autoPromotionEnabled: false</code> significa que você decide manualmente quando fazer a troca. Para promover, você executa:</li>

</ul>

<pre><code class="language-bash">kubectl argo rollouts promote meu-app-bg</code></pre>

<p>Para reverter se algo der errado:</p>

<pre><code class="language-bash">kubectl argo rollouts abort meu-app-bg</code></pre>

<h3>Blue-Green Totalmente Automatizado</h3>

<p>Se você quer automação total, ative <code>autoPromotionEnabled</code>:</p>

<pre><code class="language-yaml">apiVersion: argoproj.io/v1alpha1

kind: Rollout

metadata:

name: meu-app-bg-auto

spec:

replicas: 3

selector:

matchLabels:

app: meu-app-bg-auto

template:

metadata:

labels:

app: meu-app-bg-auto

spec:

containers:

  • name: meu-app

image: meu-app:v1

ports:

  • containerPort: 8080

strategy:

blueGreen:

activeSlotSelector: blue

prePromotionAnalysis:

templates:

  • name: meu-app-analysis

autoPromotionEnabled: true

autoPromotionSeconds: 300</code></pre>

<p>Com isso:</p>

<ol>

<li>Você atualiza a imagem.</li>

<li>Green é criado e testado com a análise.</li>

<li>Se a análise passar, após 300 segundos (5 minutos) o tráfego é automaticamente movido para green.</li>

<li>Blue permanece rodando e pode ser rapidamente reativado se necessário.</li>

</ol>

<h2>Monitoramento e Troubleshooting de Rollouts</h2>

<h3>Inspecionando o Status do Rollout</h3>

<p>Para ver o progresso de um Rollout em tempo real:</p>

<pre><code class="language-bash">kubectl get rollouts -w</code></pre>

<p>Para detalhes completos sobre o status atual:</p>

<pre><code class="language-bash">kubectl describe rollout meu-app</code></pre>

<p>Para ver o histórico de análises executadas:</p>

<pre><code class="language-bash">kubectl get analysisruns

kubectl describe analysisrun &lt;nome-do-run&gt;</code></pre>

<h3>Logs e Debugging</h3>

<p>Se uma análise falhar ou um step pausar indefinidamente, verifique os logs do controller:</p>

<pre><code class="language-bash">kubectl logs -n argo-rollouts -l app=argo-rollouts -f</code></pre>

<p>Verifique também se o recurso de Rollout está bem formado:</p>

<pre><code class="language-bash">kubectl get rollout meu-app -o yaml</code></pre>

<p>Se você tem múltiplas versões de um aplicativo e quer comparar:</p>

<pre><code class="language-bash">kubectl get rs -l app=meu-app</code></pre>

<p>Isso mostra os ReplicaSets (versões antigas e novas) que o Rollout criou.</p>

<h3>Revogando um Rollout em Andamento</h3>

<p>Se você detectar um problema durante a migração canary:</p>

<pre><code class="language-bash">kubectl argo rollouts abort meu-app</code></pre>

<p>Isso para imediatamente o rollout e mantém a versão anterior. Para saber qual versão está ativa:</p>

<pre><code class="language-bash">kubectl argo rollouts status meu-app</code></pre>

<h2>Conclusão</h2>

<p>Você aprendeu que <strong>Progressive Delivery com Argo Rollouts elimina a falsa dicotomia entre velocidade e segurança</strong>: você pode liberar múltiplas vezes ao dia para produção sem arriscar seus usuários. Canary funciona melhor quando suas métricas estabilizam rápido e você quer medir impacto em tempo real; Blue-Green é superior quando você precisa de validação offline completa ou quando quer uma janela de rollback instantâneo. Ambas as estratégias, quando acopladas a análises automáticas com Prometheus, transformam o deployment de um processo nervoso em uma atividade rotineira e confiável, com capacidade de decisão totalmente codificada e observável.</p>

<h2>Referências</h2>

<ul>

<li><a href="https://argoproj.github.io/argo-rollouts/" target="_blank" rel="noopener noreferrer">Documentação Oficial do Argo Rollouts</a></li>

<li><a href="https://github.com/argoproj/argo-rollouts/tree/master/examples" target="_blank" rel="noopener noreferrer">Argo Rollouts Examples no GitHub</a></li>

<li><a href="https://www.cncf.io/blog/" target="_blank" rel="noopener noreferrer">Progressive Delivery with Flagger and Argo Rollouts - CNCF Blog</a></li>

<li><a href="https://cloud.google.com/kubernetes-engine/docs/concepts/deployment-patterns" target="_blank" rel="noopener noreferrer">Kubernetes Best Practices: Progressive Rollouts - Google Cloud</a></li>

<li><a href="https://www.deployhub.com/continuous-delivery-handbook" target="_blank" rel="noopener noreferrer">The Continuous Delivery Handbook - DeployHub</a></li>

</ul>

<p>&lt;!-- FIM --&gt;</p>

Comentários

Mais em Docker & Kubernetes

OPA Gatekeeper em Kubernetes: Políticas como Código no Cluster: Do Básico ao Avançado
OPA Gatekeeper em Kubernetes: Políticas como Código no Cluster: Do Básico ao Avançado

O que é OPA Gatekeeper? OPA (Open Policy Agent) Gatekeeper é um validador de...

O que Todo Dev Deve Saber sobre Dockerfile em Profundidade: Cada Instrução e seu Impacto no Build
O que Todo Dev Deve Saber sobre Dockerfile em Profundidade: Cada Instrução e seu Impacto no Build

Introdução: Por que entender Dockerfile é fundamental Um Dockerfile é um scri...

O que Todo Dev Deve Saber sobre Kustomize em Kubernetes: Overlays, Patches e Bases Reutilizáveis
O que Todo Dev Deve Saber sobre Kustomize em Kubernetes: Overlays, Patches e Bases Reutilizáveis

Introdução ao Kustomize: Por que Precisamos Dele Kubernetes é poderoso, mas g...