По ходу работы над CoreOS и Kubernetes мне приходилось часто воспроизводить окружения пользователей, чтобы помочь им решить проблему. Согласитесь, что при запуске OS при помощи контейнера, не всегда можно добиться полного функционала OS, т.к. часто приходилось решать вопросы, связанные с systemd.


Так и родилась идея написать костыли, которые с легкостью помогут мне поднять кластер из почти любой оперционной системы, эдакий OpenStack в миниатюре. В настоящий момент в качестве гостевых полностью поддерживаются следующие OS:


  • Ubuntu
  • Debian
  • CentOS 6/7 + atomic
  • Fedora + atomic
  • CoreOS

Частично:



Публикации поспособствовал коллега, который случайно увидел, как я тестирую код. А теперь о преимуществах перед 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    Name                           State
----------------------------------------------------
 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. Полагаю я не единственный, кто придумал что-то подобное. Буду признателен ссылкам не более зрелые решения.

Поделиться с друзьями
-->

Комментарии (4)


  1. kvaps
    25.08.2016 12:41
    +2

    Cкрипты определенно получились у вас довольно классные и свою задачу выполняют, спасибо.
    Но в вашем случае я бы использовал OpenNebula.
    В отличие от OpenStack эта платформа очень легковестна, и ее с легкостью можно использовать к для больших датацентров, так и всего на одном компьютере. При этом она сохраняет всю свою гибкость и многофункциальность.
    Среди функций есть так же свой Marketplace с популярными образами операционных систем и автоматическое конфигурирование виртуальных машин посредством, так называемой, контекстулизации. Все машины создаются как и у вас из базового образа.
    В вашем случае для ее работы вам хватит того же самого libvirt с lvm или zfs.


    1. miron36357
      25.08.2016 13:41

      Ну не знаю, Nutanix CE тоже бы подошёл. Всё никак не могу на него перейти, надо SSD обзавестись.


  1. FruTb
    25.08.2016 21:24

    Хмм. Может я конечно ничего не понимаю но: а что мешает поднимать это-же все в LXC контейнерах? НУ к примеру тем-же docker (нужно облако — берем docker-swarm)?
    Оно еще и тормозить не будет так отчянно как через паравиртуализацию… и поднимается 1ой коммандой и описание всего что надо в ось поставить и вообще все что сделать после установи оси надо — декларатиное и легко ложиться под системы контроля версий.


    1. kay
      25.08.2016 21:31

      Низкоуровневые тесты необходимо проводить в полной изоляции.


      1) LXC у меня вешал ядро и засорял файловую систему. Виртуальная машина если и зависнет, то с малой долей вероятности повесит хост, а значи рабочему процессу не помешает.
      2) Первоначально разрабатывалось только для CoreOS, а CoreOS просто так в Docker не запустишь. Там система обновления, базирующася на GPT, readonly /usr раздел и прочие тонкости.