====== Создание ВМ в Proxmox через Terraform ======
==== Процесс автоматизации создания ВМ ====
Весь процесс выглядит следующим образом:
- Загрузка Linux Cloud Image нужного дистрибутива.
- Создание ВМ в Proxmox.
- При необходимости дополнительная настройка ВМ.
- Создание шаблона из ВМ.
- Создание ВМ из шаблона через модуль Proxmox для Terraform.
Процесс будет описан в разделах ниже (некоторые шаги объединены в один раздел).
==== Подготовка образов ====
Linux Cloud Image – это образы, которые оптимизированы для работы в публичных или частных облаках. У этих образов более гибкие и удобные инструменты для кастомизации. Но сначала такой образ нужно подготовить. Большинство из Linux дистрибутивов предоставляют такие образы.
Например, вот таким небольшим скриптом на Proxmox сервере можно подготовить образ Ubuntu Server 22.04, создать из него ВМ и конвертировать её в шаблон:
# Source guide - https://gist.github.com/zidenis/dfc05d9fa150ae55d7c87d870a0306c5
# SSH to Proxmox Server
ssh user@your-proxmox-server
su - root
# Install required tools on Proxmox Server
apt update
apt install -y libguestfs-tools
# Install qemu quest agent on Ubuntu 22.04 Cloud Image
export IMAGES_PATH="/mnt/pve/HDD_local" # defines the path where the images will be stored and change the path to it.
cd $IMAGES_PATH
wget https://cloud-images.ubuntu.com/jammy/current/jammy-server-cloudimg-amd64.img
virt-customize --install qemu-guest-agent -a "${IMAGES_PATH}/jammy-server-cloudimg-amd64.img"
export QEMU_CPU_MODEL="host"
export VM_CPU_CORES=2
export VM_CPU_SOCKETS=2
export VM_MEMORY=4098
export VM_STORAGE_NAME="local-lvm"
export VM_BRIDGE_NAME="vmbr0"
export CLOUD_INIT_USER="roman"
export CLOUD_INIT_PASSWORD="Qwerty123"
#export CLOUD_INIT_SSHKEY="/home/user/.ssh/id_rsa.pub" # Provides the path to the SSH public key for the user.
export CLOUD_INIT_IP="dhcp"
# export CLOUD_INIT_IP="192.168.10.20/24,gw=192.168.10.1" # Static example
export CLOUD_INIT_NAMESERVER="8.8.8.8"
export CLOUD_INIT_SEARCHDOMAIN="itproblog.ru"
export TEMPLATE_ID=2001
#export TEMPLATE_ID=$(pvesh get /cluster/nextid)
export VM_NAME="Ubuntu2204"
export VM_DISK_IMAGE="${IMAGES_PATH}/jammy-server-cloudimg-amd64.img"
# Create VM. Change the cpu model
qm create ${TEMPLATE_ID} --name ${VM_NAME} --cpu ${QEMU_CPU_MODEL} --sockets ${VM_CPU_SOCKETS} --cores ${VM_CPU_CORES} --memory ${VM_MEMORY} --numa 1 --net0 virtio,bridge=${VM_BRIDGE_NAME} --ostype l26 --agent 1 --scsihw virtio-scsi-single
# Import Disk
qm set ${TEMPLATE_ID} --virtio0 ${VM_STORAGE_NAME}:0,import-from=${VM_DISK_IMAGE}
# Add Cloud-Init CD-ROM drive. This enables the VM to receive customization instructions during boot.
qm set ${TEMPLATE_ID} --ide2 ${VM_STORAGE_NAME}:cloudinit --boot order=virtio0
# Cloud-init network-data
qm set ${TEMPLATE_ID} --ipconfig0 ip=${CLOUD_INIT_IP} --nameserver ${CLOUD_INIT_NAMESERVER} --searchdomain ${CLOUD_INIT_SEARCHDOMAIN}
# Cloud-init user-data
qm set ${TEMPLATE_ID} --ciupgrade 1 --ciuser ${CLOUD_INIT_USER} --cipassword ${CLOUD_INIT_PASSWORD}
# Cloud-init regenerate ISO image, ensuring that the VM will properly initialize with the desired parameters.
qm cloudinit update ${TEMPLATE_ID}
qm set ${TEMPLATE_ID} --name "${VM_NAME}-Template"
qm template ${TEMPLATE_ID}
Для подготовки образа этих действий достаточно.
Аналогичным образом подготовлим шаблон для Rocky Linux 9.
По итогу у нас получается два вот таких шаблона:
{{https://itproblog.ru/wp-content/uploads/2024/05/image-6.png?nolink&}}
==== Создание ВМ в Proxmox через Terraform ====
Сразу надо отметить, что провайдер telmate/proxmox довольно специфичен. Довольно много откровенно негативных отзывов про него. Поэтому нет гарантии, что он 100% подойдет для боевого окружения. [[https://habr.com/ru/articles/743334/|Как пишут на Хабре]] – этим инструментом инфраструктуру можно скорее завалить, чем построить.
=== Создание токена доступа на Proxmox ===
Для работы провайдера Proxmox для Terraform будем использовать доступ через токен. Для этого на сервере Proxmox сгенерируем соответствующий токен. С точки зрения безопасности лучше создать отдельную учетную запись. Поскольку в рамках этой статьи решение применяется тестовом контуре, то токен будет создан для пользователя root.
{{https://itproblog.ru/wp-content/uploads/2024/05/image-3.png?nolink&}}
Скопируйте значения Token ID и Secret:
{{https://itproblog.ru/wp-content/uploads/2024/05/image-5.png?nolink&}}
В последующем укажем эти значения в переменных для подключения к API Proxmox.
=== Установка Terraform ===
Нет смысла подробно расписывать этот процесс, т.к. это не является основной целью данной публикации. И потом про это и так написано уже слишком много статей. Инструкция по установке Terraform доступна [[https://developer.hashicorp.com/terraform/tutorials/aws-get-started/install-cli?in=terraform/aws-get-started|вот по этой ссылке.]]
Есть еще альтернативный вариант использования форка Terraform – [[https://opentofu.org/|OpenTofu]], но учитывая не очень адекватное ведение проекта мейнтейнерами, судьба этого форка под большим вопросом. Так что пока можно считать что альтернативы Terraform нет.
=== Подготовка плана инфраструктуры в Terraform ===
1. Сначала создаём отдельную директорию для хранения всех необходимых файлов Terraform:
mkdir SimpleVM
cd SimpleVM
2. Теперь создадим файл с определением переменных. В основном это переменные для подключения к Proxmox:
nano credentials.auto.tfvars
proxmox_api_url = "https://10.10.10.61:8006/api2/json"
proxmox_api_token_id = "root@pam!terraform-token"
proxmox_api_token_secret = "e4849c31-6071-448f-aa51-8a7b07057529"
storage_name = "HDD500"
3. Следующим шагом подключим провайдера:
nano provider.tf
terraform {
required_providers {
proxmox = {
source = "telmate/proxmox"
version = "3.0.1-rc2"
}
}
}
provider "proxmox" {
pm_api_url = var.proxmox_api_url
pm_api_token_id = var.proxmox_api_token_id
pm_api_token_secret = var.proxmox_api_token_secret
pm_tls_insecure = true
}
4. Теперь подготовим план нашей инфраструктуры для Terraform.
nano vm-ubuntu2204.tf
resource "proxmox_vm_qemu" "ubuntu2204" {
name = "Ununtu2204"
desc = "A test for using terraform and cloudinit"
# Node name has to be the same name as within the cluster
# this might not include the FQDN
target_node = "px01"
# The template name to clone this vm from
clone = "Ubuntu2204-Template"
# Activate QEMU agent for this VM
agent = 1
os_type = "cloud-init"
cores = 2
sockets = 2
vcpus = 0
cpu = "host"
memory = 2048
scsihw = "virtio-scsi-single"
# Setup the disk
disks {
ide {
ide3 {
cloudinit {
storage = var.storage_name
}
}
}
virtio {
virtio0 {
disk {
size = "2252M"
storage = var.storage_name
replicate = true
}
}
}
}
# Setup the network interface and assign a vlan tag: 256
network {
model = "virtio"
bridge = "vmbr0"
}
# Setup the ip address using cloud-init.
boot = "order=virtio0"
# Keep in mind to use the CIDR notation for the ip.
ipconfig0 = "ip=dhcp"
nameserver = "8.8.8.8"
ciuser = "roman"
}
5. Также создадим аналогичное определение ресурса и для Rocky linux 9.
6. Проверим синтаксис нашего определения инфраструктуры:
terraform validate
{{https://itproblog.ru/wp-content/uploads/2024/05/image-7.png?nolink&}}
7. Проверим, что Terraform создаст в Proxmox на основе нашего плана:
terraform plan
8. Все именно так, как нужно. Запускаем процесс создания инфраструктуры:
terraform apply
{{https://itproblog.ru/wp-content/uploads/2024/05/image-8.png?nolink&}}
9. Дожидаемся окончания процедуры создания инфраструктуры.
{{https://itproblog.ru/wp-content/uploads/2024/05/image-9.png?nolink&}}
Как видно выше процесс подготовки двух ВМ занял две минуты. Вручную потребовалось бы гораздо больше времени.
Можно также одномоментно уничтожить все ВМ:
terraform destroy
{{https://itproblog.ru/wp-content/uploads/2024/05/image-11.png?nolink&}}
=== Немного особенностей ===
Как уже было написано выше выше [[https://github.com/Telmate/terraform-provider-proxmox/tree/master|провайдер telmate/proxmox]] для Terraform довольно специфичен. Например, определение типа SCSI контроллера и интерфейсов подключения дисков должны совпадать в шаблоне ВМ и в определении ресурса в Terraform. Даже размер диска должен совпадать. Иначе Terraform создаст новый дополнительный пустой диск и Proxmox будет пытаться загрузить ВМ с этого диска.
т.е. вот эти параметры должны совпадать:
{{https://itproblog.ru/wp-content/uploads/2024/05/image-10-1024x559.png?nolink&}}
=== Итоговая проверка ===
По итогу получилась вот такая иерархия объектов в Proxmox.
{{https://itproblog.ru/wp-content/uploads/2024/05/image-2.png?nolink&}}