Все о Linux. LinuxRSP.Ru


Cвежие новости Linux и BSD, анонсы статей и книг прямо в почтовый ящик!
Подписаться письмом


 Сегодняшние новости:

25 лет исполнилось ядру Linux

Релиз KDevelop 5.0

Oracle открывает код JDK9 для ARM

Выпущен Timewarrior 1.0.0

Релиз Android 7.0

Percona Memory Engine для MongoDB на базе WiredTiger

PowerShell открыт и доступен для Linux

Форк TrueCrypt: VeraCrypt 1.18

Релиз Snapcraft 2.14

Релиз Go 1.7

Стабильный выпуск рабочего стола Lumina

Вышла первая версия аналога OpenCV - DCV 0.1

Выпуск минималистичной программы для мониторинга jsonmon 3

В MIT разработали новый язык программирования

Первый релиз Qt5Gtk2

Godot 2.1 - новая версия открытого игрового движка

Свободная цифровая станция звукозаписи: Ardour 5.0

Обновление SkypeWeb Plugin for Pidgin

Вышла версия 3.0 Android File Transfer для Linux (и для OS X)

Программный аналог MIDI-контроллера для создания музыки: Launchpadd v1.3

Mozilla спонсирует поддержку Python 3.5 в PyPy

Ef 0.08 - программа для моделирования динамики заряженных частиц

Обновление текстового редактора TEA до версии 42.0.0

Релиз OpenOrienteering Mapper 0.6.4

Вышли Guix и GuixSD 0.11

Релиз Opera 39

Выпуск LibreOffice 5.2

В OpenSSH обнаружены и устранены некоторые уязвимости

Эмулятор FCEUX 2.2.3

Компания Билайн переходит на российскую СУБД с открытым исходным кодом Tarantool

Google

 Новые статьи :

Утилиты для восстановления потерянных данных в Linux

Лучшие файловые менеджеры для Android

20 лучших бесплатных книг о Linux

Как сгенерировать открытый/закрытый SSH-ключ в Linux

Grive - клиент Google Drive для Linux с открытым исходным кодом

Протокол IPv6: варианты подключения

Сервер из образа: DHCP + TFTP + Initrd + OpenVZ

Обзор веб-панелей управления хостингом

Приёмы работы с Vim

Nginx как Reverse Proxy для сайта, использующего SSL

Разработка модулей ядра Linux

Мониторинг нагрузки http-сервера Apache 2

Перевод комментариев к файлу конфигурации Squid

Решение проблем при использовании "1c предприятие" 8.2 в Linux

Advanced Bash-Scripting Guide Искусство программирования на языке сценариев командной оболочки







Rambler's Top100





 
 

Сервер из образа: DHCP + TFTP + Initrd + OpenVZ

Приветствую. Нередко в крупных проектах используются довольно большие наборы одинаковых серверов, имеющих одинаковую программную конфигурацию(читай - корень). И нередко у администраторов этих машин возникает необходимость поддерживать их в симметричном состоянии - одинаковые наборы пакетов, конфигов, и т.д. и т.п. В качестве одного из решений этой проблемы предлагается загрузка таких машин по сети, дабы они имели общий корень и держали его в RAM, а хранимые данные(например /var/www для веб-серверов) держали на жестких дисках, монтируемых после загрузки. Об этом и поговорим.

Пара слов о том, что будем делать

Одна из целей, которую я ставил - максимальная простота. Поэтому в этой статье используется минимальный набор инструментов, а сами они максимально просты в использовании. Образ мы будем паковать прямо в initrd, а выдавать его тем же TFTP-сервером, который будет отдавать ядро и загрузчик.
В качестве опционального продолжения, в последнем разделе я расскажу о применении OpenVZ в этой задаче - на мой взгляд, работать с виртуальным хостом удобней, чем с chroot-окружением - особенно, если вы производите массовые обновления серверов(да и для банального тестирования удобно).
Если вы решите применять OpenVZ - подумайте над тем, чтобы поселить DHCP и TFTP сервер внутри VZ-контейнера(особенно, если у вас уже есть несколько хост-систем) - это позволит развернуть DHCP-сервер в случае отказа основной хост-системы.
Итак, поехали.

DHCP

Здесь всё просто. Я использовал dhcpd. В дефолтный конфиг вписываем:
#Включаем возможность передавать параметры из dhcpd в pxelinux
option space pxelinux;
option pxelinux.magic code 208 = string;
option pxelinux.configfile code 209 = text;
option pxelinux.pathprefix code 210 = text;
option pxelinux.reboottime code 211 = unsigned integer 32;

site-option-space "pxelinux";
option pxelinux.magic f1:00:74:7e;
if exists dhcp-parameter-request-list {
option dhcp-parameter-request-list = concat(option dhcp-parameter-request-list,d0,d1,d2,d3);
}

group
{
option pxelinux.configfile "configs/bla-bla.ru/config"; #Общий конфиг pxelinux`a для группы хостов
filename "/var/lib/tftpboot/pxelinux.0"; #Сам загрузчик
#Первый хост
host first.bla-bla.ru
{
hardware ethernet 48:5b:39:90:b9:06; #MAC первого сервера
fixed-address 192.168.0.100;
option host-name "first.bla-bla.ru";
}
#Второй хост
host second.bla-bla.ru
{
hardware ethernet 48:5b:39:90:b9:07; #MAC второго сервера
fixed-address 192.168.0.101;
option host-name "second.bla-bla.ru";
}
}

subnet 192.168.0.0 netmask 255.255.255.0 #Сеть, в которой живёт наш dhcp-сервер
{
option routers 192.168.0.1; #Шлюз
option domain-name-servers 192.168.0.2; #DNS
range 192.168.0.100 192.168.0.150; #Какие адреса будем выдавать
}

deny unknown-clients; #Незнакомым не отвечать


Рестартим dhcpd. Теперь оно будет предлагать машинкам загрузиться по сети.

TFTP

Для TFTP использовался tftp-hpa. Для его корректной работы в /etc/xinetd.d/tftp(в ubuntu файл нужно было создать самостоятельно) вписываются строки:

service tftp
{
port = 69
socket_type = dgram
wait = yes
user = root
server = /usr/sbin/in.tftpd
server_args = /var/lib/tftpboot
disable = no
}


Как видно из конфига, всё добро, предназначенное для загрузки машинок по сети мы будем хранить в /var/lib/tftpboot. Рестартим xinetd. TFTP теперь тоже готов

Загрузчик(PXELinux)

PXELinux - это брат-близнец SYSLinux`a(который используется, наверно во всех установочных Linux-CD), но ориентированный на загрузку по сети. Сам загрузчик я взял из netboot-образа Ubuntu, хотя, подозреваю, есть и другие способы его получения. Кладём бинарник(pxelinux.0) в /var/lib/tftpboot/. Его дефолтные конфиги могут лежать в поддиректории pxelinux.cfg, тогда в качестве основного будет использоваться default(полный путь для него будет таким: /var/lib/tftpboot/pxelinux.cfg/default). Но мы указали в конфиге dhcpd, что сервера группы "bla-bla.ru" будут забирать свои конфиги из configs/bla-bla.ru/config(полный путь /var/lib/tftpboot/configs/bla-bla.ru/config). Поэтому создаём необходимые директории и пишем в конфиг:

default linux
timeout 100

label linux
kernel kernels/vmlinuz-2.6.32
append panic=15 initrd=images/bla-bla.ru/current


Как видно, ядро будет храниться в kernels/, а cам образ в images/. Версию ядра, вы, конечно же, укажете позже свою. Но всё это потом, а пока мы займёмся изготовлением самого образа.

Готовим образ

Как я уже сказал, образ наш будет храниться прямо в initrd. Этот путь гораздо проще, нежели применение SquashFS + UnionFS(т.к. последний не входит в ядро, а значит требует хронических перекомпиляций последнего). И проще/надёжней nfs_root т.к. не требует дополнительных сервисов, которые могут стать дополнительными точками отказа.
Я собирал свой образ в Ubuntu, для Debian процедура будет аналогичной. Итак, нам нужен debootstrap. Создаём где-нибудь директорию(пусть это будет /root/image) и разворачиваем в неё образ. Ну, например, Ubuntu Lucid:

debootstrap lucid /root/image

Теперь chroot`имся туда и ставим ядро(в чруте). Выходим из chroot`a, а полученное ядро тащим в /var/lib/tftpboot/kernels/ и вписываем его в конфиг из предыдущего раздела. Кстати, из самого окружения его можно удалить, чтобы оно не занимало драгоценное место.
Как вы уже, наверно, поняли - это окружение и есть будущий образ. Сюда же вы можете ставить нужные пакеты и править конфиги. Так же вам обязательно нужно создать /etc/fstab(даже если вы не хотите его заполнять, хотя /proc я бы туда всё же вписал ;)) и файл init в корне(без него почему-то получался Kernel Panic, хотя на файле намеренно не стояло прав на выполнение, а содержимое было пустым). Так же советую вписать получение ip-адресов по dhcp в /etc/network/interfaces - наш DHCP-сервер может выдавать статические адреса.
Теперь мы готовы собрать образ. Но перед этим вам нужно знать об одной особенности процесса: cpio - не умеет паковать хардлинки [Не факт. - прим ред.]. Это значит, что если их не разобрать - вы лишитесь некоторых утилит - например ifup,ifdown,mkfs и некоторых других файлов.
Для решения этой проблемы я написал на Perl`е небольшой костыль, который их разбирает: код тут. Говорим этому скрипту в качестве параметра директорию /root/image, дабы он разобрал там линки. Далее заходим в директорию с окружением(/root/image) и говорим:

find | cpio -H newc -o -p > ../bla-bla.ru; gzip -9 ../bla-bla.ru;cp ../bla-bla.ru.gz /var/lib/tftpboot/images/bla-bla.ru/2011-03-16;ln -s /var/lib/tftpboot/images/bla-bla.ru/2011-03-16 /var/lib/tftpboot/images/bla-bla.ru/current

Данная команда запакует образ, как initrd, положит в нужное место и создаст на него ссылку с current(который указан в конфиге).
Вот и всё! При попытке загрузиться по сети машинка должна раскрутиться из созданного нами образа.

OpenVZ

С помощью OpenVZ мы будем делать живую модель образа. Он(OpenVZ) удобен для наших целей прежде всего всё тем, что образы VZ-виртуалок хранятся на диске "как есть" в виде дерева, а поэтому их удобно паковать. В моём случае я пошел чуть дальше и собрал DHCP+TFTP тоже внутри OpenVZ-контейнера(отдельного, разумеется).
Если вы так же хотите использовать OpenVZ в решении этой задачи - будем считать, что сервер со всем необходимым для работы этой системы виртуализации(поддержка в ядре, vzctl) у вас уже настроен - благо, документации на эту тему хватает.

Создадим виртуалку:

vzctl create 100 --hostname model.bla-bla.ru

Запускать её пока не надо. Удаляем всё содержимое private-директории( по дефолту /var/lib/vz/private/100, где 100 - VEID указанный при создании) и кладём в неё дерево директорий, которое мы сделали в предыдущем пункте.

Если вы уже успели вписать авто-получение сетевых настроек в разворачиваемую из образа систему - не поленитесь вписать в конфигурацию DHCP-сервера и выдачу адреса этой виртуалке(MAC-адрес контейнера можно узнать, зайдя в него из консоли хост-системы через vzctl enter и выполнив там ifconfig), иначе она рискует остаться без сети.

Запускаем:

vzctl start 100

При положительном исходе виртуалка сходит к DHCP-серверу за адресом и станет доступна по сети. Теперь вы можете работать с ней точно так же, как с полноценной машиной, из которой будут создаваться образы.
Для автоматической сборки образов я написал небольшой Perl-скрипт, который работает следующим образом:
  1. В заголовке мы объявляем VEID'ы "моделей" (виртуалок, с которых будем снимать образы) и dhcp-сервера. Если ваш dhcp-сервер живёт не на VZ-контейнере - просто поправьте $out_path)
  2. Для каждой виртуалки, указанной в скрипте, проверяется время изменения /var/lib/apt/extended_states(этот файл изменяется каждый раз при измнении списка пакетов - установке/обновления чего либо через apt-get), полученный тайм-штамп записывается в /var/cache/netboot/номер(директория должна существовать).
  3. Если тайм-штамп из кэша скрипта ниже, чем время изменения проверяемого файла - виртуалка, останавливается.
  4. Далее, зачищается /var/cache/apt(для экономии места) и собирается cpio-образ, после чего виртуалка запускается обратно. Предварительно, выполняется предыдущий скрипт, разбирающий хард-линки. Считается, что он лежит в директории, описанной в PATH, а сам он называется nb_links_breaker.
  5. В финальной стадии cpio-образ жмётся gzip`ом, перемещается в нужное место(по дефолту - /var/lib/tftpboot/images/имя_виртуалки/дата и к нему прикладывается линк от current.


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

Итого

Явных минусов у предложенного варианта два - расход ОЗУ на использование RAM-диска и большее время загрузки по сравнению с жесткими дисками(засчёт получения образа и его распаковки). Обратная сторона - получаемый функционал: один раз собрав образ, вы получите возможность ввести в строй новый сервер за считанные минуты, а каждый собранный образ может служить точкой отката в случае неудачного обновления.
Разумеется здесь описаны только общие принципы и манипуляции, необходимые для получения базовой системы, запакованной в initrd с возможностью загрузки по сети. Различные варианты допиливания, типа конфига mdadm`a и маленьких скриптиков, облегчающих жизнь(например, для разметки дисков на новом сервере) остаются на усмотрение читателя.

Надеюсь, что это кому-нибудь будет пригодится. Спасибо за внимание. :)
Иcтoчник
      

Связь | О проекте LinuxRSP | Реклама | О Linux
© 1999-2017 LinuxRSP