Chef и Ansible поощряют процедурный стиль — когда код пошагово описывает, как достичь желаемого конечного состояния. А вот Terraform, CloudFormation, SaltStack, Puppet и Open Stack Heat исповедуют более декларативный подход: вы описываете в своем коде нужное вам конечное состояние, а средства IaC сами разбираются с тем, как его достичь.
Вы также можете ввести команду terraformoutput, чтобы вывести список всех выходных значений без применения каких-либо изменений:
$ terraform output
public_ip = 54.174.13.5
Чтобы посмотреть значение определенной выходной переменной, можно воспользоваться командой terraformoutput<ИМЯ_ПЕРЕМЕННОЙ>:
$ terraform output public_ip
54.174.13.5
Помимо входных переменных, Terraform позволяет определять и выходные. Для этого предусмотрен такой синтаксис:
output "" {
value =
[CONFIG ...]
}
NAME — это имя выходной переменной, а в качестве VALUE можно указать любое выражение Terraform, которое вы хотите вывести. CONFIG может иметь два дополнительных (и необязательных) параметра.
•description. Этот параметр всегда желательно применять для документирования того, как используется выходная переменная.
•sensitive. Если присвоить данному параметру true, Terraform не станет сохранять этот вывод в журнал после выполнения команды terraformapply. Это полезно, когда переменная содержит деликатный материал или конфиденциальные данные, такие как пароли или секретные ключи.
Помимо входных переменных, Terraform позволяет определять и выходные. Для этого предусмотрен такой синтаксис:
output "" {
value =
[CONFIG ...]
}
NAME — это имя выходной переменной, а в качестве VALUE можно указать любое выражение Terraform, которое вы хотите вывести. CONFIG может иметь два дополнительных (и необязательных) параметра.
•description. Этот параметр всегда желательно применять для документирования того, как используется выходная переменная.
•sensitive. Если присвоить данному параметру true, Terraform не станет сохранять этот вывод в журнал после выполнения команды terraformapply. Это полезно, когда переменная содержит деликатный материал или конфиденциальные данные, такие как пароли или секретные ключи.
Указать ссылку внутри строкового литерала можно с помощью строковой интерполяции, которая имеет следующий синтаксис:
"${...}"
}
Чтобы использовать значение входной переменной в коде Terraform, следует воспользоваться выражением типа «ссылка на переменную», которое имеет следующий синтаксис:
var.
Например, так можно присвоить параметрам группы безопасности from_port и to_port значение переменной server_port:
resource "aws_security_group" "instance" {
name = "terraform-example-instance"
ingress {
from_port = var.server_port
to_port = var.server_port
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
}
Чтобы использовать значение входной переменной в коде Terraform, следует воспользоваться выражением типа «ссылка на переменную», которое имеет следующий синтаксис:
var.
Например, так можно присвоить параметрам группы безопасности from_port и to_port значение переменной server_port:
resource "aws_security_group" "instance" {
name = "terraform-example-instance"
ingress {
from_port = var.server_port
to_port = var.server_port
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
}
Обратите внимание, что у входной переменной server_port нет поля default, поэтому, если выполнить команду apply прямо сейчас, Terraform сразу же попросит ввести значение для server_port и покажет вам описание description:
$ terraform apply
var.server_port
The port the server will use for HTTP requests
Enter a value:
Если вы не хотите иметь дело с интерактивной строкой ввода, можете предоставить значение переменной с помощью параметра командной строки -var:
$ terraform plan -var "server_port=8080"
То же самое можно сделать, добавив переменную среды вида TF_VAR_, где name — имя переменной, которую вы хотите установить:
$ export TF_VAR_server_port=8080
$ terraform plan
Если же вы не хотите держать в голове дополнительные аргументы командной строки при каждом выполнении команды plan или apply, можете указать значение по умолчанию:
variable "server_port" {
description = "The port the server will use for HTTP requests"
type = number
default = 8080
}
Чтобы можно было сделать ваш код более конфигурируемым и отвечающим принципу DRY, Terraform позволяет определять входные переменные. Для этого предусмотрен следующий синтаксис:
variable "NAME" {
[CONFIG ...]
}
Тело объявления переменной может содержать три необязательных параметра.
•description. Этот параметр всегда желательно указывать для документирования того, как используется переменная. Ваши коллеги смогут просмотреть это описание не только при чтении кода, но и во время выполнения команд plan или apply (пример этого показан чуть ниже).
• default. Вы можете присвоить значение переменной несколькими способами, в том числе через командную строку (с помощью параметра -var), файл (указывая параметр -var-file) или переменную среды (Terraform ищет переменные среды вида TF_VAR_<имя_переменной>). Если переменная не инициализирована, ей присваивается значение по умолчанию. Если такого нет, Terraform запросит его у пользователя в интерактивном режиме.
•type. Позволяет применить к переменным, которые передает пользователь, ограничения типов. Terraform поддерживает ряд ограничений для таких типов, как string, number, bool, list, map, set, object, tuple и any. Если тип не указан, Terraform воспринимает значение как any.
Вот пример входной переменной, которая проверяет, является ли передаваемое значение числом:
variable "number_example" {
description = "An example of a number variable in Terraform"
type = number
default = 42
}
А вот пример переменной, которая проверяет, является ли значение списком:
variable "list_example" {
description = "An example of a list in Terraform"
type = list
default = ["a", "b", "c"]
}
Таким образом, в промышленных системах все серверы и уж точно все хранилища данных следует развертывать в закрытых подсетях, IP-адреса которых доступны только внутри VPC, но не из публичного Интернета. Все, что должно находиться в публичных подсетях, — это небольшое количество обратных прокси и балансировщиков нагрузки, в которых закрыто все, что только можно (позже в этой главе вы увидите пример того, как развернуть балансировщик нагрузки)