Модули Terraform#

Предупреждение

Terraform не является частью Astra Automation. Модули, размещенные в реестре Astra Automation Hub, со временем будут удалены.

Рассмотрим применение модулей Terraform из реестра Astra Automation Hub для развертывания базовой инфраструктуры в Yandex Cloud.

Описание сценария#

Рассматриваемый сценарий приводит к созданию инфраструктуры из следующих компонентов:

  • облачную сеть;

  • две ВМ под управлением Astra Linux Special Edition;

  • узел NAT.

    В данном примере для создания узла NAT используется образ NAT-инстанс из Yandex Cloud Marketplace.

Схема развертываемой инфраструктуры показана на рисунке:

Схема инфраструктуры Схема инфраструктуры

В этом сценарии выполните следующие операции:

  • Создайте одну облачную сеть с двумя облачными подсетями, размещенными в одной зоне доступности.

    Так как обе подсети принадлежат одной сети, трафик между ними может передаваться без использования публичных IP-адресов. Подробнее об устройстве облачных сетей и подсетей см. в документации Yandex Cloud.

  • В одной облачной подсети разместите ВМ vm-1 и vm-2, а в другой – узел NAT.

    Примечание

    Размещение узла NAT в отдельной подсети является требованием Yandex Cloud.

  • Настройте ВМ с помощью Cloud-Init, чтобы к ним можно было подключаться по SSH.

Процесс подготовки инфраструктуры состоит из следующих этапов:

  1. Создание конфигурационных файлов Terraform.

    Назначение файлов:

    • .terraformrc – настройки, позволяющие использовать копию (зеркало) репозитория Terraform, предоставляемую компанией Яндекс.

    • main.tf – описание создаваемых ресурсов;

    • metadata.yml – настройки ОС ВМ в формате Cloud-Init;

    • provider.tf – подключение и настройка провайдера Terraform для Yandex Cloud;

    • sa_key.json – пара авторизованных ключей сервисного аккаунта;

    • variables.tf – описания переменных;

    • terraform.tfvars – значения переменных.

    Подробности о типовой структуре проекта Terraform, используемой в документации Astra Automation, см. в документе Модули Terraform.

  2. Создание необходимых ресурсов в Yandex Cloud с помощью Terraform.

    Для запуска Terraform используется контейнер, описанный в документе Среда исполнения.

    Сетевые ресурсы:

    • Сеть example-network, состоящая из двух подсетей:

      • example-nat-subnet – подсеть 192.168.0.0/24 для размещения узла NAT;

      • example-ru-central1-a-0 – подсеть 10.131.0.0/24 для размещения ВМ.

      Обе подсети должны находиться в одной зоне доступности ru-central1-a.

    • Таблица маршрутизации, обеспечивающая прохождение трафика из интернета в облачные подсети.

    • Служебные DNS-зоны, необходимые для корректной работы облачной сети и маршрутизации.

    Виртуальные машины:

    Название ВМ

    Количество vCPU

    Доля vCPU

    Объем RAM, ГБ

    Размер диска, ГБ

    ОС

    example-nat-instance

    2

    100 %

    2

    12

    Ubuntu 18.04 LTS

    vm-1

    2

    50 %

    4

    30

    Astra Linux Special Edition 1.7.3

    vm-2

    2

    50 %

    4

    30

    Astra Linux Special Edition 1.7.3

    На каждой ВМ создается учетная запись administrator, от имени которой к ВМ можно будет подключиться по SSH.

Подготовка к работе#

Подготовьте рабочее окружение:

  1. Изучите описание модулей Terraform из реестра Astra Automation Hub:

  2. Подготовьте управляющий узел к работе с реестром Astra Automation Hub и стендом согласно инструкции.

  3. Создайте каталог для хранения файлов проекта, например:

    mkdir aa-tf-yc/
    

    Примечание

    Далее этот каталог будет называться каталогом проекта. Все упомянутые ниже файлы следует создавать в этом каталоге, если явно не указано иное.

  4. Согласно инструкции создайте пару ключей SSH, которая будет использоваться для подключения к ВМ. Сохраните их в каталоге проекта под именами deployment и deployment.pub соответственно.

  5. Получите идентификаторы образов Astra Linux Special Edition, доступных в Yandex Cloud Marketplace:

    yc compute image list --folder-id standard-images | grep astra
    

    В терминал выводится таблица следующего вида:

    | fd81pgsokk5vtjm1qgie | astralinux-alse-v20221221 | astralinux-alse | f2eni8mvsjeqmflq62qq | READY  |
    | fd87qct47l4isk56gucq | astralinux-alse-v20230215 | astralinux-alse | f2esbkvqjcg1kk3i29ra | READY  |
    

    Идентификаторы образов указаны в первой колонке.

  6. Получите идентификатор используемого облака:

    yc resource-manager cloud list
    

    В терминал выводится таблица следующего вида:

    +----------------------+------------+----------------------+
    |          ID          |    NAME    |   ORGANIZATION ID    |
    +----------------------+------------+----------------------+
    | b1................f4 | rbta-cloud | bp................f4 |
    +----------------------+------------+----------------------+
    

    Идентификатор облака указан в колонке ID.

  7. Получите идентификатор используемого каталога:

    yc resource-manager folder list
    

    В терминал выводится таблица следующего вида:

    +----------------------+---------------------------+--------+--------+
    |          ID          |           NAME            | LABELS | STATUS |
    +----------------------+---------------------------+--------+--------+
    | b1................bv | td.....................it |        | ACTIVE |
    +----------------------+---------------------------+--------+--------+
    

    Идентификатор каталога указан в колонке ID.

  8. В каталоге проекта разместите файл sa_key.json, содержащий пару авторизованных ключей сервисного аккаунта.

    Если у вас нет пары авторизованных ключей сервисного аккаунта, для их создания выполните инструкции из секции Создание пары авторизованных ключей доступа.

  9. Создайте в каталоге проекта файл metadata.yml с описанием настроек ОС на создаваемых ВМ.

    #cloud-config
    ---
    users:
      - name: administrator
        groups: sudo
        shell: /bin/bash
        sudo: ["ALL=(ALL) NOPASSWD:ALL"]
        ssh-authorized-keys:
          - INSERT_PUBLIC_KEY_HERE
    

    Здесь:

    Параметр

    Значение

    Описание

    name

    administrator

    Имя учетной записи

    groups

    sudo

    Список дополнительных групп, в которые должна быть включена созданная учетная запись

    shell

    /bin/bash

    Оболочка пользователя по умолчанию

    sudo

    ["ALL=(ALL) NOPASSWD:ALL"]

    Разрешение всем пользователям на выполнение с sudo любых команд без ввода паролям

    ssh-authorized-keys

    Список публичных ключей SSH, используемых для подключения к ВМ. Укажите в значении этого поля содержимое файла deployment.pub.

    Указанный публичный ключ будет автоматически добавлен в файл /home/administrator/.ssh/authorized_keys, что обеспечит возможность подключения к ВМ по SSH.

Подготовка файлов Terraform#

Для подготовки файлов Terraform выполните следующие действия:

  1. Создайте файл variables.tf со следующим содержимым:

    variable "service_account_key_file" {
      description = "Service account key file"
      type        = string
      default     = "/app/sa_key.json"
    }
    
    variable "cloud_id" {
      description = "Cloud ID"
      type        = string
    }
    
    variable "folder_id" {
      description = "ID of the folder"
      type        = string
    }
    
    variable "image_id" {
      description = "Image ID"
      type        = string
    }
    
    variable "name" {
      description = "Name to be used on all the resources as identifier"
      type        = string
      default     = "yc-tf"
      validation {
        condition     = length(var.name) <= 32
        error_message = "Must be a 32 or less character long string."
      }
    }
    
    variable "subnets" {
      description = "Subnets in folder"
      type = list(object({
        name           = optional(string)
        zone           = optional(string, "ru-central1-a")
        v4_cidr_blocks = list(string)
      }))
    }
    

    В этом файле находятся описания переменных, которые используются в плане инфраструктуры.

    Предупреждение

    Не изменяйте файл variables.tf! Для присвоения переменным фактических значений укажите их в файле terraform.tfvars.

    Список переменных в файле variables.tf:

    Переменная

    Тип

    Значение по умолчанию

    Описание

    service_account_key_file

    string

    /app/sa_key.json

    Путь к файлу с парой авторизованных ключей сервисного аккаунта. Поскольку используется контейнер EE, путь указывается относительно каталога /app внутри него

    cloud_id

    string

    Идентификатор облака Yandex Cloud

    folder_id

    string

    Идентификатор облачного каталога

    image_id

    string

    Идентификатор образа, используемого при создании ВМ

    name

    string

    yc-tf

    Префикс, добавляемый к именам создаваемых ресурсов. Требования – длина не более 32 знаков

    subnets

    Запись

    Параметры создаваемых подсетей

    Поля записи, используемой для переменной subnets:

    Имя поля

    Тип

    Описание

    name

    string

    Имя подсети, опциональный параметр

    zone

    string

    Зона доступности

    v4_cidr_blocks

    string

    Строка, задающая диапазон IP-адресов подсети.

    Подробное описание переменных см. в документации Terraform.

  2. Создайте файл terraform.tfvars со следующим содержимым:

    cloud_id  = "" # Set your cloud ID
    folder_id = "" # Set your folder ID
    image_id  = "" # Set Astra Linux Image ID
    subnets = [
      {
        zone           = "ru-central1-a"
        v4_cidr_blocks = ["10.131.0.0/24"]
      }
    ]
    
  3. Создайте файл .terraformrc со следующим содержимым:

    provider_installation {
      network_mirror {
        url     = "https://terraform-mirror.yandexcloud.net/"
        include = ["registry.terraform.io/*/*"]
      }
      direct {
        exclude = ["registry.terraform.io/*/*"]
      }
    }
    

    Здесь указаны настройки Terraform, позволяющие использовать для загрузки провайдера Yandex Cloud реестр компании Яндекс вместо реестра компании HashiCorp.

  4. Создайте файл provider.tf со следующим содержимым:

    terraform {
      required_providers {
        yandex = {
          source = "yandex-cloud/yandex"
        }
      }
      required_version = ">= 0.13"
    }
    
    provider "yandex" {
      service_account_key_file = pathexpand(var.service_account_key_file)
      cloud_id                 = var.cloud_id
      folder_id                = var.folder_id
    }
    

    Этот файл содержит описание провайдера Terraform, необходимого для работы с Yandex Cloud. Идентификаторы облака и облачного каталога, а также путь к файлу с авторизованным ключом сервисного аккаунта указаны в переменных cloud_id, folder_id и service_account_key_file соответственно.

  5. Создайте файл main.tf со следующим содержимым:

    module "vpc" {
      source              = "git::ssh://git@hub.astra-automation.ru:2222/aa-gca/AMFT/yandex-cloud-vpc.git"
      name                = "example"
      folder_id           = var.folder_id
      create_nat_instance = true
      subnets             = var.subnets
      metadata            = file("./metadata.yml")
    }
    
    module "vm" {
      count = 2
    
      source                  = "git::ssh://git@hub.astra-automation.ru:2222/aa-gca/AMFT/yandex-cloud-compute-instance.git"
      folder_id               = var.folder_id
      name                    = "vm-${count.index + 1}"
      image_id                = var.image_id
      resources_cpu           = 2
      resources_core_fraction = 50
      resources_ram           = 4
      boot_disk_size          = 30
      boot_disk_type          = "network-ssd"
      nat                     = false
      nat_ip_address          = null
      description             = "Created with Terraform"
      labels                  = {}
      metadata                = file("./metadata.yml")
      network_interfaces = [{
        subnet_id = module.vpc.subnet_ids[0]
      }]
    }
    

    Этот файл содержит описание инфраструктуры, создаваемой в Yandex Cloud с использованием модулей yandex-cloud-vpc и yandex-cloud-compute-instance из реестра Astra Automation Hub.

    Первым идет описание модуля vpc, задающего настройки создаваемых сети, подсетей и узла NAT:

    module "vpc" {
      source              = "git::ssh://git@hub.astra-automation.ru:2222/aa-gca/AMFT/yandex-cloud-vpc.git"
      name                = "vpc"
      folder_id           = var.folder_id
      create_nat_instance = true
      subnets             = var.subnets
      metadata            = file("./metadata.yml")
    }
    

    Здесь:

    • source – источник, используемый для загрузки файлов модуля. В данном случае указана ссылка для загрузки из Git-репозитория Astra Automation Hub с использованием протокола SSH.

    • name – префикс, используемый при создании ресурсов с помощью этого модуля.

    • folder_id – идентификатор облачного каталога. Используется значение переменной folder_id.

    • create_nat_instance – создание узла NAT.

      В данном случае указано значение true, а значит, будут автоматически созданы узел NAT и необходимые для его работы ресурсы:

      • отдельная подсеть;

      • таблица маршрутизации, перенаправляющая трафик из vm-1 и vm-2 через узел NAT в интернет.

    • subnets – параметры создаваемых облачных подсетей.

      Используется значение переменной subnets.

    • metadata – при создании ВМ для узла NAT к ней будут применены настройки, указанные в файле metadata.yml. Это необходимо для того, чтобы к узлу NAT можно было подключаться из интернета, используя ключи SSH.

      Предупреждение

      Настройки из этого файла будут применены только один раз – при первом запуске ВМ. Если файл содержит ошибки, и ВМ создана не с теми настройками, которые необходимы, удалите ее и создайте заново.

    В этом блоке идет описание модуля vm, задающего настройки ВМ vm-1 и vm-2:

    module "vm" {
      count = 2
    
      source                  = "git::ssh://git@hub.astra-automation.ru:2222/aa-gca/AMFT/yandex-cloud-compute-instance.git"
      folder_id               = var.folder_id
      name                    = "vm-${count.index + 1}"
      image_id                = var.image_id
      resources_cpu           = 2
      resources_core_fraction = 50
      resources_ram           = 4
      boot_disk_size          = 30
      boot_disk_type          = "network-ssd"
      nat                     = false
      nat_ip_address          = null
      description             = "Created with Terraform"
      labels                  = {}
      metadata                = file("./metadata.yml")
      network_interfaces = [{
        subnet_id = module.vpc.subnet_ids[0]
      }]
    }
    

    Здесь:

    • count – мета-аргумент, задающий количество создаваемых ресурсов данного типа.

    • source – источник, используемый для загрузки файлов модуля. В данном случае указана ссылка для загрузки из Git-репозитория Astra Automation Hub с использованием протокола SSH.

    • folder_id – идентификатор облачного каталога. Используется значение переменной folder_id.

    • name – название ВМ. Так как значения мета-аргумента count начинаются с 0, для создания ВМ с именами vm-1 и vm-2 к значению count нужно прибавить единицу.

    • image_id – идентификатор образа, используемого для создания ВМ. Используется значение, указанное в переменной image_id.

    • resources_cpu – количество ядер vCPU.

    • resources_core_fraction – доля доступности vCPU, в процентах.

    • resources_ram – количество RAM, ГБ.

    • boot_disk_size – размер загрузочного диска ВМ, ГБ.

    • boot_disk_type – тип загрузочного диска ВМ.

      Подробности о типах дисков см. в документации Yandex Cloud.

    • nat – использование NAT для предоставления ВМ доступа в интернет.

    • nat_ip_address – IP-адрес для NAT-шлюза. Поскольку обе ВМ используют для доступа к интернету узел NAT, для этого параметра задано значение null.

    • description – описание ВМ.

    • labels – метки ресурса. В данном случае обеим ВМ не присваивается никаких меток.

    • metadata – путь к файлу с настройками ОС ВМ в формате Cloud-Init. Указан путь к созданному ранее файлу metadata.yml.

    • network_interfaces – параметры сетевых интерфейсов создаваемой ВМ. Каждая ВМ создается с одним сетевым интерфейсом в первой подсети, созданной модулем vpc.

Развертывание инфраструктуры#

Для выполнения описанных далее шагов используется Execution Environment.

  1. Выполните команду инициализации проекта Terraform:

    docker run \
       --rm \
       --interactive \
       --tty \
       --volume ~/.ssh/hub.astra-linux.ru:/root/.ssh/id_rsa \
       --volume "$(pwd)/.terraformrc:/root/.terraformrc" \
       --volume "$(pwd):/app/" \
       registry.astralinux.ru/aa-base-ee:latest \
       bash -c "terraform init"
    

    Здесь:

    • ~/.ssh/hub.astra-linux.ru – путь к файлу приватного ключа SSH, используемого для доступа к Astra Automation Hub.

    • $(pwd) – команда для определения абсолютного пути к каталогу проекта.

    В терминал выводится предупреждение о подключении к узлу hub.astra-automation.ru.

    Пример сообщения
    Initializing modules...
    Downloading git::ssh://git@hub.astra-automation.ru:2222/aa-gca/AMFT/yandex-cloud-compute-instance.git for vm...
    The authenticity of host '[hub.astra-automation.ru]:2222 ([84.201.175.30]:2222)' can't be established.
    ECDSA key fingerprint is SHA256:bvbETX8oC4ZwFtiE30SCN6yOQxRyOjgGO+lq2U2Dy00.
    Are you sure you want to continue connecting (yes/no)?
    

    Введите значение yes и нажмите Enter.

    Если приватный ключ для доступа к реестру Astra Automation Hub защищен паролем, будет выведен запрос на его ввод:

    Enter passphrase for key '/root/.ssh/id_rsa':
    

    Введите пароль и нажмите Enter.

  2. Дождитесь загрузки модулей и файлов провайдера.

    В процессе загрузки в каталоге проекта создается подкаталог .terraform/, а в терминал выводится сообщение.

    Пример сообщения
    - vm in .terraform/modules/vm
    - vpc in .terraform/modules/vpc
    
    Initializing the backend...
    
    Initializing provider plugins...
    - Reusing previous version of yandex-cloud/yandex from the dependency lock file
    - Installing yandex-cloud/yandex v0.97.0...
    - Installed yandex-cloud/yandex v0.97.0 (unauthenticated)
    
    Terraform has been successfully initialized!
    
    You may now begin working with Terraform. Try running "terraform plan" to see
    any changes that are required for your infrastructure. All Terraform commands
    should now work.
    
    If you ever set or change modules or backend configuration for Terraform,
    rerun this command to reinitialize your working directory. If you forget, other
    commands will detect it and remind you to do so if necessary.
    
  3. Для проверки конфигурационных файлов Terraform выполните команду:

    docker run \
       --rm \
       --tty \
       --volume "$(pwd):/app/" \
       registry.astralinux.ru/aa-base-ee:latest \
       bash -c "terraform validate"
    

    Если в конфигурации нет ошибок, выводится сообщение:

    Success! The configuration is valid.
    

    При наличии ошибок в терминал выводится сообщение с описанием первой из них и указанием на место ее расположения.

  4. Для создания ресурсов в Yandex Cloud выполните команду:

    docker run \
       --rm \
       --tty \
       --volume ~/.ssh/hub.astra-linux.ru:/root/.ssh/id_rsa \
       --volume "$(pwd)/.terraformrc:/root/.terraformrc" \
       --volume "$(pwd):/app/" \
       registry.astralinux.ru/aa-base-ee:latest \
       bash -c "terraform apply -auto-approve"
    

    Примечание

    Дополнительный параметр -auto-approve избавляет от необходимости подтверждать выполняемые действия.

    Дождитесь завершения создания ресурсов. О завершении создания ресурсов свидетельствует строка вида:

    Apply complete! Resources: 8 added, 0 changed, 0 destroyed.
    
  5. Для завершения работы контейнера EE выполните команду:

    exit
    

Проверка работоспособности развернутой инфраструктуры#

Чтобы проверить корректность развертывания инфраструктуры, выполните следующие действия:

  1. Получите список ВМ в своем каталоге:

    yc compute instance list
    

    В терминал будет выведена таблица вида:

    +----------------------+----------------------+---------------+---------+----------------+--------------+
    |          ID          |         NAME         |    ZONE ID    | STATUS  |  EXTERNAL IP   | INTERNAL IP  |
    +----------------------+----------------------+---------------+---------+----------------+--------------+
    | fhmaruuj14ljbe8duobg | example-nat-instance | ru-central1-a | RUNNING | 158.160.38.156 | 192.168.0.3  |
    | fhmoj4t896ei2ti10o7e | vm-1                 | ru-central1-a | RUNNING |                | 10.131.0.101 |
    | fhma2ollfugoob6j9m2a | vm-2                 | ru-central1-a | RUNNING |                | 10.131.0.102 |
    +----------------------+----------------------+---------------+---------+----------------+--------------+
    

    где:

    • ID – идентификатор ВМ.

    • NAME – название ВМ.

    • ZONE ID – идентификатор зоны доступности.

    • STATUS – состояние ВМ. Значение RUNNING указывает на то, что ВМ запущена и работает.

    • EXTERNAL IP – публичный IP-адрес ВМ. Присвоен только узлу NAT.

    • INTERNAL IP – IP-адрес ВМ из диапазона соответствующей подсети.

  2. Чтобы подключиться к ВМ vm-1 или vm-2 выполните команду:

    ssh -J <nat_user>@<nat_IP> <vm_user>@<vm_IP>
    

    Где:

    • -J – аргумент, указывающий на то, что первый узел будет использоваться в качестве промежуточного (Jump host);

    • <nat_user> – название учетной записи пользователя узла NAT;

    • <nat_IP> – публичный IP-адрес узла NAT;

    • <vm_user> – название учетной записи пользователя ВМ;

    • <vm_IP> – внутренний IP-адрес ВМ.

    Например, чтобы подключиться к vm-1 из таблицы выше, выполните команду:

    ssh -J administrator@158.160.38.156 administrator@10.131.0.101
    

    При первом подключении к каждой ВМ выводится сообщение о неизвестном отпечатке ключа.

    Подтверждение подключения по SSH
    The authenticity of host '158.160.47.217 (158.160.47.217)' can't be established.
    ED25519 key fingerprint is SHA256:AJiqY0YTT9c60qsiSJX3bbLRXWAlto//aat94tB9gg4.
    This key is not known by any other names.
    Are you sure you want to continue connecting (yes/no/[fingerprint])?
    

    Введите yes и нажмите Enter.

    При успешном подключении к нужной ВМ меняется приглашение командной строки:

    administrator@vm-1:~$
    
  3. Чтобы убедиться, что ВМ работает под управлением ОС Astra Linux Special Edition, выполните команду:

    cat /etc/astra_version
    

    Она выводит в терминал номер версии ОС.

  4. Для отключения от ВМ выполните команду:

    exit
    

Освобождение ресурсов#

Если созданные ресурсы больше не нужны, для их удаления выполните команду:

docker run \
   --rm \
   --volume "$(pwd)/.terraformrc:/root/.terraformrc" \
   --volume "$(pwd):/app/" \
   registry.astralinux.ru/aa-base-ee:latest \
   bash -c "terraform destroy -auto-approve"

Особенности проекта#

Обратите внимание на следующие особенности проекта:

  • Использование конфигурационного файла .terraformrc для загрузки провайдера Terraform для Yandex Cloud с использованием ресурсов компании Яндекс.

  • Порядок подключения и использования модулей из реестра Astra Automation Hub.

  • Параметры, передаваемые в EE при запуске Terraform.

  • Настройка ОС создаваемых ВМ с помощью конфигурационного файла metadata.yml.

  • Автоматическое создание подсети и таблицы маршрутизации, необходимых для корректной работы узла NAT.

Заключение#

В этом сценарии вы познакомились с основными шагами по использованию модулей Terraform из реестра Astra Automation Hub. Из всей последовательности шагов важно выделить следующие действия:

  • Подготовка окружения.

  • Описание и использование модулей в конфигурационных файлах Terraform.

  • Использование файла с переменными.

  • Запуск Terraform с помощью EE.

  • Проверка корректности развертывания инфраструктуры.