Translate

неділю, 2 лютого 2014 р.

Віртуалізація з OpenVZ

Віртуалізація дуже актуальна тема, адже дозволяє більш раціонально використовувати ресурси серверу. Дещо раніше я писав про віртуалізацію на базі KVM, що власне є технологією повної віртуалізації, на відміну від OpenVZ, про яку і піде далі мова.

OpenVZ — це реалізація технології віртуалізації на рівні операційної системи, яка базується на ядрі Linux. OpenVZ дозволяє на одному фізичному сервері запускати безліч ізольованих копій операційної системи, так званих контейнерів (Virtual Environments, VE).

Оскільки OpenVZ базується на ядрі Linux, в ролі «гостьових» систем можуть виступати тільки дистрибутиви GNU/Linux. Проте віртуалізація на рівні операційної системи у OpenVZ дає також і певні переваги, а саме: зручність у адмініструванні, щільніше розміщення віртуальних контейнерів в хост-системі (що зазвичай позитивно відображено на вартості VPS-хостингу), і дещо кращу продуктивність в порівнянні з технологіями повної віртуалізації.

Звісно, що і недоліків достатньо. Головний із них, що на відміну від KVM, модулі OpenVZ не входять у ванільне ядро, тому для фунціонування останнього необхідне окреме ядро і версія його далеко не остання. На момент публікації цієї статті, остальна стабільна версія - 2.6.32-042stab084.14. Із цього по-суті випливає, що хост-системою на OpenVZ може виступати не кожен дистрибутив, а лише з ядром біля 2.6.32 версії. Тому скажімо OpenVZ-ядро під Ubuntu 12.04 LTS навряд заведеться (що я вже спробував), адже ядро тут версії 3.8.0. Але не все так погано, адже для RedHat 6 (CentOS 6, Scientific Linux 6) та Debian 7 "Wheezy" все просто інсталюється і ці дистрибутиви офіційно підтримуюються Parallels.

Наступний недолік в тому, що всі контейнери працюють під одним ядром, тобто ядром хост-системи, і додати необхідний модуль ядра вже буде не так просто, як у випадку з технологіями повної віртуалізації. Тому з цим необхідно буде змиритись на самому початку.
Про певні інші недоліки та переваги можна прочитати тут.

Теорія без практики – мертва, тож самий час описати установку і налаштування хост-системи для OpenVZ. У якості хост-системи я обрав CentOS 6.5 (необхідно лиш попередньо не забути перевірити наявність правил iptables). Додаємо репозиторії для установки ядра OpenVZ та утиліт для роботи із контейнерами:

# wget -P /etc/yum.repos.d/ http://ftp.openvz.org/openvz.repo
# rpm --import http://ftp.openvz.org/RPM-GPG-Key-OpenVZ

Встановлюємо ядро та утиліти:

# yum install vzctl vzquota ploop

Офіційний мануал говорить, що зі vzctl від версії 4.4 налаштування параметрів ядра ( /etc/sysctl.conf )  не обов'язкове

Перевантажуємось і перевірємо версію ядра:

# uname -a
Linux centos 2.6.32-042stab084.14 #1 SMP Mon Dec 16 18:16:56 MSK 2013 x86_64 x86_64 x86_64 GNU/Linux

Якщо версія така ж - то все зроблено вірно, інакше варто перевірити яке саме ядро завантажує GRUB.  Переходимо до створення контейнеру.

# vzctl create 103 --ostemplate debian-7.0-x86_64 --config vswap-2g
--2014-01-14 16:54:54--  http://download.openvz.org/template/precreated/debian-7.0-x86_64.tar.gz
Resolving download.openvz.org... 199.115.104.11, 2620:e6::104:11
Connecting to download.openvz.org|199.115.104.11|:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 303736979 (290M) [application/x-gzip]
Saving to: `/vz/template/cache/debian-7.0-x86_64.tar.gz'

43% [===========================>                ] 132,616,648 2.17M/s  eta 2m 1s

Темплейт для створення контейнеру із Debian 7 буде скачано із  сайту OpenVZ і встановлено. 

# vzlist -a
      CTID      NPROC STATUS    IP_ADDR         HOSTNAME
       103          - stopped   -               -

Задамо конфігурацію новому контейнеру:

# vzctl set 103 --onboot yes --save  # додаємо контейнер в автозавантаження після старту хост-системи
# vzctl set 103 --hostname debian7.example.com --save  # задаємо хостнейм
# vzctl set 103 --save --ipadd 192.168.1.31  # призначаємо IP, задання VENET-з'єднання
# vzctl set 103 --save --nameserver 8.8.8.8 --nameserver 8.8.4.4  # описуємо DNS-сервера
# vzctl set 103 --save --cpus 4  # к-ть cpu-ядер
# vzctl set 103 --save --ram 8G  # RAM
# vzctl set 103 --save --swap 4G  # swap
# vzctl set 103 --save --diskspace 100G  # задання розміру диску
# vzctl start 103  # запускаємо контейнер
# vzctl exec 103 passwd   # встановлюємо пароль root-користувачу

Таким чином було створено контейнер на Debian 7. Для зв'язку із зовнішнім світом було налаштовано VENET-з'єднання. 

Надалі можна дещо виправити конфігурацію контейнера, відредагувавши конфігураційний файл:

# vim /etc/vz/conf/103.conf

# RAM
PHYSPAGES="0:2097152"

# Swap
SWAPPAGES="0:1048576"

# Disk quota parameters (in form of softlimit:hardlimit)
DISKSPACE="104857600:104857600"
DISKINODES="200000:220000"
QUOTATIME="0"

# CPU fair scheduler parameter
CPUUNITS="1000"
VE_ROOT="/vz/root/$VEID"
VE_PRIVATE="/vz/private/$VEID"
OSTEMPLATE="debian-7.0-x86_64"
ORIGIN_SAMPLE="vswap-2g"
ONBOOT="yes"
HOSTNAME="debian7.example.com"
NETIF="ifname=eth0,mac=00:18:51:CF:E9:09,host_ifname=veth104.0,host_mac=FE:FF:FF:FF:FF:FF"
NAMESERVER="8.8.8.8 8.8.4.4"
CPUS="4"

Фізично контейнер знаходиться за адресою /vz/private/103:

# cd /vz/private/103
# ls
bin   dev  home  lib64 media  opt   root  sbin  srv      tmp  var
boot  etc  lib   lost+found  mnt    proc  run   selinux  sys  usr

Якщо контейнер працює, то всі зміни краще додавати використовуючи шлях /vz/root/103, котрий синхронізується із /vz/private/103.

Загалом OpenVZ має можливість налаштування VETH (Virtual ETHernet) чи VENET (Virtual NETwork) мережевого девайсу всередині контейнеру. VETH дозволяє broadcasts-повідомлення всередині контейнеру та має MAC-адресу на інтерфейсі, тому можна налаштувати автоматичне отримання адреси за допомогою DHCP чи налаштування Samba-серверу, що також потребує broadcasts-повідомлень. VETH-інтерфейс лише задається за допомогою vzctl, все подальше налаштування інтерфейсу (задання IP, gateway) необхідно проводити в самому контейнері. Проте скоріш за все VENET-з'єднання буде більше ніж достатньо. До переваг останнього можна віднести вищу швидкість роботи в порівнянні із VETH та швидке налаштування ресурсами хост-машини. 


Дещо більше про з'єднання контейнерів можна почитати на wiki OpenVZ

Для прикладу також наведу створення контейнеру з VETH-з'єднанням. Для цього спершу необхідно створити vmbr0 bridge. Для чого встановлюємо bridge-utils і налаштовуємо інтерфейс vmbr0 таким чином:

# vim /etc/sysconfig/network-scripts/ifcfg-vmbr0 
DEVICE="vmbr0"
BOOTPROTO="static"
IPV6INIT="no"
ONBOOT="yes"
TYPE="Bridge"
DELAY=0
IPADDR=192.168.1.30
NETMASK=255.255.255.0
GATEWAY=192.168.1.1

А eth0 переналаштовуємо таким чином:

# vim /etc/sysconfig/network-scripts/ifcfg-eth0 
DEVICE="eth0"
ONBOOT="yes"
IPV6INIT="no"
TYPE="Ethernet"
BRIDGE="vmbr0"

Попередньо eth0 був налаштований на статичний IP 192.168.1.30.

Створюємо /etc/vz/vznet.conf  із таким вмістом:

# vim /etc/vz/vznet.conf 
#!/bin/bash
EXTERNAL_SCRIPT="/usr/sbin/vznetaddbr"

Перезапускаємо хост-машину.

Цього разу оберемо інший дистрибутив для створення контейнеру із VETH мережевим з'єднанням:

# vzctl create 102 --ostemplate centos-6-x86_64 --config vswap-1g

І відповідно налаштуємо:

# vzctl set 102 --save --onboot yes
# vzctl set 102 --save --hostname centos6.example.com
# vzctl set 102 --save --netif_add eth0,,,FE:FF:FF:FF:FF:FF  # задання VETH-з'єднання
# vzctl set 102 --save --nameserver 8.8.8.8 --nameserver 8.8.4.4
# vzctl set 102 --save --cpus 4
# vzctl set 102 --save --ram 8G
# vzctl set 102 --save --swap 4G
# vzctl set 102 --save --diskspace 100G
# vzctl start 102
# vzctl exec 102 passwd

Задамо конфігурацію на інтерфейс eth0 контейнеру:

# cat << _EOF_ > /vz/root/102/etc/sysconfig/network-scripts/ifcfg-eth0
DEVICE="eth0"
HOSTNAME="centos6"
IPV6INIT="no"
MTU="1500"
TYPE="Ethernet"
ONBOOT=yes
BOOTPROTO=static
IPADDR=192.168.1.32
NETMASK=255.255.255.0
GATEWAY=192.168.1.1
_EOF_


Перезапустимо мережу в новоствореному контейнері:

# vzctl exec 102 /etc/init.d/network restart

Для Ubuntu/Debian необхідно правити файл /etc/network/interfaces:


# cat << _EOF_ > /vz/root/102/etc/network/interfaces
auto lo eth0
iface lo inet loopback
iface eth0 inet static
address 192.168.1.32
netmask 255.255.255.0
gateway 192.168.1.1
_EOF_

# vzctl exec 102 /etc/init.d/networking restart


В результаті мережеве з'єднання (VETH) має виглядати таким чином:

# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 16436 qdisc noqueue state UNKNOWN 
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: venet0: <BROADCAST,POINTOPOINT,NOARP> mtu 1500 qdisc noop state DOWN 
    link/void 
3: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN 
    link/ether 00:18:51:c0:eb:63 brd ff:ff:ff:ff:ff:ff
    inet 192.168.1.35/24 brd 192.168.1.255 scope global eth0
    inet6 fe80::218:51ff:fec0:eb63/64 scope link 
       valid_lft forever preferred_lft forever

Коли ж VENET так:

# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 16436 qdisc noqueue state UNKNOWN 
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: venet0: <BROADCAST,POINTOPOINT,NOARP,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN 
    link/void 
    inet 127.0.0.2/32 scope host venet0
    inet 192.168.1.31/32 brd 192.168.1.31 scope global venet0:0
3: eth0: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN 
    link/ether 00:18:51:a6:29:b0 brd ff:ff:ff:ff:ff:ff

Управління контейнерами чи їх квотами проводиться через утиліту vzctl. Опишу найбільш популярні команди:

# vzctl start $CTID  # старт контейнеру з номером $CTID
# vzctl stop $CTID  # зупинка контейнеру
# vzctl restart $CTID  # перевантаження
# vzctl destroy $CTID  # видалення контейнеру, попередньо необхідно його зупинити
# vzctl exec $CTID command  # запуск команди в контейнері
# vzctl enter $CTID  # логін в консоль контейнеру $CTID через хост-машину
# vzctl set $CTID different_options --save # налаштування опцій для віртуальної машини

Звичайно, що також є можливість налаштування квот для кожного із контейнерів без їх перевантаження.
Обмеження обягу диску та к-ті інод робиться наступним чином (синтаксис задання такий software_limit : hardware_limit):

# vzctl set 101 --diskspace 1000000:1100000 --save  # 1000000 - це приблизно 1GB
# vzctl set 101 --diskinodes 90000:91000 --save  # задання к-ті дискових інод.
# vzctl set 101 --quotatime 600 --save  # час на який можна збільшити квоти до hardware limit

Також можна налаштувати приорітет дискового вводу/виводу (disk I/O) . Найвищий рівень 7, найнижчий - 0. По замовчуванню disk I/O встановлюється в 4, проте це можна змінити:

# vzctl set 101 --ioprio 6 --save

А перевірити можна так:

# grep IOPRIO /etc/vz/conf/101.conf
IOPRIO="6"

Таким чином можна збільшити/зменшити к-ть ядер до 3, що буде використовувати контейнер:

# vzctl set 101 --cpus 3 --save

Якщо хост-система має менше ядер - то звичайно команда виконана не буде.
Установка кількості оперативної та swap-пам'яті відбувається настуним чином:

# vzctl set 101 --physpages 512M --save
# vzctl set 101 --swappages 512M --save

Детальніше про квоти можна почитати за адресою https://openvz.org/User_Guide/Managing_Resources
Задля перегляду всіх контейнерів і їх станів можна скористатись утилітою vzlist:

# vzlist -a
CTID NPROC STATUS   IP_ADDR       HOSTNAME
101  42    running  192.168.1.31  ubuntu1310.example.com
102  17    running   -            centos6.example.com
103  20    running   -            debian7.example.com
104  20    running   -            debian72.example.com


Дуже важливо згадати про дампи (бекап) контейнерів. Для цього є стороння утиліта, що зветься vzdump. За її допомогою можливо майже без зупинки роботи скопіювати/мігрувати/забекапити  контейнер. Спочатку її необхідно встановити:

# rpm -ivh "http://ftp.openvz.org/contrib/utils/vzdump/vzdump-1.2-4.noarch.rpm"

Користуватись нею так:

# vzdump --suspend 102
INFO: starting new backup job: vzdump --suspend 102
...
INFO: backup mode: suspend
INFO: starting first sync /vz/private/102/ to /vz/dump/vzdump-openvz-102-2014_02_02-14_05_46.tmp
INFO: Finished Backup of VM 102 (00:02:14)
INFO: Backup job finished successfuly

І одразу є можливість відресторити дамп в нову машину із новим CTID:

# vzrestore /vz/dump/vzdump-openvz-102-2014_02_02-14_05_46.tar 201
INFO: restore openvz backup '/vz/dump/vzdump-openvz-102-2014_02_02-14_05_46.tar' using ID 201
INFO: extracting archive '/vz/dump/vzdump-openvz-102-2014_02_02-14_05_46.tar'
INFO: Total bytes read: 649799680 (620MiB, 62MiB/s)
INFO: extracting configuration to '/etc/vz/conf/201.conf'
INFO: restore openvz backup '/vz/dump/vzdump-openvz-102-2014_02_02-14_05_46.tar' successful

Здається, що це все про що хотів написати. Не соромтесь ставити коментарі, якщо виникли якісь питання.

Немає коментарів:

Дописати коментар