Как и любой другой язык программирования, terraform также является декларативным языком для управления вашей инфраструктурой. Вот как компания Hashicorp определяет язык terraform
Язык Terraform является декларативным, описывающим намеченную цель, а не шаги для достижения этой цели. Порядок следования блоков и файлы, в которые они организованы, обычно не имеют значения; Terraform учитывает только неявные и явные отношения между ресурсами при определении порядка операций.
В Terraform весь ваш код может находиться всего в одном файле, заканчивающемся расширением .tf
, и он будет работать так, как ожидается. Однако давайте рассмотрим блоки, выражения и аргументы в Terraform, которые мы обычно называем компонентами, и посмотрим, имеет ли смысл держать их в одном файле или разделить на несколько файлов.
- Ресурсы Terraform отвечают за создание/изменение или уничтожение компонента инфраструктуры. Они обычно поставляются с выбранным нами провайдером (упомянутым ниже).
resource "aws_iam_role" "emr_service_role" {
count = var.instance_profile == "" ? 1 : 0
name = "${var.cluster_name}-${var.aws_region_shortname[var.aws_region]}-service-role"
assume_role_policy = join("", data.aws_iam_policy_document.emr_service_assume_role.*.json)
dynamic "inline_policy" {
for_each = local.emr_service_role_policy
content {
name = inline_policy.value.name
policy = inline_policy.value.policy
}
}
}
variable "aws_region_shortname" {
default = {
"us-west-1" = "uw1",
"us-west-2" = "uw2",
"us-east-1" = "ue1",
"us-east-2" = "ue2",
"ap-northeast-1" = "apne1",
"ap-southeast-1" = "apse1",
}
type = map(any)
}
resource "aws_iam_role" "emr_service_role" {
name = "${var.cluster_name}-${var.aws_region_shortname[var.aws_region]}-service-role"
...
...
}
terraform {
required_providers {
aws = {
source = "tfproviders/aws"
version = "4.66.0"
}
}
}
provider "aws" {
# Configuration options
}
locals {
iam_name = "${var.iam_prefix}-${var.aws_region_shortname[var.aws_region]}"
}
resource "aws_iam_role" "emr_service_role" {
name = local.iam_name
...
...
}
- Файл переменных Терраформ автоматически идентифицирует файл с
.tfvars
как файл переменных и ожидает, что все входы для переменных будут присутствовать в этом файле.
iam_prefix = "example-iam"
- Выход Переменные экспортируются для использования в качестве входных данных для других параметров или в результате выполнения
terraform
.
output "iam_name" {
description = "The Name of the IAM Role"
value = aws_iam_role.emr_service_role.name
}
Итак, теперь мы знаем, какие типы компонентов есть у terraform и для чего они используются. Теперь вопрос в том, следует ли нам разделить их или просто поместить все в один файл.
Как уже говорилось, если поместить их все в один файл .tf
, а входные данные в один .tfvars
, то все должно получиться. Однако будет очень трудно ориентироваться в коде, устанавливать взаимосвязи, иерархию или находить в нем смысл. Если вы используете несколько модулей (модуль = комбинация нескольких ресурсов) или даже несколько ресурсов, то управлять ими станет еще сложнее.
Для решения этой проблемы сообщество придумало следующую структуру файлов для любого кода терраформы
Вот как обычно выглядит репозиторий terraform
.
├── README.md
├── locals.tf
├── providers.tf
├── main.tf
├── outputs.tf
├── validators.tf
└── variables.tf
С таким разделением файлов мы можем легко идентифицировать и предположить, чего от них ожидать. Ничто не мешает нам упростить их еще больше или использовать больше файлов, которые имеют смысл, например, шаблоны, конфигурации и т.д. Что-то вроде следующего
├── README.md
├── chef-attributes.tf
├── main.tf
├── outputs.tf
├── providers.tf
├── templates
│ ├── elasticsearch7.json.tpl
│ └── elasticsearch8.json.tpl
├── tests
│ └── unittest
│ └── suites
│ ├── component-testcase01
│ │ └── unittest.auto.tfvars
│ ├── component-testcase02
│ │ └── unittest.tfvars
│ └── component-testcase03
├── validators.tf
└── variables.tf
Надеюсь, это имеет смысл и поможет вам организовать ваш код терраформирования более читабельным и управляемым способом.
Счастливого терраформирования!!!