protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
}
Этот код создает новый ресурс под названием aws_security_group (обратите внимание, что все ресурсы в AWS начинаются с aws_) и делает так, чтобы эта группа разрешала принимать на порте 8080 TCP-запросы из блока CIDR 0.0.0.0/0. Блок CIDR — это краткая запись диапазона IP-адресов. Например, блок CIDR 10.0.0.0/24 представляет все IP-адреса между 10.0.0.0 и 10.0.0.255. Блок CIDR 0.0.0.0/0 охватывает диапазон всех возможных IP-адресов, поэтому данная группа безопасности разрешает принимать на порте 8080 запросы с любого IP30.
Создания группы безопасности как таковой будет недостаточно. Нужно сделать так, чтобы сервер EC2 ее использовал. Для этого вы должны передать ее идентификатор аргументу vpc_security_group_ids ресурса aws_instance. Но сначала необходимо познакомиться с выражениями Terraform.
В Terraform выражением является все, что возвращает значение. Вы уже видели простейший тип выражений — литералы, такие как строки (например, "ami-0c55b159cbfafe1f0") и числа (скажем, 5). Terraform поддерживает много других разновидностей выражений, которые будут встречаться на страницах этой книги.
Особенно полезным типом выражений является ссылка, которая позволяет обращаться к значениям с других участков кода. Чтобы указать ID группы безопасности, нужно сослаться на атрибут ресурса с помощью такого синтаксиса:
<PROVIDER>_<TYPE>.<NAME>.<ATTRIBUTE>
PROVIDER — это имя провайдера (например, aws), TYPE — это тип ресурса (вроде security_group), NAME — имя этого ресурса (в нашем случае группа безопасности называется "instance"), а ATTRIBUTE — это либо один из аргументов ресурса (скажем, name), либо один из атрибутов, которые он экспортировал (список доступных атрибутов можно найти в документации каждого ресурса). Группа безопасности экспортирует атрибут под названием id, поэтому к нему можно обратиться с помощью такого выражения:
aws_security_group.instance.id
Вы можете использовать идентификатор этой группы безопасности в аргументе vpc_security_group_ids ресурса aws_instance:
resource "aws_instance" "example" {
ami = "ami-0c55b159cbfafe1f0"
instance_type = "t2.micro"
vpc_security_group_ids = [aws_security_group.instance.id]
user_data = <<-EOF
#!/bin/bash
echo "Hello, World" > index.html
nohup busybox httpd -f -p 8080 &
EOF
tags = {
Name = "terraform-example"
}
}
Ссылаясь в одном ресурсе на другой, вы создаете неявную зависимость. Terraform анализирует такие зависимости, строит из них граф и применяет его для автоматического определения порядка, в котором должны создаваться ресурсы. Например, если бы этот код развертывался с нуля, система Terraform знала бы о том, что группу безопасности нужно создать раньше, чем сервер EC2, поскольку последний использует ID этой группы. Вы можете даже вывести граф зависимостей с помощью команды graph:
$ terraform graph
digraph {
compound = "true"
newrank = "true"
subgraph "root" {
"[root] aws_instance.example"
[label = "aws_instance.example", shape = "box"]
"[root] aws_security_group.instance"
[label = "aws_security_group.instance", shape = "box"]
"[root] provider.aws"
[label = "provider.aws", shape = "diamond"]
"[root] aws_instance.example" ->
"[root] aws_security_group.instance"
"[root] aws_security_group.instance" ->
"[root] provider.aws"
"[root] meta.count-boundary (EachMode fixup)" ->
"[root] aws_instance.example"
"[root] provider.aws (close)" ->
"[root] aws_instance.example"
"[root] root" ->
"[root] meta.count-boundary (EachMode fixup)"
"[root] root" ->
"[root] provider.aws (close)"
}
}
Вывод выполнен на языке описания графов под названием DOT. Сам граф можно отобразить, как это сделано на рис. 2.7, с использованием настольного приложенияGraphviz или его веб-версии GraphvizOnline (bit.ly/2mPbxmg).
При прохождении по дереву зависимостей Terraform пытается как можно сильнее распараллелить создание ресурсов, что приводит к довольно эффективному применению изменений. В этом прелесть декларативного языка: вы просто описываете то, что вам нужно, а Terraform определяет наиболее эффективный способ реализации.
Рис. 2.7. Граф зависимостей для сервера EC2 и его группы безопасности
Выполнив команду apply, вы увидите, что Terraform хочет создать группу безопасности и заменить имеющийся сервер EC2 другим — с новыми пользовательскими данными:
$ terraform apply
(...)
Terraform will perform the following actions:
# aws_instance.example must be replaced
-/+ resource "aws_instance" "example" {
ami = "ami-0c55b159cbfafe1f0"