2

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

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

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

0_43fc9_2e581e6c_orig

Как следствие этой приятной особенности можно отметить создание новых 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-адрес, доступное дисковое пространство и т.п., сохраняем. Это нужно для того чтобы наша тестовая виртуалка в-принципе запустилась бы, хоть как-нибудь.

    0_43fca_b0e716c2_orig2

  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 -i -e 's/^stty/#stty/g' /etc/init.d/rc

  5. В этом же скрипте изменяем переменную CONCURRENCY на значение "none". В противном случае слишком умные init-скрипты новой ветки дистрибутива будут ругаться на метки (маркеры), расставляемые OpenVZ в init-директориях. Да и веб-интерфейс не будет отображать логи запуска демонов.

    sed -i -e '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

2 Comments

  1. Использую v1.9 Не пойму как в окне vnc терминала ввести /(слэш)

  2. Вопрос не понятен… в какой раскладке? в OpenVZ VNC или KVM VNC?

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *