Миттєвий запуск майже будь OS під Linux використовуючи libvirt + qemu

По ходу роботи над CoreOS і Kubernetes мені доводилося часто відтворювати оточення користувачів, щоб допомогти їм вирішити проблему. Погодьтеся, що при запуску OS за допомогою контейнера, не завжди можна добитися повного функціоналу OS, т. к. часто доводилося вирішувати питання, пов'язані з systemd.
Так і народилася ідея написати милиці, які з легкістю допоможуть мені підняти кластер з майже будь оперционной системи, такий собі OpenStack в мініатюрі. Зараз в якості гостьових повністю підтримуються наступні OS:
  • Ubuntu
  • Debian
  • CentOS 6/7 + atomic
  • Fedora + atomic
  • CoreOS
Частково:
  • FreeBSD (потрібно налаштування мережі та ключів ssh)
  • openSUSE (потрібне ручне налаштування мережі та ключів ssh)
  • Windows (консоль не потрапиш, але за допомогою virt-manager можна користуватися графічним інтерфейсом
посприяв Публікації колега, який випадково побачив, як я тестую код. А тепер про переваги перед Vagrant. Перша перевага — час. Наприклад, три віртуальні машини створюються всього за 20-30 секунд.
image
На момент початку роботи над сценаріями Vagrant під Linux міг запускати образи виключно використовуючи VirtualBox, підтримка libvirt/qemu була ще сира. Для VirtualBox доводилося шукати спеціально підготовлені образи і перезапуск кластера з віртуальних машин займав значний час.
зараз більшість разработчкиов операційних систем надають образи, підготовлені для роботи в оточенні OpenStack ("cloud" образи). Ці образи дуже зручно налаштовувати завдяки наявності в них
cloud-init
. За допомогою
cloud-init
на етапі першого завантаження можна з легкістю впроваджувати в образ публічні ключі SSH і налаштовувати мережу.
QEMU уміє працювати з образами віртуальної машини як з шарами (spanshots, майже як Docker). Ми можемо завантажити оффициальный "cloud" образ і використовувати його як базовий для всіх віртуальних машин з кластера. В цьому випадку всі зміни на диску будуть записуватися як різниця між базовим чином і поточним станом (як LVM snapshots). Цей спосіб також дозволяє з легкістю видалити всі машини і відновити їх в протягом декількох секунд.
Приклад редеплоя 3-х debian машинВидаляємо вже створений кластер з Debian і пересоздаем його з нуля, використовуючи скачаний офіційний образ
debian-8.5.0-openstack-amd64.qcow2

$ virsh list 
Id State Name
----------------------------------------------------
12 debian1 running
13 debian2 running
14 debian3 running
./remove_cluster.sh debian
Are you sure to remove 'debian1 debian2 debian3 '? (Type 'y' when agree) y
Domain debian1 destroyed

Domain debian1 has been undefined

Vol debian1.qcow2 deleted

# Host debian1 found: line 8
/home/user/.ssh/known_hosts.debian updated.
Original contents retained as /home/user/.ssh/known_hosts.debian.old 
Domain debian2 destroyed 

Domain debian2 has been undefined 

Vol debian2.qcow2 deleted 

# Host debian2 found: line 9 
/home/user/.ssh/known_hosts.debian updated. 
Original contents retained as /home/user/.ssh/known_hosts.debian.old 
Domain debian3 destroyed 

Domain debian3 has been undefined 

Vol debian3.qcow2 deleted 

Host debian3 not found in /home/user/.ssh/known_hosts.debian 
Pool debian destroyed 

Pool debian has been undefined

$ date && time ./deploy_vms_cluster.sh -o debian -s 3 && date
Thu Aug 25 10:26:15 CEST 2016 # <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
Using default 8.5.0 channel for debian
Using default current release for debian
Will use following path to SSH public key: /home/user/.ssh/id_rsa.pub
Pool debian created

Pool debian defined from /dev/stdin

Formatting '/home/user/libvirt_images/debian/debian1.qcow2', fmt=qcow2 size=2147483648 backing_file=/home/user/libvirt_images/debian/debian-8.5.0-openstack-amd64.qcow2 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16
Pool debian refreshed

Total translation table size: 0
Total rockridge attributes bytes: 763
Total directory bytes: 4458
Path table size(bytes): 40
Max brk space used 22000
187 extents written (0 MB)
Pool debian refreshed

Starting install...
Creating domain... | 0 B 00:00:00 
Domain creation completed.
Pool debian defined from /dev/stdin

Formatting '/home/user/libvirt_images/debian/debian2.qcow2', fmt=qcow2 size=2147483648 backing_file=/home/user/libvirt_images/debian/debian-8.5.0-openstack-amd64.qcow2 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16
Pool debian refreshed

Total translation table size: 0
Total rockridge attributes bytes: 763
Total directory bytes: 4458
Path table size(bytes): 40
Max brk space used 22000
187 extents written (0 MB)
Pool debian refreshed

Starting install...
Creating domain... | 0 B 00:00:00 
Domain creation completed.
Pool debian defined from /dev/stdin

Formatting '/home/user/libvirt_images/debian/debian3.qcow2', fmt=qcow2 size=2147483648 backing_file=/home/user/libvirt_images/debian/debian-8.5.0-openstack-amd64.qcow2 encryption=off cluster_size=65536 lazy_refcounts=off refcount_bits=16
Pool debian refreshed

Total translation table size: 0
Total rockridge attributes bytes: 763
Total directory bytes: 4458
Path table size(bytes): 40
Max brk space used 22000
187 extents written (0 MB)
Pool debian refreshed

Starting install...
Creating domain... | 0 B 00:00:00 
Domain creation completed.
Use following command to connect to your cluster: 'ssh -i "/home/user/.ssh/id_rsa" debian@debian1'

real 0m4.916s
user 0m2.112s
sys 0m0.268s
Thu Aug 25 10:26:20 CEST 2016 # <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
$ ssh debian1
Warning: Permanently added 'debian1,192.168.122.30' (ECDSA) to the list of known hosts.

The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
debian@debian1:~$ date
Thu Aug 25 08:26:38 UTC 2016 # <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

Віртуальні машини готові до використання вже через 20 секунд (ноутбук з SSD), на HDD приблизно на 10 секунд довше.
Так виглядає вміст директорії
~/libvirt_images/debian

$ find ~/libvirt_images/debian -ls
4456467 4 drwxrwxr-x 5 user user 4096 Aug 25 11:13 /home/user/libvirt_images/debian
4853836 4 drwxrwxr-x 3 user user 4096 Aug 25 11:13 /home/user/libvirt_images/debian/debian2
4853838 4 -rwxrwxr-x 1 user user 157 Aug 25 11:13 /home/user/libvirt_images/debian/debian2/rebuild_iso.sh
4853837 376 -rw-rw-r-- 1 libvirt-qemu-kvm 382976 Aug 25 11:13 /home/user/libvirt_images/debian/debian2/cidata.iso
4985097 4 drwxrwxr-x 3 user user 4096 Aug 25 11:13 /home/user/libvirt_images/debian/debian2/openstack
4985103 4 drwxrwxr-x 2 user user 4096 Aug 25 11:13 /home/user/libvirt_images/debian/debian2/openstack/latest
4985104 4 -rw-rw-r-- 1 user user 574 Aug 25 11:13 /home/user/libvirt_images/debian/debian2/openstack/latest/user_data
4985105 4 -rw-rw-r-- 1 user user 152 Aug 25 11:13 /home/user/libvirt_images/debian/debian2/openstack/latest/meta_data.json
4456468 7752 -rw-r--r-- 1 libvirt-qemu-kvm 7995392 Aug 25 11:13 /home/user/libvirt_images/debian/debian1.qcow2
4456470 7752 -rw-r--r-- 1 libvirt-qemu-kvm 7995392 Aug 25 11:13 /home/user/libvirt_images/debian/debian3.qcow2
4722884 4 drwxrwxr-x 3 user user 4096 Aug 25 11:13 /home/user/libvirt_images/debian/debian1
4722886 4 -rwxrwxr-x 1 user user 157 Aug 25 11:13 /home/user/libvirt_images/debian/debian1/rebuild_iso.sh
4722885 376 -rw-rw-r-- 1 libvirt-qemu-kvm 382976 Aug 25 11:13 /home/user/libvirt_images/debian/debian1/cidata.iso
4853832 4 drwxrwxr-x 3 user user 4096 Aug 25 11:13 /home/user/libvirt_images/debian/debian1/openstack
4853833 4 drwxrwxr-x 2 user user 4096 Aug 25 11:13 /home/user/libvirt_images/debian/debian1/openstack/latest
4853834 4 -rw-rw-r-- 1 user user 574 Aug 25 11:13 /home/user/libvirt_images/debian/debian1/openstack/latest/user_data
4853835 4 -rw-rw-r-- 1 user user 152 Aug 25 11:13 /home/user/libvirt_images/debian/debian1/openstack/latest/meta_data.json
4985106 4 drwxrwxr-x 3 user user 4096 Aug 25 11:13 /home/user/libvirt_images/debian/debian3
4985112 4 -rwxrwxr-x 1 user user 157 Aug 25 11:13 /home/user/libvirt_images/debian/debian3/rebuild_iso.sh
4985111 376 -rw-rw-r-- 1 libvirt-qemu-kvm 382976 Aug 25 11:13 /home/user/libvirt_images/debian/debian3/cidata.iso
4985107 4 drwxrwxr-x 3 user user 4096 Aug 25 11:13 /home/user/libvirt_images/debian/debian3/openstack
4985108 4 drwxrwxr-x 2 user user 4096 Aug 25 11:13 /home/user/libvirt_images/debian/debian3/openstack/latest
4985109 4 -rw-rw-r-- 1 user user 574 Aug 25 11:13 /home/user/libvirt_images/debian/debian3/openstack/latest/user_data
4985110 4 -rw-rw-r-- 1 user user 152 Aug 25 11:13 /home/user/libvirt_images/debian/debian3/openstack/latest/meta_data.json
4456469 7752 -rw-r--r-- 1 libvirt-qemu-kvm 7995392 Aug 25 11:13 /home/user/libvirt_images/debian/debian2.qcow2
4456471 474092 -rw-rw-r-- 1 libvirt-qemu-kvm 485465600 Aug 25 10:18 /home/user/libvirt_images/debian/debian-8.5.0-openstack-amd64.qcow2

Мережа і DNS настроюються за допомогою dnsmasq та
send host-name "<hostname>"
. На етапі конфігурації мережі ми присвоюємо віртуальній машині hostname, потім вона запитує IP-адреса DHCP і відправляє свій hostname в dnsmasq, dnsmasq прописує hostname у внутрішній DNS. Використовуючи dnsmasq як резолвер ми отримуємо IP нової віртуальної машини.
Я також запускав віртуальні машини всередині віртуальних машин. Вкладена (nested) віртуалізація KVM працює цілком нормально, але можливо потрібна додаткова конфігурація.
Недоліки:
  • Скрипти написані на bash
  • Необхідно заздалегідь налаштувати оточення libvirt
  • Немає гнучкості, яку надають Vagrantfile або Dockerfile, після деплоя доведеться запускати свій улюблений puppet/chef/ansible/etc.
  • Поки немає підтримки PXE boot образів, щоб емулювати/тестувати deploy з нуля таких провайдерів як Hetzner/OVH/etc.
  • Потрібна допомога по поліпшенню.
  • Потрібно придумати гарну назву.
  • У планах додати підтримку FreeBSD і bhyve.
Ну і сам репозиторій тут: https://github.com/kayrus/scripts. Там же інформація щодо налаштування оточення libvirt.
В якості бонусу в репозиторії вже є скрипт деплоя кластера Kubernetes під CoreOS.
P. S. Гадаю я не єдиний, хто придумав щось подібне. Буду вдячний посиланнях не більш зрілі рішення.
Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.