Lab 6: Failback

Lab 6: Failback – Volver al Sitio Primario

El failback siempre es manual y deliberado: primero verificás que el primario esté sano, después cambiás los Routing Controls.


Paso 1: Cargar variables

source ~/route53-arc-tf/global.env

cd ~/route53-arc-tf/03_arc
export PRIMARY_RC_ARN=$(terraform output -raw primary_rc_arn)
export SECONDARY_RC_ARN=$(terraform output -raw secondary_rc_arn)
export CLUSTER_ENDPOINT=$(terraform output -json arc_cluster_endpoints \
  | python3 -c "import json,sys; print(json.load(sys.stdin)[0]['Endpoint'])")

cd ~/route53-arc-tf/01_primary
export EC2_ID=$(terraform output -raw ec2_instance_id)
export PRIMARY_ALB_DNS=$(terraform output -raw alb_dns_name)

cd ~/route53-arc-tf/04_automation
export ALARM_NAME=$(terraform output -raw alarm_name)

echo "ALB DNS: $PRIMARY_ALB_DNS"

Paso 2: Reparar el sitio primario (si usaste Simulación B)

COMMAND_ID=$(aws ssm send-command \
  --instance-ids $EC2_ID \
  --document-name AWS-RunShellScript \
  --parameters 'commands=["systemctl start nginx && systemctl status nginx --no-pager | head -3"]' \
  --region $AWS_REGION \
  --query 'Command.CommandId' --output text)

sleep 10
aws ssm get-command-invocation \
  --command-id $COMMAND_ID --instance-id $EC2_ID \
  --region $AWS_REGION \
  --query '{Status: Status, Output: StandardOutputContent}' --output json

Paso 3: Verificar que el primario está sano

Aviso

No hagas el failback hasta confirmar que el ALB responde HTTP 200. Si volvés el tráfico antes, los usuarios seguirán viendo errores.

echo "Esperando que el primario se recupere..."

for i in $(seq 1 10); do
  TG_ARN=$(aws elbv2 describe-target-groups \
    --names route53-arc-primary-tg --region $AWS_REGION \
    --query 'TargetGroups[0].TargetGroupArn' --output text 2>/dev/null)

  TG_HEALTH=$(aws elbv2 describe-target-health \
    --target-group-arn $TG_ARN --region $AWS_REGION \
    --query 'TargetHealthDescriptions[0].TargetHealth.State' --output text 2>/dev/null)

  HTTP=$(curl -s -o /dev/null -w "%{http_code}" \
    --connect-timeout 3 --max-time 5 http://$PRIMARY_ALB_DNS/ 2>/dev/null)

  echo "[$(date '+%H:%M:%S')] Target Group: $TG_HEALTH | HTTP: $HTTP"

  if [ "$TG_HEALTH" = "healthy" ] && [ "$HTTP" = "200" ]; then
    echo "✅ Sitio primario recuperado y funcionando"
    break
  fi
  sleep 15
done

Paso 4: Ejecutar Failback

echo "=== EJECUTANDO FAILBACK ==="

aws route53-recovery-cluster update-routing-control-states \
  --update-routing-control-state-entries \
    "[{\"RoutingControlArn\":\"$PRIMARY_RC_ARN\",\"RoutingControlState\":\"On\"},
      {\"RoutingControlArn\":\"$SECONDARY_RC_ARN\",\"RoutingControlState\":\"Off\"}]" \
  --endpoint-url $CLUSTER_ENDPOINT --region $AWS_REGION

echo "✅ Failback ejecutado: Primario=ON | Secundario=OFF"

# Restablecer alarma
aws cloudwatch set-alarm-state \
  --alarm-name $ALARM_NAME \
  --state-value OK \
  --state-reason "Sitio primario recuperado – failback completado" \
  --region $AWS_REGION

echo "✅ Alarma restablecida a OK"

✅ Verificación del Lab 6

echo "=== Verificación Lab 6: Failback ==="

P=$(aws route53-recovery-cluster get-routing-control-state \
  --routing-control-arn $PRIMARY_RC_ARN \
  --endpoint-url $CLUSTER_ENDPOINT --region $AWS_REGION \
  --query 'RoutingControlState' --output text 2>/dev/null)

S=$(aws route53-recovery-cluster get-routing-control-state \
  --routing-control-arn $SECONDARY_RC_ARN \
  --endpoint-url $CLUSTER_ENDPOINT --region $AWS_REGION \
  --query 'RoutingControlState' --output text 2>/dev/null)

[ "$P" = "On"  ] && echo "✅ Primario: $P" || echo "❌ Primario: $P"
[ "$S" = "Off" ] && echo "✅ Secundario: $S" || echo "❌ Secundario: $S"

HTTP=$(curl -s -o /dev/null -w "%{http_code}" http://$PRIMARY_ALB_DNS/ 2>/dev/null)
[ "$HTTP" = "200" ] && echo "✅ Sitio primario: HTTP $HTTP" || echo "⚠️  HTTP $HTTP"

echo ""
echo "🎉 Ciclo completo: Detección → Notificación → Failover → Reparación → Failback"

Siguiente paso → Lab 7: Destroy