Поиск по моему блогу

Создание шаблона виртуальной машины для OpenVZ/ProxMox VE

Когда-то давно мне показали на ProxMox VE - Debian-based дистрибутив с удобным веб-интерфейсом для запуска виртуальных машин KVM и OpenVZ, выполненный с исользованием Perl-а. С тех пор я не то чтобы стал его фанатом, но весьма уважаю.
Одной из приятных особенностей ProxMox-а является полная автоматизация рутинных действий. Отпала необходимость знать наизусть десятки ключей утилит vzctl и kvm, все необходимые действия можно выполнить при помощи красивой веб-мордочки.

Как следствие этой приятной особенности можно отметить создание новых OpenVZ-шных виртуальных машин (далее - "контейнеров") по заранее заданному шаблону в два клика. На официальном сайте ProxMox можно скачать уже готовые шаблоны для решения наиболее популярных задач. Однако они могут кому-то и не подойти. А чтобы создать "с нуля" свой собственный (кастомный) шаблон, как показывает практика, придется хорошенько потрудиться, поскольку данная процедура не столь интуитивно понятна. Далее речь пойдет о том, как наиболее эффективно создать custom-ный шаблон контейнера на основе дистрибутива Debian Squeeze.

Disclaimer

  1. На момент написания этого поста Squeeze является тестовой веткой дистрибутива Debian GNU/Linux. Однако, насколько можно судить по новостям, она (ветка) заморожена и релиз уже "на подходе". Поэтому именно эта версия сейчас наиболее актуальна.
  2. Пост является по сути переработкой и дополнением статьи из вики проекта OpenVZ. Тем не менее, здесь учтены некоторые характерные особенности именно 6-й ветки и самого ProxMox-а.
  3. Данный пост описывает преимущественно ProxMox, но все сказанное здесь с некоторыми поправками можно применять и к "голой" OpenVZ.
  4. Данный пост относится к категории "Чтобы самому потом не забыть", поэтому рассматривается задача в столь узкоспециализированной постановке. Тем не менее, ее можно расценивать просто как пример, иллюстрирующий суть подхода к созданию произвольных шаблонов.

Подготовка

Итак, вы решили создать новый шаблон для последующего использования в ProxMox/OpenVZ. Нам понадобится:
  1. Уже работающая и запущенная хост-машина. В терминах OpenVZ - "CT0", нулевой контейнер. В моем примере хост-машина называется "rambo".
  2. Доступное зеркало репозиториев дистрибутива Debian GNU/Linux 6.0 (Squeeze). Я использую локальное зеркало. Вы можете использовать, например, зеркало "Яндекса" как самое быстрое в рунете.
  3. Понимание того, какой набор софта требуется иметь в шаблоне. Лично я буду делать максимально аскетичный шаблон, только самое необходимое.
  4. Понимание того, под какую архитектуру необходим шаблон (i386 или amd64). Выбор архитектуры - это отдельная тема, здесь она рассматриваться не будет. В данном примере я предпочту i386.

Создание заготовки

  1. Логинимся в шелл на хост-машину.
  2. Создаем пустую виртуалку. Для примера назначим ей номер 777. Проще всего это можно сделать, следующим образом. Копируем файл "/etc/vz/conf/ve-pve.auto.conf-sample" в "/etc/vz/conf/777.conf". Добавляем в этот файл строчку вида ORIGIN_SAMPLE="pve.auto".
    echo 'ORIGIN_SAMPLE="pve.auto"' >> /etc/vz/conf/777.conf
    Иначе переклинит веб-интерфейс. Создаем папку "777" в "/var/lib/vz/private"
    mkdir /var/lib/vz/private/777
    Потом в веб-интерфейсе находим виртуальную машину с номером 777 и прописываем в настройках такие параметры как hostname, IP-адрес, доступное дисковое пространство и т.п., сохраняем. Это нужно для того чтобы наша тестовая виртуалка в-принципе запустилась бы, хоть как-нибудь.
  3. Переходим в директорию "/var/lib/vz/private".
    cd /var/lib/vz/private
  4. Даем команду вида
    debootstrap --arch i386 squeeze 777 ftp://mirror.yandex.ru/debian/
    Где первый параметр - архитектура, второй параметр - ветка дистрибутива, третий - путь к папке где нужно создать образ системы, четвертый - путь к репозиторию. Ждем окончание выполнения debootsrap-а. Если он напишет
    I: Base system installed successfully
    - значит все хорошо. Если нет - надо выяснять что случилось. Как вариант, ему не удалось скачать какие-либо пакеты с зеркала репозитория.
  5. Запускаем нашу новоиспеченную машину с номером 777. Либо через веб-интерфейс, либо "vzctl start 777" в консоли. Как больше нравится. После чего забираемся вовнутрь виртуальной машины (для примера я назвал её "billet") при помощи команды "vzctl enter 777" (либо через встроенный Java-based VNC-сервер ProxMox-а, если так больше нравится) и приступаем к ее допиливанию.

Первичная обработка

Для начала нам нужно убрать все лишнее. Особенно это касается различных пакетов для работы с терминалом (TTY) и модулями ядра, ибо ни того, ни другого внутри контейнера нет. Затем установить минимально необходимый набор софта, после чего перейти к чистовой обработке. Внимание! Все последующие инструкции нужно выполнять НЕ на хост-машине, а внутри контейнера! Итак.
  1. Сносим всякие module-init-tools и udev. "Реального" железа у нас нет, поэтому и управлять им нечем.
    apt-get purge module-init-tools udev && rm -rf /etc/udev
  2. Отключаем getty в inittab. Его у нас тоже нет.
    sed -i -e '/getty/d' /etc/inittab && init q
  3. Правим файл "/etc/apt/sources.list". Прописываем там те зеркала, которые нам нужны. Например, так:
    echo 'deb ftp://mirror.yandex.ru/debian squeeze main contrib non-free' > /etc/apt/sources.list
  4. Отключаем назойливые попытки устанвливать рекомендуемые пакеты. Мы сами знаем что нам делать со своими файлами (с).
    echo 'APT::Install-Recommends "0";' > /etc/apt/apt.conf.d/02norecom
    echo 'APT::Install-Suggests "0";' >> /etc/apt/apt.conf.d/02norecom
  5. Обновляем кеш apt-а, устанавливаем пакет SSH.
    apt-get update
    apt-get install ssh
  6. Назначем root-у какой-нибудь пароль.
    passwd
  7. Выходим из контейнера ("exit"), после чего логинимся в него обратно, но уже по SSH. Поскольку на этот раз мы залогинились "честно", а не "нагло вломились" из хост-машины, то переменные окружения оказались выставлены скриптами в те значения, которые были задуманы дистростроителями. Таким образом, мы можем приступить к получистовой обработке.

Получистовая обработка

  1. Устанавливаем пакет locales.
    apt-get install locales
    Выбираем нужную локаль (в большинстве случаев это ru_RU.UTF-8):
    dpkg-reconfigure locales
    Ура, теперь оно говорит на нашем родном языке!
  2. Устанавливаем нужную timezone, чтоб оно знало где находится.
    dpkg-reconfigure tzdata
  3. Устанавливаем те пакеты, которые не входят в состав базовой системы, но тем не менее пригодятся в 90% случаев. Тут уж дело вкуса каждого. Лично я всегда для себя доустанавливаю joe, mc, less, sudo. Мне так удобнее.
    apt-get install joe mc less
  4. Хорошей идеей будет уже сейчас создать для себя непривилегированного пользователя и сразу положить в шаблон свои открытые SSH-ключи (~/.ssh/authorized_keys). Сэкономит уйму времени в дальнейшем. Также лично я отключаю в настройках демона SSH вход с проверкой пароля
    PasswordAuthentication no
    ChallengeResponseAuthentication no
    и вход от имени рута
    PermitRootLogin no
    Так безопаснее.

Если вы уверены, что уже установили полный набор софта, который хотели бы иметь в шаблоне, то можно переходить к чистовой обработке.


Чистовая обработка

На этом этапе придется учесть все многочисленные тонкости работы технологии OpenVZ. В частности то, что она подставляет контейнеру собственные urandom, системные часы, файловую систему, у нее нет терминалов. И то, что для каждой новой машины, создаваемой впоследствии по шаблону, нужно будет генерировать новые RSA и DSA SSH-ключи.
  1. Виртуалка не монтирует файловые системы самостоятельно (fstab у нее в подавляющем большинстве случаев пустой). Поэтому в запуске скрипта "checkroot" нет надобности:
    update-rc.d -f checkroot.sh remove
  2. У виртуалки нет собственных системных часов. Их ей предоставляет хост-машина. Поэтому в /etc/default/rcS добавляем переменную
    HWCLOCKACCESS=no
  3. Собственного генератора псевдослучайных чисел (/dev/urandom) у виртуалки тоже не имеется: он наследуется от "реальной" машины. Управлять, соответственно, тоже нечем.
    update-rc.d -f urandom remove
  4. В скрипте /etc/init.d/rc все еще остается упоминание о stty, которого нет. Поэтому при загрузке виртуалка будет писать в лог ошибки, с ним связанные. Чтобы они не мозолили нам глаза, закомментируем эту строку.
    sed -ie 's/^stty/#stty/g' /etc/init.d/rc
  5. В этом же скрипте изменяем переменную CONCURRENCY на значение "none". В противном случае слишком умные init-скрипты новой ветки дистрибутива будут ругаться на метки (маркеры), расставляемые OpenVZ в init-директориях. Да и веб-интерфейс не будет отображать логи запуска демонов.
    sed -ie 's/^CONCURRENCY=makefile$/CONCURRENCY=none/' /etc/init.d/rc
  6. Не знаю как вас, а меня всегда напрягает сообщение motd, по умолчанию содержащееся в файле "/etc/motd.tail". Я обычно пишу туда что-нибудь более жизнерадостное.
    echo 'Hi there, yeah!' > /etc/motd.tail
  7. По умолчанию после каждой записи в лог демон syslog делает системный вызов sync(). Вряд ли OpenVZ-виртуалка когда-либо "упадет" в отрыве от хост-машины, сама по себе. А если вдруг "упадет" хост-машина (вместе со всеми виртуалками на борту), то логи виртуалок все равно нам ничем не помогут. Поэтому ради увеличения производительности такое поведение syslog-а имеет смысл пресечь.
    sed -i -e 's@\([[:space:]]\)\(/var/log/\)@\1-\2@' /etc/*syslog.conf
  8. В папку /etc кладем текстовый файл с названием "appliance.info" ( "cat >> /etc/appliance.info" ). В нем следует отразить название шаблона, архитектуру, описание и т.д. и т.п. Это упростит поиск и выбор нужного шаблона среди прочих архивов при создании новой машины посредством веб-интерфейса. Файл должен иметь примерно следующий вид:
    Name: debian-6.0-sust
    Version: 6.0-2
    Type: openvz
    OS: debian-6.0
    Section: system
    Maintainer: SuSt 
    Architecture: i386
    Installed-Size: 211
    Infopage: http://klinkov.ya.ru/
    Description: Debian 6.0 (minimal)
     A small Debian Squeeze system including all standard packages.
    Самое главное - без ошибок заполнить поля "Name", "Version", "OS", "Architecture". Именно они потом будут фигурировать в списке доступных шаблонов.
  9. Очищаем кеш менеджера пакетов apt.
    apt-get clean
  10. И последнее на этом этапе. Когда мы будет содавать новый контейнер на основе нашего шаблона, то нужно заново генерировать SSH-ключи. Чтобы не делать этого каждый раз "руками", положим в /etc/rc2.d соответствующий скрипт, который сделает это за нас, а потом тихонько самоликвидируется.
    rm -f /etc/ssh/ssh_host_*
    cat << EOF > /etc/rc2.d/S01ssh_gen_host_keys
    #!/bin/bash
    ssh-keygen -f /etc/ssh/ssh_host_rsa_key -t rsa -N ''
    ssh-keygen -f /etc/ssh/ssh_host_dsa_key -t dsa -N ''
    rm -f \$0
    EOF
    chmod a+x /etc/rc2.d/S01ssh_gen_host_keys
Теперь выключаем виртуалку и приступаем к финишным операциям

Финишная обработка

Повторяю, данные действия нужно выполнять на хост-машине когда все предыдущие шаги выполнены и виртуальная машина уже остановлена ("vzctl stop 777").
  1. Переходим в папку с нашим почти что доделанным шаблоном
    cd /var/lib/vz/private/777
  2. Удаляем все лишнее. Внимание! Сперва проверьте, что вы находитесь в правильной директории! ("pwd")
    rm -r var/run/*
    rm -r tmp/*
    rm -r var/run/*
    find var/log -type f -exec rm {} \;
  3. Сетевые настройки CT0 тоже подставит сам при запуске.
    echo -n > etc/network/interfaces
    echo -n > etc/resolv.conf

    Примечание: если контейнеру впоследствии будет назначен veth-интерфейс (а не venet), тогда файл interfaces потом придется заполнить "ручками", но уже на созданной машине, а не в шаблоне.
В-принципе, на этом всё. Осталось только упаковать наш шаблон.

Упаковка

Упаковка представляет собой обычную процедуру архивации сперва tar-ом, потом gzip-ом. Но есть два нюанса. Файл appliance.info должен быть расположен в tar-архиве первым - это раз. Файл с архивом должен иметь определенное название - это два. Готовый архив затем кладется в папку "/var/lib/vz/template/cache/", где его сможет впоследствии сможет найти ProxMox. Лично я "накатал" для себя простенький скрипт, которым и упаковываю шаблоны.
#!/bin/bash

CONTAINER="/var/lib/vz/private/777"
TARGET="/var/lib/vz/template/cache/debian-6.0-sust_6.0.0-1_i386.tar"

/bin/tar cpf "$TARGET" --numeric-owner -C "$CONTAINER" ./etc/appliance.info
/bin/tar rpf "$TARGET" --numeric-owner -C "$CONTAINER" --exclude ./etc/appliance.info .
/bin/gzip "$TARGET"
Обратите внимание на название tar-архива. Магия заключается в том, что знаки тире и подчеркивания должны быть именно в том количестве, и в тех местах, что и в моем примере. Дело в том, что потом это имя будут парсить Perl-овые скрипты ProxMox-а. И если это имя скриптам "не понравится", то могут возникнуть проблемы. Опять-же, обратите внимание на то, что в имени должна быть указана архитектура ("i386").

Все. Готово. Можно пользоваться свежеиспеченным шаблоном для создания OpenVZ-шных виртуальных машин под управлением ProxMox VE.

Сложно? Да, не просто. Особенно если раньше этим никогда не занимался. Благо, шаблоны приходится делать не так уж и часто. Во всяком случае, явно не каждый день.
 
Источник http://klinkov.ya.ru/replies.xml?item_no=317

Комментариев нет:

Реклама от BigBN