null

Деплой больших debian окружений рядом с Windows средставами ansible по PXE

Довольно часто возникает необходимость взять пачку компьютеров и заинсталлить на них дебиан. Да ещё и не просто заинсталлить, а чтобы оставалась какая-то оркестрация, на случай допиливания новых фич и поддержки софта в актуальном состоянии. Для этого хорошо подходит ansible-pull. Почему-то статьи по его использованию довольно куцые (наверное, потому что сейчас модно деплоить докером), мы же будем его использовать для инсталляции пачки писюков. Да не просто инсталляции, а автоматической debian инсталляции рядом с предустановленной Microsoft Windows.

Сам по себе ansible-pull работает довольно глупо: клонирует/фетчит/мержит git (опционально -- другой) репозиторий, ищет в нём плейбук $hostname.yml или local.yml и запускает его. Поэтому для начала создадим простейший git репозиторий и раздадим его по сети максимально простым способом (который, почему-то, тоже редко описывается в интернете и вводит в ступор многих моих знакомых devops-ов):

  • создадим на управляющем (домен-контроллер) сервере директорию для репозитория;
  • перейдем в неё и создадим там репозиторий, который на файловом уровне будет поддерживать работу с локальными пользователями, принадлежащими определённой группе;
  • определим группу пользователей, которая владеет репозиторием (в нашем случае -- это "staff");
  • выставим права на каталог. Я не хочу, чтобы другие локальные юзеры случайно в своём find натыкались на файлы репозитория, поэтому отбираю у others права на каталог; в то же время, веб-сервер работает от имени webservd, который по понятным причинам не относится к staff и поэтому ему отдельно разрешаю доступ в каталог. Приведённая команда справедлива для solaris 10 + zfs. На других системах ACL назначаются иначе;
  • также, поскольку мы не будем использовать умный git сервер, а хотим максимально упростить себе жизнь, нам потребуется вручную при каждом обновлении репозитория перестраивать указатель на "master" ветку (это файл info/refs), это можно делать специальной командой 'git update-server-info', которая по умолчанию уже есть в хуке post-update. Поэтому скопируем этот хук из "example" в "production". На этом настройка репозитория полностью завершена.

Приведу команды, которыми пользовался я:

# mkdir /export/ansible/
# cd /export/ansible/
# git init --shared=0664 --bare
# chgrp -R staff .
# chmod o-rwx .
# chmod A0+group:webservd:read_xattr/read_data/execute/read_attributes/read_acl/synchronize:allow .
# cp hooks/post-update.sample hooks/post-update

Затем обеспечим доступ к этому репозиторию по сети. Поскольку есть желания упросить себе жизнь максимально, а на сервере уже есть nginx, то достаточно вот такого location-а (да, почему-то ни разу не видел в сети информацию, что git репозиторий для read-only можно раздавать по http):

    location /ansible/ {
        root /export/;
    }

Теперь зайдём за локального пользователя одного из администраторов и инициализируем ему репозиторий, а за одно запушим туда первый файл. Это можно сделать так:

$ git clone file:///export/ansible ansible/
$ cd ansible/
$ echo 'Repo for ansbible-pull(1)' > README
$ git add README
$ git commit -m 'Add README'
$ git push

Видим, что всё работает и доступ к репозиторию есть. Затем приступим к организации debian netinst образа. Есть куча статей по настройке PXE, описывать это тут не буду. Достаточно с помощью dhcp указать, какой файл грузить и к какому серверу обращаться по tftp. Мы же рассмотрим процесс подготовки образа инсталлятора. Ввиду того, что на компьютерах, на которые мы развёртываемся, установлены сетевые карточки, требующие проприетарной фирмвари, нам потребуется не только образ системы, но и образ фирмвари. Его мы с помощью cat приплюсовываем к initrd. Я использовал следующую последовательность команд (помним, что у меня solaris, поэтому там gtar вместо tar):

# mkdir /tftpboot/grub/stretch
# cd /tftpboot/grub/stretch
# wget http://mirror.yandex.ru/debian/dists/stretch/main/installer-amd64/current/images/netboot/netboot.tar.gz
# gtar -xf netboot.tar.gz
# cd debian-installer/amd64/
# wget http://cdimage.debian.org/cdimage/unofficial/non-free/firmware/stable/current/firmware.cpio.gz
# mv initrd.gz initrd.gz.orig
# cat initrd.gz.orig firmware.cpio.gz > initrd.gz

На этом всё, осталось только настроить наш сетевой загрузчик на загрузку этого образа и подсунуть инсталлятору preseed скрипт для автоинсталляции дебиана. Так как в моём случае используется pxelinux, пункт в меню, который я добавил выглядит так:

label auto-debian-9
   menu label ^Debian 9 auto install
   kernel stretch/debian-installer/amd64/linux
   append auto=true priority=critical vga=788 initrd=stretch/debian-installer/amd64/initrd.gz preseed/url=http://192.168.10.10/ansible/debian-9-preseed.cfg

Видно, что файл с настройками для автоинсталляции он будет скачивать по http с сервера 192.168.10.10. Поэтому положим ему следующий файл (debian-9-preseed.cfg). Думаю, что построчно пояснять назначение каждой строчки излишне, поскольку есть довольно неплохая документация на preseed. Опишу только не очевидные на первый взгляд моменты:

Упростим инсталлятору работу с IPv6:

d-i netcfg/dhcpv6_timeout string 1

Чтобы сконфигурировать прокси, необходимо использовать FQDN, поскольку инсталлятор использует busybox, в котором dhcp клиент принципиально не получает от dhcp сервера search домены:

d-i mirror/http/proxy string http://proxy.tune-it.ru:8080

Для формирования пароля суперпользователя можно воспользоваться mkpasswd(1):

d-i passwd/root-password-crypted password $1$R.zIU.88$46qDb.WtyDpIo

Чтобы не пересоздавать метку и таблицу разделов в ней, можно попросить инсталлятор выбирать максимально доступное свободное место. Главное при этом убедиться, что нет опции, которая просит инсталлятор использовать regular, raid или lvm политики (я специально в примере ставлю три решётки, чтобы было понятно, что этой опции быть НЕ должно, иначе раздел с Windows потеряется) и сразу попросим его поискать другие ОС при инсталляции загрузчика:

d-i partman-auto/init_automatically_partition select biggest_free
### d-i partman-auto/method string regular
d-i grub-installer/with_other_os boolean true

Ввиду весёлости видеокарточек у писюков, я рекомендую включить nomodeset. Иначе компы могут виснуть при загрузке:

d-i debian-installer/add-kernel-opts string nomodeset

Для инсталляции ansible можно воспользоваться следующими строками. Обратим внимание, что можно добавить ключик для репозитория, а можно просто разрешить работу с репозиториями без проверки ключа:

d-i apt-setup/local0/repository string http://ppa.launchpad.net/ansible/ansible/ubuntu trusty main
# d-i apt-setup/local0/key string http://keyserver.ubuntu.com/pks/lookup?op=get&search=0x93C4A3FD7BB9C367
d-i debian-installer/allow_unauthenticated boolean true

Попросим инсталлятор сразу доставить sudo, git, aptitude и ansible:

d-i pkgsel/include string sudo git aptitude ansible

И добавим ansible-pull в crontab установленной системы. Выполнять его каждый раз при загрузке выглядит вполне разумным, если учесть, что специально обученные люди исправно выключают компьютеры каждый день:

d-i preseed/late_command string in-target sh -c 'echo "@reboot root ansible-pull -U http://192.168.10.10/ansible/ --full -o -d /var/tmp/ansible -i localhost, > /var/log/ansible.log 2>&1" >> /etc/crontab'

Наконец, приведу результирующий файл полностью:

# locale
d-i debian-installer/locale string ru_RU.UTF-8
d-i debian-installer/language string ru
d-i debian-installer/country string RU

# keyboard
d-i keyboard-configuration/xkb-keymap select ru

# network
d-i netcfg/choose_interface select auto
d-i netcfg/get_hostname string Debian
d-i netcfg/dhcp_timeout string 60
d-i netcfg/dhcpv6_timeout string 1

# proxy
d-i mirror/http/proxy string http://proxy.tune-it.ru:8080

# users
d-i passwd/make-user boolean false
d-i passwd/root-password-crypted password $1$R.zIU.88$46qDb.WtyDpIo

# clock
d-i clock-setup/ntp boolean true
d-i clock-setup/ntp-server string proxy.elcom.spb.ru

# diskpart, auto now
d-i partman/choose_partition select finish
d-i partman/confirm boolean true
d-i partman/confirm_nooverwrite boolean true
d-i partman/default_filesystem string ext4
d-i partman-auto/init_automatically_partition select biggest_free
d-i partman-auto/choose_recipe select atomic
d-i partman-auto/disk string /dev/vda
d-i partman-md/confirm boolean true
d-i partman-partitioning/confirm_write_new_label boolean true
d-i base-installer/allow_unauthenticated boolean true

# loader
d-i grub-installer/with_other_os boolean true
d-i grub-installer/bootdev string default
d-i debian-installer/add-kernel-opts string nomodeset

# repo
d-i apt-setup/non-free boolean true
d-i apt-setup/services-select multicast security, volatile
d-i apt-setup/security_host string security.debian.org
d-i apt-setup/volatile_host string volatile.debian.org
d-i apt-setup/local0/repository string http://ppa.launchpad.net/ansible/ansible/ubuntu trusty main
# d-i apt-setup/local0/key string http://keyserver.ubuntu.com/pks/lookup?op=get&search=0x93C4A3FD7BB9C367

d-i debian-installer/allow_unauthenticated boolean true

# soft
d-i pkgsel/include string sudo git aptitude ansible
d-i pkgsel/upgrade select full-upgrade

# run ansible on each reboot
d-i preseed/late_command string in-target sh -c 'echo "@reboot root ansible-pull -U http://192.168.10.10/ansible/ --full -o -d /var/tmp/ansible -i localhost, > /var/log/ansible.log 2>&1" >> /etc/crontab'

# reboot
d-i finish-install/reboot_in_progress note

Ну и, полагаю, что описывать настройку ansible целиком не требуется, нынче все умеют писать плейбуки. Приведу свою файловую структуру:

debian-9-preseed.cfg
local.yml
README
group_vars/all
roles/common/files/apt_keys/java
roles/common/files/apt_keys/ansible
roles/common/files/apt_keys/virtualbox
roles/common/files/profile
roles/common/files/ssh_keys/admin1
roles/common/files/ssh_keys/admin2
roles/common/files/ssh_keys/admin3
roles/common/files/ca.crt
roles/common/handlers/main.yml
roles/common/tasks/main.yml
roles/common/templates/motd.j2
roles/common/templates/interface-br0.j2
roles/common/templates/interface-br1.j2

Содержимое всех файлов, полагаю, очевидно из названия. Покажу лишь плейбук:

---
- name: Local deployment
  hosts: localhost
  user: root
  connection: local

  roles:
    - common

  environment:
    http_proxy: "http://proxy:8080"
    https_proxy: "http://proxy:8080"
    no_proxy: "tune-it.ru"
    DEBIAN_FRONTEND: "noninteractive"

Очевидно, для ускорения работы можно использовать connection: local. Также, если вы не планируете использовать "встроенные" переменные, можно отключить gather_facts. 
На этом, пожалуй, всё. Теперь управление парком машин заказчика стало существенно проще. 

 

 

korg

 

Коротко о себе

Работаю в компании Tune-IT, администрирую инфраструктуру компании и вычислительную сеть кафедры Вычислительной ТехникиСПбНИУ ИТМО.

Интересы: администрирование UNIX и UNIX-like систем и активного сетевого оборудования, написание shell- и perl-скриптов, изучение технологий глобальных сетей.
Люблю собирать GNU/Linux и FreeBSD, использовать тайлинговые оконные менеджеры и писать системный софт.