TL;DR

  • El drift ocurre cuando la infraestructura real diverge del estado de Terraform — cambios manuales, ediciones en consola o applies fallidos
  • driftctl escanea tu cuenta cloud y compara contra el estado, capturando recursos que Terraform desconoce
  • El error #1: asumir que terraform plan captura todo el drift (solo verifica recursos en el estado)

Ideal para: Equipos con multiples personas accediendo consolas cloud o infraestructura heredada Omite si: Trabajas solo, todos los cambios van por Terraform y nunca tocas la consola Tiempo de lectura: 10 minutos

Tu estado de Terraform dice que tienes 3 instancias EC2. La consola AWS muestra 7. Alguien creo 4 instancias manualmente “para pruebas” hace seis meses. Siguen corriendo, costando $800/mes, y nadie sabe que hacen.

Esto es drift de infraestructura — la divergencia silenciosa entre lo que tu IaC define y lo que realmente existe. En 2026, con equipos deployando mas rapido y la complejidad cloud creciendo, la deteccion de drift no es opcional. Es como mantienes el control.

El Problema Real

El drift ocurre por multiples vectores:

Cambios en consola: Alguien corrige una regla de security group directamente en la consola AWS. Terraform no lo sabe.

Applies fallidos: terraform apply completa parcialmente antes de error. El estado y la realidad divergen.

Recursos no gestionados: Recursos creados fuera de Terraform — por otros equipos, por automatizacion, por ti durante debugging.

Bugs del provider: La API del proveedor cloud retorna estado diferente a lo que se aplico. Raro pero pasa.

La parte peligrosa: el drift es invisible hasta que algo se rompe. Ese security group editado manualmente? Funciona bien hasta que Terraform lo sobreescribe en el siguiente apply, matando trafico de produccion.

Terraform Plan No Es Suficiente

terraform plan solo detecta drift para recursos ya en el estado. Si alguien crea una instancia EC2 manualmente, Terraform no tiene idea de que existe.

# Esto solo muestra drift para recursos conocidos
terraform plan

# El output podria mostrar:
# No changes. Your infrastructure matches the configuration.

# Pero la realidad: 4 instancias desconocidas corriendo en tu VPC

Para capturar drift comprensivo, necesitas herramientas que escaneen tu cuenta cloud independientemente del estado de Terraform.

driftctl: La Herramienta Dedicada

driftctl (ahora parte de Snyk) escanea tu proveedor cloud y compara contra el estado de Terraform. Encuentra:

  • Recursos en estado pero cambiados en realidad (modificados)
  • Recursos en cloud pero no en estado (no gestionados)
  • Recursos en estado pero eliminados del cloud (faltantes)
# Instalar
brew install driftctl

# Scan basico (usa credenciales AWS del ambiente)
driftctl scan

# Scan de archivo de estado especifico
driftctl scan --from tfstate://terraform.tfstate

# Scan de workspace de Terraform Cloud
driftctl scan --from tfstate+tfcloud://WORKSPACE_ID

# Output como JSON para integracion CI
driftctl scan --output json://drift-report.json

Output de ejemplo:

Found resources not covered by IaC:
  aws_instance:

    - i-0abc123def456789
    - i-0def456789abc123
  aws_security_group:

    - sg-0123456789abcdef0

Found drifted resources:
  aws_s3_bucket.data (id: my-data-bucket)
    ~ versioning.0.enabled: false => true

Found deleted resources:
  aws_iam_role.legacy (id: legacy-role)

Coverage: 87% (142/163 resources)

La metrica de coverage es clave — muestra que porcentaje de tus recursos cloud estan gestionados por Terraform.

Integracion CI/CD

Ejecuta deteccion de drift en schedule, no solo en PR:

name: Drift Detection

on:
  schedule:

    - cron: '0 8 * * *'  # Diario a las 8 AM UTC
  workflow_dispatch:  # Trigger manual

jobs:
  drift-scan:
    runs-on: ubuntu-latest
    steps:

      - uses: actions/checkout@v4

      - name: Configure AWS credentials
        uses: aws-actions/configure-aws-credentials@v4
        with:
          aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
          aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
          aws-region: us-east-1

      - name: Install driftctl
        run: |
          curl -L https://github.com/snyk/driftctl/releases/latest/download/driftctl_linux_amd64 -o driftctl
          chmod +x driftctl
          sudo mv driftctl /usr/local/bin/

      - name: Run drift scan
        id: drift
        run: |
          driftctl scan --from tfstate://terraform.tfstate --output json://drift.json
          echo "coverage=$(jq -r '.coverage' drift.json)" >> $GITHUB_OUTPUT

      - name: Check coverage threshold
        run: |
          coverage=${{ steps.drift.outputs.coverage }}
          if (( $(echo "$coverage < 80" | bc -l) )); then
            echo "Coverage $coverage% below 80% threshold"
            exit 1
          fi

      - name: Alert on drift
        if: failure()
        uses: slackapi/slack-github-action@v1
        with:
          payload: |
            {
              "text": "Infrastructure drift detected! Coverage: ${{ steps.drift.outputs.coverage }}%"
            }
        env:
          SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}

Manejando Recursos No Gestionados

Cuando driftctl encuentra recursos no gestionados, tienes opciones:

Importar a Terraform:

# Generar bloques import
driftctl scan --output json://drift.json
cat drift.json | jq -r '.unmanaged[] | "terraform import \(.type).\(.id) \(.id)"'

# Bloques import nativos de Terraform 1.5+
import {
  to = aws_instance.imported
  id = "i-0abc123def456789"
}

Excluir del scanning (para recursos intencionalmente no gestionados):

# .driftignore
aws_iam_policy_attachment  # Attachments gestionados por AWS
aws_cloudwatch_log_group:/aws/lambda/*  # Auto-creados por Lambda
aws_security_group_rule:*  # Gestionados por otro equipo

Eliminar recursos creados manualmente:

# Despues de confirmar que el recurso es seguro de eliminar
aws ec2 terminate-instances --instance-ids i-0abc123def456789

Avanzado: terraform plan -refresh-only

Para recursos ya en estado, Terraform 1.x provee deteccion de drift dedicada:

# Verificar drift sin planear cambios
terraform plan -refresh-only

# Aplicar solo el refresh de estado (actualizar estado para coincidir con realidad)
terraform apply -refresh-only

# Luego plan para ver que cambios restaurarian el estado deseado
terraform plan

Este workflow separa “que cambio en realidad” de “que cambios haria Terraform.”

Deteccion Profunda con AWS Config

Para drift especifico de AWS, AWS Config provee monitoreo continuo:

resource "aws_config_configuration_recorder" "main" {
  name     = "config-recorder"
  role_arn = aws_iam_role.config.arn

  recording_group {
    all_supported = true
  }
}

resource "aws_config_config_rule" "required_tags" {
  name = "required-tags"

  source {
    owner             = "AWS"
    source_identifier = "REQUIRED_TAGS"
  }

  input_parameters = jsonencode({
    tag1Key = "Environment"
    tag2Key = "ManagedBy"
  })
}

AWS Config detecta drift de reglas de compliance continuamente, no solo durante scans.

Enfoques Asistidos por IA

La remediacion de drift frecuentemente requiere juicios. Las herramientas de IA ayudan.

Lo que la IA hace bien:

  • Analizar reportes de drift para priorizar recursos de alto riesgo
  • Generar bloques import de Terraform desde datos de recursos cloud
  • Sugerir si importar, ignorar o eliminar recursos no gestionados
  • Explicar por que un recurso podria haber driftado

Lo que aun necesita humanos:

  • Decidir si el drift fue intencional (fix de emergencia vs error)
  • Elegir entre importar vs recrear recursos driftados
  • Entender impacto de negocio de opciones de remediacion
  • Aprobar acciones destructivas (eliminaciones, reemplazos)

Prompt util:

driftctl encontro estos recursos AWS no gestionados:

- 3 instancias EC2 (i-xxx) en us-east-1, t3.medium, sin tags
- 2 buckets S3 con "backup" en el nombre
- 1 instancia RDS llamada "temp-db"

Ayudame a:

1. Evaluar nivel de riesgo de cada uno
2. Recomendar: importar a Terraform, eliminar o ignorar
3. Generar bloques import para recursos a mantener

Cuando Esto Falla

La deteccion de drift tiene limitaciones:

Cobertura de tipos de recurso: driftctl no soporta cada recurso AWS/Azure/GCP. Servicios nuevos tardan.

Acceso a archivo de estado: Backends de estado remoto (S3, Terraform Cloud) requieren autenticacion apropiada. Setups multi-workspace se complican.

Performance a escala: Escanear cuentas con 10,000+ recursos toma tiempo. Considera filtrar por tipo de recurso.

Falsos positivos: Algunos recursos naturalmente driftan (counts de auto-scaling, IPs dinamicas). Acumularas ignores.

Considera enfoques complementarios:

  • Policy as Code para prevenir cambios no autorizados
  • Herramientas nativas del proveedor cloud (AWS Config, Azure Policy) para compliance continuo
  • Workflows GitOps que hacen cambios manuales imposibles

Framework de Decision

Ejecuta deteccion de drift diariamente cuando:

  • Multiples equipos acceden consolas cloud
  • Heredaste infraestructura de otro equipo
  • Compliance requiere prueba de gestion de configuracion
  • Has tenido incidentes relacionados con drift

Ejecuta deteccion de drift semanalmente cuando:

  • Equipo pequeno con fuerte disciplina Terraform
  • La mayoria de cambios van por CI/CD
  • Baja tasa de intervenciones manuales

Omite deteccion de drift cuando:

  • Desarrollador solo con disciplina total de consola
  • Ambientes efimeros (recreados frecuentemente)
  • Recursos explicitamente gestionados fuera de Terraform

Midiendo el Exito

MetricaAntesDespuesComo Rastrear
Recursos no gestionadosDesconocido<10%Cobertura driftctl
Incidentes de drift por trimestreDesconocido0Reportes de incidentes
Tiempo para detectar driftDias/semanas<24 horasTimestamps de scan
Recursos importados a IaCN/A+50/trimestreHistorial git

Senales de alarma de que no funciona:

  • Archivo .driftignore creciente
  • Equipos deshabilitando alertas de drift
  • Porcentaje de coverage cayendo
  • Cambios manuales continuando a pesar de deteccion

Que Sigue

Empieza con visibilidad, luego mejora coverage:

  1. Ejecuta driftctl scan una vez manualmente para establecer baseline
  2. Documenta todos los recursos no gestionados (decide: importar, eliminar, ignorar)
  3. Configura scans diarios programados
  4. Alerta sobre nuevos recursos no gestionados
  5. Rastrea porcentaje de coverage en el tiempo (objetivo: 90%+)
  6. Agrega driftctl a checks de PR para workflows que cambian estado

El objetivo es hacer el drift visible inmediatamente, no durante investigacion de incidentes.


Articulos relacionados:

Recursos externos:

Recursos Oficiales

See Also