Terraform полезен не только в облаке. Домашняя лаборатория из Proxmox, libvirt или десятка LXC-контейнеров быстро обрастает ручными настройками, которые невозможно повторить. Описание инфраструктуры кодом превращает создание виртуальных машин в предсказуемый процесс: план, проверка, применение. Ниже — установка, структура проекта, первый план для Proxmox и правила, которые уберегут от потери состояния.

Зачем это дома

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

Terraform не заменяет Ansible. Первый создаёт инфраструктуру, второй настраивает внутри неё пакеты и сервисы. Разумная связка для дома: Terraform поднимает ВМ из шаблона, Ansible ставит на них роли. Если важна лицензионная чистота, присмотритесь к OpenTofu — форку с совместимым синтаксисом и CLI; остальные команды работают и там, только бинарник называется tofu.

Установка

В Debian и Ubuntu удобно подключить репозиторий HashiCorp. Команды ниже добавляют ключ и список пакетов, после чего terraform ставится через apt и обновляется вместе с системой.

wget -O- https://apt.releases.hashicorp.com/gpg | sudo gpg --dearmor -o /usr/share/keyrings/hashicorp-archive-keyring.gpg
echo "deb [signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg] https://apt.releases.hashicorp.com $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/hashicorp.list
sudo apt update
sudo apt install terraform
terraform -version

Если lsb_release не установлен, добавьте пакет lsb-release. На Fedora и RHEL есть аналогичный репозиторий, а на Arch пакет лежит в официальных репозиториях. Главное — проверить версию: в проекте ниже указана 1.6, этого достаточно для всех конструкций из статьи.

Структура проекта

Не складывайте всё в один main.tf. Минимальный набор файлов разделяет провайдер, переменные, ресурсы и выходные значения. Каталог .terraform и файлы состояния не коммитятся, а файл блокировки .terraform.lock.hcl — коммитится, чтобы версии провайдера были одинаковыми на всех машинах.

terraform-proxmox/
├── versions.tf
├── variables.tf
├── main.tf
├── outputs.tf
├── terraform.tfvars
└── .gitignore
.terraform/
*.tfstate
*.tfstate.*
*.tfplan
terraform.tfvars
*.auto.tfvars

Секреты в terraform.tfvars хранить нельзя, если каталог попадает в git. Для токена используйте переменную окружения TF_VAR_имя_переменной: Terraform подхватит её автоматически и не запишет в файл. Если в tfvars остаются только несекретные значения, держите рядом terraform.tfvars.example и коммитьте его.

Провайдер и подключение к Proxmox

Создайте в Proxmox API-токен с правами на управление виртуальными машинами в нужном пуле. Токен состоит из идентификатора и секрета; в конфигурации он передаётся одной строкой. Для самоподписанного сертификата PVE допускается insecure = true, но в постоянной лаборатории лучше поставить нормальный сертификат.

terraform {
  required_version = ">= 1.6"

  required_providers {
    proxmox = {
      source = "bpg/proxmox"
    }
  }
}
provider "proxmox" {
  endpoint  = "https://192.168.1.10:8006/"
  api_token = var.proxmox_token
  insecure  = true

  ssh {
    agent    = true
    username = "root"
  }
}

В ssh-блоке username должен совпадать с пользователем, от имени которого выпущен токен. Токен задайте переменной с пометкой sensitive. Считайте его без эха и экспортируйте: так он не попадёт в вывод plan и не сохранится в истории shell.

read -s -p "API token: " TF_VAR_proxmox_token
export TF_VAR_proxmox_token
variable "proxmox_token" {
  type      = string
  sensitive = true
}

variable "template_vm_id" {
  type    = number
  default = 9000
}

Первый план: две машины из шаблона

Подготовьте в Proxmox шаблон с cloud-init и запомните его VMID. Ресурс ниже клонирует шаблон дважды, задаёт имена, ядра, память и сетевой мост. Карта for_each фиксирует соответствие имени и VMID, поэтому порядок перебора предсказуем.

resource "proxmox_virtual_environment_vm" "lab" {
  for_each = {
    lab-1 = 201
    lab-2 = 202
  }

  name      = each.key
  node_name = "pve"
  vm_id     = each.value

  clone {
    vm_id = var.template_vm_id
  }

  cpu {
    cores = 2
  }

  memory {
    dedicated = 2048
  }

  agent {
    enabled = true
  }

  network_device {
    bridge = "vmbr0"
  }
}

Добавьте output, чтобы после применения видеть идентификаторы.

output "vm_ids" {
  value = { for name, vm in proxmox_virtual_environment_vm.lab : name => vm.vm_id }
}

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

terraform init
terraform fmt -recursive
terraform validate
terraform plan -out=tfplan
terraform apply tfplan

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

Состояние, дрейф и импорт

Файл terraform.tfstate — это не кэш, а источник истины о созданных ресурсах. Потеря состояния означает, что Terraform больше не знает о машинах и попытается создать их заново. Для дома достаточно локального состояния, но его нужно включать в резервное копирование. В команде из нескольких человек используйте удалённый backend с блокировкой.

terraform state list
terraform plan -refresh-only
terraform apply -refresh-only
terraform import 'proxmox_virtual_environment_vm.lab["lab-1"]' pve/201

Команда refresh-only сверяет состояние с реальностью, не меняя ресурсы. Импорт позволяет взять под управление машину, созданную вручную; формат идентификатора зависит от провайдера, поэтому сверьтесь с его документацией. Удаление через terraform destroy необратимо: сначала проверьте план с ключом -destroy и убедитесь, что в нём нет лишних ресурсов.

Чек-лист безопасности

  • Не коммитьте state, tfvars с секретами и каталог .terraform.
  • Коммитьте .terraform.lock.hcl и фиксируйте версию провайдера после первого init.
  • Передавайте токены через переменные окружения или хранилище секретов.
  • Читайте план до применения и не используйте -auto-approve вслепую.
  • Храните резервную копию состояния вне рабочей машины.
  • Разделяйте проекты по каталогам, а не только по workspaces: так меньше шансов перепутать окружения.

Итог

Terraform превращает домашнюю лабораторию в описанный и повторяемый набор ресурсов. Начните с одного проекта и двух ВМ: подключите провайдер, вынесите переменные, сохраните план и примените его. Дальше добавьте резервное копирование состояния и проверку дрейфа. Главные правила просты: состояние — это ценность, секреты — не в git, а план нужно читать до применения. Этого достаточно, чтобы перестать собирать инфраструктуру вручную и начать её версионировать.

Насколько публикация полезна?

Нажмите на звезду, чтобы оценить!

Средняя оценка 0 / 5. Количество оценок: 0

Оценок пока нет. Поставьте оценку первым.

Поделиться: Telegram ВКонтакте