Выбрать главу

    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"

полную версию книги