Здравствуйте.
Автоматическое разворачивание рабочего места — задача, можно сказать, типичная. Наверняка очень многие решали ее — отталкиваясь от инфраструктуры сети и указаний начальства личных предпочтений; используя при этом готовые решения, или создавая свои.
В этой статье я хотел бы поделиться с сообществом своим способом построения системы автоматизированной сетевой установки рабочих мест, работающих под Debian GNU/Linux. Никаких флешек, дисков и прочих внешних винчестеров, которые лично у меня почему-то имеют привычку регулярно теряться в развалах рабочего бардака, не читаться или быть очищенными для записи какой-то невероятно нужной фигни.
Если для вас такое состояние дел кажется близким и знакомым — добро пожаловать под кат.
Разворачивание среды
Для работы сетевой установки в первую очередь нужны настроенные DHCP и TFTP сервера. К сожалению, я не могу сейчас вспомнить, чем я руководствовался при их выборе, так как первые успешные эксперименты были сделаны года полтора назад, а то и раньше. В то время и были выбраны isc-dhcp-server и tftpd-hpa соответственно в качестве dhcp и tftp серверов.
aptitude install isc-dhcp-server tftpd-hpa
Для dhcp сервера надо указать используемый интерфейс в /etc/default/isc-dhcp-server и прописать соответствующие вашей сети настройки в /etc/dhcp/dhcpd.conf. Для сети 192.168.121.0/24 и интерфейса eth0 это выглядит примерно так:
sed -i 's/INTERFACES=""/INTERFACES="eth0"/g' /etc/default/isc-dhcp-server
sed -i 's/#authoritative;/authoritative;/g' /etc/dhcp/dhcpd.conf
echo -e '
subnet 192.168.121.0 netmask 255.255.255.0 {
range 192.168.121.128 192.168.121.200;
option domain-name-servers 192.168.121.1;
option routers 192.168.121.1;
filename "pxelinux.0";
}' >> /etc/dhcp/dhcpd.conf
Само собой разумеется, что у вас могут быть другие параметры и настройки. Единственная интересующая нас строчка здесь — это предпоследняя, где указывается имя файла, который будет передаваться с помощью tftpd по сети для начальной загрузки создаваемой системы.
tftpd я оставил на умолчальных настройках; изменил только параметр TFTP_DIRECTORY в файле /etc/default/tftpd-hpa, что делать в принципе не обязательно. Дальше выкачиваем в этот каталог образ для сетевой установки Debian и распаковываем его
wget http://ftp.debian.org/debian/dists/wheezy/main/installer-i386/current/images/netboot/netboot.tar.gz
tar -xzvf netboot.tar.gz
rm netboot.tar.gz
На этом этапе мы уже можем устанавливать систему по сети (да, вот так все просто), но пока только в ручном режиме. Что хотя и экономит время и нервы на поиски загрузочной флешки/компакта, но не особо, поэтому переходим к следующей части нашей автоматизации — созданию так называемого «файла ответов» на все вопросы инсталлятора.
Ответы и вопросы
Файл ответов можно встроить в initrd, можно разместить на внешнем носителе, а можно — на веб-сервере, который будет доступен в процессе установки. Последний вариант оказался для меня самым удобным как для внесения изменений (не надо пересобирать initrd), так и непосредственно в процессе работы (не надо искать флешку с ответами). Хочу заметить, что хотя у меня все это дело крутится на одном компьютере, это совершенно необязательно.
Чтобы инсталлятор «узнал», где искать ответы на все интересующие его вопросы, в файл $TFTP_DIRECTORY/debian-installer/i386/boot-screens/txt.cfg к последней строчке (которая начинается с append) нужно добавить параметры auto и url. В результате в файле будет примерно следующее
default install
label install
menu label ^Install
menu default
kernel debian-installer/i386/linux
append vga=788 initrd=debian-installer/i386/initrd.gz -- quiet auto=true url=http://192.168.121.1/pxeinstall/preseed.cfg
При желании в конфигурации меню можно также timeout 0 изменить на timeout 5, например, и избавить себя от труда нажать «Ентер» перед началом установки. Лично я вернул назад «вечный» таймаут после того, как ко мне прибежал весь в расстроенных чувствах сосед, который отправил на перезагрузку заглючившую машину и вышел покурить, а вернувшись, увидел свежеустановленный Debian вместо любимой «семерки». Мои увещевания, что свежеустановленная система тоже седьмой версии его не утешили :(
Само собой, на соответствующем хосте нужен веб-сервер с каталогом pxeinstall, который нам еще пригодится. Здесь я ничего придумывать не стал — apache и без того стоял для внутренних нужд. Если у вас еще нет веб-сервера, команда
aptitude install apache2 && mkdir /var/www/pxeinstall
должна решить эту проблему. Так что переходим к сочинению ответов.
Официальный файл-пример можно посмотреть здесь. Вы также можете получить готовый файл ответов для вашей системы, запустив команду
debconf-get-selections --installer > my.preseed.cfg
А с помощью
debconf-get-selections >> my.preseed.cfg
вы дополните этот файл также всеми ответами, которые вы давали при установке дополнительного софта.
Правда, я где-то встречал утверждение, что полученный таким образом файл может работать неправильно и — как результат — рекомендацию исправлять оригинальный файл под свои нужды, используя my.preseed.cfg лишь в качестве подсказки.
В целом изучение и правка этого файла проблем не составляет — все хорошо прокомментировано; необходимые значения нужных параметров можно подсмотреть в файле, который сгенерировал debconf. И все же есть несколько нюансов, на которых я бы хотел остановиться подробнее.
Дисковая разметка
Есть два способа провести разбивку дисков на этом этапе — выбрать предустановленный автоматический вариант разбивки, или задать размеры разделов вручную. Предустановленных вариантов три — все файлы на одном разделе; отдельный раздел под /home и отдельные разделы под /home, /tmp, /usr и /var. Указывается в файле ответов строкой
d-i partman-auto/choose_recipe select atomic
Вместо atomic можно соответственно использовать home и multi.
В качестве эксперимента, да и для многих типичных вариантов разбивки этого вполне хватает, но у нас используется разметка, при которой традиционно выделяется отдельный раздел для сервисных нужд, так что
d-i partman-auto/expert_recipe string
boot-root ::
30000 5000 40000 ext4
$primary{ } $bootable{ }
method{ format } format{ }
use_filesystem{ } filesystem{ ext4 }
mountpoint{ / }
.
20000 3000 40000 ext3
method{ format } format{ }
use_filesystem{ } filesystem{ ext3 }
mountpoint{ /srv }
.
10000 2000 10000000 ext4
method{ format } format{ }
use_filesystem{ } filesystem{ ext4 }
mountpoint{ /home }
.
50% 6000 200% linux-swap
method{ swap } format{ }
.
Вкратце, что есть что.
boot-root — это какое-то колдунство, без которого вся эта байда отказывается работать :) После него идут параметры для каждого из создаваемых разделов. В первой строке три цифры соответственно означают минимальный размер раздела, приоритет для алгоритма обсчета раздела и максимальный размер раздела. Размер указывается в мегабайтах, при этом при разбивке он будет урезан согласно размера цилиндра. Кроме целочисленных значений можно также использовать проценты от размера оперативной памяти. Допускаются также варианты типа «2000+50%», тоесть 2000МБ + половина оперативки. Приоритет — это условное «среднепотолочное» число. Чем оно ниже, тем итоговый размер раздела будет ближе к минимальному значению. Рекомендуется одному из разделов указывать максимальный размер побольше, но не больше чем 1000000000 чтобы не нарваться на переполнение: на і386 целочисленная арифметика ограничена 31 битом. Оставшееся значение — это, конечно же, тип файловой системы.
Спецификаторы $primary{ } и $bootable{ } указывают соответственно что создаваемый раздел будет первичным и/или загрузочным. method{ format } нужно указать, если раздел будет форматироваться. Кроме «format» могут также использоваться значения «swap» для раздела подкачки и «keep» для сохранения раздела нетронутым. Если указывается method{ format }, нужно также дополнительно задать еще один спецификатор format { }. Следующие спецификаторы use_filesystem{ } и filesystem{ ext4 } определяют, в какую именно файловою систему будет сформатирован раздел. Последний из используемых спецификаторов — mountpoint — определяет точку монтирования создаваемого раздела. Венчает это добро символ «точка», который отделяет описания разделов друг от друга.
Все эти параметры должны быть указаны в одной строке что делает правку или поиск ошибки довольно веселым занятием, так что традиционно используем бекслешы для придания нашей разметке более-мене сопровождабельного вида.
Более детальное описание процесса разметки дисков, включая lvm, raid и прочие радости, можно посмотреть здесь и здесь.
Расширяем возможности
Не смотря на то, что с помощью файла ответов можно полностью автоматизировать процесс установки системы, все же остаются задачи, которые он не решает. Это и разнообразные правки конфигов, и стандартный набор документов/настроек, которые должны быть у пользователя под рукой, ну и само собой котики корпоративный логотип на десктопе. Для решения этой задачи я использую возможность выполнить любую команду уже после установки системы, но со все еще смонтированным /target:
d-i preseed/late_command string
chroot /target sh -c "/usr/bin/wget -O /tmp/postinstall http://192.168.121.1/pxeinstall/postinstall && /bin/sh -x /tmp/postinstall"
Тоесть, просто выкачиваем подготовленный скрипт и запускаем его.
В файле postinstall ничего особенно выдающегося нету — подключаются репозитории с дополнительным софтом, этот же софт устанавливается. После чего подправляются кофигурационные файлы и пользователю раскатывается эталонный домашний каталог вместе со всеми необходимыми настройками.
#!/bin/bash
deployserver=192.168.121.1
deployconfig=/pxeinstall/configs
#
# Installing additional software
#
wget $deployserver$deployconfig/apt_sources.list -O /etc/apt/sources.list
export DEBIAN_FRONTEND=noninteractive
aptitude update
#Installing unzip with full cyryllic support
apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 4EEBB18420019065
aptitude -y install unzip p7zip-full
#opera has own repo
wget -O - http://deb.opera.com/archive.key | apt-key add -
aptitude update
aptitude -y install opera
#For skype we do the following
aptitude install libasound2-plugins
wget -O skype-install.deb http://www.skype.com/go/getskype-linux-deb
dpkg -i skype-install.deb
# wvdial cofig for intertelecom. Just in case.
wget $deployserver$deployconfig/wvdial.conf -O /etc/wvdial.conf
#Set adequate editor by default
update-alternatives --set editor /usr/bin/vim.basic
#
# User profile
#
username=`cat /etc/passwd | grep 1000 | awk 'BEGIN { FS = ":" } ; { print $1 }'`
cd /home/$username
wget $deployserver$deployconfig/home.tar.gz
# This archive is made by commands
# cd home && tar -czvf ../home.tar.gz .
# to include also hidden (config) files
tar -xzvf home.tar.gz
chown -R $username /home/$username
rm home.tar.gz
#
# Additional system configs
#
wget $deployserver$deployconfig/10-service.rules -O /etc/udev/rules.d/10-service.rules
wget $deployserver$deployconfig/service-blacklist.conf -O /etc/modprobe.d/service-blacklist.conf
sed -i 's/#AutoLoginEnable=true/AutoLoginEnable=true/g' /etc/kde4/kdm/kdmrc
sed -i 's/#AutoLoginAgain=true/AutoLoginAgain=true/g' /etc/kde4/kdm/kdmrc
sed -i 's/#AutoLoginUser=fred/AutoLoginUser='$username'/g' /etc/kde4/kdm/kdmrc
sed -i 's/"syntax on/syntax on/g' /etc/vim/vimrc
exit 0
При желании, в preceed.cfg можно вообще ставить только базовую систему, а все остальное делать именно с этого скрипта. Преимущество такого подхода состоит в том, что у вас будет отдельный готовый скрипт, который устанавливает и настраивает рабочее место на любом работающем debian, а не только в среде инсталлятора. Или может он уже есть и было бы неплохо его зайдействовать вместо того, чтобы искать нужные ключи в preseed.cfg. В таком случае в postinstall только скачивается полноценный скрипт, примет которого мы только что рассмотрели, и который запустится после перезагрузки уже в установленной системе.
Лично для нас еще одной причиной именно такого двухступенчатого подхода послужыло очень медленное выполнение скрипта в среде инсталлятора. Например, установка пакетов примерно на 600 МБ из репозитория в локальной сети плюс распаковка архива домашнего каталога занимает больше суток. Я не смог найти причину столь медленного исполнения скрипта, который на той же машине после перезагрузки отрабатывает за считанные минуты и буду очень рад, если кто-то из опытных читателей подскажет, где тут собака порылась.
Последняя строчка с принудительной установкой загрузчика появилась здесь после того, как на какой-то брендованный компьютер с предустановленной windows7 инсталлятор упорно не хотел ставить grub.
#!/bin/sh
# Get firstboot script
/usr/bin/wget -O /root/firstboot http://192.168.121.1/pxeinstall/firstboot
chmod +x /root/firstboot
# create a service that will run our firstboot script
cat > /etc/init.d/firstboot <<EOF
### BEGIN INIT INFO
# Provides: firstboot
# Required-Start: $networking
# Required-Stop: $networking
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: A script that runs once
# Description: A script that runs once
### END INIT INFO
cd /root
/usr/bin/nohup sh -x /root/firstboot &
EOF
chmod +x /etc/init.d/firstboot
update-rc.d firstboot defaults 99
grub-install --recheck --no-floppy /dev/sda
Само собой разумеется, в таком случае в нашем скрипте firstboot надо не забыть удалить себя после завершения работы:
update-rc.d firstboot remove
Заключение
Вышеописанный метод разворачивания рабочих мест позволяет держать в одном месте все, что касается установки ОС — скрипты, конфиги, дополнительные файлы — что упрощает бекап и позволяет не искать флешку с правильной версией образа системы. Ну и этот метод достаточно гибок для того, чтобы просто и быстро изменить сценарий установки.
С радостью рассмотрю ваши замечания и отвечу на появившиеся вопросы.
Автор: miwa