Terraform — это один из популярных инструментов Infrastructure as Code (IaC), который позволяет управлять инфраструктурой, используя различные облачные провайдеры. Он использует декларативный подход: вы просто описываете желаемую инфраструктуру, а не последовательность шагов для её создания — и она автоматически создаётся.
В этой статье будут описаны рекомендации для эффективной разработки с помощью Terraform.
Когда вы работаете над большим проектом со сложной инфраструктурой, вы должны поддерживать понятную структуру файлов и папок, чтобы упростить понимание проекта. Рекомендуется использовать одинаковый формат структуры папок, файлов и самого кода.
Пример проекта:
-- PROJECT-DIRECTORY/
-- modules/
-- <service1-name>/
-- main.tf
-- variables.tf
-- outputs.tf
-- provider.tf
-- README
-- <service2-name>/
-- main.tf
-- variables.tf
-- outputs.tf
-- provider.tf
-- README
-- ...other…
-- environments/
-- dev/
-- backend.tf
-- main.tf
-- outputs.tf
-- variables.tf
-- terraform.tfvars
-- qa/
-- backend.tf
-- main.tf
-- outputs.tf
-- variables.tf
-- terraform.tfvars
-- stage/
-- backend.tf
-- main.tf
-- outputs.tf
-- variables.tf
-- terraform.tfvars
-- prod/
-- backend.tf
-- main.tf
-- outputs.tf
-- variables.tf
-- terraform.tfvars
Оставлять весь код в одном файле main.tf
— плохая идея. Лучше разделить всё по файлам с разным назначением, например:
main.tf
— вызов модулей, источников данных для создания ресурсовvariables.tf
— описание переменных, которые используются в main.tf
outputs.tf
— описание выходных данных ресурсов, которые создаются в main.tf
versions.tf
— требования к версиям Terraform и провайдеровterraform.tfvars
— значения переменныхvps.tf
, s3.tf
, load_balancer.tf
Избегайте получения каждого ресурса в отдельном файле.README.md
с понятным описанием модуля.backend.tf
— описание Terraform Backend State.main.tf
— файл с описанием инфраструктуры.files/
templates/
count
/ for_each
внутри блока ресурса или источника данных как первый аргумент вверху и отделяйте новой строкой. Блоки tags
, depends_on
и lifecycle
, если применимо, всегда должны быть перечислены как последние аргументы, всегда в одном и том же порядке. Все они должны быть разделены одной пустой строкой.vps
Код Terraform должен быть написан так, чтобы другие люди могли легко его понять. Следование одинаковым и согласованным правилам именования объектов может упростить понимание кода
_
(нижнее подчёркивание) вместо -
, чтобы разделить наименования из множества слов.resource "aws_route_table" "public" {}
— ОКresource "aws_route_table" "public_route_table" {}
— НЕ ОКprimary
, secondary
, public
, private
).variables.tf
.description
, type
, default
, validation
.list(...)
или map(...)
.number
, string
, list(...)
, map(...)
, any
) перед специфическим типом, например, object()
, если вам не нужно иметь строгие ограничения на каждый ключ.enable_external_access
).ram_size_gb
).outputs.tf
.{name}_{type}_{attribute}
.README.md
. Автоматически генерируйте описание при коммите с помощью инструментов, таких как terraform-docs.terraform fmt
используется для перезаписи файлов конфигурации Terraform в канонический формат и стиль. terraform fmt
.gitignore
для файлов состояния Terraform. State: Locking | Terraform | HashiCorp Developer
Могут быть различные сценарии, когда более одного разработчика пытаются запустить конфигурацию terraform одновременно. Это может привести к повреждению файла состояния terraform или даже потере данных.
Поскольку несколько пользователей имеют доступ к одному и тому же файлу состояния, файл состояния должен быть заблокирован, когда он используется. Механизм блокировки помогает предотвратить такие сценарии. Он гарантирует, что в одно время только один человек запускает конфигурации terraform, и нет конфликта.
Не все бэкэнды поддерживают блокировку. например, Azure Blob storage поддерживает блокировку изначально, в то время как Amazon S3 поддерживает использование DynamoDB в AWS.
Есть много ресурсов и поставщиков данных в Terraform, которые хранят секретные значения в виде обычного текста в файле состояния. По возможности избегайте хранения секретов в файле состояния.
Для хранения секретов можно использовать сервисы (например AWS Secret Manager, HashiCorp Vault), и ссылаться на них, используя источники данных.
Радиус поражения — это ничто иное, как мера ущерба, который может произойти, если вещи не пойдут по плану. Работать с меньшим количеством ресурсов проще и быстрее. Радиус поражения меньше при меньшем количестве ресурсов.
После выполнения команды terraform apply
запустите автоматические проверки безопасности. Эти проверки могут помочь гарантировать, что инфраструктура не перейдет в небезопасное состояние.
Инструменты InSpec и Serverspec являются подходящими вариантами для этого типа проверок.
Конфигурация Terraform часто включает чувствительные входные данные, такие как пароли, токены API и др.
С флагом sensitive
Terraform будет скрывать значения чувствительных переменных в консоли и выводе журнала, чтобы уменьшить риск случайного раскрытия этих значений.
Флаг sensitive
помогает предотвратить случайное раскрытие чувствительных значений, но недостаточен для полной защиты вашей конфигурации Terraform.
variable "db_password" {
description = "Пароль администратора базы данных."
type = string
sensitive = true
}
.tfvars
или .tfvars.json
).-var-file:
terraform apply -var-file="testing.tfvars"
-var-file
, а не сохранять их внутри конфигураций terraform или на удаленном месте системы контроля версий.Модули предназначены для повторного использования кода.
Настоятельно рекомендуется использовать официальные модули Terraform. Нет необходимости изобретать модуль, который уже существует.
Каждый модуль должен концентрироваться только на одном аспекте инфраструктуры, например, создании экземпляров баз данных и т. д.
Иногда модули требуют несовместимых изменений, и вам нужно сообщить об эффектах пользователям, чтобы они могли закрепить свои конфигурации за определенной версией.
Общие модули не должны объявлять провайдеры или remote state. Вместо этого объявляйте такие параметры в корневых модулях.
Переменные и выходные значения позволяют вам определять зависимости между модулями и ресурсами. Без каких-либо выходных значений пользователи не смогут правильно использовать ваш модуль в своих конфигурациях Terraform.
Для каждого ресурса, определенного в общем модуле, включите хотя бы одно output-значение, которое ссылается на ресурс.
Такие модули позволяют организовать сложную логику Terraform в меньшие единицы и устранить дублирование общих ресурсов.
modules/$modulename
.Важно не допускать, чтобы одна корневая конфигурация становилась слишком большой, с слишком большим количеством ресурсов, хранящихся в одном каталоге и состоянии.
С меньшим количеством ресурсов в проекте проще и быстрее работать.
terraform validate
и инструменты, такие как tflint
, config-lint
, Checkov, Terrascan, tfsec, Deepsource.terraform validate
и plan
перед тем, как разрешать применять изменения terraform к окружению.Рекомендуется оставаться на последней версии Terraform, когда происходит новый крупный релиз. Вы можете легко обновиться до последней версии.
Запустите команду terraform -v
, чтобы проверить наличие нового обновления.
Убедитесь, что включена защита от удаления для stateful-ресурсов, таких как например БД.
Переменная self
— это особый вид переменной, который используется, когда вы не знаете значения переменной до развертывания инфраструктуры.
Например, вы хотите использовать IP-адрес экземпляра, который будет развернут только после команды terraform apply
, поэтому вы не знаете IP-адреса, пока он не будет запущен и работает.
Размещайте свои проекты на VDS/VPS<br>в Timeweb Cloud
Воркспейсы позволяют вам управлять несколькими экземплярами одной и той же конфигурации Terraform, и у каждого экземпляра будет своё состояние. Это полезно, когда вам нужно управлять несколькими средами, такими как dev, staging и production, с одной и той же кодовой базой Terraform.
Для создания рабочей области используйте команду terraform workspace new
, а для переключения между рабочими областями — команду terraform workspace select
. Например, вот как вы могли бы использовать рабочие области для управления средами dev и prod:
terraform workspace new dev
terraform apply
terraform workspace new prod
terraform apply
Механизм provisioners
позволяет запускать скрипты или команды на ресурсе после его создания. Это может быть полезным для настройки программного обеспечения на вновь созданном ресурсе или запуска тестов на ресурсе после его создания.
В Terraform есть два типа провайдеров: local-exec
и remote-exec
. Local-exec запускает команды локально на машине, на которой запущен Terraform, а remote-exec запускает команды на самом ресурсе. Вот пример конфигурации, которая использует провайдер local-exec для запуска скрипта после создания конфигурации:
resource "twc_server" "example-server" {
name = "Example server"
os_id = data.twc_os.example-os.id
configuration {
configurator_id = data.twc_configurator.example-configurator.id
disk = 1024 * 10
cpu = 1
ram = 1024
}
provisioner “local-exec” { command = “echo ‘Привет, Мир!’ }
}
После запуска terraform apply
выполнится команда: