Ускоренное импортозамещение или как разворачивать Linux-дистрибутив БЕЗ помощи SCCM в распределённой корпоративной сети

Готовы к захвату десктоповГотовы к захвату десктопов

Опять в интернете кто-то неправ! Натолкнулся недавно на статью и даже сначала ужасно огорчился. И один из комментариев в самую точку — зачем насиловать пингвина виндой? Разумеется, это негодование шуточное. На самом деле — это инсталляция с помощью стороннего dhcp/bootp-сервера, а то что он на windows, так это другой вопрос — у кого и что было, кто и чем умеет пользоваться. Ребята, молодцы! По крайней мере, движутся в правильном направлении. А вот насколько это проще без инфраструктуры Windows, мы сейчас и посмотрим.

Разумеется, установка образов используя виндовую инфраструктуру мне не нравится и поэтому я по шагам опишу (и разовью) один из стандартных методов.

Процесс инсталляции с локального носителя в значительно утрированном виде выглядит следующим образом: груб — монтирует минимальную файловую систему initrd и грузит ядро, ядро запускает процесс init (systemd), который, в свою очередь, запускает инсталлятор. У RedHat — это anaconda, у Debian/Ubuntu — он называется debian-installer, и далее начинается процесс установки. Я буду описывать более родную мне анаконду, а значит — это отечественные дистрибутивы ROSA и REDOS.

Загрузились. Анаконда рисует нам экраны с различными вопросами — временная зона, параметры сети, какой набор софта поставить, пользователей заводим/пароли им назначаем, как разбить диски и т.д. Когда вопросы закончатся, начинается инсталляция и мы можем спокойно идти пить чай (в молодости пили пиво). Далее одна перезагрузка и машина готова, единственное — её надо уже шлифовать под пользователя. Переносить данные, почту, ставить нестандартный софт, минимальное обучение и т.д.

Коллаж из инсталляционных скриншотов. Не соответствуют реальной последовательности установки и вроде как даже от разных версийКоллаж из инсталляционных скриншотов. Не соответствуют реальной последовательности установки и вроде как даже от разных версий

Пока всё совпадает с процессом установки Windows, по крайней мере, тем, который я ещё застал и который иногда наблюдаю у коллег. Здесь меня могут поправить и я согласен, что знания мои в этой области мизерные. Но обращаю внимание, что статья о процессе установки линукса и винду — мы больше троллить не будем.

Установка врукопашную на одну/две/три машины это ещё терпимо, но когда их значительно больше, то сразу возникает мысль об автоматизации. Как правило, это либо раскатка образов, либо более продвинутая раскатка образов с указанием каких-либо параметров и элементами миграции старых данных :). На мой взгляд, это не есть хорошо — клонированные системы грешат неожиданно всплывающими проблемами в виде неуникальных внутренних идентификаторов и девиациями на разносортном железе. Поэтому для себя я давно определил, что инсталляция должна быть полноценной, а возможная разница затрат по времени (в сравнении с клонированием) — нивелируется отсутствием (минимизацией) последующей ручной доводки.

Итак, мы впервые установили «эталонную» машину. Заходим в каталог пользователя root и видим файл anaconda-ks.cfg

Содержимое anaconda-ks для примера:

#version=DEVEL # System authorization information auth --enableshadow --passalgo=sha512 # Use CDROM installation media cdrom # Use graphical install graphical # Run the Setup Agent on first boot firstboot --enable ignoredisk --only-use=sda # Keyboard layouts keyboard --vckeymap=us --xlayouts='us','ru' --switch='grp:alt_shift_toggle' # System language lang ru_RU.UTF-8  # Network information network  --bootproto=dhcp --device=eno1 --ipv6=auto --no-activate network  --hostname=localhost.localdomain  # Root password rootpw --iscrypted $6$K2i9HR45ptnHOg4U$MflacVttGoh333/L52RHz8fwn4pnOgRJES2/eGa9MWU6bxF7PQPZscYGDTk8BVe0IIIB8JyQay1yFb8wmbAI.1 # System services services --enabled="chronyd" # System timezone timezone Europe/Moscow --isUtc user --groups=wheel --name=test --password=$6$0Rl333j/K/qIsR1Y$L.Qnf9ppQVJbo8tkOkbNNmKNJrSAbvioJIfmqR6vG24vXSqBqrK4365I8Vwoj416AyXWsur1OguUgvocCFWYo1 --iscrypted --g # X Window System configuration information xconfig  --startxonboot # System bootloader configuration bootloader --location=none autopart --type=lvm # Partition clearing information clearpart --none --initlabel  %packages @^mate-desktop-environment @base @core @desktop-debugging @dial-up @directory-client @fonts @guest-agents @guest-desktop-agents @input-methods @internet-browser @java-platform @mate-desktop @multimedia @network-file-system-client @networkmanager-submodules @print-client @rosa-utils @x11 chrony  %end  %addon com_redhat_kdump --disable --reserve-mb='auto'  %end  %anaconda pwpolicy root --minlen=6 --minquality=50 --notstrict --nochanges --notempty pwpolicy user --minlen=6 --minquality=50 --notstrict --nochanges --notempty pwpolicy luks --minlen=6 --minquality=50 --notstrict --nochanges --notempty %end 

Когда мы устанавливали систему — все наши ответы были записаны в данный файл kickstart. Этот файл можно взять и передать при установке на следующем компьютере в параметрах инсталлятору и тогда мы получим почти полную копию данной системы. Под выражением «почти полная» я подразумеваю, что будет идентичный набор программного обеспечения, сетевые адреса, пользователи и пароли и т.д., а всё, что уникально для машины — UUID дисков, размеры партиций, зависящие от физического объёма диска и т.д. будут свои.

Инсталляцию с данным файлом производим следующим образом:

  1. Копируем файл на носитель, с которого будем грузиться и ставить систему — на флешку, т.к. мне кажется, остальные варианты уже неактуальны.
  2. При загрузке в меню grub на строчке с пунктом меню для установки системы, нажимаем «e» и проваливаемся в редактирование пункта.
  3. В строчку, начинающуюся на linux — добавляем параметр inst.ks=anaconda-ks.cfg.
  4. Продолжаем загрузку. «Ctrl+x».

Теперь инсталлятор прочитает файл anaconda-ks.cfg и пропустит все экраны с вопросами. По сути, пока получили грамотное клонирование, но не достигли цели минимизации последующего ручного труда при доводке системы.

Следующий этап. Читаем документацию по синтаксису kickstart-файла (на английском, на русском). Всё очень и очень просто. Например, параметры сети меняются в одной строчке, указываются имя и пароль (хэш) локального пользователя, по набору софта — подключаем/отключаем как группами, так и индивидуально. Уже сразу (сейчас) можно нарисовать кучу файлов для каждой машины, закидать их на флешку и при установке только обозначать требуемый конфиг. Можно попробовать, но мы пойдём дальше.

Кстати, ручное создание kickstart дело весьма полезное, особенно на начальном этапе, но и соответствующие инструменты автоматизации имеются, как для создания оного (system-config-kickstart — объявлен deprecated 🙂 ), так и для проверки — ksvalidator. А также RedHat имеет особенный сервис Kickstart generator, к которому нам доступ не получить, да и не очень-то хотелось.

Держать уникальные конфиги на флешках — идея так себе. По сути, хоть в «энтерпрайзе» рабочие места и стремятся к типовым конфигурациям, но их (рабочих мест) иногда реально много и править, а потом раскладывать конфиги по всему вороху флешек становится утомительно. Значит, мы приходим к централизованному хранению конфигурационных файлов.
Сказано — сделано. Все свои kickstart-файлы разместили в каталог веб-сервера, процесс загрузки меняем минимально. Указываем параметр:

inst.ks=http://192.168.0.2/anaconda-ks-192.168.2.31.cfg

Здесь я условно написал уникальное имя конфига для нашей машины

Замечаем, что в качестве источника kickstart-файла указан сетевой ресурс. Делаем вывод, что у нас есть сеть, а как она может быть, если ip-адрес мы указываем в самом kickstart-файле?

И, разумеется, эта ситуация уже была продумана и решена. Вот пример для указания статического адреса, параметры для которого мы вписываем аналогично тому, как указывали сценарий для inst.ks:

ip=192.168.2.31::10.32.2.29:24:linux2:eno1:none 

Для dhcp проще, читаем самостоятельно. С самого начала не указал, но, может, вы обратили внимание, что вся статья заточена под статическую адресацию, ибо в моём «энтерпрайзе» это только так, но вы легко можете сделать поправку под свою инфраструктуру. Также обращаю внимание, что ip-адрес в процессе инсталляции, и ip-адрес, который будет после установки системы — можно делать разными, т.е. всю установку производить в выделенном сегменте, а потом отдавать компьютеры пользователям на их реальные рабочие места и в совершенно других сетевых сегментах.

Мысль летит дальше, и нам уже неинтересно лепить конфигурацию для отдельных машин. Хочется, чтобы всё делалось самостоятельно. Напрягаемся сами (или напрягаем ближайшего программиста) и делаем простейшую (в зависимости от потребностей) динамическую страничку для формирования kickstart-файла. Контент собирается в зависимости от параметров в запросе или IP-адреса обратившегося.

Мой вариант скрипта:
Как писал выше, адресация только статика (рай для безопасников), а локалок, мелко порубленных на сегменты, достаточно много. По большому счёту мне необходимо только задать параметры сети — адрес, маска, шлюз, адреса dns-серверов.
Параметры для всех сегментов сети находятся в файле networks.csv примерно такого вида:

192.168.0.0/24;192.168.0.1;192.168.0.3,192.168.0.2;DMZ 192.168.1.0/25;192.168.1.1;192.168.0.3,192.168.0.2;Пользователи 1 192.168.1.128/25;192.168.1.129;192.168.0.3,192.168.0.2;Принтеры 192.168.2.48/28;192.168.2.49;8.8.8.8,192.168.0.3;VIP ... 

Первое поле — сетка с префиксом, второе — шлюз, третье — адреса dns-серверов, четвёртое поле — комментарий.

Сам веб-сервер — практически однострочник на python, который можно держать в чистом виде или спрятать за балансировщиком. Используем лёгкий python веб-фреймворк: Bottle

#!/usr/bin/env python # -*- coding: utf-8 -*-  from bottle import route, run, template import ipaddress import glob  # получение конфигурационного файла configFile для хоста с адресом ipAddr @route('/<configFile>/<ipAddr>') def index(configFile, ipAddr):      ip = ipaddress.ip_address(ipAddr.decode('utf-8'))     net0 = ipaddress.ip_network(u'10.0.0.0/8')      # находим сеть с наибольшим префиксом     for n in ipdb.keys():         if ip in n:             if net0.prefixlen < n.prefixlen: net0 = n      if net0.prefixlen == 8: return ''  # сеть в нашей базе отсутствует      return template(configFile, ip=str(ip), mask=str(net0.netmask), gw=ipdb[net0]['gw'], ns=ipdb[net0]['ns'])  # получение пречня конфигурационных файлов @route('/list') def show_configs():      cfgList = '<pre>\n';      for cfgFileName in glob.glob('*.cfg'):         cfgList += cfgFileName + '\n'      return cfgList  if __name__ == '__main__':      # загрузка базы сетей     ipdb = {}     with open("networks.csv") as ipdbFile:         for line in ipdbFile:             (network, gw, ns, comment) = line.strip().split(";")             ipdb[ipaddress.ip_network(network)] = { 'gw': gw, 'ns': ns }      # запуск сервера     run(host='127.0.0.1', port=8891) 

Ну и набор конфигурационных файлов, в которых надо в двойных фигурных скобках указать изменяемые параметры (собственный шаблонизатор bottle в деле). Например, строчки с параметрами сети в моих конфигах выглядят так:

network --bootproto=static --device=eno1 --ip={{ip}} --netmask={{mask}} --gateway={{gw}} --nameserver={{ns}} --ipv6=auto --activate --hostname=lnx1 

Как этим пользоваться? При установке указываем путь к файлу:

inst.ks=http://192.168.0.2:8891/new.cfg/192.168.2.31 

где new.cfg — конфигурационный файл, а 192.168.2.31 — ip-адрес нашей будущей машины.

Также можно глянуть, какие kickstart-файлы находятся на сервере. Просто с любой машины зайти браузером на http://192.168.0.2/list.

Данный «сервер» применяйте исключительно в учебных целях! Ибо безопасность здесь отсутствует.

Студентам дарю идею: можно сделать неплохой диплом, развив подобный сервис — с блэкджеком с генератором kickstart-файлов, упорядоченным хранением и отдачей их по сети. Аналогичный сервис RedHat предоставляет это за плату (предположительно, т.к. проверить не могу).

Итак, вроде написано много, а результат, кажется, пока не очень заметен и значим. На самом деле — уже сейчас мы можем написать инструкцию на половинку листочка А4 и отправить её в самый далёкий сегмент нашей распределённой сети. Специально обученный персонал скачивает iso-файл с сервера производителя нашей отечественной ОС (либо с внутренних ресурсов), подготавливает флешку(и) и запускает инсталляцию по нашему сценарию, хоть на полусотне машин одновременно. Причём из инфраструктуры достаточно только одного легковесного веб-сервера на всю корпоративную сеть!

Осталась фаза некоего тюнинга системы. Здесь, несложно — только обозначу, а дальше сами. Как правило, админы делают некий скрипт, который вручную запускают на свежеустановленной системе. В этом скрипте обычно прописаны все необходимые действия в виде установки сертификатов, ssh-ключей, какой-либо дополнительный софт, подключение/отключение репозиториев, правил фаервола, задания в крон и прочее.

Для таких нужд в kickstart имеются две секции — %pre и %post. Секция %pre выполняется до установки. Здесь корректируем работу самого инсталлятора — например, можно изменить параметры разбивки диска в зависимости от его размера, завести какие-нибудь переменные для подстановки их значений в kickstart. У меня эта секция всегда пустая и познания чисто теоретические — пытайте как угодно, ничего не выдам 🙂

Секция %post — вот что нам нужно. Посудите сами: система установлена, chroot в неё сделан, сеть доступна, все системные конфиги сформированы, имеется полный комплект консольных утилит, права на выполнение рутовые. Вдобавок, саму скриптовую часть можно писать как на баше, так и на питоне.

Что тут пишем? Да всё, что перечислял выше:

  • скачиваем и раскладываем сертификаты, запускаем update-ca-trust,
  • заводим необходимых пользователей, скачиваем и раскладываем конфиги в sudoers.d,
  • распихиваем по всем щелям ssh-сертификаты (authorized_keys),
  • скачиваем дополнительные файлы — например, наполняем /etc/skel (man pam_mkhomedir),
  • разрешаем/запрещаем сервисы и сразу конфиги им правим,
  • ограничиваем информационные потоки (файрвол настраиваем),
  • и прочие полезные мероприятия, всё это в любом порядке и в любых количествах.

При написании секции %post обращаю особое внимание на /etc/skel/* — это те файлы, которые система скопирует в домашний каталог пользователя при его первом входе. Так как у линукса нет реестра и сопутствующих ему проблем, то необходимые текстовые конфиги (например, профили firefox, thunderbird) можно также генерировать индивидуально, на этапе инсталляции. Пример %post своих конфигов — не покажу.

Понятно, что такой конфиг не пишется сразу и начисто. Всё многократно отрабатывается на стенде. Ну и результат уж больно хорош — включили аппарат, указали каким образом взять конфигурацию и ушли пить чай или ставить другой компьютер. По завершении подходим помочь юзеру скопировать свои данные и повторно обучить азам пользования компьютером.

Вот коротко про один из методов установки RedHat-based дистрибутивов Linux. Комментируйте.


ссылка на оригинал статьи https://habr.com/ru/company/ruvds/blog/672224/

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

Ваш адрес email не будет опубликован.