Новинка Виртуальный VDS сервер в Финляндии от 390р
Выберите продукт

Packer + cloud-init: собираем золотой образ для быстрых развёртываний на VDS

Надо запускать новые VDS за минуты и без ручных правок? Разберём Packer + cloud-init: архитектуру пайплайна, минимальные HCL/YAML, провижининг, очистку перед снимком, локальную проверку и процесс релизов.
Packer + cloud-init: собираем золотой образ для быстрых развёртываний на VDS

Зачем «золотой» образ и почему Packer + cloud-init

«Золотой» образ — это эталонная, воспроизводимая и проверенная сборка ОС с базовой настройкой, драйверами виртуализации, агентами мониторинга и минимально необходимыми пакетами. Из такого образа можно быстро поднимать новые VDS без дрейфа конфигурации и долгих провижинингов на первом запуске. Ключевые выгоды: одинаковая база для всех окружений, ускорение развёртываний, предсказуемая безопасность и понятная процедура обновлений.

В связке packer и cloud-init роли разделены идеально: packer отвечает за сборку и воспроизводимость образа, а cloud-init — за первичную настройку экземпляра при первом буте (пользователь, SSH-ключи, пакеты, переменные окружения, growpart/resizefs и т. п.). Такой дуэт позволяет вынести тяжёлую работу в этап сборки, а оставшееся — автоматизировать на старте каждой виртуалки.

Цели и требования к «золотому» образу

  • Совместимость с гипервизором (обычно KVM): virtio-драйверы, qemu-guest-agent, консоль по ttyS0.
  • Установленный cloud-init с корректным порядком модулей и настроенной стратегией datasource.
  • Безопасные настройки SSH (ключи вместо паролей, запрет root-входа паролем), обновления безопасности и базовые sysctl.
  • Авторасширение раздела (growpart) и файловой системы на первом старте.
  • Чистота перед снимком: удалены временные файлы, сброшены machine-id, ssh_host_keys, логи, кеши пакетных менеджеров.
  • Маркировка версии образа (лейбл/файл с версией) и чёткая процедура обновления.

Архитектура пайплайна

Схема проста: packer поднимает временную виртуалку под qemu/kvm, устанавливает/настраивает ОС, добавляет cloud-init и агенты, оптимизирует и чистит систему, затем делает снапшот готового диска (например, qcow2). Далее образ публикуется в вашем каталоге шаблонов, откуда он используется при создании новых VDS. При первом запуске экземпляр считывает user-data через cloud-init и выполняет заключительную настройку, специфичную для проекта.

Если вы как раз уходите с общего хостинга, пригодится практическое «руководство по переезду на VDS» — смотрите материал «Переезд с общего хостинга на VDS» по ссылке в нашей базе знаний: Переезд с общего хостинга на VDS.

Сборка VM под qemu/kvm в пайплайне Packer

Минимальный HCL-шаблон packer (qemu)

Ниже — упрощённый пример. Он ставит базовую систему из ISO, включает cloud-init и qemu-guest-agent, добавляет настройки и делает очистку перед снимком. Параметры ISO/пользователя/пароля вынесены в переменные.

packer {
  required_version = ">= 1.10.0"
}

variable "image_version" { default = "2025.01" }
variable "vm_name" { default = "golden-debian" }
variable "iso_url" { description = "Path to local ISO or mirror" }
variable "iso_checksum" { description = "sha256:..." }
variable "ssh_username" { default = "packer" }
variable "ssh_password" { default = "packer" }

source "qemu" "base" {
  accelerator       = "kvm"
  headless          = true
  iso_url           = var.iso_url
  iso_checksum      = var.iso_checksum
  output_directory  = "output/${var.vm_name}-${var.image_version}"
  vm_name           = "${var.vm_name}-${var.image_version}"
  disk_size         = "12G"
  format            = "qcow2"
  http_directory    = "http"
  ssh_username      = var.ssh_username
  ssh_password      = var.ssh_password
  ssh_timeout       = "30m"
  shutdown_command  = "sudo systemctl poweroff"

  boot_wait = "5s"
  boot_command = [
    "<esc><wait>",
    "auto priority=critical preseed/url=http://{{ .HTTPIP }}:{{ .HTTPPort }}/preseed.cfg",
    "<enter>"
  ]
}

build {
  name    = "golden-image"
  sources = ["source.qemu.base"]

  provisioner "shell" {
    inline = [
      "sudo apt-get update",
      "sudo apt-get install -y cloud-init qemu-guest-agent",
      "sudo systemctl enable qemu-guest-agent"
    ]
  }

  provisioner "file" {
    destination = "/tmp/99_fastfox.cfg"
    content = <<EOT
# cloud-init baseline config
preserve_hostname: false
ssh_pwauth: false
users:
  - default
system_info:
  default_user:
    lock_passwd: true
    gecos: Golden Image Default User
    sudo: ["ALL=(ALL) NOPASSWD:ALL"]
    shell: /bin/bash
    groups: ["adm", "sudo"]
resize_rootfs: true
growpart:
  mode: auto
  devices: ["/"]
  ignore_growroot_disabled: false
EOT
  }

  provisioner "shell" {
    inline = [
      "sudo mkdir -p /etc/cloud/cloud.cfg.d",
      "sudo mv /tmp/99_fastfox.cfg /etc/cloud/cloud.cfg.d/99_fastfox.cfg",
      "echo 'GRUB_CMDLINE_LINUX=\"console=ttyS0,115200n8\"' | sudo tee /etc/default/grub.d/50-serial.cfg",
      "sudo update-grub || true"
    ]
  }

  provisioner "shell" {
    inline = [
      "sudo apt-get -y dist-upgrade",
      "sudo apt-get -y autoremove --purge",
      "sudo apt-get clean"
    ]
  }

  provisioner "shell" {
    inline = [
      "sudo systemctl stop rsyslog || true",
      "sudo rm -f /etc/ssh/ssh_host_*",
      "sudo truncate -s0 /etc/machine-id",
      "sudo rm -f /var/lib/dbus/machine-id",
      "sudo ln -s /etc/machine-id /var/lib/dbus/machine-id || true",
      "sudo cloud-init clean --logs",
      "sudo find /var/log -type f -exec truncate -s0 {} +",
      "sudo rm -rf /tmp/* /var/tmp/*"
    ]
  }
}

В боевом окружении вы можете заменить установку из ISO на использование инфраструктурного «базового» cloud-образа и донастройку через packer. Главное — обеспечить в итоге установленный cloud-init и корректный набор драйверов и сервисов для гипервизора.

Полезные настройки cloud-init в образе

Часть настроек имеет смысл «запекать» в образ, чтобы первичный user-data для отдельных проектов был минималистичным. Речь о поведении growpart, дефолтном пользователе, блокировке паролей, политике ssh_pwauth, а также приоритизации источников метаданных (datasource).

# /etc/cloud/ds-identify.cfg
policy: enabled
# Явно укажем список источников метаданных, чтобы cloud-init не тратил время на лишнее
datasource_list: [ NoCloud, ConfigDrive ]

Если в инфраструктуре используется иной источник (например, собственная служба метаданных), добавьте его в список. Так вы ускорите бут и избежите таймаутов ожидания неподходящих источников.

Минимальный user-data для проекта

На момент развёртывания конкретного VDS обычно достаточно передать небольшой user-data с ключом SSH, пакетом необходимых пакетов и парой команд:

#cloud-config
users:
  - name: deploy
    gecos: Deploy User
    sudo: ["ALL=(ALL) NOPASSWD:ALL"]
    groups: ["adm", "sudo"]
    shell: /bin/bash
    ssh_authorized_keys:
      - ssh-ed25519 AAAA... comment
package_update: true
packages:
  - htop
  - curl
  - ca-certificates
write_files:
  - path: /etc/motd.d/00-image-version
    content: |
      Golden image version: 2025.01
runcmd:
  - [ systemctl, enable, --now, qemu-guest-agent ]
  - [ sh, -c, "echo 'Deploy bootstrap OK'" ]

Чем меньше логики на этапе первого запуска — тем надёжнее. Сложные сценарии лучше переносить в этап сборки packer или в последующий слой конфигурации (например, через Ansible после старта экземпляра).

Проверка локально: быстрый цикл отладки

Перед публикацией образа удобно проверять его локально. Стандартный подход: поднять VM из собранного qcow2 и подложить seed с user-data в формате NoCloud. После загрузки проверить логи cloud-init и убедиться, что авторасширение диска, доступ по SSH и агенты отрабатывают корректно.

  • Проверить статус: cloud-init status --long.
  • Посмотреть логи: journalctl -u cloud-init -u cloud-init-local -u cloud-config -u cloud-final.
  • Убедиться, что создан пользователь, подставлены ключи, включён qemu-guest-agent, а файловая система расширена.

Проверка логов и статуса cloud-init на тестовой VM

Версионирование и неизменяемость

Рекомендуется встраивать версию образа в артефакт и внутрь файловой системы (например, /etc/image-build или файл в /etc/motd.d). Правила именования: год.месяц.пателевел или семантическая версия с build-метаданными. Не меняйте образ «на месте» — публикуйте новые версии и проводите по ним канареечные развёртывания. Это и есть практика неизменяемых серверов (immutable), которая резко снижает дрейф конфигураций.

Безопасность по умолчанию

  • Запрет паролей по SSH: ssh_pwauth: false, проверка PermitRootLogin prohibit-password в sshd_config.
  • Удаление ssh_host_keys на этапе сборки и регенерация при первом старте.
  • Включение автоматических обновлений безопасности дистрибутива.
  • Сужение списка datasources в ds-identify.cfg, чтобы исключить ложные срабатывания.
  • Логи и временные файлы — под ноль перед снимком; machine-id — обнулить.

Оптимизации времени старта

  • Серийная консоль в GRUB: console=ttyS0 для быстрых диагностик.
  • Порядок модулей cloud-init: первым cloud-init-local для сети, затем cloud-config и cloud-final.
  • Ограничение datasource_list — нет лишних таймаутов.
  • Предварительная установка необходимых пакетов в образ вместо установки на user-data.

Очистка перед публикацией

Список полезных команд для финального шага уже был в примере packer, но повторим общую идею:

  • Удалить host-ключи SSH и обнулить machine-id.
  • Очистить кеши пакетов (apt/dnf), логи в /var/log, временные файлы.
  • Запустить cloud-init clean --logs.
  • Остановить машину штатно (systemctl poweroff) для корректной фиксации файловой системы.

От ISO к «базовому» cloud-образу

Есть два подхода:

  1. Установка из ISO. Полный контроль, но больше времени на сборку: автопостановка через preseed/kickstart, затем установка cloud-init и пакетов.
  2. Кастомизация готового cloud-образа. Быстрее: cloud-init и разметка уже присутствуют, вы лишь вносите корпоративные настройки и агенты. В packer это реализуется через запуск образа в qemu и дальнейшие provisioners.

Выбор зависит от требований к прозрачности цепочки поставки и длительности сборки. Нередко в инфраструктуре применяется смешанный подход: собственный «базовый» образ, собранный из ISO, а затем — проектные кастомизации поверх. Если требуется удобная панель управления, пригодится обзор: сравнение панелей для VDS.

Тест-кейсы до выката

  • Валидность образа: поднимается ли VM, корректно ли работает сеть и консоль.
  • Отработка user-data на первом старте, включая packages, write_files, runcmd.
  • Регенерация ssh_host_keys и доступ по публичному ключу.
  • Расширение раздела и файловой системы на полный размер диска.
  • Версионирование: присутствует ли файл/лейбл версии внутри системы.

Релизы и обновления: процесс

Фиксируйте HCL и cloud-config в репозитории, используйте теги для релизов, храните артефакты с контрольными суммами. Держите две ветки: stable и next. Новая версия проходит автоматические тесты (проверка загрузки, доступности по SSH, отработки cloud-init), далее — канареечный выпуск на часть новых VDS. Только после стабилизации — перевод в stable.

FastFox VDS
Облачный VDS-сервер
Виртуальные серверы с быстрым запуском и гибкой конфигурацией от 390₽ / мес
Доступные локации
Россия Нидерланды Финляндия

Типичные ошибки и отладка

  • Долгая загрузка cloud-init. Проверьте datasource_list и сетевые таймауты. В логах часто видно ожидание ненужных источников.
  • Нет авторасширения диска. Убедитесь, что включены growpart и resize_rootfs, а корневой раздел размечён подходящим образом.
  • Не генерируются SSH host keys. Проверьте наличие соответствующих systemd-юнитов и отсутствие предзапечённых ключей в образе.
  • Проблемы с агентом гостя. Убедитесь, что установлен и включён qemu-guest-agent, проверьте сокеты и разрешения.
  • Случайные конфликты сети. Если вы используете netplan или NetworkManager, проверьте, не мешает ли им конфигурация от cloud-init. Иногда полезно делегировать сети только одной системе.

Расширение пайплайна: Ansible, тесты, подписи

packer легко дополняется Ansible-провижинингом для более сложных ролей (например, предустановка агента мониторинга, логгера, базовых правил auditd). Автотесты на стадии сборки можно реализовать через скрипты проверки сервисов и логов. Для целостности добавляйте контрольные суммы и подписи артефактов.

Итог: packer даёт воспроизводимый артефакт, cloud-init — быстрый и минималистичный провижининг на первом старте. Вместе они формируют надёжную основу для массовых развёртываний VDS, сводя ручные действия к нулю и повышая безопасность.

Чек-лист перед публикацией образа

  • cloud-init установлен, модули выполняются, datasource_list настроен.
  • Включён qemu-guest-agent, консоль доступна по ttyS0.
  • SSH-пароли отключены, ключи не запечены в образе.
  • Готовность к росту диска на первом старте.
  • Версия образа зафиксирована внутри системы и в имени артефакта.
  • Проведены локальные тесты и проверка логов cloud-init.
  • Очистка выполнена: логи, кеши, machine-id, ssh_host_keys.

Заключение

Собственный «золотой» образ — это инструмент, который окупается с первого десятка развёртываний. Связка packer + cloud-init обеспечивает быстрое масштабирование и предсказуемые релизы. Начните с минимальной базы (драйверы, cloud-init, агент гостя, безопасность по умолчанию), выстройте процесс версионирования и канареек, и через пару итераций у вас появится стабильный, хорошо документированный образ, который экономит часы на каждом новом сервере.

Поделиться статьей

Вам будет интересно

Как безопасно выполнить bootstrap MariaDB Galera после полного останова

Как безопасно выполнить bootstrap MariaDB Galera после полного останова

После одновременной остановки всех узлов Galera обычного запуска MariaDB недостаточно. Сначала найдите сервер с последней транзакц ...
CoreDNS в Kubernetes: исправляем CrashLoopBackOff, SERVFAIL и DNS-петлю

CoreDNS в Kubernetes: исправляем CrashLoopBackOff, SERVFAIL и DNS-петлю

Разберём, почему CoreDNS перезапускается или отвечает SERVFAIL, как обнаружить замкнутую пересылку DNS-запросов, проверить доступн ...
Apache Kafka KRaft на VDS: отдельные controller и broker

Apache Kafka KRaft на VDS: отдельные controller и broker

Соберём новый Kafka-кластер без ZooKeeper на шести Linux VDS: три узла controller образуют отказоустойчивый metadata quorum, а три ...