В этом разделе мы на примерах покажем, как развернуть простую инфраструктуру в облаке Сервер Молл Cloud, создадим инстансы, назначим им плавающие (внешние) IP, создадим и подключим к ним дополнительные диски.
Предварительные требования
- Учетная запись Сервер Молл Cloud.
У вас должна быть зарегистрирована учётная запись в личном кабинете Сервер Молл Cloud. Подробности в руководстве: “Регистрация аккаунта”. - Подключена услуга “Облачная инфраструктура”.
Услуга “Облачная инфраструктура” должна быть заказана и готова к работе. Как получить услугу, см. в инструкции ”Как заказать облачную инфраструктуру”. - Terraform установлен.
На компьютере должен быть установлен Terraform. Чтобы проверить, установлен ли он, выполните команду: terraform version. Если Terraform установлен, команда выведет его версию. В противном случае установите его по инструкции “Установка Terraform”. - Настроена авторизация Terraform в облаке.
Создайте конфигурационный файл и настройте авторизацию Terraform в облаке Сервер Молл Cloud по инструкции: “Аутентификация в облачной инфраструктуре через Terraform”.
Перед тем, как начать
В процессе создания конфигурации вам могут понадобиться данные о необходимых ресурсах и параметрах. Получить их можно через панель управления облачной инфраструктурой (облачная консоль) или с помощью CLI:
- Инструкция по входу в облачную консоль – “Вход в панель управления облачной инфраструктурой“.
- Список команд CLI для сбора сведений о ресурсах проекта –“Команды CLI для сбора сведений о ресурсах проекта”.
Важно: во всех примерах конфигурации заменяйте шаблонные значения (плейсхолдеры) в угловых скобках <…> на реальные параметры вашего проекта без самих скобок:
- Строковое значение:
# Исходный шаблон из примера instance_id = "<instance_id>" # После замены — конкретное значение в кавычках instance_id = "45fb7597-50db-4a39-b0f2-b6ce2eca773a" - Ссылка на Terraform-ресурс или переменную:
# Исходный шаблон из примера instance_id = "<instance_id>" # После замены — ссылка на ресурс, без кавычек instance_id = openstack_compute_instance_v2.tf_instance_1.id - Числовое значение:
# Исходный шаблон из примера volume_size = <volume_size_in_gb> # После замены — просто число, без кавычек volume_size = 30
Для более глубокого изучения настройки OpenStack Provider в Terraform вы можете обратиться к официальной документации HashiCorp, доступной на их официальном сайте по ссылке.
I. Создание инстанса через Terraform
В этом разделе мы рассмотрим создание одного и нескольких инстансов в облачной инфраструктуре Сервер Молл Cloud через Terraform. Мы покажем как создать инстанс, дополнив файл конфигурации Terraform, который мы создали, когда настраивали авторизацию Terraform в облаке, согласно инструкции: “Аутентификация в облачной инфраструктуре через Terraform”.
Создание одного инстанса
- Добавьте в файл конфигурации блок создания инстанса:
# Блок создания одного инстанса в OpenStack через Terraform resource "openstack_compute_instance_v2" "tf_instance_1" { name = "<instance_name>" # Имя создаваемого инстанса image_id = "<os_image_id>" # Идентификатор используемого образа ОС flavor_id = "<instance_flavor_id>" # Тип инстанса (определяет ресурсы CPU, RAM) key_pair = "<key_pair_name>" # Имя ключевой пары для SSH-доступа security_groups = ["default"] # Список групп безопасности, применяемых к инстансу # Подключение файла с пользовательскими данными (cloud-init) user_data = file("${path.module}/<cloud-init.yaml>") # Путь к cloud-init YAML-файлу # Блок настройки основного (загрузочного) диска инстанса block_device { uuid = "<os_image_id>" # Идентификатор образа, используемого для создания диска source_type = "image" # Тип источника данных для создания диска (образ) destination_type = "volume" # Назначение (создание диска-тома) volume_size = <volume_size_in_gb> # Размер создаваемого диска в гигабайтах volume_type = "<volume_type_id>" # Тип дискового хранилища boot_index = 0 # Порядок загрузки (0 — основной загрузочный диск) delete_on_termination = true # Удалять диск после удаления инстанса } # Блок сетевых настроек подключения инстанса network { uuid = "<network_id>" # Идентификатор сети, к которой подключается инстанс } }
- Замените значения-заполнители в угловых скобках <...> на реальные значения вашего проекта, исключая сами скобки, для следующих параметров:
- name — Уникальное имя инстанса (в рамках проекта).
- image_id — идентификатор образа операционной системы.
Узнать id образа доступные проекту можно, через облачную консоль ("Compute" > "Images" в поле "ID/Name") или через CLI (openstack image list). - flavor_id — идентификатор конфигурации инстанса, определяющий ресурсы (CPU, RAM). Узнать доступные id конфигураций можно через облачную консоль ("Compute" > "Flavors" в поле "ID/Name") или CLI (openstack flavor list).
- key_pair — имя существующей ключевой пары для SSH-подключения. Узнать доступные имена ключевых пар можно через облачную консоль ("Compute" > "Key Pairs" в поле "Name") или CLI (openstack keypair list). Если ключевой пары ещё нет, создайте её по инструкции «Создание ключевой пары».
- user_data — путь к файлу с пользовательскими данными (cloud-init или Ignition), который используется для автоматической настройки инстанса при его первом запуске.
Важно: Обязательно используйте пользовательские данные для автоматической настройки — как минимум для создания пользователя, назначения прав доступа и установки пароля. Без этого вы можете не получить доступ к инстансу для управления им.
Рекомендуется: Использовать относительный путь, основанный на переменной "
${path.module}" — она возвращает путь к директории, где находится текущий .tf-файл. Это делает конфигурацию переносимой и надёжной в разных окружениях.
Пример указания пути к файлу пользовательских данных:user_data = file("${path.module}/cloud-init.yaml")
Не рекомендуется: Указывать абсолютный путь, так как он жёстко привязан к конкретной системе и может не работать при переносе конфигурации, например:user_data = file("/home/user/project/cloud-init.yaml") # Linux/macOS user_data = file("C:/Users/admin/project/cloud-init.yaml") # Window
Примечание: Для указания пути в Windows рекомендуется использовать прямые слэши (/) в пути. Обратные слэши (\) требуют двойного экранирования (\\) и могут привести к ошибкам.
- name — Уникальное имя инстанса (в рамках проекта).
- uuid (block_device) — идентификатор образа, указанный в поле “image_id”.
- volume_size — размер создаваемого диска в гигабайтах, вводится целым числом (например, 30).
- volume_type — id типа диска:
- 25c82f52-dc3b-4337-a939-a73ec1a58d2a — Hybrid-Datastore.
- a462fa3a-8e23-492c-97bd-d493b1a8d0a4 — All-Flash-Datastore.
Доступные id типов диска можно узнать через CLI (openstack volume type list).
- uuid (network) — идентификатор внутренней сети, к которой будет подключён инстанс. Узнать его можно через облачную консоль ("Network" > "Networks" > "Current Project Networks" в поле "ID/Name") или CLI (openstack network list --internal).
"tf_instance_1" — это наименование инстанса внутри конфигурации Terraform, его вы можете произвольно изменить. Однако все упоминания инстанса должны совпадать, например, при создании инстанса, подключении дополнительного диска или плавающего IP-адреса.
Поля "security_groups", "source_type", "destination_type", "boot_index" и “delete_on_termination” не требуют изменений.
Когда изменения внесены, этот блок может выглядеть так:# Блок создания одного инстанса в OpenStack через Terraform resource "openstack_compute_instance_v2" "tf_instance_1" { name = "test_instance" # Имя создаваемого инстанса image_id = "os_image_id45fb7597-50db-4a39-b0f2-b6ce2eca773a" # Идентификатор используемого образа ОС flavor_id = "07050101-11d1-4916-a31d-153405676deb" # Тип инстанса (определяет ресурсы CPU, RAM) key_pair = "test_key_pair" # Имя ключевой пары для SSH-доступа security_groups = ["default"] # Список групп безопасности, применяемых к инстансу # Подключение файла с пользовательскими данными (cloud-init) user_data = file("${path.module}/cloud-init.yaml") # Путь к cloud-init YAML-файлу # Блок настройки основного (загрузочного) диска инстанса block_device { uuid = "45fb7597-50db-4a39-b0f2-b6ce2eca773a" # Идентификатор образа, используемого для создания диска source_type = "image" # Тип источника данных для создания диска (образ) destination_type = "volume" # Назначение (создание диска-тома) volume_size = 30 # Размер создаваемого диска в гигабайтах volume_type = "a462fa3a-8e23-492c-97bd-d493b1a8d0a4" # Тип дискового хранилища boot_index = 0 # Порядок загрузки (0 — основной загрузочный диск) delete_on_termination = true # Удалять диск после удаления инстанса } # Блок сетевых настроек подключения инстанса network { uuid = "7c63ba21-958b-4856-b1da-764ed077b4df" # Идентификатор сети, к которой подключается инстанс } }
- Сохраните изменения в файле.
Создание нескольких инстансов
Вы можете создать сразу группу из нескольких инстансов с идентичными или различными характеристиками. Основное отличие от создания одного инстанса — наличие в блоке параметра "count", указывающего количество создаваемых инстансов. Параметры инстансов могут быть заданы как единым значением для всех инстансов группы, так и в виде списков в отдельном блоке локальных переменных "locals", для каждого инстанса индивидуально. Также возможно использовать динамические значения параметров, например, добавляя порядковый номер к имени каждого инстанса, как это показано в примере ниже, в параметре “name”.
При создании нескольких инстансов имя ресурса (например, "tf_instances" из примера, приведенного ниже), используемое Terraform, является именем группы. Это имя группы мы будем использовать далее при подключении дополнительных дисков или плавающих IP-адресов.
- Добавьте в файл конфигурации следующего блока создания инстансов:
# Блок локальных переменных, укажите свои значения списком или единичным значением locals { image_ids = ["<image-id-1>", "<image-id-2>", ..., "<image-id-n>"] # Вставьте свои id образов volume_sizes = [<vol-size-1>, <vol-size-2>, ..., <vol-size-n>] # Вставьте размеры дисков (числами) flavor_ids = ["<flavor-id-1>", "<flavor-id-2>", ..., "<flavor-id-n>"] # Вставьте свои id flavor (типов инстансов) volume_types = ["<volume-type-id-1>", "<volume-type-id-2>", ..., "<volume-type-id-n>"] # Вставьте свои типы дисков key_pair = "<my-single-keypair>" # Вставьте имя своей ключевой пары user_data_files = ["${path.module}/<cloud-init-1.yaml>", "${path.module}/<cloud-init-2.yaml>", ..., "${path.module}/<cloud-init-n.yaml>"] # Пути к cloud-init файлам } # Блок создания нескольких инстансов resource "openstack_compute_instance_v2" "tf_instances" { count = length(local.image_ids) # Количество инстансов равно количеству образов (image_ids) в списке из locals. name = "instance-${count.index + 1}" # Автоматическое присвоение имени инстанса с номером image_id = local.image_ids[count.index] # id образа из списка flavor_id = local.flavor_ids[count.index] # id flavor из списка key_pair = local.key_pair # Ключевая пара (единая для всех) user_data = file(local.user_data_files[count.index]) # Индивидуальный файл пользовательских данных security_groups = ["default"] # Группа безопасности единая для всех) # Блок создания загрузочного диска block_device { uuid = local.image_ids[count.index] # id образа ОС (должен совпадать с image_id) source_type = "image" # Тип источника данных destination_type = "volume" # Назначение (диск) volume_size = local.volume_sizes[count.index] # Размер диска volume_type = local.volume_types[count.index] # Тип диска boot_index = 0 # Индекс загрузочного диска delete_on_termination = true # Удалять при удалении инстанса } # Сетевая конфигурация network { uuid = "<network-id>" # Вставьте id своей сети } }
- Измените этот блок в соответствии с вашими потребностями и внесите свои данные, изменив следующие поля и разделы:
- locals — блок локальных переменных. Здесь указываются списки параметров или единичные значения, используемые для всех инстансов. Обращение к элементу списка осуществляется через locals.<имя_параметра>[<индекс>], например, flavor_id = local.flavor_ids[count.index] (для списка) или key_pair = local.key_pair (для единичного значения).
- count — количество создаваемых инстансов. Можно задать целым числом или вычислить на основе длины списка параметров, например, count = length(local.image_ids).
- name — уникальное имя инстанса. Может задаваться динамически (например, name = "My-instance-${count.index + 1}") или списком в “locals”.
- image_id — идентификатор образа ОС, доступный из облачной консоли ("Compute" > "Images" в поле "ID/Name") или CLI (openstack image list).
- flavor_id — идентификатор конфигурации ресурсов (CPU, RAM), доступный через облачную консоль ("Compute" > "Flavors" в поле "ID/Name") или CLI (openstack flavor list)
- key_pair — имя существующей ключевой пары, доступно через облачную консоль ("Compute" > "Key Pairs" в поле "Name") или CLI (openstack keypair list).
- user_data — путь к файлу с пользовательскими данными (cloud-init или Ignition), который используется для автоматической настройки инстанса при его первом запуске. Если требуется индивидуальная настройка каждого инстанса, пути к файлам можно указать списком в разделе "locals".
Подробнее о том, как задать путь к файлу пользовательских данных, см. в разделе выше: “Создание одного инстанса”. - uuid (шт block_device) — должен совпадать с “image_id”.
- volume_size — размер диска в ГБ, может задаваться числом или списком в “locals”.
- volume_type — id типа диска:
- 25c82f52-dc3b-4337-a939-a73ec1a58d2a — Hybrid-Datastore.
- a462fa3a-8e23-492c-97bd-d493b1a8d0a4 — All-Flash-Datastore.
id типа диска доступен через CLI (openstack volume type list).
- uuid (network) — идентификатор сети, доступный через облачную консоль ("Network" > "Networks" > "Current Project Networks" в поле "ID/Name") или CLI (openstack network list --internal).
Поля “security_groups”, “source_type”, “destination_type”, “boot_index” и “delete_on_termination” также могут быть заданы единичными значениями или списками для каждого инстанса группы.
Когда изменения внесены, этот блок может выглядеть, например, так:
| # Блок локальных переменныхlocals { image_ids = ["5890aa4d-05a2-4a58-a23b-bd7affc72770", "45fb7597-50db-4a39-b0f2-b6ce2eca773a", "5890aa4d-05a2-4a58-a23b-bd7affc72770"] # id образов volume_sizes = [30, 40, 30] # Размеры дисков (числами) flavor_ids = ["07050101-11d1-4916-a31d-153405676deb", "2dadfd90-dd24-411b-b4ae-94da79404886", "07050101-11d1-4916-a31d-153405676deb"] # id flavor (типов инстансов) volume_types = ["25c82f52-dc3b-4337-a939-a73ec1a58d2a", "a462fa3a-8e23-492c-97bd-d493b1a8d0a4", "25c82f52-dc3b-4337-a939-a73ec1a58d2a"] # Типы дисков key_pair = "test-keypair" # Вставьте имя своей ключевой пары user_data_files = [ # Пути к cloud-init файлам "${path.module}/cloud-init-1.yaml", "${path.module}/cloud-init-2.yaml", "${path.module}/cloud-init-3.yaml" ]} # Блок создания нескольких инстансовresource "openstack_compute_instance_v2" "tf_instances" { count = length(local.image_ids) # Количество инстансов равно количеству образов (image_ids) в списке из locals. name = "My-instance-${count.index + 1}" # Автоматическое присвоение имени инстанса с номером image_id = local.image_ids[count.index] # id образа из списка flavor_id = local.flavor_ids[count.index] # id flavor из списка key_pair = local.key_pair # Ключевая пара (единая для всех) user_data = file(local.user_data_files[count.index]) # Индивидуальный cloud-init файл для каждого инстанса security_groups = ["default"] # Группа безопасности (единая для всех) # Блок создания загрузочного диска block_device { uuid = local.image_ids[count.index] # id образа ОС (должен совпадать с image_id) source_type = "image" # Тип источника данных destination_type = "volume" # Назначение (диск) volume_size = local.volume_sizes[count.index] # Размер диска volume_type = local.volume_types[count.index] # Тип диска boot_index = 0 # Индекс загрузочного диска delete_on_termination = true # Удалять при удалении инстанса } # Сетевая конфигурация network { uuid = "7c63ba21-958b-4856-b1da-764ed077b4df" # id внутренней сети проекта }} |
- Сохраните изменения в файле.
II. Выделение инстансу плавающего IP
При создании инстанса в OpenStack ему автоматически назначается внутренний IP-адрес для связи внутри облачной инфраструктуры. Однако для доступа к инстансу из интернета требуется назначение внешнего (плавающего) IP-адреса.
Хотя в OpenStack существует пул внешних IP-адресов, в новом проекте по умолчанию не выделено ни одного плавающего IP-адреса для использования. В этом руководстве мы рассмотрим процесс выделения плавающих IP-адресов из общего пула и их назначения как отдельным инстансам, так и группам инстансов, что обеспечит доступ к вашим виртуальным машинам из внешних сетей.
Основываться будем на файлах конфигурации из раздела I. “Создание инстанса в Terraform”, предполагая, что наша конфигурация дополнит их.
Выделение IP-адреса из пула и его последующее присвоение инстансу
- Добавьте в файл конфигурации шаблон блока выделения плавающего адреса и присвоения его инстансу:
| # Выделение плавающего IP из пула облачной инфраструктурыresource "openstack_networking_floatingip_v2" "float_ip" { pool = "<External_IP_pool_name>" # Укажите имя внешней сети, из пула которой будет выделен плавающий IP} # Подключение выделенного плавающего IP к созданному инстансуresource "openstack_compute_floatingip_associate_v2" "associate_float_ip" { floating_ip = openstack_networking_floatingip_v2.float_ip.address instance_id = openstack_compute_instance_v2.tf_instance_1.id } |
- Укажите параметр pool — имя внешней сети из пула которой будет выделен плавающий IP.
Узнать имена внешних сетей проекта вы можете через облачную консоль ("Network" > "Networks" > "External Networks" в поле "ID/Name") или CLI (openstack network list --external).
Если имя ресурса инстанса не "tf_instance_1" (не из нашего примера по созданию инстанса), замените его на ваше в строке "instance_id".
После изменений этот блок может выглядеть, например, так:
| # Выделение плавающего IP из пула облачной инфраструктурыresource "openstack_networking_floatingip_v2" "float_ip" { pool = "Floating_IP59" # Имя внешней сети из пула которой будет выделен плавающий IP} # Подключение выделенного плавающего IP к созданному инстансуresource "openstack_compute_floatingip_associate_v2" "associate_float_ip" { floating_ip = openstack_networking_floatingip_v2.float_ip.address instance_id = openstack_compute_instance_v2.tf_instance_1.id } |
- Сохраните изменения.
Присвоение ранее выделенного плавающего IP
- Добавьте в файл конфигурации блок присвоения плавающего адреса инстансу:
| resource "openstack_compute_floatingip_associate_v2" "associate_float_ip" { floating_ip = "<Выделенный_ip>" # Укажите выделенный из пула плавающий IP instance_id = "<id_Инстанса>" # Укажите id инстанса или ссылку на него в конфигурации Terraform} |
- Укажите свои значения следующих параметров:
- floating_ip — IPv4 адрес, выделенный из пула внешней сети и не привязанный ни к одному из инстансов.
Узнать доступные свободные плавающие IP-адреса в вашем проекте вы можете через облачную консоль ("Network" > "Floating IPs" в поле "ID/Floating IP", статус "DOWN") или через CLI (openstack floating ip list --status DOWN). - instance_id — id инстанса вашего проекта или ссылка на имя инстанса в конфигурации Terraform.
Узнать id инстансов вашего проекта вы можете через облачную консоль ("Compute" > "Instances" в поле "ID/Name") или через CLI (openstack server list).
- floating_ip — IPv4 адрес, выделенный из пула внешней сети и не привязанный ни к одному из инстансов.
Например, блок добавления плавающего IP-адреса для инстанса "tf_instance_1" из примера “Создание одного инстанса” из раздела 1 будет выглядеть следующим образом:
| resource "openstack_compute_floatingip_associate_v2" "associate_float_ip" { floating_ip = "198.51.100.101" # Уже выделенный из пула плавающий IP instance_id = openstack_compute_instance_v2.tf_instance_1.id # ссылка на инстанс в конфигурации Terraform} |
В этом случае указывается ссылка на имя инстанса в конфигурации Terraform.
Или так, если id инстанса указан напрямую:
| resource "openstack_compute_floatingip_associate_v2" "associate_float_ip" { floating_ip = "198.51.100.101" # Уже выделенный из пула плавающий IP instance_id = "ea6ddfe0-fadf-4c96-aa64-77a61b639112" # id инстанса} |
- Сохраните изменения конфигурации в файле.
Выделение нескольких плавающих IP и присвоение их группе инстансов
Выделение плавающих IP также возможно сразу для группы инстансов. И здесь мы рассмотрим выделение плавающих IP из пула внешних адресов и присвоение их инстансам из группы. Основываться будем на конфигурации, используя которую мы создавали группу инстансов "tf_instances", описанную в разделе I. “Создание инстанса через Terraform. Создание нескольких инстансов”.
- Добавьте в файл конфигурации шаблон блока выделения плавающего адреса и присвоения его инстансу:
| # Выделение плавающих IP-адресов из пула для каждого инстансаresource "openstack_networking_floatingip_v2" "fip" { count = length(openstack_compute_instance_v2.tf_instances) pool = "<external_network_name>" # Укажите название внешней сети, которая будет пулом плавающих IP } # Привязка выделенных плавающих IP-адресов к инстансамresource "openstack_compute_floatingip_associate_v2" "fip_associate" { count = length(openstack_compute_instance_v2.tf_instances) floating_ip = openstack_networking_floatingip_v2.fip[count.index].address instance_id = openstack_compute_instance_v2.tf_instances[count.index].id} |
Этот код выполняет следующие действия:
- Выделяет из пула внешних IP-адресов (указанного в параметре "pool") количество адресов, заданное параметром "count".
- Последовательно назначает выделенные IP-адреса инстансам из группы "tf_instances".
- Укажите в параметре “pool” наименование внешней сети, которая будет выступать пулом внешних IP-адресов.
Узнать имена доступных внешних сетей вы можете, через облачную консоль (“Network” > “Networks” > “External Networks” в поле “ID/Name”) или через CLI (openstack network list --external).
Если имя ресурса группы инстансов не "tf_instances" (не из нашего примера по созданию инстансов), замените его на ваше в строке "instance_id".
После добавления имени внешней сети этот блок может выглядеть, например, так:
| # Выделение плавающих IP-адресов из пула для каждого инстансаresource "openstack_networking_floatingip_v2" "fip" { count = length(openstack_compute_instance_v2.tf_instances) pool = "Floating_IP59" # Название внешней сети (пула плавающих IP)} # Привязка выделенных плавающих IP-адресов к инстансамresource "openstack_compute_floatingip_associate_v2" "fip_associate" { count = length(openstack_compute_instance_v2.tf_instances) floating_ip = openstack_networking_floatingip_v2.fip[count.index].address instance_id = openstack_compute_instance_v2.tf_instances[count.index].id} |
- Сохраните изменения.
III. Подключение дополнительного диска к инстансу
К инстансу можно подключить дополнительный диск. Это может быть как новый диск, так и существующий.
Подключить к инстансу дополнительный диск можно на этапе создания инстанса, продублировав блок конфигурации "block_device" и указав в нём параметры: "boot_index = -1" (диск не участвует в загрузке) и source_type = "blank" (пустой).
Но если вам нужно добавить диск уже после создания инстанса, то ниже мы покажем как это сделать на примере конфигураций из раздела I., дополнив их.
Подключение нового диска к создаваемому инстансу
- Добавьте в файл конфигурации из раздела I. “Создание инстанса в Terraform. Создание одного инстанса” блоки создания диска и подключения его к новому инстансу:
| # Создание дополнительного диска (volume)resource "openstack_blockstorage_volume_v3" "additional_volume" { name = "<volume_name>" # Укажите имя создаваемого диска size = <volume_size> # Укажите размер создаваемого диска volume_type = "<volume_type>" # Укажите тип создаваемого диска} # Подключение вновь созданного дополнительного диска к инстансуresource "openstack_compute_volume_attach_v2" "volume_attachment" { instance_id = openstack_compute_instance_v2.tf_instance_1.id volume_id = openstack_blockstorage_volume_v3.additional_volume.id} |
- Внесите в этот блок свои данные, изменив следующие поля:
- volume_name — Произвольное и уникальное в вашем проекте имя диска (например, my-additional-volume-01).
- volume_size — Размер создаваемого диска в гигабайтах, вводится целым числом (например, 20).
- volume_type — id типа диска:
- 25c82f52-dc3b-4337-a939-a73ec1a58d2a — Hybrid-Datastore.
- a462fa3a-8e23-492c-97bd-d493b1a8d0a4 — All-Flash-Datastore.
id доступных вашему проекту типов диска вы можете узнать через CLI (openstack volume type list).
Если имя ресурса инстанса не "tf_instance_1" (не из нашего примера по созданию инстанса), замените его на ваше в строке "instance_id".
После внесения изменений этот блок может выглядеть так:
| # Создание дополнительного диска (volume)resource "openstack_blockstorage_volume_v3" "additional_volume" { name = "my-additional-volume" # Имя создаваемого диска size = 20 # Размер создаваемого диска volume_type = "25c82f52-dc3b-4337-a939-a73ec1a58d2a" # Тип создаваемого диска } # Подключение дополнительного диска к инстансуresource "openstack_compute_volume_attach_v2" "volume_attachment" { instance_id = openstack_compute_instance_v2.tf_instance_1.id volume_id = openstack_blockstorage_volume_v3.additional_volume.id} |
- Сохраните изменения.
Если нужно подключить существующий диск к инстансу
- Добавьте в файл конфигурации шаблон блок подключения диска к новому инстансу:
| # Подключение существующего диска к инстансу в качестве дополнительного resource "openstack_compute_volume_attach_v2" "existing_volume_attachment" { instance_id = "<instance_id>" # Укажите id инстанса volume_id = "<existing_volume_id_here>" # Укажите id существующего диска} |
- Внесите в этот блок свои значения параметров:
- instance_id — id инстанса вашего проекта или ссылка на имя инстанса в конфигурации Terraform.
Узнать id инстансов, доступных вашему проекту, вы можете через облачную консоль, перейдя по вкладкам “Compute” > “Instances” в поле “ID/Name”использовав команду CLI: “openstack server list” или через панель управления . - volume_id — id существующего диска, который вы хотите подключить к создаваемому инстансу.
Узнать id дисков, доступных вашему проекту и свободных для подключения, вы можете через облачную консоль (“Storage” > “Volumes” диск со статусом: “available”, в поле “ID/Name”) или через CLI (openstack volume list --status available).
- instance_id — id инстанса вашего проекта или ссылка на имя инстанса в конфигурации Terraform.
Например, блок подключения дополнительного диска к создаваемому инстансу из примера “Создание одного инстанса” раздела 1 может выглядеть следующим образом:
| # Подключение существующего диска к создаваемому инстансу в качестве дополнительного resource "openstack_compute_volume_attach_v2" "existing_volume_attachment" { instance_id = openstack_compute_instance_v2.tf_instance_1.id # ссылка на id инстанса внутри конфигурации Terraform volume_id = "9874221b-018d-40ef-a717-183cdc6e30d3" # id существующего диска} |
Или так, если вы прямо указываете id существующего инстанса:
| # Подключение существующего диска к существующему инстансу в качестве дополнительногоresource "openstack_compute_volume_attach_v2" "existing_volume_attachment" { instance_id = "ea6ddfe0-fadf-4c96-aa64-77a61b639114" # id существующего инстанса volume_id = "9874221b-018d-40ef-a717-183cdc6e30d3" # id существующего диска} |
- Сохраните изменения.
Подключение нескольких новых дисков к группе инстансов
- Добавьте в файл конфигурации из раздела I. “Создание инстанса в Terraform. Создание нескольких инстансов” блоки создания дисков и их подключения к новым инстансам:
| # Блок создания дополнительных дисков для каждого инстансаresource "openstack_blockstorage_volume_v3" "extra_volumes" { count = length(openstack_compute_instance_v2.tf_instances) # Количество дополнительных томов равно количеству инстансов name = local.extra_volume_names[count.index] # Имя дополнительного тома из списка size = local.extra_volume_sizes[count.index] # Размер дополнительного тома из списка volume_type = local.extra_volume_types[count.index] # Тип дополнительного тома из списка} # Блок подключения дополнительных дисков к соответствующим инстансамresource "openstack_compute_volume_attach_v2" "extra_attachments" { count = length(openstack_compute_instance_v2.tf_instances) # Количество подключений равно количеству инстансов instance_id = openstack_compute_instance_v2.tf_instances[count.index].id # ID соответствующего инстанса volume_id = openstack_blockstorage_volume_v3.extra_volumes[count.index].id # ID соответствующего дополнительного тома} |
Примечание:
Вставьте блоки после основного блока "resource "openstack_compute_instance_v2", но до "output" или "network"-секции (если такие имеются).
А блок "locals" дополните данными о параметрах создаваемых дисков:
| # Блок локальных переменных для дополнительных дисков. Укажите здесь свои значения параметровlocals { extra_volume_names = ["<extra-volume-name-1>", "<extra-volume-name-2>", …, "<extra-volume-name-n>"] # Вставьте имена дополнительных дисков extra_volume_sizes = [<extra-size-1>, <extra-size-2>,…, <extra-size-n>] # Вставьте размеры дополнительных дисков (целыми числами) extra_volume_types = ["<extra-volume-type-1>", "<extra-volume-type-2>",…,"<extra-volume-type-n>"] # Вставьте id типов дополнительных дисков} |
Примечание:
Если вы хотите указать уникальные значения для каждого диска — например, разные имена или размеры — укажите соответствующие списки в блоке "locals" и используйте их в ресурсах.
Если же значения параметров одинаковы для всех дисков (например, одинаковый размер) или могут быть сгенерированы динамически (например, имя с порядковым номером), тогда эти параметры не нужно указывать в "locals". Вместо этого укажите их напрямую внутри ресурса.
- Внесите в блок "locals" свои данные для каждого из дисков, изменив значения параметров в следующих списках:
- extra_volume_names — Произвольные и уникальные в вашем проекте имена дисков.
- extra_volume_sizes — Размеры создаваемых дисков в гигабайтах, вводится целым числом (например, 20).
- extra_volume_types — id типов дисков:
- 25c82f52-dc3b-4337-a939-a73ec1a58d2a — Hybrid-Datastore.
- a462fa3a-8e23-492c-97bd-d493b1a8d0a4 — All-Flash-Datastore.
Узнать id доступных вашему проекту типов диска вы можете через CLI (openstack volume type list).
Если имя ресурса группы инстансов не "tf_instances" (не из нашего примера по созданию инстансов), замените его на ваше в строке "instance_id".
Если все параметры дисков заданы индивидуально, то содержание блоков, которые вы добавили выше не изменится, а блок "locals" будет дополнен, например, следующими данными:
| # Дополнение в блок локальных переменныхlocals { # Параметры дополнительных дисков extra_volume_names = ["extra-disk-1", "extra-disk-2", "extra-disk-3"] extra_volume_sizes = [10, 20, 15] extra_volume_types = ["25c82f52-dc3b-4337-a939-a73ec1a58d2a", "a462fa3a-8e23-492c-97bd-d493b1a8d0a4", "25c82f52-dc3b-4337-a939-a73ec1a58d2a"]} |
В случае, если, например, указать один размер для всех дисков, а их имена генерировать динамически, то блок создания дополнительных дисков будет выглядеть так:
| # Создание дополнительных дисков для каждого инстансаresource "openstack_blockstorage_volume_v3" "extra_volumes" { count = length(openstack_compute_instance_v2.tf_instances) # Количество томов = количеству инстансов name = "extra-volume-${count.index + 1}" # Автоматическое имя тома с номером size = 10 # Единый размер для всех дисков (в ГБ) volume_type = local.extra_volume_types[count.index] # Тип диска — индивидуальный для каждого} |
Блок подключения дополнительных дисков к инстансам в этом случае останется неизменным, как в изначальном шаблоне.
В этом случае в блоке "locals" нужно указать только типы дисков:
| # Дополнение в блок локальных переменныхlocals { extra_volume_types = ["25c82f52-dc3b-4337-a939-a73ec1a58d2a", "a462fa3a-8e23-492c-97bd-d493b1a8d0a4", "25c82f52-dc3b-4337-a939-a73ec1a58d2a"] # Типы дополнительных дисков} |
- Сохраните изменения.
IV. Вывод информации о созданных ресурсах: использование блока "output"
После создания элементов облачной инфраструктуры может быть полезно получить информацию об идентификаторах созданных ресурсов — инстансов, дисков, плавающих IP-адресов и т.д. Для этого в Terraform используется специальный блок "output", который выводит нужные данные в терминал после выполнения операций. Блок "output" также позволяет использовать выводимые параметры в CI/CD пайплайнах, внешних скриптах и для доступа к данным из других модулей.
Блоки "output" добавляются в конец файла конфигурации и не влияют на саму инфраструктуру.
Структура блока "output"
Блок "output" имеет следующую структуру:
| output "<имя_вывода>" { value = <значение или ссылка на параметр> description = "<необязательное описание>" sensitive = <true|false> # скрывает значение в терминале} |
Здесь:
- output "<имя_вывода>" — произвольное название, под которым будет отображаться результат. По этому названию можно получить доступ к выводу из других модулей.
- value — значение или ссылка на параметр. Формирование этого параметра описано ниже.
- description — описание выводимого параметра. Это необязательный параметр.
- sensitive — необязательный параметр. Если указать "true", значение не будет выведено в терминал при выполнении "terraform apply", но останется доступным программно (в том числе для других модулей). По умолчанию считается "false" и обычно его не указывают.
Формирование значения параметра "value" блока "output"
Значение параметра "value" формируется следующим образом:
| value = <тип_ресурса>.<имя_ресурса>.<параметр> |
где:
- <тип_ресурса> — тип ресурса Terraform. Ресурсы доступные для отображения приведены ниже;
- <имя_ресурса> — имя ресурса, заданное вами в блоке "resource";
- <параметр> — параметр, который нужно вывести: "id", "address", "name" и т.д.
Если значение не нужно передавать в другой модуль, но вы хотите отобразить его с пояснением в терминале, то параметр "value" можно сформировать следующим образом:
| value = "<текст пояснения>${<тип_ресурса>.<имя_ресурса>.<параметр>}" |
Например:
| value = "ID инстанса: ${openstack_compute_instance_v2.tf_instance_1.id}" |
Основные типы ресурсов OpenStack в Terraform
- openstack_compute_instance_v2 — виртуальная машина (инстанс);
- openstack_blockstorage_volume_v3 — дополнительный диск (том);
- openstack_compute_volume_attach_v2 — подключение диска к инстансу;
- openstack_networking_floatingip_v2 — выделение внешнего IP-адреса;
- openstack_compute_floatingip_associate_v2 — назначение IP инстансу;
- openstack_networking_port_v2 — создание сетевого порта;
- openstack_keypair_v2 — импорт или генерация SSH-ключа;
- openstack_security_group_v2 — создание группы безопасности.
Полный список доступных ресурсов приведён в официальной документации Terraform-провайдера для OpenStack.
Межмодульное использование "output"
Если вы используете модульную структуру, блок "output" позволяет передавать значения из одного модуля в другой. Это полезно при разделении логики: один модуль может создавать инфраструктуру, а другой — использовать полученные ресурсы для настройки, мониторинга или подключения.
Например, модуль может возвращать IP-адрес, пароль или идентификатор ресурса, а модуль, который его вызывает, может получить это значение через конструкцию:
| module.<имя_модуля>.<имя_output_блока> |
где:
- module — ключевое слово Terraform, обозначающее доступ к модулю;
- <имя_модуля> — имя, присвоенное модулю в конфигурации;
- <имя_output_блока> — имя выходного параметра, заданное в модуле через блок "output".
Например:
| module.vm_setup.instance_ip |
Эта конструкция возвращает IP-адрес из блока "output" с именем "instance_ip", определённого в модуле "vm_setup", который внутри может выглядеть так:
| # Внутри модуля vm_setupoutput "instance_ip" { value = openstack_networking_floatingip_v2.fip.address} |
Примеры оформления блоков "output"
Один инстанс:
| output "instance_id" { value = openstack_compute_instance_v2.tf_instance_1.id description = "ID созданного инстанса"} |
Вывод:
| instance_id = "ea6ddfe0-fadf-4c96-aa64-77a61b639112" |
Группа инстансов:
| output "instance_ids" { value = [for instance in openstack_compute_instance_v2.tf_instances : instance.id] description = "Список ID всех созданных инстансов"} |
Вывод:
| instance_ids = [ "f01fa473-e7d5-4a2e-bf8e-45e4bd1aa622", "e24e2875-8fb1-45d7-9d53-1fd94d89f02c"] |
Один плавающий IP:
| output "floating_ip" { value = openstack_networking_floatingip_v2.float_ip.address description = "Плавающий IP-адрес, назначенный инстансу"} |
Вывод:
| floating_ip = "198.51.100.101" |
Группа плавающих IP:
| output "floating_ips" { value = [for fip in openstack_networking_floatingip_v2.fip : fip.address] description = "Список всех назначенных плавающих IP-адресов"} |
Вывод:
| floating_ips = [ "198.51.100.201", "198.51.100.202"] |
Один дополнительный диск:
| output "volume_id" { value = openstack_blockstorage_volume_v3.additional_volume.id description = "ID дополнительного диска"} |
Вывод:
| volume_id = "4f6c2340-63d4-4b64-84c3-3aa3f8b0cf12" |
Несколько дополнительных дисков:
| output "volume_ids" { value = [for vol in openstack_blockstorage_volume_v3.extra_volumes : vol.id] description = "Список ID всех созданных дополнительных дисков"} |
Вывод:
| volume_ids = [ "b90a4304-90c8-42b3-8c84-0c5a2f0aa3d3", "3f2c8896-1e72-4a38-8053-d3e7e6c4bbff"] |
V. Применение изменений в инфраструктуре
После того как файл конфигурации готов, его нужно применить к облачной инфраструктуре. Для этого выполните следующие шаги:
- Откройте терминал:
- Для Windows: PowerShell или CMD;
- Для macOS/Linux: Bash, Zsh или другой терминал.
- Перейдите в каталог с конфигурационным файлом:
- Для Linux и macOS, например:
| cd /home/user/terraform/conf |
- Для Windows (PowerShell или CMD), например:
| cd "C:\Program Files\terraform\conf" |
- Инициализируйте Terraform, если ещё не сделали этого:
| terraform init |
При успешной инициализации вы увидите сообщение:
| Terraform has been successfully initialized! |
- Проверьте конфигурационные файлы на наличие ошибок:
| terraform validate |
Если проверка прошла успешно, то вы увидите следующее сообщение:
| Success! The configuration is valid. |
Если в ходе проверки выявлены ошибки — устраните их до перехода к следующему шагу.
- Отформатируйте .tf-файлы в текущем каталоге согласно официальным рекомендациям HashiCorp:
| terraform fmt |
Это улучшит читаемость кода и обеспечит единообразие конфигурации.
- Отобразите и проверьте план изменений в инфраструктуре:
| terraform plan |
Если планируемые изменения не соответствуют вашим ожиданиям — внесите соответствующие изменения до перехода к следующему шагу.
- Примените изменения в облачной инфраструктуре:
| terraform apply |
При этом Terraform выведет запрос на подтверждение:
| Do you want to perform these actions? Terraform will perform the actions described above. Only 'yes' will be accepted to approve. Enter a value: |
- Введите: "yes" и нажмите "Enter", чтобы подтвердить выполнение изменений.
После успешного применения вы увидите сообщения о созданных ресурсах и итоговое уведомление, например:
| Apply complete! Resources: 2 added, 0 changed, 0 destroyed. |