Ext4.

Я выбрал всё таки файловую систему ext4, хотя многие тесты упорно рекомендуют ext3. Журналирование в файловых системах, естественно, не прибавляет скорости в I/O, но с ним можно разобраться, а сама ext4, помимо журнала, тоже получила множество улучшений и жаль было бы их терять. Ведь Google не зря перешёл с ext3 на ext4 без журнала!

К этому времени мне уже было известно о благотворном влиянии отключения шлагбаумов barrier=0 (или nobarrier).

Что за шлагбаумы? Код файловой системы обязан перед созданием записи фиксации [журнала] быть абсолютно уверенным, что вся информация о транзакции помещена в журнал. Просто делать запись в правильном порядке недостаточно; современные диски имеют кэш большого объёма и меняют порядок записи для оптимизации производительности. Поэтому файловая система обязана явно сообщить диску о необходимости записать все журнальные данные на носитель перед созданием записи фиксации; если сначала будет создана запись фиксации, журнал может быть повреждён. Блокирующая система ввода-вывода ядра предоставляет такую возможность благодаря использованию механизма ? «шлагбаумов» (barriers); проще говоря, «шлагбаум» запрещает запись любых блоков, посланных после него, до того момента, как всё, что было прислано перед «шлагбаумом», будет перенесено на носитель. При использовании «шлагбаумов» файловая система может гарантировать, что всё, что находится на диске, целостно в любой момент времени. Отключая шлагбаум barrier=0, мы ускоряем операции записи на разделы ext4.

В одной из англоязычных статей, её автор приводил тесты для файловых систем для MySQL сервера и с barrier=0 ext4 была не хуже ext3.

Кроме barrier=0, добавлены такие опции как relatime и commit=600.
relatime — атрибут времени доступа (atime) обновляется, но только в том случае, если изменились данные файла (атрибут mtime) или его статус (атрибут ctime).
commit – время между сбросами буферов на диск.

Естественно, такие манипуляции проводятся, так как точно будет использоваться источник бесперебойного питания. То есть UPS это один из ускоряющих элементов сервера.

Планировщик.

Где-то в глубине души я знал, что с планировщиком CFQ нам не по пути, он сделан под углом честного дележа доступа к диску и пытается сортировать очередь к диску, зная про головки HDD и минимизацию их перемещения. Но имеет ли смысл что-то сортировать у виртуального диска?

Вначале я выставил планировщик noop, который является простейшим планировщиком и ничего не сортирует. Но статьи уважаемой IBM по лучшему использованию KVM утверждают, что лучше использовать планировщик deadline и что так поступает сама IBM. Да и Canonical вместо CFQ стала использовать deadline.

Пока решил довериться IBM и Canonical и выставить deadline по умолчанию.

Советы IBM по вопросам работы памяти.

IBM считает, и наверное не безосновательно, что для бо́льшой производительности нужно отключить zone_reclaim_mode и выставить swappiness=0.

NUMA (Non-Uniform Memory Access — неравномерный доступ к памяти или Non-Uniform Memory Architecture — Архитектура с неравномерной памятью) — схема реализации компьютерной памяти, используемая в мультипроцессорных системах, когда время доступа к памяти определяется её расположением по отношению к процессору.

numa
Оборудование большинства операционных систем — это системы NUMA, со своей штрафом-платой (NUMA penalty) при удалённом доступе к памяти.

NUMA penalty = CPIremote / CPIlocal , где CPI — cycles per instruction.

Если NUMA penalty становится высокой, то операционная система осуществляет очистку (zone reclaim).

Для примера, операционная система выделяет память в ноде NUMA, но нода NUMA полна. В таком случае, операционная система начинает очистку памяти локальной ноды NUMA, а не выделяет немедленно память на удалённой ноде NUMA. Выигрыш в выделении памяти на локальной ноде перевешивает недостаток скорости при очистке памяти (reclaiming memory).

Однако, в некоторых ситуациях очистка памяти (reclaiming memory) снижает производительность до такой степени, что верно и обратное. Иными словами, выделение памяти на удалённой ноде NUMA будет быстрее, чем очищение памяти на локальной ноде.

Гостевые операционные системы могут вызывать zone reclaim в следующих случаях:

  • гостевая операционная система использует гигантские страницы (huge pages).
  • используется Kernel SamePage Merging (KSM) для слияния одинаковых страниц памяти гостевых операционных систем.

Настройка huge pages, использование KSM и отключение zone reclaim эти шаги IBM считает хорошей практикой при использовании виртуализации KVM.

zone_reclaim_mode.

Для отключения zone_reclaim_mode на KVM хосте, нужно убедиться в текущем состоянии дел.

cat /proc/sys/vm/zone_reclaim_mode

Моя Proxmox VE нода выдала 0 и значит разработчики Proxmox VE уже решили нашу задачу. Если у вас не ноль, то в /etc/sysctl.conf нужно указать vm.zone_reclaim_mode=0 и рестарт.

swappiness.

Дефолтное значение swappiness = 60. Можно выставить от 0 до 100. Когда выставлен swappiness = 0 на системах Intel Nehalem, то менеджер виртуальной памяти удаляет страничный кеш (page cache) и кеш буфера (buffer cache), а не скидывает программу из памяти в swap.

Платформа Intel Nehalem использует расширенные таблицы страниц Extended Page Table (EPT). EPT не устанавливает бит доступа к страницам, которые используются гостевыми операционными системами. Таким образом, менеджер виртуальной памяти Linux не может использовать свой алгоритм LRU (least recently used), чтобы точно определить какие страницы не нужны. Точнее сказать, алгоритм LRU не может точно определить какие страницы в гостевых операционных системах являются лучшими кандидатами на вытеснение в swap. В это ситуации, во избежание ненужного своппинга лучше выставить swappiness=0.

Системы с процессорами Advanced Micro Devices (AMD) и с технологией Nested Page Table (NPT) не имеют описанной выше проблемы.

Узнайте текущее значение cat /proc/sys/vm/swappiness

Для KVM хоста в /etc/sysctl.conf нужно указать vm.swappiness=0.

huge pages.

Приложения, которые используют много непрерывных участков памяти, получат максимальную выгоду от huge pages, поскольку будет генерироваться меньше промахов Translation Lookaside Buffer (TLB).

Процессор чаще находит нужное отображение в TLB и реже сканирует таблицу страниц.

Таким образом, huge pages увеличивает производительность приложений, которые используют большие и непрерывные участки памяти.

Приложения, которые используют маленькие и непрерывные блоки памяти, не получат от huge pages выгоды.

Huge pages нужно настраивать в ручную и знать необходимость приложения в огромных блоках памяти. По этой причине, пока не стал связываться с ними.

Быстродействие MySQL сервера.

Исторически так сложилось, что каждый из физических серверов под конкретную задачу обладал установленным на нём сервере MySQL для хранения данных. Чтобы удобно было администрировать задачу через веб интерфейс нужен веб сервер Apache. Другими словами сложилась ситуация — всё свое ношу с собой.

Так было с DHCP сервером — самописная веб морда, записи MAC и IP в MySQL, PHP, Perl, Apache. Такая же участь у почтовика — Postfix, учётные записи в MySQL, PostfixAdmin, PHP, Apache. Биллинг Интернет трафика — Squid, Squid2Mysql, учётные записи в MySQL, PHP, Apache.

Тяжело вырваться из этого круга, но хотелось сделать единый MySQL сервер с единым Apache и местом обитания всех веб морд. Создал виртуальную машину mysqlserver, которая обладала сервером MySQL и веб сервером Apache.

Единый MySQL позволит легко манипулировать доступом к базам данным. Но с другой стороны, я опасался эффекта «все яйца в одной корзинке». Зависимость от отдельного MySQL сервера могла сделать неработоспособной какую-либо службу при недоступности MySQL сервера.

Частично негативный эффект от единой точки отказа был сглажен. Например, DHCP сервер берёт записи из базы MySQL и формирует свой dhcpd.conf при изменениях в записях MAC и IP адресов. При отказе MySQL физически не изменить базу данных через веб интерфейс и, следовательно, DHCP сервер не увидит изменений и будет работать с ранее сформированным dhcpd.conf.

Новый Squid 3 изменил представление о сохранении своих логов вместо файлов в базу данных MySQL.

logformat squid_mysql %ts.%03tu %6tr %>a %Ss %03Hs %<st %rm %ru %un %Sh %<A %mt
access_log daemon:/etc/star_scripts/squid/log_mysql_daemon.conf squid_mysql
logfile_daemon /etc/star_scripts/squid/log_mysql_daemon.pl

Пришлось по другому запихивать логи в базу, нежели как раньше скриптом из проекта squid2mysql. Нашёл perl скрипт труд итальянца Marcello Romani, но у него своя схема базы данных и шикарные представления view, которые создают отличные запросы на все случаи жизни прокси сервера. Чтобы веб морда Squid2Mysql ничего не заметила и продолжала нормально свою работу, не смотря на новую схему от итальянца, я просто сделал нужный view и сопоставил новые поля из новой таблицы в старые поля старой таблицы. При недоступности MySQL скрипт от итальянца работает идеально и Squid продолжает работу и предоставляет доступ в Интернет. Единственное, что трафик не учитывается, но это лучший расклад при гипотетической неработоспособности отдельного сервера MySQL. Лучше терять логи, но дать доступ в Интернет.

То есть DHCP и Squid не смертельно связаны с MySQL и могут некоторое время прожить и без него. Но Postfix с MySQL связаны более жёстко. В MySQL хранятся почтовые пользователи и Postfix при своей работе постоянно обращается к базе данных. Для защиты от спама и вирусов, Postfix связан с Amavis + SpamAssassin, которые частично используют базу данных, чтобы получать белые списки людей, которых нужно исключить из защиты.

DELAY_KEY_WRITE.

Решил поиграть в великого оптимизатора MySQL и получить порцию знаний по этой теме. Почитал замечательную книгу авторства Бэрон Шварц, Петр Зайцев, Вадим Ткаченко, Джереми Заводны, Арьен Ленц, Дерек Боллинг «MySQL. Оптимизация производительности». Для себя открыл, неведомый мне прежде, режим отлаженной записи ключей DELAY_KEY_WRITE. Это ускоряет многочисленные INSERT в таблицу, так как с этой опцией индексы хранятся только в памяти и записываются на диск в последнюю очередь, по команде FLUSH TABLES или по завершению mysqld.

Для таблицы access_log, в которую записываются огромные логи Squid 3 скриптом итальянца, я сделал ALTER TABLE access_log DELAY_KEY_WRITE = 1, помня об недостатках DELAY_KEY_WRITE и обязательному наличию UPS.

Сегментированные таблицы.

Прочёл на Хабре срач про сегментированные таблицы, которые калькой с английского часто называют партицированием. Кто-то говорил о сырости и глюкавости данного решения, дескать написанное криворукими индийцами за горстку риса. Кто-то утверждает, что это бред сивой кобылы.

Смысл в том, что сегментированная таблица позволит призрачно разделить таблицу по какому-либо критерию на призрачные таблицы с меньшим количеством строк. Меньше количество строк = меньше нагрузка при запросах. Меня бы устроило разделение access_log по дате месяца, так как жизнь показала, что база очень быстро распухает и работа с ней замедляется.

Профи советуют сегментировать примерно так.

ALTER TABLE access_log
PARTITION BY RANGE( TO_DAYS(date_day) )
(
PARTITION y2013m01 VALUES LESS THAN( TO_DAYS('2013-01-01') ),
PARTITION y2013m02 VALUES LESS THAN( TO_DAYS('2013-02-01') ),
...
PARTITION y2020m11 VALUES LESS THAN( TO_DAYS('2020-11-01') ),
PARTITION y2020m12 VALUES LESS THAN( TO_DAYS('2020-12-01') ),
PARTITION pcatchall VALUES LESS THAN (MAXVALUE)
);

Не большой совет от гуру — создать секции заранее, чтобы потом было проще. Вместо ... много много строк по аналогии от 2013 до 2020 года и все их месяцы.
Теперь EXPLAIN PARTITIONS SELECT покажет, что использование WHERE date_day будет затрагивать определённую секцию, что благотворно влияет на быстродействие.

Но принявшись за сегментирование, меня ждал fail. Как я понял, банально попал под ограничения секционированных таб­лиц и запрос ALTER TABLE access_log PARTITION BY RANGE ( TO_DAYS (date_day) ) выдал A PRIMARY KEY must include all columns in the table's partitioning function.

Гуру SQL объяснили: ограничение, которое встретилось вам, звучит примерно так: каждый уникальный ключ (включая PK, который является UK NOT NULL) должен содержать все колонки, используемые в выражении, по которому идет секционирование. Вызвано это тем, что в MySQL отсутствуют глобальные индексы, так как поддержание подобных индексов достаточно дорогая операция. Иными словами, имея PK id и секционирование по полю ddate, MySQL бы пришлось каким-то образом гарантировать, что id уникален во всех партициях сразу. Для этого нужен индекс, проходящий сквозь все секции. MySQL такого не умеет. А вот если PKем станет пара id, ddate, то достаточно, чтобы внутри каждой секции эти значения были уникальными. Так как ddate в разных секциях будет разный, то это автоматически гарантирует уникальность пары id, ddate на всей таблице.

Получается или нужно сегментирование или детально разбираться в не в своей схеме таблицы и грамотно изменить индексы. Решил пока повременить с сегментацией таблицы.

Оптимизация запросов.

Решил в скриптах Perl и PHP, которые за многие годы до меня администраторы на создавали для упрощения администрирования, разобраться и оптимизировать запросы в них.

Начал с простого. Ищем все SELECT FROM WHERE и анализируем колонки таблиц, участвующие в запросе. Банальное создание индексов на такие поля и EXPLAIN SELECT показывает не множество задетых строк, а единицы. Вроде мелочь, а проектировщик в прошлом не удосужился сделать такую отличную вещь, как индекс для поля. Минус у индекса, если можно назвать это минусом, можно считать необходимость в дополнительном обновлении индекса при операциях INSERT, UPDATE в таблице. Но кроме access_log все остальные таблицы не испытывают мощных INSERT, UPDATE и можно смело навешивать index налево и направо.

В поиске столбцов, которые участвуют в запросах и не имеют индекса, очень помогает параметр log-queries-not-using-indexes в /etc/mysql/my.cnf. Чтение лога mysql помогает найти виновника и устранить недоразумение. В логе сразу видно кто, откуда и каким запросом умудряется цеплять множество строк таблиц, не используя индексы.

Из книги «MySQL. Оптимизация производительности» узнал, что поле с индексом в запросе с WHERE должен стоять левее и когда встречал сложное условие, то переписывал его так, чтобы сначала было поле, а потом уже больше-меньше и выражение.

Потом пошла оптимизация посложнее. Автор Squid2MySQL в веб админке постоянно использовал запросы к «тяжёлой» таблице squidlog, хотя часто нужные данные лежали в более «лёгкой» таблице rdnload, в которой уже лежали пред вычисленные значения скаченного трафика. Логику автора не понять. Как писал выше, данные по скачанному через Squid теперь заносились скриптом итальянца, а не родным скриптом проекта, поэтому squidlog стал представлением (VIEW) для таблицы access_log. Но скрипты веб интерфейса Squid2Mysql я всё равно изменил, чтобы запросы больше обращались к таблице rdnload, чем через представление squidlog к access_log.

Оптимизация Apache.

Самая лучшая оптимизация Apache — это использовать что-то полегче, чем Apache . Но известность и популярность Апача немаловажные вещи. Решено поставить именно его, но настроить его под низкие требования малочисленных администраторов.

У нас не высоконагруженный проект, а сайт с вебмордами админок. В общем, параметры такие:

StartServers 1
MinSpareServers 1
MaxSpareServers 2
MaxClients 5
MaxRequestsPerChild 300

StartServers определяет количество процессов сервера, запускаемых изначально, сразу после его старта. MinSpareServers и MaxSpareServers определяют минимальное и максимальное количество дочерних «запасных» процессов Apache. Такие процессы находятся в состоянии ожидания входящих запросов и не выгружаются, что даёт возможность ускорить реакцию сервера на новые запросы. MaxClients определяет максимальное количество параллельных запросов, одновременно обрабатываемых сервером. Когда количество одновременных соединений превысит это количество, новые соединения будут поставлены в очередь на обработку. MaxClients определяет максимально-допустимое число дочерних процессов Apache, запущенных одновременно. MaxRequestsPerChild определяет количество запросов, которое должен обработать дочерний процесс Apache, прежде чем завершить своё существование. Когда обработанных запросов станет больше MaxRequestsPerChild, то дочерний процесс будет перезапущен и это помогает при возможных утечках кривых скриптов.

Установка VirtIO в FreeBSD.

Про паравиртуальные драйвера VirtIO я уже писал, поэтому повторно расписывать что это, не имеет смысла. Привожу пример установки virtio-драйверов в гостевую систему FreeBSD.
Обновляем систему
# freebsd-update fetch
# freebsd-update install

Устанавливаем пакет virtio-kmod. В диалогах везде принимаем настройки по умолчанию.
# cd /usr/ports/emulators/virtio-kmod
# make clean install

После установки копируем модули в каталог ядра
# cp -Rp /usr/local/modules/* /boot/kernel/
# kldxref /boot/kernel

Правим конфигурацию загрузчика
# vi /boot/loader.conf
virtio_load="YES"
virtio_pci_load="YES"
virtio_blk_load="YES"
if_vtnet_load="YES"
virtio_balloon_load="YES"

Правим /etc/fstab, использование virtio определяет другое именование блочных устройств
# vi /etc/fstab
# Device        Mountpoint      FStype  Options Dump    Pass#
/dev/vtbd0p2    /               ufs     rw      1       1
/dev/vtbd0p3    none            swap    sw      0       0

Имена сетевых карт также изменятся, поэтому следует отредактировать имена в rc.conf
# vi /etc/rc.conf
ifconfig_vtnet0="DHCP"

Выключаем гостя.
# shutdown -p now

Перед запуском меняем настрйоки виртуальной машины, менятем тип блочного устройства на virtio. После чего запускаем машину и проверяем что VirtIO включено и используется.
# kvm ... -drive file=/dev/vg00/k101-fbsd-root,if=none,index=0,id=disk101 -device virtio-blk-pci,drive=disk101
— netdev tap,ifname=itap101,id=itap101,script=no,downscript=no -device virtio-net-pci,netdev=itap101,mac=00:fc:44:d5:01:01
# kldstat
Id Refs Address            Size     Name
1   12 0xffffffff80200000 11cdab0  kernel
2    5 0xffffffff813ce000 4ca0     virtio.ko
3    1 0xffffffff813d3000 5880     virtio_pci.ko
4    1 0xffffffff813d9000 5010     virtio_blk.ko
5    1 0xffffffff813df000 aeb0     if_vtnet.ko
6    1 0xffffffff813ea000 3210     virtio_balloon.ko

Как сжать виртуальный жесткий диск qcow2

Имейте в виду! Не забывайте остановить виртуальную машину! Запуск этого команды при запущенной виртуальной машине категорически запрещено!

qemu-img convert  source_not_compressed_qcow2.img -O qcow2 -c  target_compressed_qcow2.img

Ubuntu 10.04 серверов и настольных

В Ubuntu, доступ к управлению слоя контролируется через членство в группе libvirtd UNIX.

Чтобы включить Libvirt управления доступом для пользователей, добавьте их в эту группу на хост-сервере виртуализации:

  $ sudo usermod-G-libvirtd usersrssh

Они будут иметь доступ к управлению Libvirt удаленно.

Следуйте инструкциям в нижней части этой страницы, чтобы проверить работоспособность.

Затем изменить /etc/libvirt/libvirtd.conf и раскомментируйте следующие строки:

  unix_sock_group = "Libvirt"
  unix_sock_rw_perms = "0770"

После чего перезапустить libvirt и проверить подключение с удаленного хоста

mount -t debugfs debugfs /sys/kernel/debug

Для контроля за работой KVM необходимо в fstab добавить :

debugfs /sys/kernel/debug debugfs 0 0
 и контролировать командой
  kvm_stat

Сегодня хочу поделиться с вами одним из своих наработанных мануалов, который отточен многоразовым применением, про который с уверенностью могу сказать, что «точно работает!» без лишних танцев с бубном.
Ориентирована статья скорее на начинающих системных администраторов, чем на гуру (для них тут ничего нового нет 🙂 ), и в ней я постараюсь раскрыть рабочий и довольно быстрый вариант развертывания сервера виртуальных машин, стараясь при этом охватись как можно больше нюансов и подводных камней.

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

Начнем с того, что если Вы читаете это, то у вас уже готова ОС CentOS 6 (я использовал версию 6.3), причем для установки гостевых ВМ разной битности (32 или 64), хост-сервер (физический сервер, на котором и будем устанавливать KVM вместе с ВМ) должен быть именно с 64-битной ОС.
Все действия выполняются из-под пользователя root.

Итак, приступим к руководству.

1. Шаг — Подготовка

Посмотрим информацию по процессору

# cat /proc/cpuinfo | egrep "(model name|flags)"

Некоторые флаги

1. HT — Hyper-Threading support
Реализация технологии одновременной мультипоточности. Технология увеличивает производительность процессора при определённых рабочих нагрузках. Если включена, то система определяет два логических процессора на один физический процессор (ядро). Присутствует исключительно в сериях процессоров Intel Xeon, Pentium 4, Atom, Core i3, Core i5, Core i7.
2. LM — Long Mode (x86-64 support)
Грубо говоря, если указана, процессор выполнен по 64-битной технологии (также имеет названия: x86-64, x64, AMD64, Intel64, EM64T). Это расширение архитектуры x86 с полной обратной совместимостью. В процессорах Intel поддержка появилась с поздних Pentium 4, у AMD — c Athlon64.
3. VMX (Intel), SVM (AMD) — Hardware virtualization support
Поддержка процессором технологий Intel VT-x или AMD-V означает наличие дополнительных инструкций для предоставления прямого доступа к ресурсам процессора из гостевых систем. Позволяет приблизить производительность гостевых систем к реальным и сократить затраты производительности на поддержание хостовой платформы. В настоящий момент Virtual Machine Extensions поддерживается во многих процессорах Intel & AMD, хотя подобные расширения имеют и другие процессорные архитектуры, например, Cell.
4. SSE*, SSSE*, XMM*, 3DNow!, MMX и пр.
Различные наборы инструкций для процессоров. Широко используются компиляторами в целях оптимизации кода под конкретную архитектуру.
5. AES — Intel Advanced Encryption Standard
Этот довольно спорный набор инструкций увеличивает производительность при кодировании/декодировании AES, присутствующий только у серии Intel Xeon. Часто используется фанатами Intel для подкрепления крутизны серверной линейки CPU, хотя довольно известен тот факт, что процессоры AMD более сильны в криптовании данных, например, в алгоритме SHA.

Проверяем, поддерживает ли CPU аппаратную виртуализацию:

#egrep '(vmx|svm)' --color=always /proc/cpuinfo

Если вывод не пустой и искомые флаги подсвечены цветом,  значит — процессор поддерживает аппаратную виртуализацию.

 

Кому интересно, все действия выполнялись на конфигурации Intel Xeon Quad Core E3-1230 3.20 GHz / 8GB / 2x 1TB.

Устанавливаем KVM и библиотеки виртуализации:

# apt-get install qemu-kvm libvirt-bin virtinst  uml-utilities

теперь нужно вклчючить возможность форвардинга и проксирования arp запросов

#sudo sysctl net.ipv4.conf.all.forwarding=1
#sudo sysctl net.ipv4.conf.all.proxy_arp=1

добавим в /etc/sysctl.conf

echo 'net.ipv4.conf.all.forwarding=1' >> /etc/sysctl.conf
echo 'net.ipv4.conf.all.proxy_arp=1' >> /etc/sysctl.conf

и применить их

#sysctl -p 

Запускаем сервис KVM

# service libvirtd start

Смотрим, загружен ли модуль KVM

# lsmod | grep kvm

Должны получить вывод:

kvm_intel              52890  16
kvm                   314739  1 kvm_intel

В данном случае видим, что загружен модуль kvm_intel, так как произволитель CPU — Intel.

Проверка подключения к KVM

# virsh sysinfo

Должны получить вывод:

<sysinfo type='smbios'>
  <bios>
    <entry name='vendor'>HP</entry>
    <entry name='version'>J01</entry>
  .....

2. Шаг — Создание хранилища для виртуальных машин (Storage Pool)

[urlspan]Здесь[/urlspan] приводится описание, как настроить хранилище разных видов.
В рассматриваемом же примере описан простой тип хранилища — для каждой ВМ создается свой файл *.img под виртуальный жесткий диск (или диски — если добавить их несколько), размещены они будут в директории /guest_images.
Только у нас эта директория будет точкой монтирования отдельного жесткого диска хост-сервера, специально отведенного для этих нужд.
Безопасность сохранения данных и то, что нужно создавать как минимум зеркальный raid массив, чтобы не потерять данные ВМ в случае сбоя жесткого диска, мы не будем, так как это — отдельная тема.

Просмотрим список физических дисков на хост-сервере:

# fdisk -l

Получился вывод:

Disk /dev/sda: 1000.2 GB, 1000204886016 bytes
......
Disk /dev/sdb: 1000.2 GB, 1000204886016 bytes
......

На жестком диске sda установлена ОС, его не трогаем, а вот на sdb создаем раздел на все свободное место диска с файловой системой ext4:
(более подробно про следующие операции можно почитать здесь)

Выбираем диск для редактирования

# fdisk /dev/sdb

Создаем новый раздел

Command (m for help): n
Command action
   e   extended
   p   primary partition (1-4)
p
Partition number (1-4): 1

Сохраняем изменения

Command (m for help): w
The partition table has been altered!

Создаем файловую систему ext4 на всем свободном месте диска /dev/sdb

# mkfs.ext4 /dev/sdb1

Создаем точку монтирования нашего жесткого диска для файлов виртуальных машин:

# mkdir /cd_images
# chmod 700 /cd_images# ls -la /cd_images
total 8
drwx------.  2 root root 4096 May 28 13:57 .
dr-xr-xr-x. 26 root root 4096 May 28 13:57 ..

//***************В разработке*****************************//
Многие советуют отключить вообще Selinux, однако мы выберем иной путь. Мы настроим его правильно.

<span class="comment"># semanage fcontext -a -t virt_image_t /cd_images</span>

Если выполнение этой команды не будет успешным, надо установить дополнительный пакет. Сначала узнаем, какой пакет предоставляет данную команду

# yum provides /usr/sbin/semanage

Получим вывод:

Loaded plugins: rhnplugin
policycoreutils-python-2.0.83-19.8.el6_0.x86_64 : SELinux policy core python utilities
Repo        : rhel-x86_64-server-6
Matched from:
Filename    : /usr/sbin/semanage
policycoreutils-python-2.0.83-19.1.el6.x86_64 : SELinux policy core python utilities
Repo        : rhel-x86_64-server-6
Matched from:
Filename    : /usr/sbin/semanage

Устанавливаем policycoreutils-python

# yum -y install policycoreutils-python

После этого снова:

# semanage fcontext -a -t virt_image_t /vm/cd_images (/vm/kvmcd)

//********************************************//
Смонтируем раздел /dev/sdb1 в /vm/kvmcd

# mount -t ext4 /dev/sdb1 /vm/kvmcd

Отредактируем файл /etc/fstab для того, чтобы при перезагрузке хост-сервера раздел с ВМ монтировался автоматически

# mcedit /etc/fstab

Добавляем строку по примеру тех, что уже имеются в файле

/dev/sdb1               /vm/kvmcd           ext4    defaults        1 1

Сохраняем файл и продолжаем создание хранилища:

# virsh pool-define-as cd_images dir localhost /vm/kvmcd /dev/sdb1 cd_image /vm/kvmcd
Pool cd_images defined
или
# virsh pool-define-as cd_images dir ---- --target /var/lib/libvirt/images/cd

Проверяем, создалось ли оно:

# virsh pool-list --all
Name                 State      Autostart
-----------------------------------------
default              active     yes
cd_images            inactive   no

Далее:

# virsh pool-build cd_images
Pool cd_images built

Запускаем хранилище:

# virsh pool-start cd_images
Pool cd_images started
# virsh pool-list --all
Name                 State      Autostart
-----------------------------------------
default             active     yes
cd_images           active     no

Добавляем в автозагрузку:

# virsh pool-autostart cd_images
Pool guest_images_dir marked as autostarted
# virsh pool-list --all
Name                 State      Autostart
-----------------------------------------
default              active     yes
cd_images            active     yes

Проверяем:

# virsh pool-info cd_images

3. Шаг — Настройка сети на хост-сервере

!!! ВАЖНО!!!

# apt-get install bridge-utils

Положим, что для выхода «в мир» использовался интерфейс eth0 и он был соответствующим образом настроен.
На нем настроен IP-адрес 10.110.10.15 из /24 сети, маска — 255.255.255.0, шлюз 10.110.10.1.
Продолжаем, создаем сетевой интерфейс типа «bridge» на хост-сервере

# mcedit /etc/network/interfaces

Содержимое файла

# The loopback network interface
auto lo
iface lo inet loopback

# The primary network interface
allow-hotplug eth0
#iface eth0 inet static
iface eth0 inet manual
auto kvmbr0
iface kvmbr0 inet static
address 172.16.174.248
netmask 255.255.255.0
network 172.16.174.0
broadcast 172.16.174.255
gateway 172.16.174.1
bridge_ports eth0
# dns-* options are implemented by the resolvconf package, if installed
dns-nameservers 172.16.174.3
dns-search adminunix.ru

 

!!! Важно!!!
DEVICE=«eth0» Имя интерфейса должно остаться таким, как было в системе. Если у вас для выхода в Интернет использовался интерфейс eth1, тогда редактировать надо его.

Когда проверили все, перезагружаем сеть:

# service network restart

Проверяем состояние подключения типа «bridge»:

# brctl show

Получаем что-то вроде этого

bridge name	bridge id		STP enabled	interfaces
kvmbr0		8000.0007e92a9957	no		eth0

Делаем настройки в iptables, чтобы трафик виртуалок «ходил» через соединение типа bridge

# iptables -I FORWARD -m physdev --physdev-is-bridged -j ACCEPT
# service iptables save
# service iptables restart

Опционально: можно улучшить быстродействие соединения bridge, поправив настройки в /etc/sysctl.conf

sudo sysctl net.ipv4.conf.all.forwarding=1
#sudo sysctl net.ipv4.conf.all.proxy_arp=1

После этого

# sysctl -p /etc/sysctl.conf
#/etc/init.d/libvirt-bin restart

4. Шаг — Установка новой виртуальной машины

Установка CentOS на гостевую ВМ:

virt-install -n VMName_2 --ram 1024 --arch=x86_64
--vcpus=1 --cpu host --check-cpu
--extra-args="vnc sshd=1 sshpw=secret ip=static reboot=b selinux=0"
--os-type linux --os-variant=rhel6 --boot cdrom,hd,menu=on
--disk pool=guest_images_dir,size=50,bus=virtio
--network=bridge:br0,model=virtio
--graphics vnc,listen=0.0.0.0,keymap=ru,password=some.password.here
--noautoconsole --watchdog default,action=reset --virt-type=kvm
--autostart --location http://mirror.yandex.ru/centos/6.3/os/x86_64/

Примечание 1:
VMName_2 — имя новой виртуальной машины
–ram 1024 — кол-во виртуальной памяти
–arch=x86_64 — архитектура ОС виртуалки
–vcpus=1 — кол-во виртуальных процессоров
–os-type linux — тип ОС
–disk pool=guest_images_dir,size=50 — размещение хранилища, размер вирт. диска
–network=bridge:br0

Примечание 2:
Если на ВМ нужна «белая сеть», тогда ставим
--network=bridge:br0
Если на ВМ требуется «серая сеть», тогда ставим
--network=bridge:virbr0
В этом случае для ВМ будет присвоен серый IP по DHCP от хост-сервера.
--graphics vnc,listen=0.0.0.0,keymap=ru,password=some.password.here
Тут указываем пароль для подключения к ВМ по vnc

Установка Windows на гостевую ВМ:

virt-install --connect qemu:///system --arch=x86_64
-n VMName_1 -r 1024 --vcpus=1
--disk pool=guest_images_dir,size=50,bus=virtio,cache=none
-c /iso/Windows2008R2RU.ISO --graphics vnc,listen=0.0.0.0,keymap=ru,password=some.password.here
--noautoconsole --os-type windows --os-variant win2k8
--network=bridge:br0,model=e1000 --disk path=/iso/virtio-win.iso,device=cdrom,perms=ro

Примечание:
Параметры такие же, как и в примере с установкой CentOS. Но есть различия.
При установке ОС Windows не увидит виртуального жесткого диска, поэтому надо подгрузить дополнительный виртуальный cdrom с драйверами /iso/virtio-win.iso — расположение файла ISO с драйверами виртуального диска. Взять можно отсюда.

Выполняем команду на установку новой ВМ, затем подключаемся по vnc к хост-серверу для продолжения установки ОС. Для того, чтобы узнать порт для подключения, выполняем:

 

# netstat -nltp | grep q
tcp        0      0 0.0.0.0:5900                0.0.0.0:*                   LISTEN      64141/qemu-kvm
tcp        0      0 0.0.0.0:5903                0.0.0.0:*                   LISTEN      63620/qemu-kvm
tcp        0      0 0.0.0.0:5904                0.0.0.0:*                   LISTEN      6971/qemu-kvm
tcp        0      0 0.0.0.0:5905                0.0.0.0:*                   LISTEN      57780/qemu-kvm

При установке новой ВМ, порт vnc-сервера увеличится на 1. При удалении ВМ, порт освобождается,
и затем выдается новой ВМ. То есть, номер порта последней ВМ не обязательно самый большой из 590…
Чтобы узнать, на каком порту vnc виртуалка с определенным названием, вводим:

 

# virsh vncdisplay VMName_1
:3

где VMName_1 — имя ВМ, :3 — номер по порядку порта, начиная с 5900, то есть подключаться надо на порт 5903, но в программе UltraVNC сработает и так 10.110.10.15:3
kvm_05

Примечание
Если при создании ВМ вылетает ошибка Permission denied, kvm не может открыть файл диска ВМ *.img,
значит, надо разрешить выполнение действий qemu-kvm из-под root (предполагается, что управление
ВМ производится из-под специально созданного для этих целей пользователя, например, libvirt). Но мы обойдемся и пользователем root.

Поправляем конфиг:

# vi /etc/libvirt/qemu.conf

Находим и раскомментируем в нем строки:

# The user ID for QEMU processes run by the system instance.
user = "root"
# The group ID for QEMU processes run by the system instance.
group = "root"

Полезно знать:
Конфиги ВМ находятся здесь /etc/libvirt/qemu/
Для того, чтобы отредактировать параметры (добавить процессор, ОЗУ или еще что-то),
ищем конфиг ВМ с нужным названием, редактируем:

# vi /etc/libvirt/qemu/VMName_1.xml

К примеру, можно указать статический порт vnc для конкретной ВМ, чтобы всегда подключаться к нужному порту

<graphics type='vnc' port='5914' autoport='no' listen='0.0.0.0' passwd='some.password.here'>
<listen type='address' address='0.0.0.0'/>
</graphics>

Теперь у этой ВМ порт vnc будет — 5914. Не забудьте перезагрузить libvirtd для применения изменений. Саму ВМ тоже следует перезагрузить. Поэтому изменяйте конфигурационный файл ВМ пока она выключена, далее выполняйте service libvirtd reload, затем стартуйте ВМ.

Команды для управления ВМ:

virsh -c qemu:///system help
Встроенная помощь по командам

virsh -c qemu:///system list --all
Посмотреть статус установленных ВМ 

virsh -c qemu:///system start vsrv1
Запусить ВМ vsrv1 

virsh -c qemu:///system shutdown vsrv1
Послать команду завершения работы ВМ 

virsh -c qemu:///system destroy vsrv1
Принудительно завершить работу ВМ 
virsh -c qemu:///system undefine vsrv1
Удалить ВМ

5. Шаг — Настройка сети в случае «серых» IP-адресов в ВМ

Если на 4 шаге вы выбрали серую сеть для новой ВМ (--network=bridge:virbr0), то надо выполнить следующие действия (на хост-сервере!) для проброса трафика на ВМ
Разрешить форвардинг трафика на уровне ядра ОС:

# sysctl net.ipv4.ip_forward=1
# iptables -I FORWARD -j ACCEPT
# iptables -t nat -I PREROUTING -p tcp -d 10.110.10.15 --dport 5910 -j DNAT --to-destination 192.168.122.170:5901

Здесь 10.110.10.15 — белый (внешний) IP хост-сервера. 192.168.122.170 — серый IP-адрес гостевой ОС.

# iptables -t nat -I POSTROUTING -p tcp -s 192.168.122.170 --sport 5901 -j SNAT --to-source 10.110.10.15:5910

На примере установки ОС CentOS на гостевой машине, когда установка перешла в графический режим, и предлагает подключиться на локальный порт 5901 гостевой ОС.
Подключаемся из ПК, за которым сидите, по vnc к 10.110.10.15:5910 или 10.110.10.15:10 тоже сработает в UltraVNC.

По такому же принципу можно прокинуть порт (стандартный) RDP 3389 или SSH 22 в гостевую ОС.

6. Шаг — Подготовка к управлению виртуальными машинами удаленного сервера с удобным графическим интерфейсом (используя virt-manager)

Есть много способов «прокинуть» графику удаленного сервера на ПК, за которым выполняете действия администрирования. Мы остановимся на ssh-туннелировании.
Положим, что вы выполняете действия с локального ПК под управлением Windows (в операционных системах под управлением Linux сделать это куда легче :), нужно выполнить всего одну команду ssh -X username@12.34.56.78, конечно, с оговоркой, что на удаленном сервере X11 forwarding разрешен и вы сидите за локальным Linux ПК c графической оболочкой), тогда нам необходимо

1. Всем знакомый PuTTY,
2. Порт сервера X для Windows — Xming
3. В настройках PuTTY включить «Enable X11 Forwarding»
Сделать, как показано на картинке:
kvm_01

В момент подключения к удаленному серверу Xming должен быть уже запущен.
На хост-сервере с CentOS для SSH включить X11 Forwarding, для этого отредактируйте файл sshd_config:

# mcedit /etc/ssh/sshd_config
X11Forwarding yes
X11DisplayOffset 10
X11UseLocalhost yes

После этого

# /etc/init.d/sshd restart

Устанавливаем virt-manager на хост-сервере:

# apt-get install virt-manager

Еще один компонент

# apt-get install xorg-x11-xauth

7. Шаг — Непосредственный запуск virt-manager

После этого надо перезайти по SSH к удаленному серверу. Xming должен быть запущен.
Запускаем графическую утилиту управления виртуальными машинами

# virt-manager

Откроется окно virt-manager
kvm_02

Консоль управления ВМ
kvm_03

Конфигурация ВМ и ее изменение
kvm_04

Надеюсь, читателю понравилась статья. Лично я, прочитай бы подобную в своё время, резко сократил бы потраченное время на то, чтобы перелопатить множество мануалов от разных админов, для разных ОС; сохранил бы кучу времени, потраченное на гугление, когда появлялись все новые и новые нюансы.

KVM tools

Type the following command to install kvm-tools package which contains some diagnostics and debugging tools for KVM, such as kvmtrace and kvm_stat, enter:

# yum -y install kvm_tools

You need to mount debugfs, enter:

# mount -t debugfs debugfs /sys/kernel/debug

fstab

# debugfs /sys/kernel/debug debugfs 0 0

# kvm_stat

Пример, получаемый при запуске kvm_stat

kvm-stat-tool

 

Другие полезные инструменты для отладки работы

  • ps, pstree, and top
  • vmstat, iostat, and lsof
  • tcpdump, brctl, ip, and ifconfig