CentOS Stream 10: налаштування «наступного RHEL» для лабораторій і CI

Було корисно?

Немає нічого, що більше кричить «професійна інженерна культура», ніж хост у лабораторії, який завантажується в аварійному шеллі за п’ять хвилин до викатки релізу. Або CI-раннер, який починає втрачати збірки, бо закінчилися іноди, а не диск. Це не цікаві збої — це запобіжні збої, зазвичай спричинені неакуратною інсталяцією та ще менш акуратною ментальною моделлю.

CentOS Stream 10 добре підходить для лабораторій і CI, бо він достатньо близький до RHEL, щоб навчити вас тим самим експлуатаційним урокам, але при цьому зміни з’являються раніше — саме те, що треба при валідації пайплайнів, драйверів, поведінки ядра та власних припущень.

Що таке CentOS Stream 10 насправді (і чому він вам потрібен)

CentOS Stream — це не «безкоштовний RHEL». Це дистрибутив з безперервною доставкою, який розташовується між Fedora та RHEL у потоці розробки. Практично це означає: зміни сюди потрапляють першими, перед тим як їх зафіксують у наступному мінорному релізі RHEL. Для лабораторій і CI це корисно: ви можете зловити майбутні ABI-зміни, зрушення в інструментарії та пакувальні особливості ще до того, як вони дістануться ваших платних флітів — або флітів ваших клієнтів.

Тут є пастка: люди встановлюють Stream і ставляться до нього як до спокійної довготривалої корпоративної ОС. Не робіть так. Ставтеся до нього як до контрольованого, продакшн-подібного канарки. Якщо вам потрібне щось, що ви ігноруєте три роки, використайте інше і будьте чесні щодо цього.

Коли CentOS Stream 10 — правильний вибір

  • Ви збираєте RPM або модулі ядра та хочете раннє попередження про зміни buildroot.
  • Ваш CI потребує поведінки, схожої на RHEL: systemd, SELinux, firewalld, NetworkManager і той самий загальний інструментарій.
  • Ви хочете валідувати ролі Ansible і базові-настроювання під «наступний RHEL».
  • Ви запускаєте KVM/libvirt або хости для контейнерів і потребуєте відносно стабільної бази, але можете терпіти швидші оновлення, ніж у класичному ентерпрайзі.

Коли це неправильний вибір

  • Ваша лабораторія насправді — тіньове продакшн-середовище без контролю змін.
  • Ви не можете часто патчити або у вас немає тестових воріт.
  • Ваш «CI-раннер» — це «пет» VM, в який люди заходять по SSH і змінюють його вручну.

Факти та історія, що мають операційне значення

Ось конкретні контексти, які дійсно впливають на рішення, а не факти для світської бесіди на конференції:

  1. CentOS Stream був представлений як rolling preview RHEL, що змінило стару модель, коли CentOS Linux перебудовувався після релізів RHEL. Це змінює ваш профіль ризику: ви ближчі до передової черги змін.
  2. Раніше клон RHEL був стандартним вибором «безкоштовного корпоративного Linux», що виховало покоління команд ставитися до перебудов як до ідентичних. Stream ламає це припущення за замовчуванням.
  3. systemd вже давно є init-системою для сімейства RHEL, і саме в Stream ви побачите деякі зміни за замовчуванням сервісів першими (таймаути, залежності, опції жорсткого захисту).
  4. NetworkManager у більшості реальних розгортань уже не опціональний, бо інструменти, поведінка cloud-init і сучасне іменування NIC очікують його. Боротьба з ним — марна трата часу.
  5. SELinux у режимі «Enforcing» — це стандарт у адекватних середовищах, і екосистема RHEL витратила десятиліття на роботу над цим. Вимикати його досі популярно — переважно серед тих, хто не має чергувань.
  6. Anaconda історично потужна, але її легко неправильно налаштувати, особливо в частині кастомного розбивання диска і розташування завантажувача. «Я майже впевнений, що вибрав правильний диск» — це не стратегія зберігання.
  7. DNF замінив YUM як користувацький пакетний менеджер вже роки тому, і поведінка метаданих репо (і кешування) має значення, коли CI тягне сотні пакетів на день.
  8. cgroups v2 став стандартом у сучасних системах, схожих на RHEL, що змінює поведінку контейнерів і обмеження ресурсів порівняно зі старими флітами, які ще пам’ятають v1.
  9. Podman (rootless) — перший класний інструмент для контейнерів у сімействі RHEL, і він кращий за замовчуванням для багатьох CI-настроювань, ніж «просто запускати Docker як root і сподіватися».

Цілі дизайну для лабораторій і CI (виберіть сторону)

До того як запускати інсталятор ISO, вирішіть, за що ви оптимізуєте. Лабораторії і CI — це не одне й те саме, але вони мають спільну вимогу: передбачуваність відмов.

Мета 1: Відтворюваність важливіша за хитру інженерію

Для CI-раннерів я хочу образ, який можна відтворити з нуля і привести до потрібного стану автоматизацією менше ніж за годину. Якщо ви не можете швидко його перебудувати, ви будете зберігати його «на всякий випадок», і так утворюється хост, який став «особливим» після минулої людської зміни.

Мета 2: Зберігання повинно виходити з ледь помітною відмовою

CI-навантаження жорсткі до зберігання: багато дрібних файлів, високий обіг, кеші ростуть до межі і лог-файли, що не зупиняються. Ваша схема має робити помилку «диск заповнений» гучною й локалізованою, а не тихою і глобальною.

Мета 3: За замовчуванням безпека повинна залишатися увімкненою

Не вимикайте SELinux, бо одного разу збірка впала. Виправте маркування. Не чистіть файрвол, бо ваш тест-раннер не дістає до порту. Відкрийте порт. Якщо лабораторія у вас на плоскому мережевому сегменті, найменша загроза — не голлівудські хакери, а «тимчасова» служба іншої команди, що слухає на 0.0.0.0.

Сухе зіткнення з реальністю: хост у лабораторії без обмежень — це просто продакшн, тільки ніхто в цьому не зізнається. Так виникають «неочікувані» відмови, що насправді є «неочікуваною відповідальністю».

Шлях інсталяції: від ISO до першого завантаження без драми

Stream 10 можна встановлювати інтерактивно або через Kickstart. Для лабораторій і CI перевага за Kickstart, бо він перетворює племінні знання на файл. Інтерактивні інсталяції підходять для одноразових тестових VM, але саме вони перетворюють «стандартну збірку» на п’ять різних.

Виберіть відповідний профіль інсталяції

Для CI-раннерів і безголових серверів лабораторії: встановлюйте мінімальне середовище плюс потрібні пакети. GUI-збіри зручні, поки ви не змушені патчити 50 хостів і не усвідомлюєте, що тягнете десктоп-стек як кулю з ланцюгом.

UEFI проти BIOS: просто оберіть UEFI, якщо нема причин інакше

Сучасні сервери та VM мають бути UEFI. Це нудно, узгоджено, і інструменти дозріли. BIOS/legacy — для сумісності зі старими гіпервізорами або вбудованою технікою, яку ви не можете замінити.

Позиція щодо Kickstart

Kickstart для лабораторій/CI має робити такі речі:

  • Явно фіксувати диск інсталяції (не покладатися на «перший диск» у порядку).
  • Визначати розділи й LVM-томи з обґрунтованими розмірами та правилами росту.
  • Створити адміністративного користувача з SSH-ключами (і заблокувати парольний SSH).
  • Увімкнути SELinux в режимі enforcing і firewalld.
  • Встановити часовий пояс, NTP і стабільну схему імен хостів.
  • За потреби зареєструвати внутрішні репозиторії/дзеркала, якщо трафік CI великий.

Жарт #1: Ставтеся до «Далі, Далі, Готово» як до зарядженої зброї. Один клік може навчити ваш завантажувач нових, цікавинських дисків.

Схема зберігання: розділи, LVM і домени відмов

Зберігання — це те місце, де більшість інсталяцій для лабораторій/CI стають ледачими. Потім зберігання стає вузьким місцем, і всі звинувачують «мережу», бо приємніше жалітися на щось непомітне.

Як виглядає хороша схема

Для одномісного диску в VM або невеликого bare-metal вузла розумна за замовчуванням схема:

  • UEFI system partition (ESP): маленький, фіксований.
  • /boot: фіксований розмір, ext4.
  • LVM PV для всього решта.
  • Окремі LV для / (root), /var і, за потреби, /var/lib/containers або /var/lib/libvirt.

Чому розділяти /var? Бо CI записує в /var, ніби платять за байт. Логи, кеші пакетів, шари контейнерів, артефакти збірок і тимчасові файли люблять /var. Якщо /var заповниться і він на тому ж файловому сховищі, що й /, ви не отримаєте просто «диск заповнений» — отримаєте «система не може записувати стан». Це зовсім інша одиниця болю.

Ext4 проти XFS

XFS поширений у RHEL-подібних середовищах і добре поводиться з великими файлами та паралельними IO. Ext4 усе ще цілком гідний вибір для /boot і іноді для менших томів. Реальне правило: не вигадуйте. Використовуйте те, що очікує ваш інструментарій, і те, що ваша команда може відновити о 3 ранку.

LVM thin: будьте обережні

LVM thin provisioning може виглядати як вільний простір. Це не вільний простір. Це обіцянка вашому майбутньому «я», що ви будете моніторити використання пулу й реагувати до 100%. Thin-пули хороші у віртуалізованих лабораторіях, де зрозуміла overcommit. Вони катастрофічні, коли їх ніхто не спостерігає.

Swap: оберіть політику, а не інтуїцію

Для CI-раннерів із піками пам’яті трохи swap може запобігти вбиванню build job ядром. Для хостів, чутливих до затримки, занадто багато swap може приховати дефіцит пам’яті, поки продуктивність не стане «таємничо повільною». Якщо не впевнені: тримайте помірний swap і покладіться на моніторинг для налаштування.

Мережевий базис: передбачувані IP і DNS

CI-раннери, що падають через флап DNS — це не героїчна історія. Це провал базових речей.

Статична адресація проти DHCP

Для ефермерних CI-раннерів, які створюються і знищуються автоматично, DHCP підходить, якщо ваш DHCP і DNS надійні й інтегровані. Для довготривалих лабораторних хостів і bare-metal статичні IP зменшують сюрпризи. Якщо ви робите статичні IP, робіть це через профілі NetworkManager, а не правкою випадкових файлів вручну і надією, що згадаєте, що робили.

Імена хостів і search-домени

Оберіть схему найменування, яка переживе перевстановлення. Наприклад: роль + сайт + індекс. Не кодуйте секрети або внутрішні питання в іменах. Також тримайте search-домени мінімальними. Надто широкі search-домени викликають дивні затримки й непередбачуване резолювання, коли внутрішній DNS не в порядку.

Базові налаштування безпеки: SELinux, firewalld і SSH

Контролі безпеки — це не лише про безпеку. Вони про операційну передбачуваність. SELinux і firewalld змушують вас явно вказувати, що роблять ваші сервіси. Це полегшує розуміння систем.

SELinux: тримайте в режимі enforcing

Enforcing ловить неправильне маркування, погані налаштування і «на моєму лаптопі працювало» запуски контейнерів. Якщо щось ламається, ваша перша реакція має бути: прочитати AVC denials і виправити маркування або політику. Ваша остання реакція має бути: setenforce 0.

firewalld: визначайте зони і відкривайте тільки необхідне

CI-хости зазвичай потребують вхідного SSH і, можливо, вхідного прометей-скрепінгу. Вони не потребують світу, що дістає до випадкових ефемерних портів. Якщо ви запускаєте зеркало реєстру або кеш артефактів — це інше; відкривайте порти навмисно і документуйте це.

SSH: ключі, не паролі

Вимкніть парольну аутентифікацію, якщо можете. Якщо не можете, щонайменше обмежте її внутрішніми мережами і вимагайте сильні паролі. CI-раннери не мають бути місцем, де брутфорс паролів отримує плацдарм.

Цитата, яку варто тримати поряд з терміналом: Надія — не стратегія. — Gene Kranz

CI/runtime вибір: Podman, контейнери і віртуалізація

Для лабораторій і CI зазвичай обирають один із трьох підходів:

  • Збірки на хості: встановлювати toolchain на самому хості. Швидко, але з часом розпадається і стає «сніжинкою».
  • Збірки в контейнерах: ізолювати середовища збірки за допомогою Podman. Відтворювано, простіше очищення, хороший дефолт.
  • Збірки у VM: повна ОС на джоб через libvirt/KVM. Важчі, але ближчі до реальної поведінки розгортання.

Мій упереджений погляд: контейнерні збірки для більшості пайплайнів, VM-збірки для роботи з ядром/драйверами і «потрібно тестувати завантаження та системні сервіси», а збірки на хості — лише коли це справді необхідно (наприклад деякі апаратно-зв’язані тулчейни).

Практичні завдання з командами (і що вирішувати за результатами)

Це не іграшкові команди. Це те, що ви запускаєте в перший день і знову коли щось здається неправильним. Кожне завдання включає: команду, приклад виводу, що це означає і що далі вирішувати.

Завдання 1: Підтвердити, що ви встановили те, що думаєте

cr0x@server:~$ cat /etc/os-release
NAME="CentOS Stream"
VERSION="10"
ID="centos"
ID_LIKE="rhel fedora"
VERSION_ID="10"
PLATFORM_ID="platform:el10"
PRETTY_NAME="CentOS Stream 10"

Значення: Ви на Stream 10, і ідентифікатор платформи — EL10-подібний. Якщо тут інше, ваш pipeline образів бреше.

Рішення: Якщо це не те, що ви очікуєте, зупиніться і виправте джерело збірки. Не «продовжуйте так».

Завдання 2: Перевірити ядро і режим завантаження (UEFI проти legacy)

cr0x@server:~$ uname -r
6.12.0-0.el10.x86_64
cr0x@server:~$ test -d /sys/firmware/efi && echo UEFI || echo BIOS
UEFI

Значення: Версія ядра вказує, що ви дебагатимете. Режим завантаження важливий для grub, behavior secure boot і як розбито диски.

Рішення: Стандартизувати на UEFI для нових збірок, якщо немає обмежень платформи для BIOS.

Завдання 3: Ідентифікувати диски і впевнитися, що ви розбили потрібний

cr0x@server:~$ lsblk -o NAME,SIZE,TYPE,FSTYPE,MOUNTPOINTS,MODEL
NAME        SIZE TYPE FSTYPE MOUNTPOINTS MODEL
sda         200G disk                 QEMU HARDDISK
├─sda1      600M part vfat   /boot/efi
├─sda2        1G part ext4   /boot
└─sda3    198.4G part LVM2_member
  ├─cs-root   40G lvm  xfs    /
  ├─cs-var    80G lvm  xfs    /var
  └─cs-home   20G lvm  xfs    /home

Значення: Ви бачите карту розділів і що змонтовано. Якщо ви бачите, що ваш диск даних тримає /boot, у вас вже поганий день.

Рішення: Якщо використано неправильний диск, перевстановіть. Спроба «поправити пізніше» зазвичай обходиться дорожче за чисту перебудову.

Завдання 4: Перевірити ємність файлової системи та запас інодів

cr0x@server:~$ df -hT
Filesystem          Type  Size  Used Avail Use% Mounted on
/dev/mapper/cs-root xfs    40G  3.2G   37G   8% /
/dev/mapper/cs-var  xfs    80G   12G   68G  15% /var
/dev/sda2           ext4  1020M  238M  713M  26% /boot
cr0x@server:~$ df -i
Filesystem           Inodes IUsed   IFree IUse% Mounted on
/dev/mapper/cs-var  41943040 92321 41850719    1% /var

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

Рішення: Якщо /var малий або використання інодів швидко зростає, виділіть більше під /var зараз. Майбутній ви не зробить цього спокійно.

Завдання 5: Перевірити здоров’я LVM і вільні екстенти для росту

cr0x@server:~$ vgs
  VG #PV #LV #SN Attr   VSize   VFree
  cs   1   3   0 wz--n- 198.38g 58.38g
cr0x@server:~$ lvs -a -o lv_name,vg_name,lv_size,lv_attr,data_percent,metadata_percent
  LV   VG  LSize  Attr       Data%  Meta%
  root cs  40.00g -wi-ao----      
  var  cs  80.00g -wi-ao----      
  home cs  20.00g -wi-ao----      

Значення: У вас є вільне місце у VG, щоб розширити /var коли CI виросте зубами. Якщо ви бачите VFree = 0, ви розміряли його до краю.

Рішення: Залишайте запас у VG. «Ми використали весь диск» — це не досягнення; це майбутній інцидент.

Завдання 6: Підтвердити каденцію оновлень і стан репозиторіїв

cr0x@server:~$ dnf repolist
repo id                       repo name
baseos                        CentOS Stream 10 - BaseOS
appstream                     CentOS Stream 10 - AppStream
cr0x@server:~$ dnf check-update
Last metadata expiration check: 0:12:17 ago on Tue 06 Feb 2026 09:10:44 AM UTC.
kernel.x86_64                  6.12.2-0.el10           baseos

Значення: Репозиторії доступні, метадані актуальні і є оновлення. У Stream оновлення — це частина угоди.

Рішення: Якщо метадані сильно застарілі або repolist пустий, виправте DNS/proxy/дзеркала перш ніж довіряти хосту для CI.

Завдання 7: Перевірити синхронізацію часу (CI не любить зсуви)

cr0x@server:~$ timedatectl
               Local time: Tue 2026-02-06 09:23:18 UTC
           Universal time: Tue 2026-02-06 09:23:18 UTC
                 RTC time: Tue 2026-02-06 09:23:18
                Time zone: UTC (UTC, +0000)
System clock synchronized: yes
              NTP service: active
          RTC in local TZ: no
cr0x@server:~$ chronyc tracking
Reference ID    : 0A0B0C0D (ntp1.example)
Stratum         : 3
Last offset     : -0.000021 seconds
RMS offset      : 0.000112 seconds

Значення: Годинник синхронізований. Підписи токенів, TLS, часові мітки артефактів і розподілені збірки всі ламаються дурними способами при зсуві часу.

Рішення: Якщо NTP не активний, виправте це перш ніж дебагати «випадкові» TLS-помилки.

Завдання 8: Інспектувати мережеву конфігурацію через NetworkManager

cr0x@server:~$ nmcli -t -f NAME,DEVICE,TYPE,STATE con show --active
Wired connection 1:ens192:802-3-ethernet:activated
cr0x@server:~$ nmcli dev show ens192 | egrep 'IP4.ADDRESS|IP4.GATEWAY|IP4.DNS'
IP4.ADDRESS[1]:                         10.20.30.40/24
IP4.GATEWAY:                            10.20.30.1
IP4.DNS[1]:                             10.20.30.10

Значення: У вас активний профіль з’єднання і адекватні IP/DNS. Якщо CI не може резолвити репозиторії, тут починайте.

Рішення: Якщо DNS вказує кудись дивно (наприклад на домашній роутер), виправляйте. Не «обходьте» це через /etc/hosts.

Завдання 9: Перевірити режим SELinux і останні відмови

cr0x@server:~$ getenforce
Enforcing
cr0x@server:~$ sudo ausearch -m avc -ts recent | tail -n 5
type=AVC msg=audit(1738833941.112:842): avc:  denied  { name_connect } for  pid=2213 comm="podman" dest=53 scontext=system_u:system_r:container_t:s0 tcontext=system_u:object_r:dns_port_t:s0 tclass=tcp_socket permissive=0

Значення: SELinux у режимі enforcing і є AVC denial, пов’язаний з контейнером, який намагається дістатися DNS. Це не «SELinux просто дратує»; це сигнал про маркування/політику та правила контейнерної мережі.

Рішення: Дослідіть контекст і потрібну політику; не вимикайте SELinux глобально. Виправляйте корінь проблеми (політика контейнера, маркування порту DNS або конфігурацію рантайму контейнера).

Завдання 10: Перевірити стан firewalld і відкриті порти

cr0x@server:~$ sudo systemctl status firewalld --no-pager
● firewalld.service - firewalld - dynamic firewall daemon
     Loaded: loaded (/usr/lib/systemd/system/firewalld.service; enabled; preset: enabled)
     Active: active (running) since Tue 2026-02-06 09:02:11 UTC; 22min ago
cr0x@server:~$ sudo firewall-cmd --get-active-zones
public
  interfaces: ens192
cr0x@server:~$ sudo firewall-cmd --list-services
ssh

Значення: Фаєрвол увімкнений, інтерфейс у зоні public, відкрито тільки SSH. Хороша база.

Рішення: Якщо вам потрібен node_exporter, додайте порт/сервіс явно. Якщо бачите «services: dhcpv6-client samba cockpit whatever», почистіть це.

Завдання 11: Перевірити тиск ресурсів системи (CPU, пам’ять, IO) швидко

cr0x@server:~$ uptime
 09:27:51 up  1:12,  1 user,  load average: 0.26, 0.18, 0.09
cr0x@server:~$ free -h
               total        used        free      shared  buff/cache   available
Mem:           15Gi       1.8Gi       11Gi       170Mi       2.4Gi        13Gi
Swap:          4.0Gi         0B       4.0Gi

Значення: Навантаження низьке, пам’ять здорова, swap не використовується. Якщо CI jobs повільні, зараз це, ймовірно, не через голий CPU.

Рішення: Якщо навантаження високе і доступної пам’яті мало, вирішіть: додати RAM, зменшити конкурентність або ізолювати «галасливі» задачі.

Завдання 12: Помітити вузькі місця IO і стрибки затримки

cr0x@server:~$ iostat -xz 1 3
Linux 6.12.0-0.el10.x86_64 (runner01)  02/06/2026  _x86_64_ (4 CPU)

avg-cpu:  %user   %nice %system %iowait  %steal   %idle
          12.10    0.00    3.20    8.60    0.00   76.10

Device            r/s     rkB/s   rrqm/s  %rrqm r_await rareq-sz     w/s     wkB/s   wrqm/s  %wrqm w_await wareq-sz aqu-sz  %util
sda              8.00    320.0     0.00   0.00    6.20    40.00   45.00   2048.0     2.00   4.26   18.40    45.51   0.92  68.00

Значення: iowait немаленький, write await доволі високий, і використання диска високе. Класичний профіль CI-раннера: багато записів, метадантичний обіг і кеші.

Рішення: Розгляньте швидше сховище, відокремлення дисків для збірок/робочих просторів або переміщення кешів у tmpfs/ramdisk вибірково (з лімітами). Також зменшіть кількість одночасних задач на вузол.

Завдання 13: Підтвердити, що journald/збереження логів не з’їсть /var

cr0x@server:~$ sudo journalctl --disk-usage
Archived and active journals take up 1.2G in the file system.
cr0x@server:~$ sudo grep -E 'SystemMaxUse|RuntimeMaxUse' /etc/systemd/journald.conf
#SystemMaxUse=
#RuntimeMaxUse=

Значення: Журнали вже займають місце, і немає явного ліміту. На галасливих CI-ноди це росте, доки не вдарить в ліміт файлової системи.

Рішення: Встановіть SystemMaxUse (і, можливо, SystemMaxFileSize) у розумний ліміт відповідно до розміру /var.

Завдання 14: Перевірити розташування сховища контейнерів і його ріст

cr0x@server:~$ sudo podman info --format '{{.Store.GraphRoot}}'
/var/lib/containers/storage
cr0x@server:~$ sudo du -sh /var/lib/containers/storage
6.4G	/var/lib/containers/storage

Значення: Шари контейнерів живуть під /var. Ось чому розмір /var має значення.

Рішення: Якщо ви запускаєте важкі контейнерні збірки, розгляньте розташування сховища контейнерів на власному LV (або виділеному диску), щоб уникнути голодування системного стану.

Завдання 15: Перевірити cgroups v2 і сумісність контейнерів

cr0x@server:~$ stat -fc %T /sys/fs/cgroup/
cgroup2fs

Значення: Ви на cgroups v2. Деякі старі інструменти контейнерів і агенти моніторингу ще припускають семантику v1.

Рішення: Переконайтеся, що ваше CI-пЗ підтримує cgroups v2. Якщо ні — оновіть інструменти, ніж понижувати поведінку ОС, хіба що немає вибору.

Завдання 16: Перевірити готовність до віртуалізації (якщо ви запускаєте KVM/libvirt)

cr0x@server:~$ lscpu | egrep 'Virtualization|Vendor ID|Model name'
Vendor ID:                       GenuineIntel
Model name:                      Intel(R) Xeon(R) CPU
Virtualization:                  VT-x
cr0x@server:~$ lsmod | egrep 'kvm|kvm_intel'
kvm_intel             503808  0
kvm                  1490944  1 kvm_intel

Значення: CPU підтримує віртуалізацію і модулі KVM завантажені.

Рішення: Якщо віртуалізація недоступна, не витрачайте час на дебаг libvirt. Виправте налаштування BIOS або оберіть інший хост/профіль гіпервізора.

Плейбук для швидкої діагностики

Це плейбук, який я хочу бачити на стіні поряд із CI-кластером. Коли збірки повільні або інсталяції нестабільні, не «шукати» — йти найкоротшим шляхом до вузького місця.

По-перше: доведіть, що це не DNS/доступ до репо

  • Перевірте резолюцію DNS і доступність репо/дзеркал. Помилки CI часто виглядають як «install package failed», але корінь — ім’я або проксі.
  • Підтвердіть синхронізацію часу. TLS-помилки і проблеми з метаданими репо можуть бути через зсув часу.
cr0x@server:~$ getent hosts mirror.internal
10.20.30.50   mirror.internal
cr0x@server:~$ chronyc tracking | head
Reference ID    : 0A0B0C0D (ntp1.example)

Рішення: Якщо DNS повільний або нестабільний, виправляйте це перш ніж торкатись чогось іншого. Ви не можете оптимізувати систему, яка не знаходить свої залежності.

По-друге: перевірте тиск на зберігання і затримки IO

  • Диск повний? Іноди вичерпані? Thin pool заповнений? Це проявляється як «випадкові помилки».
  • IO latency (await) високий? Ось чому збірки повільні.
cr0x@server:~$ df -hT | sed -n '1,6p'
Filesystem          Type  Size  Used Avail Use% Mounted on
/dev/mapper/cs-root xfs    40G  3.2G   37G   8% /
/dev/mapper/cs-var  xfs    80G   78G  2.0G  98% /var
cr0x@server:~$ iostat -xz 1 2 | tail -n 5
sda              9.00    360.0     0.00   0.00    8.10    40.00   60.00   2600.0     1.00   1.64   25.90    43.33   1.40  85.00

Рішення: Якщо /var зайнятий на 98%, зупиніться. Очистіть кеші/логи або розширте LV. Якщо disk await високий, зменшіть конкурентність або апгрейдьте сховище.

По-третє: перевірте CPU, пам’ять і контенцію планувальника

  • Високе навантаження з низьким IO wait? Ймовірна насиченість CPU.
  • Мало доступної пам’яті зі swap-активністю? Тиск пам’яті або неконтрольовані задачі.
  • Високий steal time? Контенція у гіпервізора; ваш VM хост перескуплений.
cr0x@server:~$ vmstat 1 5
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
 1  0      0 1123456  81234 2234560  0    0     5    80  150  300 12  3 77  8  0
 3  1      0  123456  40000  900000  0    0     0  2000  500 1200 40 10 10 40  0

Рішення: Якщо st (steal) ненульовий і постійний, справжній вузький місце upstream. Ескалюйте до команди віртуалізації або перемістіть раннери.

Типові помилки: симптом → корінна причина → виправлення

1) Симптом: CI jobs раптово падають із «No space left on device», але df показує вільне місце

Корінна причина: Вичерпані іноди (занадто багато дрібних файлів) або заповнений інший том (часто /var або /tmp).

Виправлення: Перевірте df -i і використання за точками монтування. Збільшіть інод-контингент шляхом зміни/пересоздання файлової системи (довгостроково) і зменшіть обіг файлів (прибирання, політика збереження артефактів). Розділіть /var на ранній стадії.

2) Симптом: Зборки повільні лише на деяких раннерах

Корінна причина: Різниця в затримках зберігання (різні рівні дисків) або steal time на перескуплених гіпервізорах.

Виправлення: Порівняйте iostat -xz і vmstat між раннерами. Стандартизуйте бекенд дисків. Не змішуйте «швидкі» і «повільні» ноди в одному пулі, якщо ваш шедулер не знає топологію.

3) Симптом: Після оновлення сервіс не стартує; логи говорять про permission denied

Корінна причина: SELinux denial після зміни шляху, нового порту або жорсткішої одиниці сервісу.

Виправлення: Використайте ausearch -m avc, щоб знайти відмови, потім виправте маркування з restorecon або налаштуйте політику. Не вимикайте SELinux глобально.

4) Симптом: Хост завантажується в dracut emergency shell після перезавантаження

Корінна причина: Неправильний UUID у fstab, відсутні драйвери в initramfs або зміни порядку дисків у шаблоні VM.

Виправлення: Завантажтеся в rescue, перевірте blkid і /etc/fstab, при потребі перебудуйте initramfs. Віддавайте перевагу монтуванню за UUID і стабільним іменам пристроїв.

5) Симптом: DNF повільний, «metadata download» зависає

Корінна причина: Проблеми DNS, проксі MTU або проблеми вибору дзеркал.

Виправлення: Валідируйте DNS (getent hosts), перевірте MTU і віддавайте перевагу внутрішнім дзеркалам для CI-важких середовищ.

6) Симптом: Контейнерні збірки падають після оновлення ОС, а збірки на хості працюють

Корінна причина: Питання cgroups v2, обмеження rootless мережі або зміни SELinux-політик, що впливають на зберігання контейнерів.

Виправлення: Підтвердіть cgroups (stat -fc %T /sys/fs/cgroup), перевірте podman info, перегляньте AVC denials і оновіть контейнерний інструментарій/образи.

7) Симптом: SSH працює з деяких підмереж, але не з інших

Корінна причина: Призначення зони firewalld або невідповідність згори мережевих ACL.

Виправлення: Перевірте активні зони і інтерфейси, потім встановіть явні правила. Не вимикайте firewalld через складність мережі.

Три корпоративні міні-історії (про те, чим не хваляться)

Міні-історія 1: Інцидент через хибне припущення

Компанія мала акуратний CI-кластер: дюжина VM, кілька кешів збірок і щотижневе вікно патчів, яке всі ігнорували, поки щось не зламалося. Вони вирішили перейти з клона RHEL на CentOS Stream для «ранньої сумісності». Звучить відповідально.

Хибне припущення було непомітним: вони думали, що Stream поводитиметься як їхній старий rebuild в одному конкретному відношенні — стабільність репозиторіїв. Їхній pipeline почав тягнути оновлення вдень, бо хтось залишив запланований dnf -y update таймер на раннерах. Одного дня апдейт тулчейна зайшов, версія компілятора змінилася на мінор, і частина збірок почала давати трохи інші артефакти. Спочатку нічого явно не падало. Але перевірка чексуми показала різницю, і релізний процес зупинився.

Команди сперечалися про «недетерміновані збірки» і «можливо кеш корумпований». Жодне з них. Це були раннери, що оновилися посеред потоку. Болісна частина була не в виправленні; болісна частина — усвідомлення, що у них немає політики, коли і як оновлюється CI-інфраструктура.

Вони відновилися, заморозивши оновлення в робочий час, будуючи золоті образи щотижня і прокочуючи їх через staging CI-пул перед основним. Stream не був лиходієм. Лиходій — віра, що оновлення робляться за нагадуванням.

Міні-історія 2: Оптимізація, яка зіграла злий жарт

Ще одна організація мала хитрий план зберігання: вони використовували LVM thin provisioning для робочих просторів CI, бо це дозволяло «виділяти» величезні томи без купівлі додаткового диска. На папері елегантно. В реальності thin pool ділився занадто багатьма ентузіастичними проєктами.

Вони також «оптимізували», піднімаючи конкурентність задач. Збірки стали швидшими — поки не перестали бути такими. Одного ранку кілька раннерів почали падати з помилками файлової системи. Thin pool досяг 100% використання даних. Thin provisioning не падає ввічливо; воно падає як пастка. Записи зависають, файлові системи панікують, і всі раптом дізнаються, що таке «metadata percent».

Термінове виправлення було непривабливим: зупинити все, видалити кеші і розширити базове сховище. Довгострокове виправлення було нудним: налаштувати моніторинг використання thin pool, ввести квоти по проєкту і перестати oversubscribe сховище без guardrails.

Вони залишили thin provisioning, але тільки там, де було сповіщення і чітка відповідальність. Оптимізація не була неправильною. Вона була передчасною, немоніторною і продавалась як «безкоштовна ємність», що є найдорожчою брехнею у зберіганні.

Міні-історія 3: Нудна, але правильна практика, що врятувала ситуацію

Третя команда отримала репутацію «повільних», бо наполягала на Kickstart-збірках і строгому pipeline базових образів. Розробники хотіли свободу підправляти раннери вручну. SRE казали «ні» і викликали невдоволення на зборах.

Потім оновлення ядра в лабораторії виявило регресію, що впливала на певний NIC-драйвер під великим навантаженням. Кілька раннерів почали втрачати мережеві з’єднання під час завантаження артефактів. Схоже на випадкову непостійність — саме те, що витрачає тижні.

Оскільки команда мала pipeline золотих образів, вони могли відкотитися до попереднього відомо-гарного ядра по всьому фліту контрольовано. І головне — вони могли відтворити проблему, піднімаючи тестові раннери з обох образів і порівнювати поведінку під однаковим навантаженням. Ніякої археології. Ніякого «хто що змінив». Просто контрольований експеримент.

Postmortem був майже розчаровано спокійним. Їхня нудна практика — ім’ідж-орієнтовані образи, контрольовані оновлення та staging-пул — перетворила потенційний багатокомандний скандал на невеликий інцидент. Вони відправили реліз вчасно. Ніхто не писав драматичних Slack-повідомлень. Це перемога.

Жарт #2: Найкращий CI-раннер схожий на хорошу сантехніку — ніхто його не помічає, доки хтось не вирішить «оптимізувати».

Чеклісти / покроковий план

Покроковий план інсталяції (інтерактивно або через Kickstart)

  1. Визначте роль: CI-раннер, гіпервізор лабораторії або універсальний тест-хост. Це визначає зберігання і підбір пакетів.
  2. Обрати завантаження UEFI (якщо немає обмежень) і підтвердити налаштування прошивки VM перед інсталяцією.
  3. Виберіть мінімальну інсталяцію плюс потрібні пакети; уникайте GUI, якщо нема явної потреби.
  4. Схема зберігання:
    • Створіть ESP і фіксовані розділи /boot.
    • Створіть LVM PV і VG із запасом.
    • Створіть окремий LV для /var, розмір під логи + контейнери + кеші.
  5. Мережа: налаштуйте через NetworkManager, переконайтеся, що DNS вказує на надійний резолвер.
  6. Час: встановіть часовий пояс UTC для серверних флітів; увімкніть NTP.
  7. Користувачі: створіть адміністратора; за можливості обмежте SSH ключами.
  8. Безпека: тримайте SELinux в enforcing; тримайте firewalld увімкненим.
  9. Політика оновлень: визначте каденцію патчів і чи самостійно оновлюються раннери. Моя порада: без авто-оновлень на раннерах без воріт.
  10. Snapshot/золотий образ: зніміть базовий образ лише після проходження валідаційних команд.

Пост-інсталяційний чекліст (запустіть перед додаванням у CI-пул)

  • Ідентичність ОС правильна: /etc/os-release
  • Режим завантаження правильний: перевірка UEFI
  • Розбивка диска правильна: lsblk, df -hT, df -i
  • Є запас у LVM: vgs
  • Репозиторії здорові: dnf repolist, dnf check-update
  • Синхронізація часу: timedatectl, chronyc tracking
  • Мережа правильна: вивід nmcli збігається з очікуваними IP/DNS
  • SELinux в enforcing: getenforce; немає несподіваного AVC-спаму
  • firewalld увімкнений і мінімальний: firewall-cmd
  • Базова перевірка продуктивності: iostat, vmstat під пробною збіркою

Операційний чекліст (щотижня)

  • Застосовуйте оновлення у контрольоване вікно; прокочуйте через staging-пул перш ніж у основний.
  • Перевіряйте тенденції росту /var; обмежуйте journald; чистіть шари контейнерів.
  • Перевіряйте NTP; слідкуйте за дрейфом часу на VM.
  • Переглядайте AVC denials; вирішуйте повторювані належним чином.
  • Переконайтеся, що конкурентність CI відповідає ємності диска, а не бажанням.

FAQ

1) Чи стабільний CentOS Stream 10 для CI?

Так, якщо ваш CI сконструйований так, щоб витримувати зміни: staged rollouts, відтворювані образи і політика патчів. Якщо ваші раннери обслуговуються вручну як «пет», Stream швидко це виявить.

2) Чи варто використовувати Stream 10 у продакшні?

Іноді так, але не робіть це за замовчуванням. Для продакшну питання не «чи може це працювати», а «чи є у вас дисципліна для управління швидшим рухом оновлень?» Багато організацій цього не мають.

3) Мінімальна інсталяція чи повна серверна?

Мінімальна. Додавайте тільки необхідне. Кожен зайвий пакет — це площа поверхні для оновлень і потенційних конфліктів у CI.

4) Чи справді потрібен окремий /var?

Якщо ви запускаєте CI-навантаження — так. /var — місце зустрічі стану системи і високого обігу CI-сміття. Відокремлення — недорога страховка.

5) XFS чи ext4 для CI-раннерів?

XFS — надійний дефолт для / і /var у RHEL-подібних системах. Тримайте ext4 для /boot. Не вводьте екзотичні файлові системи, якщо ваша команда не має плану відновлення і досвіду.

6) Чи варто відключати SELinux, щоб полегшити збірки контейнерів?

Ні. Використовуйте журнали AVC, щоб виправити маркування/політику. Вимкнення SELinux обмінює вирішувану конфігураційну проблему на постійний ризик і непослідовну поведінку між середовищами.

7) Як зупинити дрейф раннерів з часом?

Золоті образи + управління конфігурацією. Перебудовуйте раннери регулярно. Якщо раннер «особливий», він також недовірливий.

8) Мої DNF інсталяції повільні в CI. Як найкраще виправити?

Використовуйте внутрішнє дзеркало або кеш-проксі і виправляйте DNS. Потім настройте кешування DNF. CI підсилює неефективності пакетного менеджера у реальні гроші та час.

9) Контейнери чи VM для CI джобів?

Контейнери — для більшості збірок і тестів. VM — коли потрібно тестувати поведінку при завантаженні, взаємодію з ядром або системні сервіси в реалістичному середовищі.

10) Яке найпоширеніше вузьке місце на CI-хостах на базі Stream?

Зберігання. Зокрема: заповнення /var, розростання шарів контейнерів і затримки IO під навантаженням. CPU зазвичай на другому місці.

Висновок: наступні кроки, що справді зменшують pager noise

CentOS Stream 10 — це правильний різновид дискомфорту для лабораторій і CI: він штовхає вас до дисциплінованих інсталяцій, чіткої політики оновлень і інфраструктури, що переносить зміни. Якщо ви встановите його як хобі-ОС, він поводитиметься відповідно. Якщо встановите його як продакшн, він стане гострим раннім попередженням про «наступний RHEL».

Практичні наступні кроки:

  • Напишіть (або виправте) ваш Kickstart так, щоб вибір диска, розмір /var і налаштування безпеки були явними.
  • Підніміть staging CI-пул, що патчиться першим; просувайте в основний пул тільки після дня чистих прогонів.
  • Обмежте journald, чистіть зберігання контейнерів і моніторьте використання /var та інодів.
  • Впровадьте плейбук швидкої діагностики і зробіть його стандартною відповіддю на «CI повільний».
  • Визначте політику оновлень письмово. Потім забезпечте її автоматизацією, а не добрими намірами.
← Попередня
Міфи про прив’язку CPU в Proxmox — налаштування, яке погіршує затримку
Наступна →
Обліковий запис Microsoft проти локального облікового запису: компроміси безпеки

Залишити коментар