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 — не синтаксические ошибки, а ресурсы, которые существуют в production, но не находятся в вашем state-файле. terraform import и регулярные сканирования дрифта — вот как ты избавляешься от этих призраков.” — Yuri Kan, Senior QA Lead

Неуправляемые ресурсы: Ресурсы созданные вне 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 видимым немедленно, а не во время расследования инцидентов.

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

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

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

FAQ

Что вызывает дрифт Terraform state?

Дрифт вызывается ручными изменениями в облачных консолях и изменениями вне контроля Terraform. Согласно документации Terraform, terraform plan обнаруживает весь дрифт.

Как исправить дрифт Terraform state?

Используй terraform import для включения неуправляемых ресурсов, terraform state rm для удаления ресурсов или terraform apply для reconciliation.

Что такое команда terraform refresh?

terraform refresh запрашивает фактическое состояние ресурсов и обновляет state-файл без изменений ресурсов.

See Also