Вопрос или проблема
Я пытаюсь создать стек из нескольких виртуальных машин на KVM_HOST с использованием Terraform. Проблема в том, что я использую pxeboot и kickstart для установки. Файл kickstart должен содержать некоторую динамическую информацию, такую как статические IP-адреса, имя хоста и т.д., поэтому я должен создавать его для каждой виртуальной машины, и этот файл kickstart должен оставаться там, пока виртуальная машина не прочитает его и не начнет установку. Затем создается следующий файл kickstart для второй виртуальной машины, и он должен оставаться там, пока vm2 не прочитает его для установки. Поэтому должно быть некоторое задержка в создании этих ресурсов, либо с помощью цикла, либо с помощью параметра depend_on, но что я получаю, так это то, что файлы kickstart для всех виртуальных машин генерируются сразу, последний, естественно, перезаписывается, поэтому корректная информация не передается.
вот два ресурса, которые мне нужно зациклить последовательно на количество значений переменных qty
variable "vm_count" {
type = number
default = 1
}
ниже приведены ресурсы
resource "null_resource" "delay" {
count = var.vm_count
provisioner "local-exec" {
command = "sleep 150"
}
depends_on = [libvirt_domain.vm]
}
resource "local_file" "kickstart_file" {
count = var.vm_count
content = templatefile("ks.tpl", {
ip = "192.168.1.${117 + count.index}"
netmask = var.netmask
gateway = var.gateway
dns = var.dns
hostname = "${var.hostname}-${count.index + 1}"
disk_size_rounded = ((var.disk_size - 1) * 1024) -1
})
filename = "/var/www/html/kickstart/ks-terraform.cfg"
}
resource "libvirt_domain" "vm" {
count = var.vm_count
name = "${var.hostname}-${count.index + 1}"
memory = var.memory
vcpu = var.cpu
arch = "x86_64"
cpu {
mode = "host-passthrough"
}
boot_device {
dev = ["hd", "network"]
}
disk {
volume_id = libvirt_volume.default_disk[count.index].id
}
graphics {
type = "vnc"
listen_type = "address"
autoport = true
}
network_interface {
bridge = "virbr0"
macvtap = false
}
depends_on = [local_file.kickstart_file, null_resource.delay]
}
как я могу улучшить логику с помощью depends on или for_each?
Хорошо, что я нашел, это удивительно, pxeboot позволяет pxemenu быть специфичным для виртуальной машины с использованием mac-адреса, таким образом я создаю уникальный файл pxemenu для каждой виртуальной машины, который может ссылаться на отдельный файл kickstart для каждой виртуальной машины. Хорошая вещь в том, что это не требует перезапуска службы.
просто создайте файл меню для каждой виртуальной машины по пути
/var/lib/tftp/pxelinux.cfg/01-(в след за mac-адресом виртуальной машины, разделенным дефисами, не двоеточиями
например, так
/var/lib/tftpboot/pxelinux.cfg/01-52-54-dd-dd-dd-dd
и его файл меню содержит ссылку на файл kickstart, вот так
default menu.c32
prompt 0
timeout 300
ontimeout 2
menu title PXE Boot Menu
label 1
menu label ^1 - Установить Rocky Linux 9
kernel images/vmlinuz
append initrd=images/initrd.img showopts inst.repo=http://{ PXEBOOT_SERVER }/os-dvd/ devfs=nomount inst.ks=http://{ PXEBOOT_SERVER }/kickstart/os-minimal-vm1.cfg
Ответ или решение
Когда вы пытаетесь создать стек из нескольких виртуальных машин (VM) на KVM_HOST с использованием Terraform, часто возникает необходимость в конфигурации с учетом зависимостей между ресурсами. В вашей ситуации, где используется PXE-загрузка и kickstart для установки, каждая VM требует специфического конфигурационного файла kickstart, который должен удерживаться до тех пор, пока виртуальная машина не получит его для начала установки. Это типичная проблема в системах автоматизации, где сложность увеличивает количество отключенных от зависимости ресурсов.
Теоретическая часть
Terraform и управление зависимостями:
Terraform управляет созданием и конфигурацией облачных инфраструктурных ресурсов, обеспечивая декларативный способ описания. Одним из его основных преимуществ является управление зависимостями через механизм графов. Это позволяет организовать ресурсы так, чтобы их создание или изменения происходили в определенном порядке.
Директива depends_on
:
Эта директива явным образом указывает на зависимости между ресурсами. Хотя Terraform автоматически вычисляет зависимости ресурсов на основе ссылок между ними, depends_on
позволяет уточнить порядок выполнения операций, особенно когда это не столь очевидно.
Механизм count
и зависимости:
count
предоставляет возможность создавать несколько экземпляров ресурса по определенному количеству. Это схоже с циклами в других языках программирования, но не поддерживает условные конструкции внутри. Это делает управление зависимостями для ресурса, созданного с помощью count
, более сложным, поскольку все экземпляры ресурса считаются равнозначными.
Пример и пояснение
Ваша конфигурация использует переменную vm_count
для определения количества создаваемых виртуальных машин. Каждый экземпляр создается при помощи count
, как для ресурса libvirt_domain.vm
, так и для local_file.kickstart_file
. Основная проблема заключается в том, что все kickstart-файлы создаются одновременно, с последующей их перезаписью, так как все они имеют одинаковое имя.
Пример с использованием for_each
:
resource "local_file" "kickstart_file" {
for_each = toset([for i in range(var.vm_count) : i])
content = templatefile("ks.tpl", {
ip = "192.168.1.${117 + each.value}"
netmask = var.netmask
gateway = var.gateway
dns = var.dns
hostname = "${var.hostname}-${each.value + 1}"
disk_size_rounded = ((var.disk_size - 1) * 1024) -1
})
filename = "/var/www/html/kickstart/ks-${each.value + 1}.cfg"
}
В этом примере ресурс local_file.kickstart_file
использует for_each
, чтобы создать уникальные файлы kickstart. Обратите внимание, что теперь переменная filename
динамична и зависит от значения each.value
, что предотвращает перезапись файлов.
Применение и улучшения
-
Использование уникальных файлов kickstart:
Создание уникальных файлов kickstart для каждой VM избавляет от проблемы перезаписи. Это достигается динамическим именованием файлов. Применениеfor_each
вместоcount
открывает больше возможностей для управления зависимостями между отдельными экземплярами. -
Управление задержкой:
Введенная задержка в 150 секунд черезnull_resource
выглядит как временное решение. Перейдите к более надежным методам, используя, например, более специфическое ожидание событий от внешних систем, таких как сигнал готовности VM к чтению файла. -
Конфигурация PXE-меню:
Персонализация процессов PXE через использование MAC-адресов позволяет избежать задержек и одновременно сохранить гибкость генерации конфигураций. Создавая уникальные PXE-меню для каждой VM по MAC-адресу, вы обеспечиваете индивидуальный процесс загрузки, что расширяет возможности автоматизации.
В результате этих изменений конфигурация станет более устойчивой и предсказуемой, что чрезвычайно важно для масштабных развертываний. Такой подход может быть расширен дополнительным функционалом, например, проверкой целостности файлов, отслеживанием статусов VM и интеграцией с другими инструментами автоматизации. Используя полную мощность Terraform, можно достичь высокого уровня автоматизации, сократив вручную управляемые процессы.