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 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.
Argo Rollouts funciona através de um recurso customizado chamado Rollout. 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.
Instalando Argo Rollouts
Antes de criar seu primeiro Rollout, você precisa instalar o controller no cluster. Argo Rollouts roda como um deployment no namespace argo-rollouts:
kubectl create namespace argo-rollouts
kubectl apply -n argo-rollouts -f https://github.com/argoproj/argo-rollouts/releases/latest/download/install.yaml
Após a instalação, verifique se o controller está rodando:
kubectl get pods -n argo-rollouts
Você deve ver um pod com nome argo-rollouts-* em estado Running. Se estiver em CrashLoopBackOff, verifique os logs com kubectl logs -n argo-rollouts <pod-name>.
Estratégia Canary: Implantação Gradual com Validação Automática
Conceito e Fluxo
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.
O nome "canary" 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 "avisa" se a nova versão tem problemas.
Exemplo Prático: Canary com Análise Automática
Vamos criar um Rollout que faz implantação canary automática. Suponha que você tem uma API simples em Go:
package main
import (
"fmt"
"net/http"
"os"
)
func handler(w http.ResponseWriter, r *http.Request) {
version := os.Getenv("APP_VERSION")
if version == "" {
version = "v1"
}
fmt.Fprintf(w, "Hello from %s\n", version)
}
func main() {
http.HandleFunc("/", handler)
http.ListenAndServe(":8080", nil)
}
Você conteirizará isso em uma imagem Docker chamada meu-app:v1 e depois meu-app:v2 com APP_VERSION=v2.
Agora crie um Rollout que faz canary automático:
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: "v1"
strategy:
canary:
steps:
- setWeight: 20
- pause: {duration: 5m}
- setWeight: 50
- pause: {duration: 5m}
- setWeight: 100
revisionHistoryLimit: 2
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.
Para atualizar para a versão v2, você muda a imagem:
kubectl patch rollout meu-app --type='json' \
-p='[{"op": "replace", "path": "/spec/template/spec/containers/0/image", "value":"meu-app:v2"}]'
Ou edite o YAML diretamente com kubectl edit rollout meu-app.
Integração com Análise (Prometheus)
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 AnalysisTemplate. Vamos supor que você tem Prometheus rodando no cluster:
apiVersion: argoproj.io/v1alpha1
kind: AnalysisTemplate
metadata:
name: meu-app-analysis
spec:
metrics:
- name: error-rate
interval: 60s
successCriteria: "{{ result <= 0.05 }}"
provider:
prometheus:
address: http://prometheus:9090
query: |
sum(rate(http_requests_total{job="meu-app",status=~"5.."}[5m])) /
sum(rate(http_requests_total{job="meu-app"}[5m]))
- name: response-latency
interval: 60s
successCriteria: "{{ result < 500 }}"
provider:
prometheus:
address: http://prometheus:9090
query: |
histogram_quantile(0.95, sum(rate(http_request_duration_seconds_bucket{job="meu-app"}[5m])) by (le))
Agora modifique seu Rollout para usar essa análise:
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
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.
Estratégia Blue-Green: Troca Instantânea com Validação Offline
Conceito e Fluxo
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.
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.
Exemplo Prático: Blue-Green com Validação Manual
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
Neste Rollout Blue-Green:
activeSlotSelector: bluesignifica que atualmente o slot "blue" (v1) está recebendo tráfego.- Quando você atualiza a imagem para
meu-app:v2, o Argo cria pods novos no slot "green" sem mudar tráfego. prePromotionAnalysisroda testes antes de promover green para ativo. Você pode fazer chamadas HTTP, verificar logs, etc.autoPromotionEnabled: falsesignifica que você decide manualmente quando fazer a troca. Para promover, você executa:
kubectl argo rollouts promote meu-app-bg
Para reverter se algo der errado:
kubectl argo rollouts abort meu-app-bg
Blue-Green Totalmente Automatizado
Se você quer automação total, ative autoPromotionEnabled:
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
Com isso:
- Você atualiza a imagem.
- Green é criado e testado com a análise.
- Se a análise passar, após 300 segundos (5 minutos) o tráfego é automaticamente movido para green.
- Blue permanece rodando e pode ser rapidamente reativado se necessário.
Monitoramento e Troubleshooting de Rollouts
Inspecionando o Status do Rollout
Para ver o progresso de um Rollout em tempo real:
kubectl get rollouts -w
Para detalhes completos sobre o status atual:
kubectl describe rollout meu-app
Para ver o histórico de análises executadas:
kubectl get analysisruns
kubectl describe analysisrun <nome-do-run>
Logs e Debugging
Se uma análise falhar ou um step pausar indefinidamente, verifique os logs do controller:
kubectl logs -n argo-rollouts -l app=argo-rollouts -f
Verifique também se o recurso de Rollout está bem formado:
kubectl get rollout meu-app -o yaml
Se você tem múltiplas versões de um aplicativo e quer comparar:
kubectl get rs -l app=meu-app
Isso mostra os ReplicaSets (versões antigas e novas) que o Rollout criou.
Revogando um Rollout em Andamento
Se você detectar um problema durante a migração canary:
kubectl argo rollouts abort meu-app
Isso para imediatamente o rollout e mantém a versão anterior. Para saber qual versão está ativa:
kubectl argo rollouts status meu-app
Conclusão
Você aprendeu que Progressive Delivery com Argo Rollouts elimina a falsa dicotomia entre velocidade e segurança: 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.