Где хранить состояние инфраструктуры? Практическое руководство
Вы только что закончили писать конфигурацию Terraform, которая разворачивает несколько серверов и базу данных. Вы запускаете terraform apply на своем ноутбуке, и всё работает. Ваш коллега, которому нужно добавить балансировщик нагрузки, запускает ту же конфигурацию со своей машины. И тут база данных исчезает. Не потому, что код был неправильным, а потому что локальный state-файл коллеги не знал, что база данных уже существует.
Этот сценарий не гипотетический. Он происходит каждый день в командах, которые хранят состояние инфраструктуры в виде локального файла на каждом компьютере разработчика. Проблема проста: когда несколько человек управляют одной и той же инфраструктурой, локальное состояние каждого быстро устаревает. Ресурсы перезаписываются, дублируются или случайно уничтожаются. Решение столь же простое: храните состояние в общем защищенном месте, доступном всем членам команды.
Что такое состояние и почему оно важно?
Состояние (state) — это запись всего, что создал ваш инструмент управления инфраструктурой. Оно содержит идентификаторы ресурсов, IP-адреса, значения конфигурации, а иногда даже пароли или ключи API, хранящиеся в открытом виде. Когда вы запускаете terraform plan, инструмент читает текущее состояние, чтобы понять, что уже существует и что нужно изменить. Без точного состояния инструмент не может определить, нужно ли создать ресурс, обновить его или оставить как есть.
Если состояние потеряно или повреждено, инструмент теряет связь с вашей инфраструктурой. В результате вы получаете осиротевшие ресурсы, которые потребляют деньги, но больше не управляются. Или, что еще хуже, вы случайно пересоздаете уже работающие ресурсы, вызывая простой.
Ловушка локального файла
Самый простой способ хранить состояние — это файл на вашей собственной машине. Для обучения или личных проектов это работает нормально. Вы единственный, кто трогает инфраструктуру, поэтому конфликтов не возникает.
Но как только присоединяется второй человек, локальное состояние ломается. Вот что происходит:
- Вы создаете сервер. Ваш state-файл записывает его.
- Ваш коллега запускает ту же конфигурацию. Его state-файл пуст, поэтому инструмент пытается создать еще один сервер с тем же именем.
- Облачный провайдер отклоняет дубликат, или, что еще хуже, инструмент перезаписывает существующий сервер, потому что не знает о его существовании.
Даже если вы делитесь state-файлом через систему контроля версий, вы сталкиваетесь с конфликтами слияния. Два человека не могут одновременно редактировать один и тот же state-файл, не перезаписывая изменения друг друга. Вот почему команды, которые совместно управляют инфраструктурой, должны использовать удаленный backend.
Чтобы помочь вам выбрать подход, подходящий для вашей ситуации, вот блок-схема принятия решений:
Удаленный backend: единый источник истины
Удаленный backend хранит состояние в месте, доступном всем членам команды. Распространенные варианты включают S3-бакет в AWS, GCS-бакет в Google Cloud или контейнер Azure Storage. Все указывают своему инструменту инфраструктуры на один и тот же backend, поэтому состояние всегда согласовано.
Вот минимальная конфигурация backend Terraform, которая использует S3-бакет для хранения состояния и таблицу DynamoDB для блокировки:
terraform {
backend "s3" {
bucket = "my-company-terraform-state"
key = "production/network/terraform.tfstate"
region = "us-east-1"
dynamodb_table = "terraform-state-locks"
encrypt = true
}
}
Перед использованием этой конфигурации создайте S3-бакет с включенным версионированием и таблицу DynamoDB с первичным ключом LockID (тип String). Настройка encrypt = true гарантирует, что state-файл будет зашифрован при хранении.
Но удаленный backend — это не просто общая папка. Прежде чем выбрать его, нужно учесть несколько вещей.
Контроль доступа обязателен
State-файлы содержат конфиденциальную информацию. Идентификаторы ресурсов, IP-адреса, а иногда и учетные данные хранятся в открытом виде. Если кто-то за пределами вашей команды получит доступ на чтение к состоянию, он сможет увидеть детали всей вашей инфраструктуры. Если он получит доступ на запись, он сможет повредить или удалить ресурсы.
Заблокируйте бакет или контейнер, где хранится состояние. Используйте политики IAM или управление доступом на основе ролей, чтобы только авторизованные люди и системы могли читать или записывать состояние. Относитесь к бакету состояния как к рабочей базе данных.
Компромиссы между скоростью и стоимостью
Локальное состояние быстрое, потому что файл находится на вашей машине. Удаленные backend требуют загрузки состояния перед plan или apply и выгрузки после. Для небольших команд с несколькими десятками ресурсов это добавляет секунду-другую. Для крупной инфраструктуры с тысячами ресурсов загрузка и выгрузка могут занять минуты.
Некоторые backend взимают плату за операцию или за гигабайт хранилища. S3, например, взимает плату за PUT и GET запросы. Если ваша команда запускает terraform plan десятки раз в день, эти расходы накапливаются. Выбирайте backend, который соответствует характеру использования вашей команды.
Версионирование спасает от ошибок
Некоторые удаленные backend поддерживают версионирование. S3 может хранить историю каждого изменения state-файла. Если кто-то применит изменение, которое ломает систему, вы можете откатиться к предыдущей версии состояния и восстановиться.
Версионирование не включено по умолчанию. Вы должны включить его явно. Не предполагайте, что ваш backend автоматически хранит историю. Проверьте документацию и включите версионирование до того, как оно вам понадобится.
Управляемые backend снижают операционные затраты
Если вы не хотите самостоятельно управлять бакетом, политиками доступа и версионированием, рассмотрите управляемый backend, такой как Terraform Cloud или HashiCorp Consul. Эти сервисы специально разработаны для управления состоянием. Они включают версионирование, историю, блокировку и интеграцию с CI/CD пайплайнами.
Плата за это — стоимость и привязка к вендору. Управляемые backend взимают плату за пользователя или за рабочее пространство. Вы также зависите от доступности и времени работы API провайдера. Для команд, которые хотят сосредоточиться на инфраструктуре, а не на управлении состоянием, этот компромисс часто оправдан.
Блокировка предотвращает одновременные изменения
Даже с удаленным backend два человека могут одновременно запустить terraform apply. Без блокировки обе операции читают одно и то же состояние, вносят изменения и записывают обратно. Вторая запись перезаписывает первую, и изменения первого человека теряются.
Большинство удаленных backend поддерживают блокировку. S3 с DynamoDB, например, использует таблицу DynamoDB для хранения блокировки. Когда кто-то запускает операцию, инструмент захватывает блокировку. Другие операции должны ждать, пока блокировка не будет снята. Это предотвращает повреждение состояния из-за одновременных записей.
Блокировка не является опциональной для команд. Если ваш backend ее не поддерживает, найдите тот, который поддерживает.
Практический чек-лист для хранения состояния
Прежде чем решить, где хранить состояние, пройдитесь по этому чек-листу:
- Доступен ли backend всем, кому он нужен?
- Ограничен ли доступ только авторизованными людьми и системами?
- Поддерживает ли backend версионирование?
- Поддерживает ли backend блокировку?
- Приемлема ли стоимость для характера использования вашей команды?
- Приемлема ли задержка для вашего рабочего процесса?
Если вы ответили «да» на все шесть пунктов, у вас надежный backend для состояния.
Конкретный вывод
Не храните состояние инфраструктуры на своем ноутбуке. Используйте удаленный backend, который поддерживает контроль доступа, версионирование и блокировку. Те несколько минут, которые вы потратите на настройку правильного backend для состояния, сэкономят вам часы отладки, когда кто-то случайно удалит ресурс или перезапишет изменения коллеги. Ваша инфраструктура настолько надежна, насколько надежно состояние, которое ее отслеживает. Убедитесь, что это состояние хранится в безопасном месте.