Despliegues Canary con Istio Service Mesh
Como usar el splitting de trafico de Istio para realizar despliegues canary seguros desplazando gradualmente usuarios entre versiones de aplicaciones
Istio proporciona gestion de trafico granular a traves de virtual services y destination rules. Al dividir trafico entre versiones estable y canary de un servicio, puedes validar nuevos releases con trafico real de usuarios manteniendo la capacidad de rollback instantaneo si los errores aumentan.
Cuando Usar Esto
- Despliegas a Kubernetes y necesitas desplazamiento progresivo de trafico. Consulta Blue-Green Deployment para releases sin downtime.
- Los nuevos releases requieren validacion en el mundo real antes del rollout completo. Consulta Feature Flags para rollouts graduales.
- Quieres minimizar el radio de impacto de fallos de despliegue. Consulta Health Check Endpoint para detección temprana de fallos.
Requisitos Previos
- Cluster de Kubernetes con Istio instalado
- Dos versiones de una aplicacion desplegadas con labels diferentes
Solucion
1. Desplegar Ambas Versiones
# deployment-v1.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: api-v1
spec:
replicas: 3
selector:
matchLabels:
app: api
version: v1
template:
metadata:
labels:
app: api
version: v1
spec:
containers:
- name: api
image: myapp:1.0.0
ports:
- containerPort: 8080
# deployment-v2.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: api-v2
spec:
replicas: 1
selector:
matchLabels:
app: api
version: v2
template:
metadata:
labels:
app: api
version: v2
spec:
containers:
- name: api
image: myapp:1.1.0
ports:
- containerPort: 8080
2. Crear Destination Rule para Subsets
# destination-rule.yaml
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
name: api
spec:
host: api
trafficPolicy:
connectionPool:
tcp:
maxConnections: 100
http:
http1MaxPendingRequests: 50
outlierDetection:
consecutive5xxErrors: 5
interval: 30s
baseEjectionTime: 30s
subsets:
- name: v1
labels:
version: v1
- name: v2
labels:
version: v2
3. Configurar Division de Trafico
# virtual-service-canary.yaml
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: api
spec:
hosts:
- api
http:
- route:
- destination:
host: api
subset: v1
weight: 90
- destination:
host: api
subset: v2
weight: 10
4. Script de Rollout Progresivo
#!/bin/bash
# canary-rollout.sh
set -e
function set_weight() {
local v1_weight=$1
local v2_weight=$((100 - v1_weight))
cat <<EOF | kubectl apply -f -
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: api
spec:
hosts:
- api
http:
- route:
- destination:
host: api
subset: v1
weight: ${v1_weight}
- destination:
host: api
subset: v2
weight: ${v2_weight}
EOF
}
# Fase 1: 10% de trafico a v2
set_weight 90
echo "v2 desplegado al 10%. Monitoreando por 5 minutos..."
sleep 300
# Fase 2: 50% de trafico a v2
set_weight 50
echo "v2 desplegado al 50%. Monitoreando por 5 minutos..."
sleep 300
# Fase 3: 100% de trafico a v2
set_weight 0
echo "v2 desplegado al 100%. Canary completo."
5. Rollback Automatizado via Prometheus
# canary-analysis.yaml
apiVersion: flagger.app/v1beta1
kind: Canary
metadata:
name: api
spec:
targetRef:
apiVersion: apps/v1
kind: Deployment
name: api
service:
port: 8080
analysis:
interval: 1m
threshold: 5
maxWeight: 50
stepWeight: 10
metrics:
- name: request-success-rate
thresholdRange:
min: 99
interval: 1m
- name: request-duration
thresholdRange:
max: 500
interval: 1m
webhooks:
- name: load-test
url: http://flagger-loadtester.test/
timeout: 5s
metadata:
cmd: "hey -z 1m -q 10 -c 2 http://api:8080/health"
Como Funciona
- DestinationRule define subsets basados en labels de pods
- VirtualService asigna pesos de trafico a cada subset
- Desplazamiento Progresivo mueve trafico en etapas monitoreando tasas de error
- Outlier Detection ejecta automaticamente pods no saludables
- Rollback revierte pesos de trafico si las metricas exceden umbrales
Consideraciones de Produccion
- Usa Flagger para analisis automatizado de canary y promocion
- Monitorea latencia, tasa de error y throughput independientemente durante el rollout
- Manten replicas canary pequenas inicialmente; escala solo despues de validacion
- Combina con feature flags para dark launches de nueva funcionalidad
Errores Comunes
- Enviar trafico canary a endpoints internos de admin que los usuarios nunca usan
- No monitorear metricas de negocio (tasa de checkout, conversion de registro)
- Olvidar escalar hacia abajo la version vieja despues de promocion completa
Tips de Rendimiento
- Usa LEAST_REQUEST load balancing. Previene que el pod canary sea abrumado:
loadBalancer:
simple: LEAST_REQUEST
- Habilita telemetría de Istio selectivamente. Telemetría completa agrega overhead. Deshabilita access logs durante canaries de alto tráfico:
telemetry:
accessLogLogging:
disabled: true
- Pre-calienta pods canary. Envía una pequeña cantidad de tráfico antes de iniciar el rollout para JIT-compilar código y calentar cachés:
# Pre-calentar con 1% de tráfico por 2 minutos
set_weight 99
sleep 120
# Luego iniciar el rollout real Preguntas frecuentes
¿Esta solución está lista para producción?
Sí. Los ejemplos de código arriba muestran implementaciones probadas. Adapta el manejo de errores y la configuración a tu entorno específico antes de desplegar.
Routing Canary Basado en Headers
# Rutear testers internos a v2 independientemente del peso
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: api-header-routing
spec:
hosts:
- api
http:
- match:
- headers:
x-canary-test:
exact: "true"
route:
- destination:
host: api
subset: v2
- route:
- destination:
host: api
subset: v1
weight: 100
Mirroring de Trafico (Shadow Traffic)
# Espejar 100% del trafico a v2 sin afectar respuestas
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: api-mirror
spec:
hosts:
- api
http:
- route:
- destination:
host: api
subset: v1
weight: 100
mirror:
host: api
subset: v2
mirrorPercentage:
value: 100.0
Circuit Breaking con DestinationRule
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
name: api-circuit-breaker
spec:
host: api
trafficPolicy:
connectionPool:
tcp:
maxConnections: 50
http:
http1MaxPendingRequests: 20
maxRequestsPerConnection: 10
outlierDetection:
consecutive5xxErrors: 3
interval: 10s
baseEjectionTime: 30s
maxEjectionPercent: 50
loadBalancer:
simple: LEAST_REQUEST
Limpieza Post-Promoción
#!/bin/bash
# cleanup-old-version.sh
# Después de la promoción completa del canary a v2:
# 1. Remover pesos viejos del VirtualService
kubectl apply -f virtual-service-v2-only.yaml
# 2. Escalar hacia abajo el deployment v1
kubectl scale deployment api-v1 --replicas=0
# 3. Esperar a que los pods terminen
kubectl wait --for=delete pod -l app=api,version=v1 --timeout=60s
# 4. Remover deployment v1
kubectl delete deployment api-v1
# 5. Remover subset v1 del DestinationRule
kubectl apply -f destination-rule-v2-only.yaml
echo "Limpieza completa. Solo v2 está corriendo."
Recursos Relacionados
Desplegar Contenedores en AWS ECS con Fargate
Como desplegar contenedores Docker en AWS ECS usando computacion serverless Fargate con Terraform y GitHub Actions
RecipeProvisiona una VPC de AWS con Terraform
Como usar Terraform para provisionar una VPC de AWS lista para produccion con subredes publicas y privadas, NAT gateways y security groups
GuideInfrastructure as Code — Terraform y Pulumi
Guía práctica para gestionar infraestructura como código: beneficios de enfoques declarativo vs imperativo, manejo de estado, módulos y testing de cambios de infraestructura.
DocPlantilla de Configuracion de Entornos
Una plantilla para documentar variables de entorno, secretos, endpoints y configuraciones de infraestructura para cada entorno de despliegue.
DocChecklist de Despliegue sin Tiempo de Inactividad
Un checklist para garantizar que los despliegues en produccion se completen sin interrumpir el servicio usando patrones de rollout seguros.
RecipeReceta: Despliegue Blue-Green
Despliega con zero downtime usando ambientes blue-green, conmutación instantánea de tráfico y capacidades de rollback automatizado.