Сообщество - Лига Сисадминов

Лига Сисадминов

2 407 постов 18 923 подписчика

Популярные теги в сообществе:

9

Какой дистрибутив посоветуете?

Требования.

  1. Бесплатный. УПДшечка- бесплатный, в том числе и для коммерческих целей и для организаций.

  2. Простая и легкая установка серверов 1С 8.3

  3. Простая и легкая установка Yandex браузер Корпоративный со всеми плагинами для работы с Крипто-Про.

  4. Простая и легкая установка Крипто-Про.

  5. Простая и легкая установка программного обеспечения с функционалом на подобии Active Directory.

    Пост носит скорее юмористически-развлекательный характер, но буду рад советам.

9

Организация труда по сменам – как лучше?

Для лиги лени: проблема выбора графика работы сотрудников службы мониторинга

С овечьей шкурой к скорняку
Зашел Вартан-сосед:
- Из этой шкуры шапку сшить
Ты можешь или нет?

- Могу! - сказал в ответ скорняк,
На шкуру посмотрев.
- А выйдет две? - спросил Вартан,
На корточки присев.
Басня С. Михалкова "Жадный Вартан".
Жадный богач, мультфильм 1980 года

У одного из клиентов возник вопрос – они росли, росли, и, наконец, выросли до того, чтобы работать 24*7. Но, чтобы работать 24*7, им нужна круглосуточная поддержка первой линии, и это должны быть живые люди, а не только авто ответчик или ML\AI (он тоже есть).
В наличии: 8 человек в сменных парах.

Практика
Есть устоявшиеся в практике и законодательстве графики работы, это:
Сутки-трое. 24 часа человек работает, как-то, три дня потом занят своим делом.
Сутки-двое. 24 часа человек работает, как-то, два дня потом занят своим делом.
День, ночь, отсыпной, выходной.
Смены по 8 часов.
И еще несколько вариантов.
Законодательство не РФ, но похоже, так что ограничения есть.

Подводные камни
Сутки-трое
И моя личная практика, и практика коллег, показывают, что 24 часа в мониторы никто не смотрит. Если дежурных двое, то они перекрывают друг друга хотя бы два раза в сутки на 4 часа.
Проспавшая дежурная смена – настолько обычное дело, что встречается везде.
В данном случае нежелательно. Производство не опасное, то есть взорваться не взорвется, но возможны случаи типа пожаров, утечек газа, итд. Крайне редко, но бывает.
То есть на начальном этапе еще так-сяк годится, но в длительной перспективе не самый лучший вариант.
Еще один минус графика сутки-трое, это то, что это достаточно негативно влияет на способность к обучению и способность к принятию осознанных решений. То есть люди способны действовать по простой инструкции - выдернуть шнур, выдавить стекло, но думать уже сложно.
Что еще хуже, сложно учиться, а у клиента есть пожелание брать вчерашних студентов и доучивать их в процессе.

Сутки-двое. Все те же минусы, что у сутки-трое.

День, ночь, отсыпной, выходной
Этот график чуть лучше в части того, что 12 часов человек, с перерывами, способен проработать, и даже принимать более-менее осознанные решения, и даже как-то учиться, но все равно вот эти прыжки графика влияют на все.

Смены по 6-8 часов со сдвинутым выходным
Тут уже возникает проблема обязательных выходных и учета рабочего времени. Я никогда не интересовался, как этот график строят и учитывают на производствах непрерывного цикла, типа нефтехимии и химии, и как в этом случае движутся выходные.

Проблемы отпусков, больничных и увольнений
Люди уходят в отпуска, люди болеют. Иногда болеют сильно. Превращать каждый раз такие события в личный подвиг – совсем не хочется. Раздувать штат – тоже. Найм с текущим состоянием HR под вопросом. Да и дело не в найме, дообучение, практика и сопровождение – это минимум месяц. Неделя на знакомство с системой, неделя работы «смотри что я делаю», неделя работы «делай как я», неделя самостоятельной работы под контролем наставников. Это все человеко-часы наставников, а времени у них не так много. Вводный курс и симуляцию стандартных шаблонных событий уже сделали, но его надо еще и дорабатывать в процессе. То есть ввод даже сотрудника первой линии уже означает дополнительную работу.
К тому же, я уже сталкивался с тем, что один сотрудник в отпуске, а его сменщик в аварию попал. Такие ситуации в сценарии тоже обязательно предусматривать.
Одно дело, если 200 человек в системе с устоявшимся графиком, другое когда система только строится, и там 8 планируется человек.

Проблемы нагрузок и SLA
Нагрузка по задачам в разное время меняется. Днем (речь про ИТ сервисы) нагрузка где-то выше на людей (и работу с людьми), ночью на технику и события по технике. SLA различается, то есть при работе с людьми желательно отвечать «быстрее», при работе с техникой лишние 5 минут ничего особо не решат, отказоустойчивость для техники отрабатывает быстрее.

Проблема нагрузок при инциденте или аварии
Иногда бывают аварии. Поскольку текст больше про ИТ сервисы, то при массовой аварии – например, экскаватор перекопал линию ввода, необходимо оповестить всех заказчиков, что проблема найдена, локализована, и не беспокойтесь.
Такая ситуация не критична, но нужно все равно оповестить заказчика, вдруг у него сотрудники запланировали работы на второй линии.
Любая такая авария – это рост нагрузки на первую линию, и необходимо предусматривать какой-то запас по рабочим часам сотрудников на время инцидента.

Проблема передачи знаний
Как-то получается так, что дообучать сотрудников может оказаться нужно моему отделу.
Я думаю, что можно подойти к вопросу формально, что лекцию по видео прокрутили, анкету «2+2 = 4» и ответы 1)да, 2)вроде да 3)скорее всего да – выдали, и вроде молодцы.
Или же, строить систему обучения, но тогда нужно что-то делать с рабочим графиком, потому что известно:
1 Дети до 12 лет не могут сохранять концентрацию дольше 20 минут.
2 Дети с 12 до 16 не могут сохранять концентрацию дольше 40 минут, без перерыва 10-15 минут.
3 Студенты не могут сохранять концентрацию дольше 2 раз по 40 минут с перерывом 5 минут
4 Взрослые не могут сохранять высокую концентрацию больше 1.5 – 2 часов
Это давно исследовано, еще и Тейлором, и военными в первую и вторую мировые войны, и исследованиями «потом», поэтому если нужно реально учить, то надо что-то делать с рабочим графиком, в первую очередь с графиком сна.

Размышления

Можно делать график так, что часть сотрудников работает сутки-трое, часть день-ночь-отсыпной-выходной, с возможностью менять местами сотрудников. Это не очень удобно, и бухгалтерия будет не в восторге от пересчетов.
Можно делать странные графики работы, но это сложно по производственным соображениям, и по графикам. Слишком сложная схема приводит к сбоям при инцидентах.

Вопрос:
Кто сталкивался с графиком 2-2-3, графиком DuPont (4-3-4-7) и с 12-часовым графиком Питмана?
потому что даже в иностранной литературе пишут, что график 9/80 не всякий бухгалтерский софт нормально потянет.

Заключение

Надо думать. Пока ничего не понятно, область не моя.

Литература
ВБ График работы «сутки через двое»
ВБ Скользящий график работы: оформление и оплата в 2025 году
ВБ Сменный график работы: оформление и оплата в 2025 году
КП График работы день ночь отсыпной выходной
Пикабу Плюсы и минусы сменного графика и пятидневки
Пикабу Ответ на пост «Плюсы и минусы сменного графика и пятидневки
24-часовой график сменности: Советы, примеры и шаблоны
Иностранная литература Hints and tips for shift-workers
Иностранная литература Tips for Shift Workers
Иностранная литература Managing 24/7: Common traits of successful shiftworkers
Иностранная литература 9 Tweaks To Make Shift Working Even Better For Your Employees
Иностранная литература What is a 2-2-3 Schedule and How Does it Work?
Иностранная литература 9/80 Work Schedule: What It Is, When To Use It, Plus Benefits and Challenges

Показать полностью 2
1

Вышел Windows 11 версия 25H2 (сборка 26200)

Вышел Windows 11 версия 25H2 (сборка 26200) - это второе крупное обновление 2025 года, содержащее новые функции, улучшения безопасности и производительности.

Вышел Windows 11 версия 25H2 (сборка 26200)



Способы обновления


Вариант 1: Центр обновления Windows (Рекомендуемый)


Параметры → Центр обновления Windows → Проверить наличие обновлений

Если не сработал, идем через вариант 2:


Вариант 2: PowerShell скрипт (от Администратора)


1. Запускаем PowerShell от администратора


2. Настройка политики выполнения


# Временное разрешение выполнения скриптов (для текущей сессии)
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope Process -Force


3. Скачивание скрипта обновления


$ScriptPath = "$env:USERPROFILE\Downloads\Win11-25H2-Update" New-Item -ItemType Directory -Path $ScriptPath -Force
Invoke-WebRequest -Uri "https://raw.githubusercontent.com/paulmann/Windows-11-25H2-U..." -OutFile "$ScriptPath\Upgrade-Win11-To-25H2.ps1" -UseBasicParsing
Set-Location "$env:USERPROFILE\Downloads\Win11-25H2-Update"
.\Upgrade-Win11-To-25H2.ps1


Собственно, все. После обновления нужно перезагрузить компьютер.

Показать полностью
8

Ответ на пост «Новое место работы»1

хотел бы задать встречный вопрос. с текущего 2025 года начал действовать "национальный режим", который предписывает закупки техники по 44ФЗ делать в перимущественном порядке либо Российского производства либо по лицензии ЕАЭС. как выкручиваетесь? я в относительно небольшом муниципальном учреждении. в свое время, до моего трудоустройства они каким-то чудом приобрели сервер Supermicro 11X, все это хозяйство просто стояло. а в работе был совершенно трухлявый и старый сервер. AGILE - подобными аккуратными шагами я мигрировал на этот Х11 сделал его гипервизором с RAID 10, на виртуалках завел AD, Asterisk, DrWeb - на линуксе для сети. Телефонию поднля на Cisco-фонах бэушных. Настал 2025 год - как жить? Все что "отечественное" ужасно дорогое. если раньше можно было купить что-то импортное за недорого, то теперь мне местная закупщица не покупает вообще ничего.

121

Новое место работы1

Доброго днища господа и дамы, просто решил поделиться своим новым местом работы. Ну и узнать у коллег по цеху, бывало ли в их истории что-то похожее или даже хуже 🤓

Тут у нас серверная, и сразу же кабинет системного администратора.
Душный, пыльный, грязный и не проветриваемый кабинет.
Постоянного админа тут небыло очень давно, были только удалёнщики, приходящие вечерние и студенты которые помогали администрации.

В стойке находится:
2 роутера РТК с оптикой
1 для ЕСПД, второй с обычной линией.
Коммутатор DGS 1250 28X.
Коммутационная панель netlan.
Коммутатор DGS 1052.
Еле дышащий и старый сервер.
Сетевое хранилище (вирусняков там мама не горюй).
Под ним ПК с 1С.
И рядом ПК с консультантом.

Всё это дело рассчитано под +250 машин
Сетевого др веба никто не ставил, хотя кто работает в образовании в курсе что его выдавали.
На пк и то не везде стоит тотал 360 и мс дифендр.

Парк пк старый, но для бюджетной организации даже не плохой. В основом стоит 7 и 10, примерно 50 на 50, астру поставили буквально на пару тройку машин.

Большое количество проблем с пк в учреждении в целом и с сетью тоже, на днях метров 250-300 вытянул мертвых витушек из кабель каналов, которые были воткнуты в коммутаторы, и обрезаны или порваны на другом конце.
Вот как то так, глаза и руки разбегаются не знаю за что хвататься)
Паролей и каких либо данных с документацией мне никто не передавал, а что передали по паролям не подошло)

Пост несёт чисто вовлекающий характер, интересно узнать мнение коллег и подискутировать.

ПС, за ошибки и кривое оформление поста прошу прощения, писал очень уставший, но пока был наплыв захотелось поделиться)


Небольшой бонус, в прошлый четверг, роутер начал ловить дикий перегрев (под 80 градусов) и уходить в отруб, роутеру как выяснилось лет 5-6 где-то было.
Пришлось импровизировать пока РТКашники не привезли замену через 3 дня.

Показать полностью 2
12

Ansible для детского сада. Часть 5. Приделываем костыли

У меня постоянное ощущение того, что я описываю не велосипед с костылями, а велосипед, который давно изобретен, на котором все катались лет 15 назад, если не 20. Что-то типа «введение в линукс и все вокруг для 10 класса». Что на информатике учат.

Для лиги лени: много примеров, как делать не надо, и как точно не работает

Ansible для детского сада в скольки то частях. Часть 1.Про все сразу
Ansible для детского сада в скольки то частях. Часть 2. Костылируем жалкое подобие WSUS - Linux Server Update Services (LSUS)
Ansible для детского сада. Часть 3. Настраиваем подобие безопасности и все остальное
Подготовка Git

Ansible для детского сада. Часть 4. Первичная настройка конечного клиента
4.1 Теоретически все просто
4.2 Сначала готовим открытую часть сертификата без пароля через Putty в Windows и еще раз вспоминаем что генерирует Putty в Windows, а что нужно в ssh
4.3 Детский скрипт, и как не надо делать
4.4 Отлаживаем SSH, снова и опять
4.5 Проблемы с переносом строки и не только
4.6 Проверяем, что получилось
4.7 Почти переходим к второму Ansible плейбуку
4.8 Воюем с пробелами в Anisble и восстанавливаем пример из первой статьи
4.9 Возвращаемся к основной задаче

Ansible для детского сада в скольки то частях. Часть 5. Приделываем костыли
5.1 Теоретическое обоснование костылей, или «зачем».
5.2 Выбор dataflow
5.3 Собираем Ansible facts без плейбука
5.4 Разбираем полученную выгрузку

Ansible для детского сада в скольки то частях. Часть 5. Приделываем костыли

5.1 Теоретическое обоснование костылей, или «зачем».

С какого-то возраста появился вопрос: «Зачем?» Вот раньше тебе звонил приятель, например, говорил: «Слушай, я познакомился с двумя девушками, у них отдельная квартира в Отрадном, я выпить купил. Поехали!» И ты сразу ехал. Если бы тебя спросили: «А зачем?», ты бы сказал: «Ну как, зачем? Ты че, дурак? Две девушки, отдельная квартира! Посидим, выпьем, ну...» А сейчас...

Перед тем, как идти дальше, необходимо принять решение про архитектуру Linux Server Update Services (LSUS) на первом этапе. Поскольку сейчас я хочу только собирать и показывать статистику в нужном мне виде, с нужной детализацией. Часть информации я могу получать, не изобретая новую систему учета, а взяв имеющуюся, и переформатировав отчет из нее. Но насколько это будет сложно и долго? Нужен ли мне будет настоящий разработчик для такой задачи, потому что разработчик сделает ее быстрее, но сделает ли так, как мне надо? Учитывая, что я сам не знаю, как мне надо, значит, остается только попробовать сделать.

5.2 Выбор dataflow
Про что это? В результате обработки (входных данных) я получу (обработанные входные данные). Затем мне надо понять:
Где я буду обрабатывать сырые данные, на хосте с ansible или сделаю файл «как есть», положу его в общую папку (или как-то еще ?), заберу с хоста с Windows и там обработаю. Мне все равно, под что писать простой обработчик, под Windows или под Linux, и на чем писать – могу на баш (много секса, мало смысла), могу на питоне, могу на powershell. При малых объемах нет принципиальной разницы, обработается ли файл на 100 – 1.000 – 10.000 хостов за минуту, или за две.
Куда я помещу обработанные входные данные, в csv, xlsx, xml, или в web\html.
Если в web, то на каком веб-сервере? Апач, нжинкс, IIS, или даже MiniWeb и Small HTTP Server.
Нужно ли хранить исторические данные ?

Все это, и даже больше, я писал во второй части –

С целевой структурой данных ситуация сложнее. Для своего предпоследнего пет проекта под похожие задачи я просто развернул базу данных (Postgre), и туда клал разное. Нужно ли на первом шаге такое решение? Не знаю, мне не нужно, мне и бинарной таблицы хватит. Но что туда класть? Очевидно, туда должны попасть: FQDN, IP, дистрибутив, версия дистрибутива, ядро сейчас, последние дата и время доступности, аптайм. Должно ли туда попадать предыдущее состояние объекта, и какие-то еще настройки? Не очень важно, всегда можно расширить схему данных, добавить к объекту еще пару свойств.

Пока получается так, что сначала надо разобрать входной объект (файл, выгрузку), собрать из него данные в удобный мне массив объектов (или в список объектов, но это вопрос выбора алгоритма и понимания разницы работы с массивом и работы со списком). Когда будет массив данных в нужном мне виде, из него можно собрать уже то, что нужно мне.

5.3 Собираем Ansible facts без плейбука

Во второй части факты собирались одной командой,
ansible proxmox -m setup -a "filter=ansible_uptime_seconds" --ask-pass
В предыдущей (4-й) части я остановился на выполнении плейбука

ansible-playbook report23.yml --inventory  /home/user/second_inventory.ini --private-key  /home/ansible1/.ssh/ansible_key

Нужно ли делать плейбук именно для сбора фактов? Получается, что нет. Достаточно еще раз прочитать про ключи к ansible, и сделать:
[-i INVENTORY] [--list-hosts] [-l SUBSET] [--flush-cache]
[--private-key PRIVATE_KEY_FILE] [-u REMOTE_USER]

То есть выполнить все в одну команду:

ansible all --module-name setup --inventory  /home/user/second_inventory.ini --private-key  /home/ansible1/.ssh/ansible_key

не забывайте про all, даже если указываете --inventory  /home/user/second_inventory.ini.

на выводе вы получите текст ужасающей длины, в формате с {}, [], и еще чем-то. 150 килобайт на мои 3 (три) тестовые виртуальные машины.

Из этого огромного массива представляет интерес:

FQDN, IP, дистрибутив, версия дистрибутива, ядро сейчас, последние дата и время доступности, аптайм. То есть, в нужный мне объект должны попасть:
Удачность соединения: 192.168.1111.2222 | SUCCESS => {
FQDN: "ansible_fqdn"
Hostname: "ansible_hostname"
IP: "ansible_all_ipv4_addresses"
IPv6: "ansible_all_ipv6_addresses":
тип: "ansible_board_name": "Virtual Machine",
Текущие сессии: "SSH_CONNECTION":
Текущий пользователь "USER": "ansible1",. С этим параметром надо поработать, а то есть любители забыть закрыть сессию.
MAC "macaddress": ". Нужен, но не для сетевых настроек, а для сверки, не сделал ли кто-то, случайно, клонирование с совпадающим MAC адресом. Бывает и такое легаси.
"ansible_kernel": "6.1.0-40-amd64",
"ansible_kernel_version": "#1 SMP PREEMPT_DYNAMIC Debian 6.1.153-1 (2025-09-20)",
"ansible_lsb": {
"codename": "bookworm",
"description": "Debian GNU/Linux 12 (bookworm)",
"id": "Debian",
"major_release": "12",
"release": "12"

Все вместе выглядит или как начало поиска готового решения «как свернуть xml в набор объектов», или как задача первого (для начинающих) уровня сложности с AlgoMap.io  \ Codility \ LeetCode \ итд, свертывание xml в объект со свойствами.  Не взяв xml.etree.ElementTree, а все сам, все руками. Дело не сложное, но надо вспоминать лаго алгоритм

Но, у меня сейчас дел вдруг привалило, что я даже не знаю, когда дописать цикл. Новый проект, новые задачи.

Поэтому сделаю быстро, грязно, на powershell под windows, и так делать, вообще говоря, не нужно.

Еще придется не забыть сразу сделать выгрузку с примером ошибки недоступности хоста, и что-то с этим делать.

5.4 Разбираем полученную выгрузку

Поскольку все сделано в непревзойденном стиле «давайте не будем спрашивать нейросеть», то не удивляйтесь, что написано не просто плохо, а отвратительно плохо. Ирония не в том, могу ли я сделать задачу «сверните xml в массив вложенных объектов», как на интервью для джуна, а в том, хочу ли я потом искать, в какой путь это свернулось.

Поэтому вот вам еще один образец, как делать плохо и неправильно. Еще и неполный образец. Еще и на Powershell. Короче, сплошной позор.

# Ansible facts parser

Write-Host "Start 01 ================="

$Version = "AFP001"

$ScriptPath = $PSScriptRoot

$DataFromFile001 = Get-Content ($ScriptPath + "\" + "resultv01.txt")

Write-Host 'Read from file total' $DataFromFile001.count

Write-Host 'Read from file first' $DataFromFile001[0]

Write-Host 'Read from file last' $DataFromFile001[$DataFromFile001.count -1]

$SplitStartMark = '| SUCCESS => {'


Write-Host "Start 02 ================="

for ($Mark = 0; $Mark -lt $DataFromFile001.count; $Mark++){

if ($DataFromFile001[$Mark] -like "*$SplitStartMark") {Write-Host "Mark" $Mark ';' $DataFromFile001[$Mark]

}}


Class Split{

[int]$Position

[string]$String

}


Write-Host "Start 03 ================="

$SplitStartMarkPosition = @()


for ($Mark = 0; $Mark -lt $DataFromFile001.count; $Mark++){

if ($DataFromFile001[$Mark] -like "*$SplitStartMark") {

Write-Host "Mark" $Mark ';' $DataFromFile001[$Mark]

$NewHost = [Split]::new()

$NewHost.Position = $Mark

$NewHost.String = $DataFromFile001[$Mark]

$SplitStartMarkPosition += $NewHost

Remove-Variable NewHost

}}

Write-Host "Total" $SplitStartMarkPosition.Count


Write-Host "Start 04 ================="

Class AnsibleFacts01{

[string]$IsSUCCESS

[string]$FQDN

[string]$IP

[string]$ansible_kernel_version}



$NewHost1 = [AnsibleFacts01]::new()

$NewHost1.IsSUCCESS = $DataFromFile001[0]

for ($Mark = 0; $Mark -lt $SplitStartMarkPosition[1].Position; $Mark++){


if ($DataFromFile001[$Mark] -like '*ansible_fqdn*') {$NewHost1.FQDN = $DataFromFile001[$Mark]}

if ($DataFromFile001[$Mark] -like '*ansible_all_ipv4_addresses*') {$NewHost1.IP = $DataFromFile001[$Mark+1]}

if ($DataFromFile001[$Mark] -like '*ansible_kernel_version*') {$NewHost1.ansible_kernel_version = $DataFromFile001[$Mark]}

}


$NewHost1 | fl


Write-Host "Start 05 ================="

$NewHost2 = [AnsibleFacts01]::new()

$NewHost2.IsSUCCESS = $DataFromFile001[$SplitStartMarkPosition[1].Position] -replace "[^a-z][^A-Z]" -replace "{",""

for ($Mark = $SplitStartMarkPosition[1].Position; $Mark -lt $SplitStartMarkPosition[2].Position; $Mark++){

if ($DataFromFile001[$Mark] -like '*ansible_fqdn*') {$NewHost2.FQDN =  $DataFromFile001[$Mark] -replace '"ansible_fqdn":',"" -replace " ", "" -replace ",","" -replace '"',""}

if ($DataFromFile001[$Mark] -like '*ansible_all_ipv4_addresses*') {$NewHost2.IP = ($DataFromFile001[$Mark+1] -replace '"',"").TrimStart()}

$kv = ''

if ($DataFromFile001[$Mark] -like '*ansible_kernel_version*') {$NewHost2.ansible_kernel_version = ($DataFromFile001[$Mark] -replace '"ansible_kernel_version":', ""  -replace "," -replace '"',"").TrimStart()}

}


$NewHost2 | fl

Что делать дальше – понятно. Тут и обработка ошибок, и нормальное формирование объекта, и что делать, если хост не отвечает, и сравнение состояния «как есть» и «как надо».

Заключение
На написание 5 заметок ушло где-то 10-15 дней, по часу в день. Не каждый день. Хотя один выходной я потратил, с обеда до ужина.
На запуск такого костыля «чтобы посмотреть, что там в простой инфраструктуре», зная как, и куда смотреть, ушло бы примерно 3 рабочих дня для 1 джуна. Даже если в инфраструктуре вообще ничего нет. Остальные работы, доведение выгрузки до читаемого вида, сбор образцов, итд, заняли бы еще пару дней с кофе.
Поэтому, если где-то нет такой выгрузки, то я не знаю, чем там занимается и отдел ИТ, и отдел имитации безопасности.

Литература
ahuffman / ansible-sudoers
Ansible docs: ansible
Microsoft: Windows PowerShell - Build User-Friendly XML Interfaces with Windows PowerShell
Microsoft:  Add-Member Module: Microsoft.PowerShell.Utility Module
Microsoft:  Everything you wanted to know about PSCustomObject
Microsoft:  about_Regular_Expressions

Показать полностью
7

Ansible для детского сада. Часть 4. Первичная настройка конечного клиента

У меня постоянное ощущение того, что я описываю не велосипед с костылями, а велосипед, который давно изобретен, на котором все катались лет 15 назад, если не 20. Что-то типа «введение в линукс и все вокруг для 10 класса». Что на информатике учат.
Теперь еще и форматирование при оформлении слетает, хотел быстренько выложить, пока обед, а придется потратить полчаса.

Для лиги лени: много примеров, как делать не надо, и как точно не работает
Ansible для детского сада в скольки то частях. Часть 1.Про все сразу
Ansible для детского сада в скольки то частях. Часть 2. Костылируем жалкое подобие WSUS - Linux Server Update Services (LSUS)
Ansible для детского сада. Часть 3. Настраиваем подобие безопасности и все остальное
Подготовка Git

Ansible для детского сада. Часть 4. Первичная настройка конечного клиента
4.1 Теоретически все просто
4.2 Сначала готовим открытую часть сертификата без пароля через Putty в Windows и еще раз вспоминаем что генерирует Putty в Windows, а что нужно в ssh
4.3 Детский скрипт, и как не надо делать
4.4 Отлаживаем SSH, снова и опять
4.5 Проблемы с переносом строки и не только
4.6 Проверяем, что получилось
4.7 Почти переходим к второму Ansible плейбуку
4.8 Воюем с пробелами в Anisble и восстанавливаем пример из первой статьи
4.9 Возвращаемся к основной задаче

Ansible для детского сада в скольки то частях. Часть 5. Приделываем костыли

Ansible для детского сада. Часть 4. Первичная настройка конечного клиента

В предыдущей части оказалось, что в системе есть узкое место – первичная настройка.

4.1 Теоретически все просто:

пишем отдельный плейбук типа такого: Reddit Creating System Users for Ansible Execution

# From a clean system with root ssh access:
# - Install sudo
# - Add the ansible user
# - Enable wheel group for sudo

- name: add wheel group
group:
name: wheel
state: present

- name: add ansible user
user:
name: ansible
groups: wheel
password: "{{ ansible_become_password }}"
createhome: yes
home: /var/local/ansible
state: present
shell: /bin/bash
uid: 20000

- name: install sudo
apt:
name: sudo
state: installed
when: ansible_os_family == 'Debian'

- name: configure sudoers
lineinfile:
dest: /etc/sudoers.d/ansible
line: "%wheel ALL=(ALL) ALL"
state: present
create: yes
validate: 'visudo -cf %s'
owner: root
group: root
mode: 0440

- name: create ansible user authorized_keys file from id_ed25519
authorized_key:
user: ansible
manage_dir: no
path: /etc/ssh/ansible
key: "{{ lookup('file', ansible_ssh_key) }}"

Практически это означает ручную настройку для рута «еще раз». Как раз этого хочется избежать, потому что в том же Debian по умолчанию ssh для root закрыт. Изменить настройку можно. Но не нужно.

4.2 Сначала готовим открытую часть сертификата без пароля через Putty (PUTTYGEN) в Windows и еще раз вспоминаем что генерирует Putty в Windows, а что нужно в ssh

Это все помнят, но необходимо повторить еще раз.

По результатам опытов и вопросов «что ж не работает то» ключ я сделал на целых 4096 бит, а вовсе не по умолчанию в 2048. Вроде бы, должно и так работать, но ведь нет!

Когда PUTTYGEN генерирует пару ключей, открытый и закрытый ключ, то мы получаем два файла.

В моем примере:

ex1_public.pkb – файл с открытым ключем. Можно было сделать без расширения, значения это не имеет
ex1_private.ppk – файл с закрытой частью ключа.
ex1_public выглядит как:

---- BEGIN SSH2 PUBLIC KEY ----

Comment: "key-4-pikabu"

AAAABС(длинный ключ)

---- END SSH2 PUBLIC KEY ----

ex1_private.ppk выглядит как:

PuTTY-User-Key-File-3: ssh-rsa

Encryption: none

Comment: key-4-pikabu

Public-Lines: 6

AAAABС (длинный ключ на 6 строк, он же лежит в ex1_public.pkb)

Private-Lines: 14

AAABAF(длинный ключ)A==

Private-MAC: f(длинная последовательность)

если вы нажимали еще какие-то кнопки и настройки, то могут встречаться строки типа:

Key-Derivation: Argon2id

Argon2-Memory: 8192

Argon2-Passes: 34

В /home/user/.ssh/ authorized_keys лежит только строка из открытого ключа в формате:

ssh-rsa AAAABС.. (и так далее) вплоть до конца строки.

PUTTYGEN так и показывает , КАК НАДО.

4.3 Детский скрипт, и как не надо делать

Перепишу все, что выше, обратно в ssh \ bash:

В процессе отладки выяснилось, что есть такое ограничение, как регистр имени пользователя в Linux, описанное как
User/group names must match [a-z_][a-z0-9_-]*[$],

то есть можно и нужно было посмотреть в тот же chkname.c., и увидеть там

* is_valid_user_name(), is_valid_group_name() - check the new user/group

дебиан сорцы, наведение через ЖЖ - Формат имени пользователя в Linux.

Поэтому, сделать

username=Ansible1

можно, и даже пароль ему поставить можно, но потом разбираться с chmod\chown для \home\ Ansible1\.ssh – это какой-то совсем не очевидный процесс. Хотя при входе с паролем такое имя пользователя работает, но разбираться еще и с этим в рамках статьи было лень, и, значит, пусть все будет строчное.

username=ansible1

/usr/sbin/useradd -m -s /bin/bash "$username"

# как не надо изобретать свои костыли

# Superrandom1=$RANDOM*$RANDOM+$RANDOM-$RANDOM*$RANDOM

# это строка, и математика так не сработает. Это и не важно

# PASS1=$(echo -n $Superrandom1 | sha256sum)

# echo $PASS > ps1.txt

# echo ${PASS:0:64} > ps2.txt

# PASS2=`date`

# PASS3=${PASS2:0:3}-${PASS:0:60}

#PASS2=${PASS:0:61}

# echo -e $PASS2\n$PASS2 | passwd "$username"

# так не работает, потому что в sha256sum попадаются простые сочетания.# echo $PASS3

# echo $username:$PASS3 | /usr/sbin/chpasswd #тут почему-то denied

PASS4=`cat /dev/urandom | fold -w 32 | head -n 1`

echo $username:$PASS4 | /usr/sbin/chpasswd

Пароль поставили. Но он не нужен, потому что вход будет по сертификату. Пока переделывал оформление, вспомнил, что не отключил вход по паролю.

Добавлю группу и юзера в группу

groupname=ans_demo1

/usr/sbin/groupadd $groupname

/usr/sbin/usermod --append --groups $groupname $username

Теперь sudoers для группы:

mkdir -p /etc/sudoers.d

и дальше

curl --header "PRIVATE-TOKEN: glpat-norDQhvwoTxyAtM9ANhV" http://192.168.1111.2222/api/v4/projects/2/repository/files/ansible/raw?ref=main -o /etc/sudoers.d/ansible

где 2 – ID проекта, а токен ваш токен. Токен в примере выше я сменил, и это токен из домашней лабы, и с этим токеном не так много можно увидеть даже в домашней лабе. Можно увидеть открытую часть ключа, и метод генерации случайного пароля.

Содержание sudoers.d/ansible

## Allow root to run any commands anywhere

root ALL=(ALL) ALL

## Allows people in group wheel to run all commands

%ans_demo1 ALL=(ALL) ALL

## Same thing without a password

%ans_demo1 ALL=(ALL) NOPASSWD: ALL

и остается сделать только

curl --header "PRIVATE-TOKEN: glpat-norDQhvwoTxyAtM9ANhV" http://192.168.1111.2222/api/v4/projects/2/repository/files/authorized_keys/raw?ref=main -o /home/$username/.ssh/authorized_keys --create-dirs

Думали все так просто? Ничего подобного. Так работать без дополнительной магии не будет.

4.4 Отлаживаем SSH, снова и опять

Эти пара абзацев написаны после того, как в разделе 4.9 ничего не заработало, потому что я попросту забыл настроить права на файл. Вроде, столько раз делал, и опять забыл.

По результатам перегенерации всех паролей и настроек я имею:

Локально, на ПК с Windows,
Было ex1_public.pkb, стало pikabu_part4_public – файл с открытым ключем. Расширение значения не имеет
Было ex1_private.ppk, стало pikabu_part4_private.ppk - файл с закрытой частью ключа.

Это два текстовых файла. Конечно, лучше бы файл с закрытой частью ключа хранить на зашифрованном разделе, или в волте, или как-то еще, «закрыто».

Файл pikabu_part4_export4ssh. Это экспорт файла для ssh, потом будет нужен.
В гите, в файле authorized_keys, лежит, в одну строку, длинная строка с началом

ssh-rsa AAAAB… и окончанием == и какой-то комментарий, который вы сами пропишете при создании ключа.

Поскольку дело происходит в Debian, то речь про
tail -f /var/log/auth.log – не идет, а в
journalctl -ru ssh | grep 'Could not open user' -
будет
Could not open user 'Ansible1' authorized keys '/home/Ansible1/.ssh/authorized_keys': Permission denied

В интернетах пишут: сделайте chmod да chown, и будет вам радость да счастье. Возьму да сделаю!

chmod 600 /home/ansible1/.ssh/authorized_keys
chmod 700 /home/ansible1/.ssh/
chown ansible1 /home/ansible1/.ssh/ -R
systemctl restart ssh.service

Про вот такое еще пишут знающие люди в интернетах, но я пожалуй, воздержусь.

chown ansible1:ans_demo1 /home/ansible1/.ssh –R

И вот замечу я, что когда все буковки в имени пользователя стали маленькие, то волшебным образом все заработало. А пока user был Ansible1, то есть с большой буквы, то сделав

passwd Ansible1

все работало, а через ssh – нет. И магия это мне не понятна, поскольку и ключи я переделал, и все переписал, и три раза перегрузил, а ишь ты – не работало, и хоть ты что делай.

Потому делал я всякое непотребное,
pkill -KILL -u ansible1
и
/usr/sbin/deluser ansible1

и неоднократно.

4.5 Проблемы с переносом строки и не только

Если вы копипастите из винды \ текстового файла (в формате винды с переносом строки и возвратом каретки), и потом тащите этот файл в git, и потом на Linux машину, не забудьте сменить формат переноса строки через

sed -i 's/\r$//' filename

Потому что иногда так получается, что скрипт в две строки, из примера в третьей части, работает нормально. Вот такой еще работает,

#!/bin/bash
date

А что-то длиннее начинает ругаться на
command not found
или
unexpected token `newline

Прям печаль и беда. Что остается? Костыли.

curl --header "PRIVATE-TOKEN: glpat-norDQhvwoTxyAtM9ANhV" http://192.168.1111.2222/api/v4/projects/2/repository/files/second.sh/raw?ref=main -o ansible4.txt && sed -i 's/\r$//' ansible4.txt && bash ansible4.txt

Конечно, правильнее хранить токены не в коде, а в vault. Но если у этого токена доступ только к этому проекту, то .. и так сойдет.
И, конечно токен не стоит хранить в коде, а имеет смысл передавать как параметр в командной строке. Или нет.

4.6 Проверяем, что получилось

Во первых. Оказалось, что я забыл установить пакет sudo. Нет его в Debian12 и Debian 13 by Proxmox. Не забудьте дописать
Во вторых. Оказалось, что я на одном из хостов не прописал Nexus в /etc/apt/sources.list, отчего обновления не шли. Тоже не забывайте.
В третьих. На одном хосте словил: bash: curl: command not found
Потому что curl там лежит, почему-то, только в:
/usr/share/bash-completion/completions/curl
/usr/lib/python3/dist-packages/curl

как это в одном дебиане работает, в другом нет, я даже не пытаюсь понять. Поэтому:
сначала nano /etc/resolv.conf (где у меня с времен тестов SSSD прописан DNS от AD DC), потом

apt install curl -y

Итого я забыл:

apt install curl -y
apt install sudo -y

заменить или исправить /etc/resolv.conf
заменить или исправить /etc/apt/sources.list. Причем, при использовании Nexus, это будут разные sources.list.

Или нет ? Прописать то я могу что угодно.
Отредактировать /etc/ssh/sshd_config – для входа только по сертификату, сделать PasswordAuthentication no

И про велосипед.

Вопрос «что лучше, исправить или заменить» - мне не ясен. И та и другая операция приводит к одному виду, а что «правильнее» ?

В скрипте выше в строке
PASS4=`cat /dev/urandom | fold -w 32 | head -n 1`
возникают ошибки
ansible4.txt: line 17: warning: command substitution: ignored null byte in input
Да и путь -o ansible4.txt правильнее переписать как -o ~/ansible4.txt, но опять же, если это все работает не от рута, потому что у рута домашняя директория (~) вовсе не /home/user.

И что с этим делать, мне тоже не понятно. То есть, мне то понятно, ничего не делать.
Осталось удалить созданную в ходе опытов директорию ''$'\r'?. Оказалось, что проще всего ее сначала переименовать, иначе удаление делает некоторые фокусы, особенно если сделать rm $'*

Еще от влияния переноса строки образовалась не только \home\Ansible1, но и:
'Ansible1'$'\r' и 'Ansible1'$'\r\r'
И в скрипт можно бы и дописать, rm ansible5.txt.
Или даже и apt update && apt upgrade -y, вдруг забыл кто-то, кто систему ставил, сделать сразу же после настройки /etc/apt/sources.list.

4.7 Почти переходим к второму Ansible плейбуку

Вначале было слово, потом был вообще не плейбук, а команда
ansible proxmox -m setup -a "filter=ansible_uptime_seconds" --ask-pass

Первый плейбук, /home/user/uptime_report.yml, описан в первой статье, как и перечень хостов к нему,/home/user/1st_hosts.ini.
Итоговая команда была:

ansible-playbook uptime_report.yml --ask-pass --user root --inventory /home/user/1st_hosts.ini

При этом, я еще и умудрился файл uptime_report.yml сломать. Точнее, случайно удалить, и при переписывании получить:

[ERROR]: YAML parsing failed: This may be an issue with missing quotes around a template block.
Origin: /home/user/uptime_report.yml:11:19
9 msg:
10 Hostname: {{ inventory_hostname }}
11 Uptime: {{ (ansible_uptime_seconds / 86400) | int }} days,
^ column 19

Вот она, проблема vibe кода. Какой запрос был, я, конечно, не помню. Почему сломалось – не знаю, и написано не понять. Починить? Могу, но.
Но я так люблю возню с пробелами, кавычками, и даже со скобками, вы не представляете насколько.

4.8 Воюем с пробелами в Anisble и восстанавливаем пример из первой статьи

В статье Slurm: Примеры Ansible-Playbook есть максимально простой пример (пробелы в начале строки заменены на ! для лучшей считаемости числа пробелов). Файл: example01.yml

- hosts: all

!!tasks:

!!!!- name: Проверить доступность

!!!!!!ping:

Такой сценарий работает, и ему, кстати, безразлична возня с переносами строки.

Если же я пойду в справочник Ansible ansible.builtin.debug module – Print statements during execution, и сделаю

---

- name: Print the gateway for each host when defined

ansible.builtin.debug:

msg: System {{ inventory_hostname }} has gateway {{ ansible_default_ipv4.gateway }}

when: ansible_default_ipv4.gateway is defined

То я получу новую ошибку:

[ERROR]: 'ansible.builtin.debug' is not a valid attribute for a Play

То есть, пример Simple Ansible playbook to get the Linux host uptime – работает, а пример из документации – не работает, то есть не совсем не работает, но это очередной случай «в документации забыли прописать очевидное тем, кто ее пишет, и не очевидное тем, кто ее читает первый раз».

Возьму часть примера из статьи Simple Ansible playbook to get the Linux host uptime и продолжу с ним

Пример 2 (файл: example2) «Не работает!!!!!111111». Пробелы заменены на 1234.

Ошибка: [ERROR]: YAML parsing failed: Colons in unquoted values must be followed by a non-space character.

- name: Print the gateway for each host when defined

12hosts: all

12gather_facts: true # Ensure facts are gathered to get ansible_uptime_seconds

12tasks:

12- name: Display uptime for each host

123456debug:

12345678msg: " Examlpe test 2 "

123456when: (uptime_days | int) > 30

Пример 3 (файл: example3) так работает проверка синтаксиса, но не исполнение yml. Пробелы заменены на 1234

- name: Print the gateway for each host when defined

12hosts: all

12gather_facts: true # Ensure facts are gathered to get ansible_uptime_seconds

12tasks:

1234- name: Display uptime for each host

123456debug:

12345678msg: " Examlpe test 3 "

123456when: (uptime_days | int) > 30

Как легко заметить (не легко, но можно):
Не работающий пример:
12- name: Display uptime for each host
Пример с работающей проверкой синтаксиса:
1234- name: Display uptime for each host

Пример 3 (выше), хотя и проходит проверку, но не будет работать с ошибкой:
[ERROR]: Task failed: Error while evaluating conditional: 'uptime_days' is undefined

Еще раз читаем статью Simple Ansible playbook to get the Linux host uptime, и пытаемся сделать так же. Можно найти статью Отладка плэйбуков ansible.

Пример «НЕ Работает #21 ». Пробелы заменены на 1234
Точнее, не проходит проверку синтаксиса командой
ansible-playbook --syntax-check report21.yml, с ошибкой
YAML parsing failed: This may be an issue with missing quotes around a template block.

---

- name: Get and display system uptimes 21

12hosts: all

12gather_facts: true # Ensure facts are gathered to get ansible_uptime_seconds

12tasks:

1234- name: Display uptime for each host

123456ansible.builtin.debug:

12345678msg:

1234567890Hostname: {{ inventory_hostname }}

1234567890Uptime: {{ (ansible_uptime_seconds / 86400) | int }} days,

1234567890{{ ((ansible_uptime_seconds % 86400) / 3600) | int }} hours,

1234567890{{ (((ansible_uptime_seconds % 86400) % 3600) / 60) | int }} minutes,

1234567890{{ (((ansible_uptime_seconds % 86400) % 3600) % 60) | int }} seconds

123456when: ansible_uptime_seconds is defined

Пример «Работает #22». Пробелы заменены на 1234

Это то, что генерит google AI для примеров, и оно даже работает. Пока не надо отлаживать.

---

- name: Show uptime for each host in seconds

12hosts: all

12gather_facts: true # Ensure facts are gathered

12tasks:

1234- name: Display uptime in seconds

123456ansible.builtin.debug:

12345678msg: "Host {{ inventory_hostname }} has been up for {{ ansible_uptime_seconds }} seconds."

Пример «Работает #23».

Только картинкой, отличия от #21 очевидны – кавычки открыли, кавычки закрыли.

12345678msg:
и
12345678msg: "

4.9 Возвращаемся к основной задаче

Для следующего подхода нам потребуется два, а лучше три файла.
первый - second_inventory.ini

В комментариях мне в файл с настройками ткнули, все правильно сделали, но еще не время переходить к такой конфигурации.
Поэтому сначала:
cp /etc/ansible/hosts /home/user/second_inventory.ini.

Не забыв прочитать Ansible How to build your inventory, и вписав в конфигурацию секцию для закрытой части ssh ключа.

[ansible4]

192.168.1111.2222 ansible_user= ansible1

192.168.1111.3333 ansible_user= ansible1

192.168.1111.4444 ansible_user= ansible1

# compare with: files/second.sh

[all:vars]

ansible_python_interpreter=/usr/bin/python3

[defaults]

private_key_file = /home/ansible1/.ssh/ansible_key

Какой-то странный хардкод получается. Потому что при смене имени я должен прописать новое имя и в скрипте настройки, и в коде для Ansible. Если бы я вел документацию, то подумал бы, как сделать иначе, и прописал бы это где-то в ридми.

Не забываем, что закрытый ключ из Puttygen в Windows нужно экспортировать в другой формат. Как это сделать, знает даже AI,

To copy a private key generated by PuTTYgen for use with Ansible, which typically expects OpenSSH format keys, you need to convert it and then copy the resulting OpenSSH-formatted private key.

Steps to Convert and Copy the Private Key:

Open PuTTYgen: Launch the PuTTY Key Generator application.

Load the Private Key: Click the "Load" button and navigate to your existing private key file (usually with a .ppk extension) generated by PuTTYgen. Enter the passphrase if prompted.

Export as OpenSSH Key:

Go to the "Conversions" menu.

Select "Export OpenSSH key."

You will likely be prompted to save it without a passphrase; choose "Yes" if you want to use it without a password in Ansible (which is common for automated tasks).

Save the OpenSSH Key: Choose a location and filename for the exported OpenSSH-formatted private key (e.g., id_rsa or ansible_key). This file will not have a .ppk extension.

Copy the Key to your Ansible Control Machine: Transfer this newly exported OpenSSH private key file to your Ansible control machine. A common location for private keys on Linux-based systems is ~/.ssh/.

Set Permissions (on Ansible Control Machine): Ensure the private key file has appropriate permissions, typically read-only for the owner to prevent unauthorized access.

chmod 400 ~/.ssh/ansible_key

Не забываем настроить WinSCP,

Open WinSCP: and navigate to the main menu.

Select Options > Preferences.

In the Preferences dialog box, go to the Panels tab.

Locate the option "Show hidden files" and check the box next to it.

Click OK to apply the changes.

Работать так все равно не будет, если вы, конечно, не пошли от рута. Поэтому положим куда попало и переложим от рута локально
переложим файл pikabu_part4_export4ssh в /home/user и сделаем
mv pikabu_part4_export4ssh /home/ansible1/.ssh/ansible_key

Проверим что получилось.
ansible-playbook report23.yml --inventory /home/user/second_inventory.ini

и получим

Failed to parse inventory with 'ini' plugin: Failed to parse inventory: Expected key=value host variable assignment, got: Ansible1

Кто нашел ошибку сам – тот молодец.

кто не нашел, может сравнить

192.168.1111.2222 ansible_user= ansible1
192.168.1111.2222 ansible_user=ansible1

Отдельно надо сказать про ошибку с блоком [defaults]

[defaults]
private_key_file

потому что достаточно прочитать обсуждение ошибки private_key_file vs ansible_ssh_private_key_file #79186 , связанную с определение порядка переменных - Understanding variable precedence, но это уже другая история.

Поэтому, этот блок из конфигурации я пока удалю, и сделаю ручную проверку,

ansible-playbook report23.yml --inventory /home/user/1st_hosts.ini --user ansible1 --private-key /home/ansible1/.ssh/ansible_key

Которая не сработает, и поэтому переходить дальше, к команде

ansible-playbook report23.yml --inventory /home/user/second_inventory.ini --private-key /home/ansible1/.ssh/ansible_key

еще рано.

Потому что команда может и не сработает, с сообщением Server refused our key.
Потому что после копирования ключа, атрибуты на файл /.ssh/ansible_key никто не перепроверил.
Потому что все, что выше, было написано до появления раздела 4.4 Отлаживаем SSH, снова и опять

Потому что 192.168.1111.2222 настроен на порт 2424, а на порту 22 висит ssh до одного из контейнеров, и надо прописать не

192.168.1111.2222 ansible_user=ansible1
а
192.168.1111.2222 ansible_user=ansible1 ansible_port=2424

С чем еще пришлось столкнуться.

С недостатком памяти на VM. Я, в ходе опытов, снизил оперативную память VM с 5000 до 4750 мегабайт. Как оказалось, 4750 МАЛОВАТО.

В остальном поздравляю, вы великолепны, и можете сделать то, ради чего все затевалось, но про это будет уже в пятой части.

Литература

stackexchange Proper way to add a user account via bash script
stackexchange Why is this random password flagged saying it is too simplistic/systematic?
stackoverflow Change user password with one Bash command line
S/KEY
Ansible Connection methods and details
Ansible How to build your inventory
Ansible ansible.builtin.debug module – Print statements during execution
Статья: Отладка плэйбуков ansible

Перевод: Как убить вашу сеть с помощью Ansible. Оригинал: How to kill your network with Ansible
Перевод: Плейбуки Ansible — советы и примеры. Оригинал: Working with Ansible Playbooks — Tips & Tricks with Examples
slurm: Примеры Ansible-Playbook
пример Simple Ansible playbook to get the Linux host uptime

Тег Ansible не добавляется, ну что тут сделать.

@editors, как теги то добавлять??

Показать полностью 3
Отличная работа, все прочитано!