TL;DR

  • Drift происходит когда реальная инфраструктура расходится с состоянием Terraform — ручные изменения, правки в консоли или неудачные apply
  • driftctl сканирует ваш cloud аккаунт и сравнивает с состоянием, обнаруживая ресурсы о которых Terraform не знает
  • Ошибка #1: предполагать что terraform plan ловит весь drift (он проверяет только ресурсы в состоянии)

Подходит для: Команд где несколько человек имеют доступ к cloud консолям или унаследованной инфраструктуре Пропустите, если: Вы работаете один, все изменения идут через Terraform и вы никогда не трогаете консоль Время чтения: 10 минут

Ваше состояние Terraform говорит что у вас 3 EC2 инстанса. AWS консоль показывает 7. Кто-то создал 4 инстанса вручную “для тестирования” шесть месяцев назад. Они всё ещё работают, стоят $800/месяц, и никто не знает что они делают.

Это инфраструктурный drift — тихое расхождение между тем, что определяет ваш IaC, и тем, что реально существует. В 2026 году, когда команды деплоят быстрее, а сложность cloud растёт, обнаружение drift не опционально. Это способ поддерживать контроль.

Настоящая Проблема

Drift происходит через множество векторов:

Изменения в консоли: Кто-то исправляет правило security group напрямую в AWS консоли. Terraform не знает.

Неудачные apply: terraform apply частично завершается до ошибки. Состояние и реальность расходятся.

Неуправляемые ресурсы: Ресурсы созданные вне Terraform — другими командами, автоматизацией, вами во время отладки.

Баги провайдера: API облачного провайдера возвращает состояние отличное от применённого. Редко, но бывает.

Опасная часть: drift невидим пока что-то не сломается. Тот security group отредактированный вручную? Работает нормально пока Terraform не перезапишет его при следующем apply, убивая production трафик.

Terraform Plan Недостаточен

terraform plan обнаруживает drift только для ресурсов уже в состоянии. Если кто-то создаёт EC2 инстанс вручную, Terraform понятия не имеет о его существовании.

# Это показывает drift только для известных ресурсов
terraform plan

# Output может показать:
# No changes. Your infrastructure matches the configuration.

# Но реальность: 4 неизвестных инстанса работают в вашем VPC

Чтобы ловить комплексный drift, нужны инструменты которые сканируют ваш cloud аккаунт независимо от состояния Terraform.

driftctl: Специализированный Инструмент

driftctl (теперь часть Snyk) сканирует вашего облачного провайдера и сравнивает с состоянием Terraform. Он находит:

  • Ресурсы в состоянии но изменённые в реальности (modified)
  • Ресурсы в cloud но не в состоянии (unmanaged)
  • Ресурсы в состоянии но удалённые из cloud (missing)
# Установка
brew install driftctl

# Базовый скан (использует AWS credentials из окружения)
driftctl scan

# Скан конкретного state файла
driftctl scan --from tfstate://terraform.tfstate

# Скан workspace Terraform Cloud
driftctl scan --from tfstate+tfcloud://WORKSPACE_ID

# Output как JSON для интеграции CI
driftctl scan --output json://drift-report.json

Пример output:

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)

Метрика coverage ключевая — она показывает какой процент ваших cloud ресурсов управляется Terraform.

Интеграция CI/CD

Запускайте обнаружение drift по расписанию, не только на PR:

name: Drift Detection

on:
  schedule:

    - cron: '0 8 * * *'  # Ежедневно в 8 AM UTC
  workflow_dispatch:  # Ручной запуск

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 }}

Работа с Неуправляемыми Ресурсами

Когда driftctl находит неуправляемые ресурсы, у вас есть варианты:

Импорт в Terraform:

# Генерация import блоков
driftctl scan --output json://drift.json
cat drift.json | jq -r '.unmanaged[] | "terraform import \(.type).\(.id) \(.id)"'

# Нативные import блоки Terraform 1.5+
import {
  to = aws_instance.imported
  id = "i-0abc123def456789"
}

Исключение из сканирования (для ресурсов намеренно неуправляемых):

# .driftignore
aws_iam_policy_attachment  # AWS managed attachments
aws_cloudwatch_log_group:/aws/lambda/*  # Автосозданные Lambda
aws_security_group_rule:*  # Управляются другой командой

Удаление вручную созданных ресурсов:

# После подтверждения что ресурс безопасно удалить
aws ec2 terminate-instances --instance-ids i-0abc123def456789

Продвинутое: terraform plan -refresh-only

Для ресурсов уже в состоянии, Terraform 1.x предоставляет специализированное обнаружение drift:

# Проверка drift без планирования изменений
terraform plan -refresh-only

# Применение только refresh состояния (обновить состояние для соответствия реальности)
terraform apply -refresh-only

# Затем plan чтобы увидеть какие изменения восстановят желаемое состояние
terraform plan

Этот workflow разделяет “что изменилось в реальности” от “какие изменения сделает Terraform.”

Глубокое Обнаружение с AWS Config

Для AWS-специфичного drift, AWS Config предоставляет непрерывный мониторинг:

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 обнаруживает drift от правил compliance непрерывно, не только во время сканов.

AI-Ассистированные Подходы

Исправление drift часто требует решений на основе суждений. AI инструменты помогают.

Что AI делает хорошо:

  • Анализ отчётов drift для приоритизации high-risk ресурсов
  • Генерация Terraform import блоков из данных cloud ресурсов
  • Предложения импортировать, игнорировать или удалить неуправляемые ресурсы
  • Объяснение почему ресурс мог задрифтовать

Что всё ещё требует людей:

  • Решения был ли drift намеренным (экстренное исправление vs ошибка)
  • Выбор между импортом и пересозданием задрифтовавших ресурсов
  • Понимание бизнес-влияния вариантов исправления
  • Одобрение деструктивных действий (удаления, замены)

Полезный промпт:

driftctl нашёл эти неуправляемые AWS ресурсы:

- 3 EC2 инстанса (i-xxx) в us-east-1, t3.medium, без тегов
- 2 S3 bucket с "backup" в имени
- 1 RDS инстанс с именем "temp-db"

Помоги мне:

1. Оценить уровень риска каждого
2. Рекомендовать: импортировать в Terraform, удалить или игнорировать
3. Сгенерировать import блоки для ресурсов которые оставить

Когда Это Не Работает

Обнаружение drift имеет ограничения:

Покрытие типов ресурсов: driftctl не поддерживает каждый AWS/Azure/GCP ресурс. Новые сервисы отстают.

Доступ к state файлу: Remote state backends (S3, Terraform Cloud) требуют правильной аутентификации. Multi-workspace setups усложняются.

Производительность на масштабе: Сканирование аккаунтов с 10,000+ ресурсами занимает время. Рассмотрите фильтрацию по типу ресурса.

Ложные срабатывания: Некоторые ресурсы естественно дрифтуют (counts auto-scaling, динамические IP). Накопите ignores.

Рассмотрите дополнительные подходы:

  • Policy as Code для предотвращения неавторизованных изменений
  • Нативные инструменты облачного провайдера (AWS Config, Azure Policy) для непрерывного compliance
  • GitOps workflows которые делают ручные изменения невозможными

Фреймворк Принятия Решений

Запускайте обнаружение drift ежедневно когда:

  • Несколько команд имеют доступ к cloud консолям
  • Вы унаследовали инфраструктуру от другой команды
  • Compliance требует доказательств управления конфигурацией
  • Были инциденты связанные с drift

Запускайте обнаружение drift еженедельно когда:

  • Маленькая команда с сильной Terraform дисциплиной
  • Большинство изменений идут через CI/CD
  • Низкая частота ручных вмешательств

Пропускайте обнаружение drift когда:

  • Solo разработчик с полной дисциплиной консоли
  • Эфемерные окружения (часто пересоздаются)
  • Ресурсы явно управляемые вне Terraform

Измерение Успеха

МетрикаДоПослеКак Отслеживать
Неуправляемые ресурсыНеизвестно<10%Покрытие driftctl
Инциденты drift за кварталНеизвестно0Отчёты об инцидентах
Время обнаружения driftДни/недели<24 часаTimestamps сканов
Ресурсы импортированы в IaCN/A+50/кварталИстория git

Тревожные признаки что не работает:

  • Растущий файл .driftignore
  • Команды отключают алерты drift
  • Процент coverage падает
  • Ручные изменения продолжаются несмотря на обнаружение

Что Дальше

Начните с видимости, затем улучшайте покрытие:

  1. Запустите driftctl scan один раз вручную для установки baseline
  2. Задокументируйте все неуправляемые ресурсы (решите: импорт, удаление, игнор)
  3. Настройте ежедневные запланированные сканы
  4. Алертьте о новых неуправляемых ресурсах
  5. Отслеживайте процент coverage со временем (цель: 90%+)
  6. Добавьте driftctl в PR checks для workflows изменяющих состояние

Цель — сделать drift видимым немедленно, а не во время расследования инцидентов.


Связанные статьи:

Внешние ресурсы:

Официальные ресурсы

See Also