DevOps. Terraform. Построение динамических зависимостей в depends_on

от автора

Terraform — это Open source решение для управления IaC от компании Hashicorp, вышедшее в 2014 году. Terraform придерживается декларативного стиля управления инфраструктурой. Это значит, что вы описываете финальное состояние инфраструктуры в конфигурационном файле, а Terraform приводит её к нему. Достаточно написать конфигурацию, в которой будет изложено, как вы видите вашу будущую инфраструктуру, а главное, если описывать конфигурацию инфраструктуры в человеко-читаемом текстовом формате, то после применения данной конфигурации начинаются создаваться ресурсы в заранее определённых зависимостях.

При создании дополнительных дисков, они создаются параллельно и подключаются по мере создания.
При создании дополнительных дисков, они создаются параллельно и подключаются по мере создания.

Данный метод не позволяет использовать заранее определённую статическую конфигурацию разметки и подключения дисков.

Необходимо настроить подключение дисков в определённой последовательности, чтобы в дальнейшем с помощью Ansible, на дисках создать разделы и подмонтировать их в нужные папки.

Вариант без зависимостей

resource "vcd_vm_internal_disk" "server_disk_swap" {   vapp_name       = vcd_vm.server.vapp_name   vm_name         = vcd_vm.server.name   vdc             = vcd_vm.server.vdc   bus_type        = "paravirtual"   size_in_mb      = 51200   bus_number      = 0   unit_number     = 1   storage_profile = "VC7-SSD" }  resource "vcd_vm_internal_disk" "server_disk_app" {   vapp_name       = vcd_vm.server.vapp_name   vm_name         = vcd_vm.server.name   vdc             = vcd_vm.server.vdc   bus_type        = "paravirtual"   size_in_mb      = 102500   bus_number      = 0   unit_number     = 2   storage_profile = "VC7-SSD" }  resource "vcd_vm_internal_disk" "server_disk_db" {   vapp_name       = vcd_vm.server.vapp_name   vm_name         = vcd_vm.server.name   vdc             = vcd_vm.server.vdc   bus_type        = "paravirtual"   size_in_mb      = 204800   bus_number      = 0   unit_number     = 3   storage_profile = "VC7-SSD" }

Код для создания дисков без зависимостей

resource "vcd_vm_internal_disk" "disk_1" { unit_number     = 1 } resource "vcd_vm_internal_disk" "disk_2" { unit_number     = 2 } resource "vcd_vm_internal_disk" "disk_3" { unit_number     = 3 }

Если использовать подобную конструкцию, тогда диски будут создаваться в случайной последовательности. В свойствах виртуальной машины у дисков будут правильные Unit Number, но не правильный Index. На хосте так же имена дисков будут не в той последовательности, которая необходима.

Решение со статическими зависимостями

resource "vcd_vm_internal_disk" "server_disk_swap" {   vapp_name       = vcd_vm.server.vapp_name   vm_name         = vcd_vm.server.name   vdc             = vcd_vm.server.vdc   bus_type        = "paravirtual"   size_in_mb      = 51200   bus_number      = 0   unit_number     = 1   storage_profile = "VC7-SSD"   depends_on      = [vcd_vm.server] }  resource "vcd_vm_internal_disk" "server_disk_app" {   vapp_name       = vcd_vm.server.vapp_name   vm_name         = vcd_vm.server.name   vdc             = vcd_vm.server.vdc   bus_type        = "paravirtual"   size_in_mb      = 102500   bus_number      = 0   unit_number     = 2   storage_profile = "VC7-SSD"   depends_on      = [vcd_vm_internal_disk.server_disk_swap] }  resource "vcd_vm_internal_disk" "server_disk_db" {   vapp_name       = vcd_vm.server.vapp_name   vm_name         = vcd_vm.server.name   vdc             = vcd_vm.server.vdc   bus_type        = "paravirtual"   size_in_mb      = 204800   bus_number      = 0   unit_number     = 3   storage_profile = "VC7-SSD"   depends_on      = [vcd_vm_internal_disk.server_disk_app] }

Решение со статическими зависимостями

resource "vcd_vm_internal_disk" "disk_1" { unit_number     = 1 depends_on      = [vcd_vm.vm] } resource "vcd_vm_internal_disk" "disk_2" { unit_number     = 2 depends_on      = [vcd_vm_internal_disk.disk_1] } resource "vcd_vm_internal_disk" "disk_3" { unit_number     = 3 depends_on      = [vcd_vm_internal_disk.disk_2] }

В данном решении указаны статические объекты, которые ссылаются на предыдущий элемент.

Если в переменную depends_on подставить какую-нибудь переменную, тогда получаем ошибку «A single static variable reference is
required: only attribute access and indexing with constant keys. No
calculations, function calls, template expressions, etc are allowed
here.». Использование
переменных depends_on запрещены из-за особенности построения структуры создания
ресурсов. Как видим на рисунке 2 диски создаются параллельно и ничего друг о
друге они не знают, т.к. находятся в параллельных ветках зависимостей.

depends_on = [vcd_vm.vm] — указывает, что необходимо ждать пока создастся виртуальная машина (можно эту зависимость не указывать, terraform сам распределяет очерёдность создания и он не создаст диск, пока не будет создана виртуальная машина

depends_on  = [vcd_vm_internal_disk.disk_1] — указывает, что ждём пока не создастся ресурс vcd_vm_internal_disk.disk_1

depends_on  = [vcd_vm_internal_disk.disk_2] — указывает, что ждём пока не создастся ресурс vcd_vm_internal_disk.disk_2

Это рабочий вариант, когда нам нужно создать не большое количество виртуальных машин, но когда их много, тогда код будет очень громоздкий и в нём будет очень сложно разобраться.

Решение с динамическими зависимостями

Для данного решения вынесем создание диска в отдельный модуль modules>disks>main.tf

resource "time_sleep" "wait" {   depends_on = [var.vms]   create_duration = "${var.sleep}s" }  resource "vcd_vm_internal_disk" "disks" {   vapp_name       = var.vapp_name   vm_name         = var.vm_name   vdc             = var.vdc   bus_type        = var.bus_type   size_in_mb      = var.size_in_mb   bus_number      = 0   unit_number     = var.unit_number   storage_profile = "VC7-SSD"   depends_on = [time_sleep.wait] }

Код модуля для создания дисков

Основной код ./main.tf

module "disks" {     count = length(var.vcd_host.disks)      source      = "../disks"     vapp_name   = vcd_vm.vms.vapp_name     vm_name     = vcd_vm.vms.name     vdc         = vcd_vm.vms.vdc     vms         = vcd_vm.vms     bus_type    = var.vcd_host.disks[count.index].bus_type     size_in_mb  = var.vcd_host.disks[count.index].size_in_mb     unit_number = count.index + 1     sleep       = (30 * count.index) + 1 }

Решение с динамическими интервалами создания

Переменная откуда берётся список дисков (variables.tf)

disks = [      {bus_type = "paravirtual", size_in_mb = 51200},      {bus_type = "paravirtual", size_in_mb = 102400},      {bus_type = "paravirtual", size_in_mb = 204800} ]

Список необходимых дисков в определённой последовательности

Теперь с помощью цикла мы можем создать то количество дисков, которое нам необходимо, и в нужной последовательности. Если последовательность нарушается, тогда можно увеличить время ожидания с 30 до 60 и т.д.

module "disks" { count = length(var.vcd_vm.disks) size_in_mb  = var.vcd_vm.disks[count.index] unit_number = count.index + 1 sleep = (30 * count.index) + 1 }

В модуле с помощь переменной sleep мы регулируем, когда начинать создание диска. Для таймера мы так же указываем, чтобы он не начинал отсчёт, пока не будет создана машина, указанная в переменной vcd_vm.

resource "time_sleep" "wait" { depends_on = [var.vcd_vm] create_duration = "${var.sleep}s" }

Заключение

Как видите, при создании ресурсов с помощью terraform есть определённые сложности для организации последовательности. Для разрешения этих сложностей можно использовать несколько вариантов. Для создания инфраструктуры, в которой более 50-ти машин, мне пригодился вариант с динамическими зависимостями, который очень сильно сократил и оптимизировал код. Надеюсь, данное решение пригодится тебе в работе.

Автор: Алексей Цветков.


ссылка на оригинал статьи https://habr.com/ru/articles/716506/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *