TL;DR

  • Что: Обнаружение дрифта выявляет различия между вашими определениями IaC и фактически развёрнутой инфраструктурой
  • Зачем: Ручные изменения, неудачные деплои и внешние модификации вызывают дрифт конфигурации, приводящий к инцидентам
  • Инструменты: Terraform plan, AWS Config, driftctl, Spacelift, env0
  • Ключевая метрика: 100% ресурсов отслеживается с алертами о дрифте в течение 1 часа после изменения
  • Начните здесь: Запланируйте ежедневные запуски terraform plan и алертуйте о любых обнаруженных изменениях

В 2025 году 67% инцидентов в продакшене были связаны с дрифтом конфигурации — различиями между намеченным и фактическим состоянием инфраструктуры. Когда инженеры делают “быстрые исправления” через облачные консоли или автоматизация тихо падает, инфраструктура расходится с кодом. Обнаружение дрифта ловит эти расхождения до того, как они вызовут сбои.

Это руководство охватывает внедрение комплексного обнаружения дрифта по всей инфраструктуре. Вы научитесь обнаруживать дрифт с Terraform и специализированными инструментами, настраивать автоматический мониторинг и устанавливать процессы, предотвращающие возникновение дрифта.

Что вы узнаете:

  • Как реализовать обнаружение дрифта с Terraform и AWS Config
  • Автоматический мониторинг и алерты об изменениях инфраструктуры
  • Стратегии и рабочие процессы устранения дрифта
  • Техники предотвращения, устраняющие ручные изменения
  • Лучшие практики от организаций, управляющих тысячами ресурсов

Понимание дрифта инфраструктуры

Что такое дрифт инфраструктуры?

Дрифт инфраструктуры происходит, когда фактическое состояние развёрнутых ресурсов отличается от желаемого состояния, определённого в вашем Infrastructure as Code. Этот разрыв между кодом и реальностью может быть вызван:

  • Ручными изменениями через облачные консоли (ClickOps)
  • Неудачными или частичными деплоями
  • Внешними системами, модифицирующими ресурсы
  • Механизмами автомасштабирования или самовосстановления
  • Shadow IT, создающим неотслеживаемые ресурсы

Почему это важно

Дрифт создаёт серьёзные операционные риски:

  • Риск инцидентов: Неизвестные конфигурации вызывают неожиданное поведение
  • Нарушения соответствия: Ручные изменения обходят контроли безопасности
  • Сбои деплоя: Terraform apply падает из-за несоответствия состояния
  • Пробелы в аудите: Фактическая инфраструктура не соответствует документированному состоянию

Типы дрифта

ТипОписаниеПример
Дрифт конфигурацииСвойства ресурса отличаются от IaCПравила security group изменены через консоль
Дрифт состоянияРесурсы существуют, но их нет в файле состоянияВручную созданный S3 bucket
Осиротевшие ресурсыРесурсы в состоянии, но удалены извнеEC2 инстанс завершён вручную
Теневые ресурсыРесурсы вообще не управляются IaCТестовые базы данных, созданные разработчиками

Реализация обнаружения дрифта с Terraform

Предварительные требования

Перед началом убедитесь, что у вас есть:

  • Установленный Terraform 1.5+
  • Настроенный удалённый backend состояния (S3, Azure Blob, GCS)
  • Pipeline CI/CD (GitHub Actions, GitLab CI, Jenkins)
  • Учётные данные облачного провайдера с доступом на чтение

Шаг 1: Базовое обнаружение дрифта с Terraform Plan

Простейшее обнаружение дрифта использует terraform plan:

# Запуск plan и захват вывода
terraform plan -detailed-exitcode -out=plan.out

# Коды выхода:
# 0 = Нет изменений (нет дрифта)
# 1 = Ошибка
# 2 = Обнаружены изменения (дрифт!)

Скрипт автоматического обнаружения:

#!/bin/bash
set -e

cd /path/to/terraform

terraform init -input=false
terraform plan -detailed-exitcode -out=plan.out

EXIT_CODE=$?

if [ $EXIT_CODE -eq 2 ]; then
    echo "ДРИФТ ОБНАРУЖЕН!"
    terraform show -json plan.out > drift-report.json
    # Отправка алерта
    curl -X POST "$SLACK_WEBHOOK" \
        -H "Content-Type: application/json" \
        -d '{"text": "Обнаружен дрифт инфраструктуры! Проверить: '$BUILD_URL'"}'
    exit 1
elif [ $EXIT_CODE -eq 1 ]; then
    echo "Terraform plan упал"
    exit 1
else
    echo "Дрифт не обнаружен"
fi

Шаг 2: Запланированное обнаружение дрифта в CI/CD

Workflow GitHub Actions:

name: Drift Detection

on:
  schedule:

    - cron: '0 */6 * * *'  # Каждые 6 часов
  workflow_dispatch:

jobs:
  drift-check:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        environment: [production, staging]

    steps:

      - uses: actions/checkout@v4

      - name: Setup Terraform
        uses: hashicorp/setup-terraform@v3
        with:
          terraform_version: 1.6.0

      - name: Terraform Init
        working-directory: terraform/${{ matrix.environment }}
        run: terraform init

      - name: Check for Drift
        id: plan
        working-directory: terraform/${{ matrix.environment }}
        run: |
          terraform plan -detailed-exitcode -out=plan.out
        continue-on-error: true

      - name: Report Drift
        if: steps.plan.outcome == 'failure'
        uses: slackapi/slack-github-action@v1.24.0
        with:
          payload: |
            {
              "text": "Дрифт обнаружен в ${{ matrix.environment }}",
              "blocks": [
                {
                  "type": "section",
                  "text": {
                    "type": "mrkdwn",
                    "text": "*Алерт о дрифте инфраструктуры*\nОкружение: ${{ matrix.environment }}\nWorkflow: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}"
                  }
                }
              ]
            }
        env:
          SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK }}

Шаг 3: Детальный анализ дрифта

Парсинг вывода terraform plan для деталей:

# Генерация JSON плана
terraform show -json plan.out > plan.json

# Извлечение ресурсов с дрифтом
jq '.resource_changes[] | select(.change.actions | contains(["update"]) or contains(["delete"]))' plan.json

Пример отчёта о дрифте:

{
  "address": "aws_security_group.web",
  "change": {
    "actions": ["update"],
    "before": {
      "ingress": [{"from_port": 443, "to_port": 443}]
    },
    "after": {
      "ingress": [
        {"from_port": 443, "to_port": 443},
        {"from_port": 22, "to_port": 22}
      ]
    }
  }
}

Верификация

Подтвердите работоспособность настройки:

  • terraform plan запускается без ошибок
  • Запланированные запуски выполняются вовремя
  • Алерты срабатывают при обнаружении дрифта

Продвинутые техники обнаружения дрифта

Техника 1: Использование driftctl для полного покрытия

Когда использовать: Когда нужно обнаруживать ресурсы, не управляемые Terraform (shadow IT).

Установка и настройка:

# Установка driftctl
brew install driftctl

# Сканирование аккаунта AWS
driftctl scan

# Вывод:
# Found 150 resources
# - 120 managed by Terraform
# - 25 unmanaged (drift!)
# - 5 missing from cloud

Интеграция с CI:

- name: Run driftctl
  run: |
    driftctl scan --from tfstate://terraform.tfstate \
      --output json://drift-results.json

- name: Check for unmanaged resources
  run: |
    UNMANAGED=$(jq '.summary.total_unmanaged' drift-results.json)
    if [ "$UNMANAGED" -gt 0 ]; then
      echo "Найдено $UNMANAGED неуправляемых ресурсов!"
      exit 1
    fi

Преимущества:

  • Обнаруживает ресурсы, о которых Terraform не знает
  • Выявляет действительно осиротевшие ресурсы
  • Предоставляет метрики покрытия

Техника 2: Правила AWS Config

Обнаружение дрифта с использованием нативных инструментов AWS:

# Правило AWS Config для обязательных тегов
resource "aws_config_config_rule" "required_tags" {
  name = "required-tags"

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

  input_parameters = jsonencode({
    tag1Key   = "Environment"
    tag2Key   = "Owner"
    tag3Key   = "ManagedBy"
    tag3Value = "terraform"
  })
}

# Кастомное правило для дрифта security group
resource "aws_config_config_rule" "security_group_drift" {
  name = "security-group-open-ports"

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

  input_parameters = jsonencode({
    authorizedTcpPorts = "443,80"
  })
}

Техника 3: Обнаружение дрифта в реальном времени с CloudTrail

Обнаружение дрифта в момент его возникновения:

# Lambda функция, вызываемая CloudTrail
import json
import boto3

def lambda_handler(event, context):
    sns = boto3.client('sns')

    for record in event['Records']:
        detail = json.loads(record['body'])

        # Фильтр ручных изменений из консоли
        if detail.get('userIdentity', {}).get('type') == 'IAMUser':
            if 'Console' in detail.get('userAgent', ''):
                # Обнаружено ручное изменение!
                sns.publish(
                    TopicArn='arn:aws:sns:us-east-1:123456789:drift-alerts',
                    Message=json.dumps({
                        'event': detail['eventName'],
                        'user': detail['userIdentity']['userName'],
                        'resource': detail['requestParameters'],
                        'source': 'Console'
                    }),
                    Subject='Обнаружено ручное изменение инфраструктуры'
                )

    return {'statusCode': 200}

Примеры из реальной практики

Пример 1: Управление дрифтом в Netflix

Контекст: Netflix управляет инфраструктурой в нескольких аккаунтах AWS с тысячами инженеров.

Проблема: Инженеры, делающие быстрые исправления через консоль AWS, вызывали инциденты в продакшене.

Решение: Комплексное обнаружение и предотвращение дрифта:

  • Ежечасные запуски terraform plan по всем аккаунтам
  • Интеграция с CloudTrail для обнаружения ручных изменений в реальном времени
  • Автоматическое создание тикетов Jira на любой дрифт
  • Владельцы сервисов ответственны за устранение в течение 24 часов

Результаты:

  • 92% снижение инцидентов, связанных с дрифтом
  • Среднее время обнаружения дрифта: 15 минут
  • 100% ресурсов отслеживается в Terraform

Ключевой вывод: 💡 Делайте дрифт видимым и назначайте ответственных — инженеры исправляют то, за что они отвечают.

Пример 2: Политика нулевого дрифта в Capital One

Контекст: Финансовая компания со строгими требованиями соответствия.

Проблема: Аудиторы требуют доказательств, что продакшен соответствует определениям IaC.

Решение: Применение нулевого дрифта:

  • Доступ к консоли убран для продакшен-аккаунтов
  • Все изменения требуют PR и terraform apply
  • Непрерывное сканирование дрифта с автоматическим устранением
  • Дашборды соответствия, показывающие статус дрифта

Результаты:

  • Ноль ручных изменений в продакшене за 2 года
  • Время подготовки к аудиту сокращено на 80%
  • Полный аудиторский след каждого изменения инфраструктуры

Ключевой вывод: 💡 Уберите возможность дрифта — если инженеры не могут получить доступ к консоли, они не могут делать ручные изменения.


Лучшие практики

Делать ✅

  1. Запускайте обнаружение дрифта часто

    • Минимум: ежедневно для продакшена
    • Рекомендуется: каждые 6 часов
    • Идеально: непрерывно с интеграцией CloudTrail
  2. Алертуйте на весь дрифт, расследуйте быстро

    • Настройте алерты PagerDuty/Slack
    • Установите SLO на время устранения
    • Отслеживайте метрики дрифта со временем
  3. Используйте удалённое состояние с блокировкой

    • Предотвращайте конкурентные модификации
    • Включите версионирование состояния для отката
    • Ограничьте доступ к состоянию только CI/CD
  4. Импортируйте существующие ресурсы

    • Не оставляйте ресурсы неуправляемыми
    • Используйте terraform import для существующей инфры
    • Документируйте все импортированные ресурсы

Не делать ❌

  1. Не игнорируйте “ожидаемый” дрифт

    • Изменения автомасштабирования должны моделироваться в IaC
    • Самовосстанавливающиеся системы требуют правильной конфигурации
    • Документируйте любой принятый дрифт
  2. Не устраняйте вслепую

    • Поймите, почему произошёл дрифт
    • Исправляйте корневую причину, а не симптомы
    • Ручные изменения могут указывать на пробелы в IaC

Pro Tips 💡

  • Совет 1: Используйте terraform plan -refresh-only для обнаружения дрифта без планирования изменений
  • Совет 2: Тегируйте ресурсы метаданными последней модификации для расследований
  • Совет 3: Создавайте отдельные алерты для разных уровней серьёзности дрифта

Распространённые ошибки и решения

Ошибка 1: Слишком много ложных срабатываний

Симптомы:

  • Команды игнорируют алерты о дрифте
  • Автомасштабирование вызывает постоянные уведомления
  • Легитимные изменения помечаются как дрифт

Корневая причина: Не учитываются ожидаемые изменения состояния в IaC.

Решение:

# Игнорировать изменения желаемой ёмкости автомасштабирования
resource "aws_autoscaling_group" "web" {
  name                = "web-asg"
  min_size            = 2
  max_size            = 10
  desired_capacity    = 2

  lifecycle {
    ignore_changes = [desired_capacity]
  }
}

# Игнорировать теги, управляемые другими системами
resource "aws_instance" "app" {
  # ...

  lifecycle {
    ignore_changes = [
      tags["aws:autoscaling:groupName"],
      tags["kubernetes.io/cluster/*"]
    ]
  }
}

Предотвращение: Моделируйте ожидаемое поведение в IaC; используйте ignore_changes с осторожностью.

Ошибка 2: Повреждение файла состояния

Симптомы:

  • Terraform показывает ресурсы как новые, когда они существуют
  • Plan показывает destroy/recreate для неизменённых ресурсов
  • Состояние не соответствует фактической инфраструктуре

Корневая причина: Конкурентные запуски, ручные правки состояния или проблемы с хранилищем.

Решение:

  • Включить блокировку состояния в backend
  • Никогда не редактировать файлы состояния вручную
  • Использовать версионирование состояния для восстановления
# Backend S3 с блокировкой и версионированием
terraform {
  backend "s3" {
    bucket         = "terraform-state"
    key            = "prod/terraform.tfstate"
    region         = "us-east-1"
    dynamodb_table = "terraform-locks"
    encrypt        = true
  }
}

Предотвращение: Всегда используйте удалённое состояние с блокировкой; ограничивайте прямой доступ к состоянию.


Инструменты и ресурсы

Рекомендуемые инструменты

ИнструментЛучше дляПлюсыМинусыЦена
Terraform PlanБазовое обнаружение дрифтаВстроен, надёженТолько управляемые ресурсыБесплатно
driftctlОбнаружение shadow ITНаходит неуправляемые ресурсыТребует настройкиБесплатно
AWS ConfigНативное обнаружение AWSРеальное время, нативная интеграцияТолько AWSПлатно за правило
SpaceliftEnterprise IaCПолная платформа, авто-устранениеСложный, дорогойПлатно
env0GitOps workflowsХорошее обнаружение дрифта, видимость затратТребует платформуПлатно

Критерии выбора

Выбирайте на основе:

  1. Покрытие: Только Terraform → нативный plan; Shadow IT → driftctl
  2. Масштаб: Маленькая команда → бесплатные инструменты; Enterprise → Spacelift/env0
  3. Облако: Одно облако → нативные инструменты; Мультиоблако → Terraform + driftctl

Дополнительные ресурсы


Управление дрифтом с помощью ИИ

Современные инструменты ИИ улучшают обнаружение и устранение дрифта:

  • Анализ корневых причин: ИИ определяет, почему произошёл дрифт
  • Предложения по устранению: Генерация terraform кода для исправления дрифта
  • Обнаружение паттернов: Выявление повторяющихся источников дрифта
  • Прогноз влияния: Оценка риска обнаруженного дрифта

Инструменты: Firefly, ИИ-функции Env0, кастомные интеграции LLM.


Framework принятия решений: Стратегия обнаружения дрифта

КритерийБазовый подходПродвинутый подход
Размер команды<5 инженеров>5 инженеров
Количество ресурсов<100 ресурсов>100 ресурсов
РеализацияЗапланированный terraform planРеальное время + driftctl
РеагированиеРучное ревьюАвтоматическое устранение
Доступ к консолиРазрешён с логированиемПолностью убран

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

Отслеживайте эти метрики для эффективности обнаружения дрифта:

МетрикаЦельИзмерение
Время обнаружения дрифта<1 часЛатентность CloudTrail → алерт
Время устранения дрифта<24 часаАлерт → PR merged
Ресурсы с дрифтом0%Результаты сканирования дрифта
Неуправляемые ресурсы0Сканирование driftctl
Изменения из консоли0/месяцАнализ CloudTrail
Инциденты, связанные с дрифтом0/кварталPost-mortem инцидентов

Заключение

Ключевые выводы

  1. Обнаружение дрифта необходимо — нельзя управлять тем, что не измеряешь
  2. Планируйте частые сканирования — минимум ежедневно, предпочтительно ежечасно
  3. Обнаруживайте shadow IT — используйте driftctl для поиска неуправляемых ресурсов
  4. Предотвращайте, а не обнаруживайте — уберите доступ к консоли где возможно

План действий

  1. Сегодня: Запустите terraform plan на вашей продакшен-инфраструктуре
  2. На этой неделе: Настройте запланированное обнаружение дрифта в CI/CD
  3. В этом месяце: Внедрите обнаружение в реальном времени и рабочие процессы устранения

Смотрите также


Как ваша команда справляется с дрифтом инфраструктуры? Поделитесь своими стратегиями обнаружения и предотвращения в комментариях.

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