Vagrant [353.4]

Рейтинг: 40.9% · 8 голосов
Специализация LPIC-3 305 (v3.0): KVM/QEMU и libvirt, Xen, образы дисков, контейнеры (namespaces/cgroups, LXC/LXD, Docker), оркестрация (Compose, Swarm, Kubernetes, Helm), Vagrant/Packer/cloud-init.
Ответить
Аватара пользователя
Sergey_Sysadmin
Сообщения: 134
Зарегистрирован: 11 май 2026, 05:31

Vagrant [353.4]

Сообщение Sergey_Sysadmin »

Оглавление курса (16)
  1. Введение в LPIC-3 305: виртуализация и контейнеризация
  2. Концепции и теория виртуализации [351.1]
  3. Xen [351.2]
  4. QEMU и KVM [351.3]
  5. Управление ВМ через libvirt [351.4, часть 1]
  6. libvirt: виртуальные сети и пулы хранилищ [351.4, часть 2]
  7. Управление образами дисков ВМ [351.5]
  8. Концепции контейнеризации [352.1]
  9. LXC и LXD [352.2]
  10. Docker: образы и контейнеры [352.3, часть 1]
  11. Docker: тома, сети, логирование, ресурсы [352.3, часть 2]
  12. Оркестрация контейнеров
  13. Облачные инструменты: OpenStack и Terraform [353.1]
  14. Packer [353.2]
  15. cloud-init [353.3]
  16. Vagrant [353.4] (вы здесь)
Урок 15. Vagrant [353.4]

Перед инженером часто стоит задача: дать команде из десяти человек одинаковое окружение, которое поднимается одной командой и в котором гарантированно нет фразы "а у меня локально работало". Vagrant решает именно это - он описывает виртуальную машину (или их связку) текстовым файлом, который лежит рядом с кодом в git. В этом уроке разберём структуру Vagrantfile, откуда берутся boxes, чем отличаются провайдеры libvirt и VirtualBox, как настраивается provisioning через shell и ansible, как работают синхронизация папок и проброс портов, и как собрать многомашинный стенд из нескольких узлов.

Изображение

Как это работает

Vagrant - это не гипервизор и не контейнерный движок. Это оркестратор-обёртка на Ruby, который переводит декларативное описание в вызовы конкретного провайдера. Сам он ничего не виртуализирует: за создание ВМ отвечает libvirt/KVM, VirtualBox, Hyper-V или даже docker. Vagrant лишь говорит провайдеру "создай машину с такими ресурсами, из такого образа, прокинь такие папки и порты".

Базовый образ называется box. Это упакованный шаблон диска плюс метаданные: для какого провайдера он собран и какая версия. Box скачивается один раз в кэш (~/.vagrant.d/boxes) и используется как основа для всех ВМ. При vagrant up Vagrant делает linked clone от box - новая машина не копирует весь диск, а наследует его слоем поверх, поэтому поднимается за секунды.

Состояние конкретного проекта Vagrant хранит в скрытой папке .vagrant рядом с Vagrantfile. Там лежит привязка имени машины к её ID в провайдере. Поэтому Vagrantfile коммитят в репозиторий, а .vagrant добавляют в .gitignore.

Provisioning - это шаги, которые выполняются внутри гостя один раз при первом up (или принудительно по vagrant provision). Через них ставят пакеты, конфигурируют сервисы, накатывают ansible-плейбуки. Идея в том, что box остаётся чистым и универсальным, а вся специфика проекта описана в provisioning и тоже лежит в git.

Команды и примеры

Установка. В Debian 13 и Ubuntu 24.04 пакет vagrant есть в репозитории, но он обычно отстаёт - актуальнее ставить из репозитория HashiCorp. В RHEL 10 и Fedora 41+ аналогично через dnf.

Код: Выделить всё

# Debian/Ubuntu
sudo apt update
sudo apt install -y vagrant
# или свежее из репозитория HashiCorp (apt-репозиторий releases.hashicorp.com)

# RHEL/Fedora
sudo dnf install -y vagrant
Для провайдера libvirt нужен плагин и установленный KVM. Для VirtualBox - пакет virtualbox.

Код: Выделить всё

# libvirt-стек (Debian/Ubuntu)
sudo apt install -y qemu-system-x86 libvirt-daemon-system virtinst
vagrant plugin install vagrant-libvirt

# libvirt-стек (RHEL/Fedora)
sudo dnf install -y @virtualization
sudo systemctl enable --now libvirtd
vagrant plugin install vagrant-libvirt
Минимальный Vagrantfile. Файл - это Ruby, читается сверху вниз.

Код: Выделить всё

Vagrant.configure("2") do |config|
  config.vm.box = "generic/debian13"
  config.vm.hostname = "web1"

  config.vm.provider :libvirt do |lv|
    lv.memory = 2048
    lv.cpus   = 2
  end

  config.vm.network "forwarded_port", guest: 80, host: 8080
  config.vm.synced_folder "./app", "/var/www/app", type: "nfs"

  config.vm.provision "shell", inline: <<-SHELL
    apt-get update
    apt-get install -y nginx
  SHELL
end
Базовый цикл работы.

Код: Выделить всё

vagrant up                 # создать и запустить, прогнать provisioning
vagrant ssh                # зайти в гостя
vagrant status             # состояние машин проекта
vagrant provision          # перепрогнать provisioning без пересоздания
vagrant reload --provision # перезагрузить ВМ и заново провижинить
vagrant halt               # выключить (диск сохраняется)
vagrant destroy -f         # удалить ВМ целиком
vagrant box list           # boxes в локальном кэше
Указать провайдера явно, если их в системе несколько:

Код: Выделить всё

vagrant up --provider=libvirt
vagrant up --provider=virtualbox
Provisioning через ansible. Vagrant сам подставит inventory и адреса машин в плейбук.

Код: Выделить всё

config.vm.provision "ansible" do |a|
  a.playbook = "site.yml"
  a.compatibility_mode = "2.0"
end
Если ansible не установлен на хосте, используют ansible_local - тогда Vagrant ставит ansible внутрь гостя и запускает плейбук изнутри.

Многомашинное окружение. Внутри одного Vagrantfile описываем несколько define-блоков. Это типовой стенд "веб плюс база".

Код: Выделить всё

Vagrant.configure("2") do |config|
  config.vm.box = "generic/debian13"

  config.vm.define "db" do |db|
    db.vm.hostname = "db"
    db.vm.network "private_network", ip: "192.168.56.20"
    db.vm.provision "shell", inline: "apt-get update && apt-get install -y postgresql"
  end

  config.vm.define "web" do |web|
    web.vm.hostname = "web"
    web.vm.network "private_network", ip: "192.168.56.10"
    web.vm.network "forwarded_port", guest: 80, host: 8080
    web.vm.provision "ansible" do |a|
      a.playbook = "web.yml"
    end
  end
end
Машины поднимаются командой vagrant up, а адресовать конкретную можно по имени: vagrant ssh web, vagrant provision db. Через private_network они видят друг друга по статическим IP.

Где брать boxes. Публичный каталог - Vagrant Cloud (app.vagrantup.com). Имена вида generic/debian13, bento/ubuntu-24.04, rockylinux/10. Семейство generic собрано сразу под несколько провайдеров, поэтому удобно для libvirt. Свой box делают из настроенной ВМ командой vagrant package или сборкой через Packer.

Частые грабли
  • Box собран под другой провайдер. Образ под VirtualBox не запустится в libvirt и наоборот. Перед выбором смотрите, какие провайдеры поддерживает box на Vagrant Cloud; берите generic/* для кросс-провайдерности.
  • synced_folder с типом nfs требует, чтобы на хосте работал NFS-сервер, а в Debian/Ubuntu - пакет nfs-kernel-server. Без него up падает на этапе монтирования. Тип virtualbox (vboxsf) и 9p/virtiofs (libvirt) такого не требуют, но медленнее или капризнее по правам.
  • Дефолтная синхронизация . в /vagrant включена всегда. Если её тип несовместим с провайдером, машина не поднимется - отключайте строкой config.vm.synced_folder ".", "/vagrant", disabled: true.
  • Конфликт портов на хосте: два проекта пробрасывают на host: 8080. Второй up выдаст ошибку занятого порта. Указывайте auto_correct: true либо разносите порты.
  • vagrant up не перепрогоняет provisioning на уже созданной машине - он идёт только при первом создании. Для повторного нужен vagrant provision или up --provision.
  • Плагин vagrant-libvirt чувствителен к версии Vagrant. После обновления пакета плагин может перестать грузиться - переустановите его через vagrant plugin install.
  • Права на сокет libvirt: пользователь должен быть в группе libvirt, иначе Vagrant не достучится до демона и попросит root.
Мини-лаба
  • Установите Vagrant и стек libvirt (KVM), добавьте себя в группу libvirt и перелогиньтесь.
  • Создайте папку проекта, выполните vagrant init generic/debian13 и откройте сгенерированный Vagrantfile.
  • Пропишите провайдер libvirt с 1 CPU и 1024 МБ памяти, проброс порта 80 на хост 8080 и shell-provisioning, ставящий nginx.
  • Поднимите стенд: vagrant up --provider=libvirt. Проверьте nginx через curl http://localhost:8080 с хоста.
  • Расширьте Vagrantfile до двух машин web и db с private_network и статическими IP; поднимите обе и убедитесь, что web пингует db по адресу.
  • Сломайте provisioning намеренно (опечатка в имени пакета), запустите vagrant provision и разберите вывод ошибки; исправьте и перепрогоните.
  • Уничтожьте стенд через vagrant destroy -f и убедитесь по vagrant box list, что сам box остался в кэше.
Контрольные вопросы
  • Чем box отличается от запущенной Vagrant-машины и где физически хранится каждый из них?
  • Почему один и тот же box нельзя использовать с любым провайдером и как это проверить заранее?
  • В каких случаях provisioning выполняется автоматически, а в каких его нужно запускать вручную?
  • Какие типы synced_folder доступны для libvirt и VirtualBox и какие у каждого требования к хосту?
  • Как в многомашинном Vagrantfile адресовать отдельную ВМ для ssh и provisioning?
  • Чем ansible отличается от ansible_local как способов provisioning и когда выбирают второй?
👍2 ❤️2 🔥 😄 🤔
Аватара пользователя
torhacker
Сообщения: 1
Зарегистрирован: 02 июн 2026, 22:36

Re: Vagrant [353.4]

Сообщение torhacker »

А если box на Vagrant Cloud есть только под virtualbox, а у меня libvirt - реально его сконвертить или проще искать generic аналог?
👍 ❤️2 🔥 😄 🤔
Аватара пользователя
stokar
Сообщения: 1
Зарегистрирован: 01 июн 2026, 20:23

Re: Vagrant [353.4]

Сообщение stokar »

Поймал грабли с дефолтным /vagrant: на rocky 10 up падал на vboxsf, помогло disabled: true плюс отдельный synced_folder через virtiofs
👍2 ❤️1 🔥 😄 🤔1
Ответить
← Предыдущая глава
cloud-init [353.3]

Все главы курса «LPIC-3 305: виртуализация и контейнеризация»

Поделиться темой: ✈ Telegram VK

Вернуться в «LPIC-3 305: виртуализация и контейнеры»

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и 1 гость