Как профессионал в области программного обеспечения, работающий с Infrastructure as Code (IaC), скорее всего, вы много работаете с Terraform. Когда вы помогаете новым клиентам использовать IaC, обычно стараетесь упростить процесс, но управление файлом состояния Terraform является первой проблемой, с которой вы сталкиваетесь. По сути, Terraform state содержит конфиденциальную информацию, которую не следует хранить в системе контроля версий, но в то же время это не масштабируется, если у вас есть несколько пользователей, работающих над одним и тем же состоянием Terraform. Ответ на этот вопрос? Backends.
Важно отметить, что вы можете хранить этот файл состояния в S3 bucket и использовать DynamoDB для управления блокировкой состояния. Однако этот подход заставит вас создавать дополнительные ресурсы, что делает его сложным вариантом, особенно если клиент использует GitLab. Недавно GitLab снизил барьер интеграции Terraform, предоставив способ хранения и управления состоянием Terraform, а также простой способ настройки CI вокруг него.
В этой статье мы объясним, что такое файл состояния Terraform, как перенести его в GitLab и настроить для него CI-конвейер. Вы можете посетить наш репозиторий здесь.
Содержание
- Что такое состояние Terraform?
- Как заставить GitLab управлять состоянием Terraform
- Как заставить GitLab запускать ваше IaC через CI-конвейер
- Бонусный совет: Infracost
- Заключение
Что такое состояние Terraform?
Terraform записывает любую информацию о инфраструктуре, определенной в вашем коде, через файл состояния. Написанный на JSON, он по сути регистрирует сопоставление от кода Terraform к реальным ресурсам, созданным. Ниже приведен пример того, как может выглядеть terraform.tfstate
. В основном, каждый раз, когда вы запускаете Terraform, он будет запрашивать последний статус для своей инстанции EC2 и сравнивать его с вашим конфигурационным файлом Terraform, чтобы определить, какие изменения необходимо применить:
{
"version": 4,
"terraform_version": "0.12.0",
"serial": 1,
"lineage": "1f2087f9-4b3c-1b66-65db-8b78faafc6fb",
"outputs": {},
"resources": [
{
"mode": "managed",
"type": "aws_instance",
"name": "example",
"provider": "provider.aws",
"instances": [
{
"schema_version": 1,
"attributes": {
"ami": "ami-0c55b159cbfafe1f0",
"availability_zone": "us-west-2a",
"id": "i-00a123a0accffffff",
"instance_state": "running",
"instance_type": "t2.micro",
"(...)": "(truncated)"
}
}
]
}
]
}
По умолчанию, этот terraform.tfstate
хранится локально, где у вас есть файлы Terraform, план и примените изменения. Для личного проекта, где вы просто проводите некоторые тесты; это нормально, но не рекомендуется, вот почему:
- Хранение в общем расположении: если бы вы размещали этот файл состояния на своем рабочем компьютере и должны были работать с другим инженером, ситуация стала бы сложной. Оба вам пришлось бы убедиться, что вы используете последнюю версию состояния, и вы могли бы столкнуться с условиями гонки, если вы запустите план Terraform или примените одновременно.
- Защита конфиденциальной информации: Сгенерированный файл состояния может содержать ключи шифрования и пароли инфраструктуры. Однако файлы состояния не шифруются по умолчанию, и хранить конфиденциальную информацию в открытом виде плохая идея.
- Блокировка: Большинство систем контроля версий не поддерживают какую-либо форму блокировки, которая предотвращает одновременный запуск команды Terraform apply двумя членами команды на одном файле состояния. Это еще одна причина, по которой мы не увидим файл состояния, управляемый контролем версий.
Как настроить GitLab для управления состоянием Terraform
Поскольку Terraform считается стандартом в области предоставления облачных инфраструктур, около года назад GitLab начал предлагать способ хранения и управления вашим состоянием Terraform. По этой причине мы хотели поделиться процессом миграции, так как недавно начали использовать GitLab для управления нашей IaC.
Для этой статьи мы предполагаем, что вы используете локальное состояние и управляете своим состоянием с помощью AWS S3 Bucket или другого решения для бэкенда.
Во-первых, вам нужно изменить ваш backend.tf
для использования HTTP:
terraform {
backend "http" {}
}
Далее, вам нужно установить четыре переменные в вашей терминале:
1. PROJECT_ID
: Вы можете легко найти это, перейдя в ваш репозиторий на странице “Обзор проекта”.
2. TF_USERNAME
: Имя пользователя GitLab, который имеет доступ к репозиторию, над которым вы работаете.
3. TF_PASSWORD
: Токен доступа, сгенерированный от вашего пользователя GitLab.
4. TF_ADDRESS
: URL удаленного бэкенда состояния.
PROJECT_ID="28450092"
TF_USERNAME="florianpialoux"
TF_PASSWORD="123456789"
TF_ADDRESS="https://gitlab.com/api/v4/projects/${PROJECT_ID}/terraform/state/aws-buckets"
Теперь вы можете запустить команду миграции, которая переместит ваше состояние Terraform из предыдущего места в GitLab с помощью следующей команды:
terraform init \
-migrate-state \
-backend-config=address=${TF_ADDRESS} \
-backend-config=lock_address=${TF_ADDRESS}/lock \
-backend-config=unlock_address=${TF_ADDRESS}/lock \
-backend-config=username=${TF_USERNAME} \
-backend-config=password=${TF_PASSWORD} \
-backend-config=lock_method=POST \
-backend-config=unlock_method=DELETE \
-backend-config=retry_wait_min=5
Вам потребуется предоставить подтверждение “да”, чтобы GitLab начал управлять вашим файлом состояния. Вот пример с локального состояния в GitLab:
Пример с S3 в GitLab:

I noticed for some of the state files I had from S3 will be blank even after using the migrate-state
command ran previously. In this case, you can run this:
terraform state pull > aws-buckets.json
Скопируйте и вставьте содержимое из состояния S3 и запустите push:
terraform state push -lock=true aws-buckets.json
GitLab поддерживает контроль версий для вашего файла состояния Terraform, но просмотр/восстановление старых версий через веб-интерфейс потребует наличия плана GitLab Premium. В противном случае вам придется использовать запрос к API GraphQL запрос.
Как заставить GitLab запускать вашу IaC через конвейер CI
GitLab предоставляет образ Docker, который содержит GitLab-Terraform, представляющий собой тонкую оболочку скрипта вокруг официального бинарного файла Terraform. В качестве альтернативы можно использовать официальный образ Docker от Hashicorp. Более подробная информация о образе GitLab Terraform доступна здесь.
После запуска задачи Terraform apply вы сможете увидеть, когда использовалось состояние и с каким конвейером.
gitlab-ci.yml
looks like here. Below, are the variables that will need to be defined on the project level.Бонусный совет: Infracost
Как вы могли заметить, в нашем gitlab-ci.yaml
мы добавили Infracost, что позволяет нам иметь больший контроль над нашими расходами на облако, так как он предоставляет оценку стоимости каждый раз, когда вы определяете новый ресурс для вашей IaC.
Заключение
Имея ваш состояние Terraform и CI, работающие на GitLab, отличный способ следовать лучшим практикам GitOps. Они прекрасно дополняют друг друга для разработки и развертывания IaC. Поскольку многие из вас, вероятно, уже используют GitLab для своих репозиториев, становится намного проще иметь вашу IaC под одной крышей и позволить GitLab управлять вашим состоянием Terraform, поддерживая шифрование при передаче и на стороне клиента, а также версионирование, блокировку и разблокировку состояния.
Source:
https://dzone.com/articles/how-to-migrate-terraform-state-to-gitlab-cicd