Перейти к основному содержимому
Background Image
  1. Статьи/

Автоматическая установка виртуальных машин в Proxmox 9.0.3 с помощью Terraform в Docker

·2438 слов·12 минут· loading · loading · ·
Stilicho2011
Автор
Stilicho2011
Пишу о homelab, self-hosting, автоматизации и open-source решениях
Оглавление
Автоматизация в Proxmox - This article is part of a series.
Part : This Article

Этой статьей я продолжаю тему по автоматизации установки и настройки нашей инфраструктуры с помощью Proxmox. Если вам понравилась настоящая статья, то можете поддержать автора став спонсором на бусти (ссылка в разделе контакты).

Ранее я рассказывал как можно создавать шаблоны в Proxmox - это “слепок” состояния виртуальной машины или LXC-контейнера на нужный нам момент времени, из которого мы потом можем “разворачивать” копии машин; и как создавать вируальные машины с помощью cloud-init. Теперь воспользуемся этими тайными знаниями и пойдем по пути автоматизации развертывания нашей инфраструктуры еще дальше и начнем использовать Terraform.

Зачем автоматизировать создание виртуальных машин в принципе?
#

Ручное создание ВМ в Proxmox удобно на начальном этапе, но с ростом количества инстансов процесс становится трудоёмким, а соответственно подверженным ошибкам. Более того, ну одну, две вм мы еще развернем, не развалимся. А что если нужно одновременно развернуть > 5 виртульаных машин?

Зачем автоматизировать создание виртуальных машин дома?
#

То, что вы создаёте, должно поддерживаться. Ведь всю вашу, с таким трудом созданную, инфрастуктуру легко развалить или даже сломать, если не уделять вопросу поддержки или обслуживания должного внимания.

Вы потратили бесчисленные часы на построение своей инфраструктуры, выверяя каждую деталь, читая много статьей, мануалов, просмотрели кучу ютуб роликов разной степени полезности. Но что случится, если что-то пойдёт не так, и вам придётся всё восстанавливать с нуля? Что если весь ваш тяжёлый труд просто исчезнет по мановению случайного Ctrl+Alt+Del?

Тема настоящей статьи
#

В этой статье и видео в начале статьи я покажу вам, как настроить Terraform для обслуживания вашей инфраструктуры так, чтобы вам никогда не пришлось всё пересобирать заново с нуля, роясь в своих записях (если вы их ведете), или роясь в самых потаенных уголках своей памяти (если она у вас работает) в попытке воостановить последовательность ваших действий.

Будь то небольшое изменение конфигурации или управление целыми виртуальными машинами — Terraform поможет вам всё держать под контролем.

Использование Terraform позволяет описать конфигурацию вашей инфраструктуры как код (IaC), благодаря чему вы можете:

  • Создавать ВМ с одинаковыми параметрами за секунды.
  • Версионировать инфраструктуру.
  • Интегрировать развертывание в CI/CD.
  • Повысить воспроизводимость и предсказуемость среды.

На всякий случай поясню, что инфрастурктура как код - это когда мы с вами описываем аппаратную часть нашей системы в текстовом формате. Не путайте с Ansible, где принцип такой же, но там мы описываем программную среду.

Что такое Terraform?
#

Terraform – это инструмент от компании Hashicorp, помогающий декларативно управлять инфраструктрой с помощью соответствующих конфигурационных файлов. Это значит - нам не надо вручную создавать виртуальные машины, сети и т.д. Достаточно написать конфигурацию, в которой будет изложено, как вы видите вашу будущую инфраструктуру. Такая конфигурация создается в текстовом формате yaml. Соответственно изменения в нашу инфраструктуру тоже вносятся с помощью правок текстового файла. Новичкам - может показаться сложно и непонятно по началу, но когда втянетесь, вы поймете всю прелесть хранения всей вашей инфраструктуры в паре текстовых файлов. Вы же понимаете прелесть описания вашего софта в docker-compose файле? Вот и тут почти также. При этом Terraform поддерживает множество платформ, включая Proxmox VE.

Учтите, что в настоящий момент для доступа к сайту Terraform может потребоваться соответствующая технология, так как они от нас закрылись.

Варианты установки Terraform
#

Как установить Terraform в Docker

Terraform может быть установлен несколькими способами, условно разделю их на два варианта: нативно и с помощью Docker. Я буду описывать установку с помощью Docker. Почему?

Оба способа установки Terraform — нативно и с помощью Docker — имеют свои плюсы и минусы. Выбор зависит от целей, окружения и предпочтений. Давайте посмотрим на плюсы и минусы, как это вижу я. Кстати, если не согласны, пишите в комментариях под роликом. Я надеюсь, что вы понимаете, - все плюсы и минусы это достаточно условно?

🔧 Нативная установка Terraform
#

✅ Плюсы:
#

  • Простой и прямой доступ: можно вызывать terraform напрямую из терминала.
  • Интеграция с другими инструментами CLI: Ansible, Packer и пр.
  • Поддержка IDE: автокомплит, подсветка синтаксиса и плагины в VS Code и других редакторах.
  • Удобное редактирование и тестирование локально.
  • Быстрее запускается, чем через Docker.

❌ Минусы:
#

  • Требует ручного контроля версий. Высока вероятность проблем в работе с провайдером о которых чуть позже.
  • Возможны конфликты между проектами с разными версиями Terraform.
  • Нужно устанавливать и обновлять вручную.

Кому может подойти:
#

Оптимально для локальной разработки, частой работы с инфраструктурой и гибкой настройки.

🐳 Установка Terraform с помощью Docker
#

✅ Плюсы:
#

  • Не требует установки Terraform на хост.
  • Легко переключаться между версиями с помощью тегов Docker-образа.
  • Идеально для CI/CD пайплайнов (GitHub Actions, GitLab CI и пр.).
  • Изоляция окружения — никакого конфликта зависимостей.

❌ Минусы:
#

  • Менее удобно для интерактивной работы.
  • Требуется пробрасывать volume и прописывать пути вручную (-v $(pwd):/workspace).
  • Медленнее запуск по сравнению с нативной установкой.
  • Не работает напрямую с локальным SSH-агентом, переменными окружения без явного проброса.

Кому может подойти:
#

Идеально подходит для автоматизации, CI/CD и одноразовых сценариев, когда важна изоляция среды. Для дома вообщем хорошо подходит.

🏁 Выводы
#

СценарийРекомендованный подход
Локальная разработка, частое взаимодействиеНативно
Автоматизация и CI/CDDocker
Работа с несколькими версиями TerraformDocker
Гибкость и глубокая интеграция с системойНативно

Обратите внимание В видео ролике я использую VS Code, как более простой инструмент. Я предполагаю, что у вас уже настроена виртуальная машина в Proxmox и установлен docker, а также подготовлен шаблон виртуальной машины на Ubuntu в Proxmox VE, как мы это с вами делали в предыдущей статье.

Установка Terraform
#

Создаем директорию и назовем ее terraform, чтобы не запутаться

Шаг 1: Создание структуры проекта
#

mkdir terraform
cd terraform

Создайте файл docker-compose.yml со следующим содержимым:

services:
  terraform:
    image: hashicorp/terraform:latest #Официальный образ terraform
    volumes:
      - .:/terraform # маппим тома. Точка показывает, что установка будет в директорию terraform, в который мы с вами сейчас находимся 
    working_dir: /terraform # Описываем рабочую директорию. Она должна совпадать с той, что задана строчкой выше. В противном случае terraform обидется и не будет работать
    network_mode: host # обязательно указываем тип сети как хост. Это нужно для того, что terraform мог взаимодействовать с proxmox и нам не нужно будет делать дополнительные настройки сети, которые понимают не только лишь все

Шаг 2: Установка расширения Terraform в VS Code
#

Откройте VS Code → Extensions → найдите Terraform → Установите. Это расширение поможет нам взаимодействовать с Terraform, интерпретируя язык Terraform в понятную нам структуру и формат. Я пользуюсь официальным плагином от Hashicorp - разработчик Terraform

Шаг 3: Создаем файл с учётными данными
#

Формально учетные данные мы могли бы указать и в файле provider.tf (о нем чуть позже), но формально это неправильно с точки зрения безопасности. Поэтому давайте хотя бы здесь постараюсь показать правильно.

Создайте файл в нашей директории командой :

touch credentials.auto.tfvars
# tf.vars означает переменные (variables) terraform 

Пример содержимого credentials.auto.tfvars:

proxmox_api_url        = "https://<ВАШ_IP>:8006/api2/json"
proxmox_api_token_id   = "root@pam!terraform"
proxmox_api_token_secret = "<ВАШ_СЕКРЕТ>" # proxmox показывает его один раз, поэтому сразу скопируйте 
Правильно создавать конечно отдельного юзера в Proxmox и задать ему сначала соответствующие права. Но я хочу для целей этой статьи сделать все максимально проcто, поэтому я буду использовать пользователя root. С точки зрения безопасности - это неправильно!

Создайте токен в Proxmox:

  • Datacenter → Permissions → API Tokens → Add
  • Пользователь: root@pam
  • Token ID: terraform
  • Снимите галочку с “Privilege Separation”

Шаг 4: Провайдер (provider.tf)
#

Сначала давайте определимся, что такое provider. Provider в нашем случае - это некий бридж между Terraform и вашей платформой, на которой вы разворачиваете Terraform. В нашем случае - это Proxmox VE, но в продакшене это может быть любая серьезная облачная инфраструктура типа AWS, Azure и т.д. При этом для каждой платформы свой провайдер.

Мы будем использовать провайдера от Telmate. Связано это с тем, что официального провайдера для Proxmox от разработчиков нет. И тут есть один хитрый момент. У этого провайдера есть проблемы с версионностью. То есть не каждая версия провайдера заведется с разными версиями Proxmox VE. В интернете по этому поводу всегда много стонов. Очень похожая ситуация с Nextcloud - всем нужен, все плачут, но продолжают использовать.

Открываем Terraform Registry → ищем terraform proxmox → выбираем ссылку от Telmate. Я выбрал его, потому что он широко используется, а поэтому его легче “дебажить”.

Нажимаем “Use Provider” и копируем предложенный код в наш файл для данных провайдера.

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

Содержимое:

terraform {
  required_providers {
    proxmox = {
      source = "Telmate/proxmox"
      version = "3.0.2-rc03"
    }
  }
}

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
}

variable "proxmox_api_url" {
  type        = string
  description = "URL API Proxmox, например https://proxmox.example.com:8006/api2/json"
}

variable "proxmox_api_token_id" {
  type        = string
  description = "API token id в формате user@realm!tokenid, например root@pam!terraform"
}

variable "proxmox_api_token_secret" {
  type        = string
  description = "Секретный ключ API токена"
  sensitive   = true
}

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

Шаг 5: Инициализация Terraform
#

В терминале переходим в директорию где у нас находятся наши файлы.

Вводим следующую команду

docker compose -f docker-compose.yml run --rm terraform init

Сейчас поясню, что это значит.

В своих роликах я никогда не запускал докер с флагом -f, но тут особый случай.

Флаг -f определяет какой конкретно файл надо запустить. В нашем случае docker-compose.yml. Команда –rm говорит, что контейнер должен самоликвидироваться, после того, как он выполнит свои темные делишки. Запускаем команду. После того как контейнер будут скачан, наш проект будет запущен. То есть скачивается контейнер Terraform, скачивается провайдер, установливаются все необходимые бекэнд файлы. В итоге мы должны получить сообщение, что Terraform инициализирован. В нашей директории Terraform мы увидим новые файлы. Трогать их нам не надо, но просто само их наличие говорит о том, что все в порядке. Так и должно быть. Фактически Terraform проверяет возможность соеденения с ProxmoxVE

В версии Proxmox 9.0.3 вы получите ошибку, которая нам скажет, что Terraform понятия не имеет, что это за провайдер такой Telmate, откуда брать его данные и т.д. Решить это можно только путем ручного скачивания бинароного файла нашего провайдера и прописывания соответствующих путей в docker-compose файле.

Сделаем с вами следующее

 sudo mkdir -p ~/.terraform.d/plugins/registry.terraform.io/telmate/proxmox/3.0.2-rc03/linux_amd64 #создаем директорию для плагина
 
 wget https://github.com/Telmate/terraform-provider-proxmox/releases/download/v3.0.2-rc03/terraform-provider-proxmox_3.0.2-rc03_linux_amd64.zip #скачиваем нужную версию плагина
 
 
 sudo unzip terraform-provider-proxmox_3.0.2-rc03_linux_amd64.zip -d ~/.terraform.d/plugins/registry.terraform.io/telmate/proxmox/3.0.2-rc03/linux_amd64 #разархивируем плагин и переместим его во вновь созданную директорию

После того как мы все с вами скачали, разархивировали и переместили в нужную директорию, надо внести изменения в наш docker compose файл

services:
  terraform:
    image: hashicorp/terraform:latest
    volumes:
      - .:/terraform
      - ~/.terraform.d/plugins/registry.terraform.io/telmate/proxmox/3.0.2-rc03/linux_amd64:/root/.terraform.d/plugins/registry.terraform.io/telmate/proxmox/3.0.2-rc03/linux_amd64:ro  
    working_dir: /terraform 
    network_mode: host 

Тут мы руками прописываем путь, по которому надо смотреть/искать нашего провайдера.

Опять вводим команду

docker compose -f docker-compose.yml run --rm terraform init

В этот раз у нас все должно быть хорошо и проект должен пройти инициализацию

Шаг 6: Проверка текущего состояния
#

Запускаем следующую команду.

docker compose -f docker-compose.yml run --rm terraform plan

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

Но в версии Proxmox 9.0.3/4 по состоянию на дату написания статьи у вас опять выскочит ошибка. Ошибка будет связана с “якобы” недостаточным объемом прав у токена. Это на самом деле не так. Дело в том, что в Proxmox 9 разработчики переименовали некоторые вещи, а Telmate об этом еще не знает. Мы же токен от пользователя root создавали, у нас прав выше крыши. Чтобы избавиться от этой ошибки внесем изменения в файл provider.tf.

terraform {
  required_providers {
    proxmox = {
      source = "Telmate/proxmox"
      version = "3.0.2-rc03"
    }
  }
}

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
  pm_minimum_permission_check = false # отключем проверку прав
}

variable "proxmox_api_url" {
  type        = string
  description = "URL API Proxmox, например https://proxmox.example.com:8006/api2/json"
}

variable "proxmox_api_token_id" {
  type        = string
  description = "API token id в формате user@realm!tokenid, например root@pam!terraform"
}

variable "proxmox_api_token_secret" {
  type        = string
  description = "Секретный ключ API токена"
  sensitive   = true
}

Мы укажем новую переменную pm_minimum_permission_check = false, которая отключает проверку прав. На дату написания статьи - это был единственный рабочий вариант

Теперь, когда мы с вами введем еще раз команду

docker compose -f docker-compose.yml run --rm terraform plan

то мы увидим что конфигурация применена. На самом деле никакой конфигурации мы еще не сформировали,- это просто проверка работоспособности на будущее

Шаг 7: Создание первой виртуальной машины (youtubetest.tf)
#

Давайте заставим Terraform создать первую виртуальную машину на Ubuntu из нашего предварительно созданного шаблона. Как создать шаблон у меня есть статья на сайте и видео на канале. И даже есть плейлист с названием автоматизация в Proxmox. Пора уже заняться всем по взрослому.

Прежде всего опять зайдем на сайт Telmate и подсмотрим там нужные нам переменные в разделе proxmox_vm_qemu.

Создаем соответствующий файл с названием youtubetest.tf. Именно в нем мы будем задавать значения для нашей виртуальной машины, которую мы будем создавать с помощью Terraform.

touch youtubetest.tf

Пример содержимого:

resource "proxmox_vm_qemu" "youtubetest" { 
  vmid        = 357 #id создаваемой машины
  name        = "youtubetest" # ее название
  target_node = "belisarius" # название ноды
  clone       = "ubuntutemplate" # название шаблона из которого все разворачиваем
  full_clone  = true 
  bios        = "ovmf"
  agent       = 1 # установить qemu-guest-agent
  scsihw      = "virtio-scsi-single"
  os_type     = "ubuntu"
  cpu_type    = "x86-64-v2-AES"
  cores       = 2
  sockets     = 1
  memory      = 2048

  disks {
    scsi {
      scsi0 {
        disk {
          size    = "32G"
          storage = "local"
          format  = "qcow2"
        }
      }
    }
  }

  network {
    id     = 0
    model  = "virtio"
    bridge = "vmbr0"
  }
}

Это мы с вами создаем нашу первую, самую простенькую, виртуальную машину с помощью текстового файла.

Теперь давайте еще раз применим уже известную нам команду

docker compose -f docker-compose.yml run --rm terraform plan

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

Шаг 8: Применение конфигурации
#

Давайте теперь уже начнем разворачивать нашу виртуальную машину в реальности.

docker compose -f docker-compose.yml run --rm terraform apply

Нужно будет подтвердить наше потайное желание начать создание виртуальной машины вводом команды:

yes

Теперь начнётся клонирование ВМ в Proxmox, статус будет виден в логах ProxmoxVE. После завершения ВМ автоматически запустится.

В Summary вы увидите IP — благодаря guest-agent.

Можно открыть консоль — ВМ загружена и готова.

Шаг 9: Тест восстановления
#

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

Удалим ВМ вручную в ProxmoxVE, затем опять запустим уже известную нам команду :

docker compose -f docker-compose.yml run --rm terraform apply

Шаг 10: Обновление конфигурации
#

Давайте изменим нашу конфигурацию ВМ, например:

memory = 8192
cores  = 2

Повторно примените:

docker compose -f docker-compose.yml run --rm terraform apply

Пару секунд и вуаля, у нас все обновилось.

Если эта статья вам помогла, то можете подписаться на мой ютуб канал и стать спонсором на бусти.

Автоматизация в Proxmox - This article is part of a series.
Part : This Article