Зараз 02:17. Пейджер кричить, бюджети помилок тануть, а дашборд виглядає, ніби його лопатою підкопали. Хтось питає: «Хто знає, як це працює?» У кімнаті настає тиша. Потім називають ім’я. Одне ім’я.
Якщо для роботи вашої продуктивної системи потрібна конкретна людина, яка має бути працевлаштована, здорова, досяжна й не спить — у вас немає надійності. У вас хиткий перемир’я з фізикою і HR.
Що насправді означає «bus factor» в продакшені
Bus factor — це кількість людей, які можуть зникнути (аварія, хвороба, звільнення, підвищення, придбання, життя), перш ніж ваш проєкт зупиниться або сервіс не зможе відновитися. Люди ставляться до цього як до похмурої кумедної фрази; операційні команди живуть із цим як із рядком бюджету.
На практиці bus factor рідко означає «одна людина знає все». Зазвичай це «одна людина знає гострі краї». Неписаний прапор. Чому саме ми тримаємо ту версію ядра. Справжнє значення кастомної мітки Prometheus, яка контролює алерти. Таємне рукопотискання для імпорту знімків у запасний кластер. Правило маршрутизації пейджера, яке було «тимчасовим» вісімнадцять місяців тому.
Bus factor — це не лише знання. Це повноваження (тільки одна людина може затвердити зміни), доступ (тільки одна людина має потрібні токени) і довіра (усі інші бояться торкатися). Якщо ви виправите документацію, але залишите доступ заблокованим на одному ноутбуку — ви все одно ведете переговори про викуп, просто з приємнішим Markdown.
Одна цитата, яку варто пам’ятати, коли вас тягне «просто спитайте Олекса», замість того щоб записати це:
Приписують Джину Кіму (парафраз): Мета — швидкий потік і стабільність; героїчні зусилля — ознака того, що система й процеси не витримують навантаження.
Дві важливі ясності:
- Високий bus factor не означає низьку кваліфікацію. Це може означати сильну спеціалізацію. Проблема виникає, коли спеціалізація перетворюється на неперевірену єдину точку відмови.
- Bus factor — це системна проблема. «Інженер bus factor» часто робить раціональне в ірраціональній організації: відправляє релізи, патчує, гасить пожежі і вбирає контекст, бо іншим нікому не дозволяють час на навчання.
Жарт №1: Інженер bus factor не є «незамінним». Його можна замінити; система просто бере консультаційний збір у вигляді із-аутів.
Чому це відбувається (і чому розумні команди все одно потрапляють у пастку)
1) Стимули винагороджують швидкість, а не передачу знань
Більшість організацій просуває ту людину, яка розблокує запуск, а не ту, хто забезпечує можливість запуску без себе. Якщо ваша система оцінювання винагороджує «вплив», найвидиміший вплив — стати вузьким місцем. Ви раптом опиняєтесь на кожному мітингу, у кожній ревью, у кожному інциденті. Ваш календар стає архітектурою.
2) «Тимчасове виключення» стає постійною інфраструктурою
Аварійні зміни бувають корисні. Постійні аварійні зміни — запах проблеми. Інженер bus factor часто єдиний, хто пам’ятає, чому ми обійшли нормальний пайплайн «тільки цього разу». Цей обхід потім стає пайплайном.
3) Складність накопичується там, де зміни робляться швидко
Там, де зміни можна зробити швидко, вони й робляться. Якщо одна людина має привілеї й контекст, система еволюціонує навколо її робочого процесу. З часом робочий процес стає залежністю. Так з’являється продакшн-автоматизація, що вимагає, щоб людина SSH-нула і виконала однорядкову команду з історії shell.
4) Документація провалюється, коли її трактують як прозу
Документи, які кажуть «перезапустіть сервіс», — це не документація; це настрій. Справжня операційна документація виконувана, перевірна і прив’язана до реальності: точні команди, очікуваний вивід і що робити далі.
5) Страх заразний
Якщо система вже вкусила людей раніше — втрата даних, kernel panic, «загадкова корупція» — команда вчиться не торкатися її. З часом єдина людина, яка її обслуговує, стає єдиною, хто може це робити. Так крихкі стеки сховищ роками «належать» одному інженеру.
Факти й історичний контекст, що пояснюють цю модель
Bus factor здається сучасним, бо ми говоримо про нього в термінах GitHub, але модель стара: спеціалізація плюс швидкість плюс крихкі інтерфейси. Трохи контексту, що допомагає зрозуміти, чому це повторюється:
- Термін «bus factor» — родич старішого «truck factor», який використовували в командах розробки для опису того ж ризику; метафора змінилася, режим відмови — ні.
- Дизайни NASA «single string» vs «dual string» (одна проти резервних керуючих ліній) популяризували ідею, що резервування — не опція в системах з високими ставками; люди — частина системи.
- У ранні епохи телефонії та мейнфреймів «знання операторів» були буквальними. Runbook-и існували, бо системи вимагали ручних кроків; коли знання були заховані в людях, час роботи страждав.
- Впровадження on-call ротацій у веб-операціях змусило команди формалізувати племінне знання, бо інциденти не підлаштовуються під відпустку єдиного експерта.
- Рух «DevOps» не лише пропонував співпрацю dev+ops; він імпліцитно виступав проти чорних скриньок власності та героїчного обмеження доступу як моделі масштабування.
- Культура постмортемів стала популярною, бо організаціям потрібен інструмент перетворювати інциденти на спільне навчання замість приватного знання.
- Системи управління конфігурацією (CFEngine, Puppet, Chef, Ansible) частково виникли як відповідь на «snowflake servers», які розумів лише один адміністратор; кодування стану — антипатерн bus-factor.
- Сучасні структури командування при інцидентах (стиль ICS) вийшли за межі екстрених ситуацій, бо розділення «хто робить» і «хто знає» робить відповідь масштабованою і придатною для навчання.
- Системи управління секретами існують, бо «пароль у голові Стіва» — це не безпека; це відмова в обслуговуванні, що чекає, щоб статися.
Діагностика ризику bus-factor: сигнали, які можна виміряти
Bus factor емоційний — команди сперечаються про власність і довіру — але його також можна виміряти. Якщо хочете знизити його, перестаньте сперечатися і почніть спостерігати.
Сигнал 1: Хто зливає зміни?
Якщо одна людина затверджує або зливає більшість змін до системи, ви вже централізували знання й повноваження. Це може бути виправдано з міркувань безпеки, але тоді потрібен другий затверджувач з еквівалентною компетенцією й доступом.
Сигнал 2: Хто пейджиться і хто фіксує?
Подивіться хронологію інцидентів. Якщо одна й та сама людина постійно з’являється як «приєднався і виправив» — вона не просто обізнана; її єдина, кому довіряють діяти. Це не комплімент. Це режим відмови, який ви нормалізуєте.
Сигнал 3: Документація «в Slack»
Якщо runbook — це «пошукайте канал і знайдіть тред із минулого року», у вас немає runbook-а. У вас археологія.
Сигнал 4: Асиметрія доступів
Якщо IAM-модель дозволяє лише одній людині аварійно зайти в продакшн, у вас є єдина точка відмови. Якщо ви не можете надати більше доступів, потрібен суворо контрольований, аудитований і задокументований процес break-glass, який будь-який on-call може виконати.
Сигнал 5: Відновлення — ритуал
Коли відновлення залежить від «зробіть ці сім кроків у правильному порядку й не питайте навіщо», ви в пастці знань. Системи, які можна відновити лише ритуалом, не відновляться під стресом.
Сигнал 6: Система стабільна… доки ні
Ризик bus-factor ховається в стабільних системах, бо вони не вимагають уваги. Потім щось змінюється — оновлення ядра, прошивки, поведінка API хмарного провайдера, ротація сертифікатів — і ви дізнаєтесь, що система була стабільною лише тому, що одна людина мала набір компенсаційних поведінок.
Швидкий плейбук діагностики: знайти вузьке місце швидко
Це чекліст «вбігти в палаючу кімнату». Мова про те, щоб за хвилини визначити найімовірніше вузьке місце, а не писати дисертацію під час пожежі в базі.
По-перше: ідентифікуйте домен відмови і припиніть його погіршення
- Підтвердьте масштаб: один хост, одна AZ, один регіон, одна залежність, один сегмент клієнтів.
- Заморозьте ризикові релізи: поставте на паузу пайплайни, зупиніть авто-масштабування, припиніть пакетні завдання, якщо вони витісняють продуктивність.
- Перевірте явне насичення: CPU, пам’ять, диск IO, мережа, дескриптори файлів.
По-друге: перевірте «нудну» інфраструктуру
- DNS та сертифікати: прострочені сертифікати й DNS-збої дивно добре імітують проблеми додатків.
- Час: дрейф NTP може зламати автентифікацію, логи, розподілену координацію й ваше нервове здоров’я.
- Здоров’я сховища: IO-стопи маскуються під «повільний додаток», поки хтось не перевірить диски.
По-третє: знайдіть поточний лімітатор
- Облік бюджету затримки: де витрачається час — в додатку, базі, мережі чи на очікуванні IO?
- Шукайте зростання черг: пули потоків, пули підключень, брокери повідомлень, черга виконання ядра, IO-черги.
- Підтвердіть шлях відкату/фейловеру: якщо можна безпечно зменшити навантаження або переключитися, зробіть це раніше, ніж будете сперечатися годину.
Twist bus-factor: якщо кроки «швидкої діагностики» вимагають від інтерпретації конкретної людини, ваша спостережуваність декоративна. Виправте це до наступного інциденту.
Три корпоративні міні-історії з практики
Міні-історія №1: Інцидент через хибне припущення
Середня SaaS-компанія тримала самописний storage gateway перед об’єктним сховищем. Gateway кешував метадані локально для швидкості. Працювало досить добре, тож ніхто не ставив під сумнів; оригінальний інженер перейшов в іншу команду, але фактично все ще «володів» ним.
Під час планової технічної паузи інший інженер повернув сертифікати хостів і по черзі перезавантажив вузли gateway. На папері: безпечно. Насправді: кеш метаданих був не просто кешем. Він містив авторитетний стан для multipart-завантажень у процесі, а задача «rehydration», яка відновлювала стан з об’єктного сховища, була відключена місяці тому після того, як викликала піки навантаження.
Хибне припущення було тонким: «Якщо це кеш, його можна відбудувати». Це правда доти, доки хтось тихо не додасть «тимчасовий, але критичний» стан і не оновить ментальну модель.
Після перезавантаження клієнти почали повторювати завантаження. Повторні спроби підсилювали трафік, трафік підсилював затримку, і gateway почав таймаутити перевірки здоров’я. Авто-відновлення замінило вузли, що стерло ще більше «кешу», що стерло ще більше стану. Система не просто впала; вона перетворила себе на кратер.
Виправлення не було героїчним. Вони знову ввімкнули задачу rehydration з лімітуванням швидкості, написали runbook, який явно вказував, які дані де живуть, і додали canary-перезавантаження у CI для AMI шлюзу. Найголовніше — вони оформили «семантику кешу» як договір і призначили двох інженерів у ротацію для змін у зберіганні.
Міні-історія №2: Оптимізація, яка відгукнулася боком
Платформа торгової аналітики мала кластер Postgres на швидких NVMe. Один інженер — блискучий, недоспаний і довірений — вирішив «допомогти ядру», налаштувавши параметри dirty page writeback і IO scheduler. Він зменшив затримки в бенчмарках і оголосив перемогу.
Зміна жила в кастомному sysctl-файлі на хостах бази, не в CM, бо це було «швидке налаштування». Місяці потому компанія оновила образ ОС. Нове ядро обробляло writeback інакше. Старі значення sysctl стали патологічними під реальним навантаженням: спалахи записів накопичувалися, а потім скидалися масивними хвилями, що блокували читання. Запити не гальмували поступово; вони врізалися в стіну.
On-call бачив простій CPU і припустив, що база «в порядку». Інженери додатку ганялись за пулами підключень. Тим часом шар зберігання зазнавав синхронного страждання. Єдина людина, яка розуміла sysctl-правку, була в трансатлантичному рейсі.
Коли експерт приземлився, він відмінив sysctl і система одразу відновилась. Постмортем був неприємним: оптимізація була реальна, але вона була прив’язана до поведінки ядра, недокументована, нетестована і фактично не мала власника в команді.
Тривале виправлення полягало в тому, щоб ставитися до налаштувань ядра як до коду: версіонована конфігурація, явні власники, canary-хост, тести регресій продуктивності і суворе правило, що «швидкі» налаштування повинні мати план відкату й чітке пояснення.
Міні-історія №3: Нудна, але правильна практика, що врятувала день
Одна медкомпанія запускала ZFS-backed NFS для внутрішньої аналітики. Нічого гламурного. Інженер зі збереження наполягав на щотижневому scrub, щомісячних тренуваннях відновлення та крихітному runbook-у з точними командами й скриншотами очікуваного виводу. Всі дражнили його за старомодність.
Одного четверга помилка прошивки в партії SSD почала повертати періодичні помилки читання. ZFS виявив невідповідності контрольних сум і почав ремонтувати з резервів. Алерти спрацювали, але сервіс лишався здебільшого здоровим. On-call команда не панікувала, бо runbook пояснював, що робить scrub, що означає «errors: No known data errors» і коли ескалювати.
Вони замінили несправні диски в контрольованому вікні, перевірили прогрес resilver і провели відновлення зі свіжих знімків. Ніякої драми, ніякого «ми думаємо, що все ок», ніякого чекання спеціаліста, щоб він прокинувся.
Суть не в магії ZFS. Суть у операційному м’язовому пам’яті: команда практикувала нудні кроки, і ці кроки були записані так, щоб неексперт міг діяти у правильному напрямку.
Жарт №2: У кожної команди є «та система, до якої ніхто не торкається». Це як музейний експонат, тільки іноді він вас пейджить.
Практичні завдання: команди, виводи та рішення (12+)
Це не «поради». Це конкретні перевірки, які перетворюють систему з bus-factor на командну систему. Кожне завдання включає команду, що означає вивід і яке рішення з цього випливає.
Завдання 1: Виявити, хто має доступ у продакшн (Linux host)
cr0x@server:~$ getent group sudo
sudo:x:27:root,alice,bob,oncall
Що це означає: Цей хост дозволяє підвищувати привілеї root, alice, bob і oncall.
Рішення: Якщо аварійний доступ у продакшн залежить від однієї конкретної людини, додайте рольову групу (наприклад, oncall) з аудитованим членством і регулярною перевіркою доступів.
Завдання 2: Перевірити SSH-ключі та останні входи (знайти ситуації «тільки Пат може зайти»)
cr0x@server:~$ sudo last -a | head
reboot system boot 6.5.0-21-generic Mon Jan 29 03:12 still running - server
alice pts/0 10.0.2.14 Mon Jan 29 03:20 still logged in - 10.0.2.14
bob pts/1 10.0.3.19 Mon Jan 29 02:55 - 03:40 (00:45) - 10.0.3.19
Що це означає: Хто реально заходить на машину і звідки. Якщо ви бачите лише одне ім’я, можливо, проблема «тіньової» власності.
Рішення: Впровадьте індивідуальні облікові записи + спільні рольові акаунти для аварійного доступу, і вимагайте, щоб щонайменше дві людини могли залогінитись під час інциденту.
Завдання 3: Підтвердити, що секрети не лежать «в чиїйсь домашній теці»
cr0x@server:~$ sudo grep -R --line-number "BEGIN PRIVATE KEY" /home 2>/dev/null | head
/home/alice/.ssh/id_rsa:1:-----BEGIN PRIVATE KEY-----
Що це означає: Знайдено приватний ключ у домашній теці. Це може бути легітимно для SSH-користувача, але часто це ключ сервісу або облікові дані деплойменту, які стали «проблемою Alice».
Рішення: Перенесіть сервісні облікові дані у керований секретний сховок; проведіть ротацію скомпрометованих/перевикористаних ключів; задокументуйте доступ і процеси ротації.
Завдання 4: Перевірити, чи сервіси конфігуровані вручну (детекція дрейфу)
cr0x@server:~$ sudo systemctl cat nginx | sed -n '1,25p'
# /lib/systemd/system/nginx.service
[Unit]
Description=A high performance web server and a reverse proxy server
After=network-online.target remote-fs.target nss-lookup.target
[Service]
Type=forking
ExecStartPre=/usr/sbin/nginx -t -q -g 'daemon on; master_process on;'
ExecStart=/usr/sbin/nginx -g 'daemon on; master_process on;'
Що це означає: Файл сервісу стандартний. Добре. Якщо ви бачите перевизначення в /etc/systemd/system/nginx.service.d/override.conf, яких немає в Git — це дрейф.
Рішення: Помістіть перевизначення у CM; додайте «дрейф-чек» у CI або заплануйте аудит.
Завдання 5: Підтвердити, що слухає на порту (виявити «таємні порти» одного інженера)
cr0x@server:~$ sudo ss -lntp
State Recv-Q Send-Q Local Address:Port Peer Address:Port Process
LISTEN 0 4096 0.0.0.0:443 0.0.0.0:* users:(("nginx",pid=1321,fd=6))
LISTEN 0 4096 127.0.0.1:9000 0.0.0.0:* users:(("gatewayd",pid=2104,fd=12))
Що це означає: Є локальний сервіс на 9000 з ім’ям gatewayd. Якщо ніхто не може пояснити його без питань одній людині — це видима реалізація bus-factor.
Рішення: Змепіть кожен порт на власника, репозиторій і runbook. Якщо не можете — заплануйте короткий інвентарний інцидент до того, як настане реальний інцидент.
Завдання 6: Швидко перевірити стан дисків (SRE triage, версія для зберігання)
cr0x@server:~$ lsblk -o NAME,SIZE,TYPE,MOUNTPOINT,FSTYPE,MODEL
sda 1.8T disk Samsung_SSD_860
├─sda1 512M part /boot ext4
└─sda2 1.8T part / ext4
Що це означає: Базовий інвентар. Якщо система залежить від конкретної моделі диска/прошивки, відомої лише одній людині, ви хочете це показати.
Рішення: Записуйте моделі дисків/прошивку і стандартизуйте. Гетерогенні парки ок, доки вам не треба узгодженого оброблення відмов.
Завдання 7: Шукати тиск IO (система повільна через повільне сховище?)
cr0x@server:~$ iostat -xz 1 3
Linux 6.5.0-21-generic (server) 02/02/2026 _x86_64_ (8 CPU)
avg-cpu: %user %nice %system %iowait %steal %idle
12.31 0.00 4.22 25.80 0.00 57.67
Device r/s w/s rkB/s wkB/s await %util
sda 80.0 120.0 6400.0 9800.0 38.2 98.7
Що це означає: %iowait високий і %util диска близький до 100% з підвищеним await. Класичний випадок «додатки виглядають повільними, CPU ні».
Рішення: Тротлінгуйте пакетні джоби, зменшіть write amplification (логи, compact), або переключіться на менш навантажене сховище. Почніть потік інциденту, сфокусований на зберіганні; не дозволяйте усім ганятись за привидами додатку.
Завдання 8: Перевірити ємність файлової системи та вичерпання inode
cr0x@server:~$ df -h /
Filesystem Size Used Avail Use% Mounted on
/dev/sda2 1.8T 1.7T 55G 97% /
cr0x@server:~$ df -i /
Filesystem Inodes IUsed IFree IUse% Mounted on
/dev/sda2 120586240 119900000 686240 100% /
Що це означає: У вас закінчились inode. Така відмова виглядає як «випадкові» помилки запису, навіть якщо місця на диску ще є.
Рішення: Знайти й видалити каталоги з великою кількістю файлів (кеш, tmp, шарди логів). Додати моніторинг використання inode. Оновити runbook: «disk full» включає inode.
Завдання 9: Виявити «ядро — лімітатор» за чергою виконання й навантаженням
cr0x@server:~$ uptime
02:21:10 up 17 days, 6:14, 2 users, load average: 24.18, 23.77, 20.06
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
18 6 0 128000 52000 910000 0 0 820 2400 4100 8200 13 5 55 27 0
Що це означає: Load високий, і значення b (blocked) плюс wa (IO wait) вказують, що процеси застрягли в очікуванні IO.
Рішення: Розглядайте це як вузьке місце IO/бекінг-стору, а не масштабування CPU. Ескалюйте до зберігання, зменшіть IO і знайдіть топ-споживачів IO.
Завдання 10: Знайти топ-споживачів IO (доведіть, хто шкодить диску)
cr0x@server:~$ sudo iotop -boPa -n 3 | head -n 12
Total DISK READ: 120.00 M/s | Total DISK WRITE: 85.00 M/s
PID PRIO USER DISK READ DISK WRITE SWAPIN IO> COMMAND
2104 be/4 app 65.00 M/s 12.00 M/s 0.00 % 15.20 % gatewayd --cache /var/lib/gw
1887 be/4 postgres 40.00 M/s 60.00 M/s 0.00 % 12.30 % postgres: checkpointer
Що це означає: Ви маєте курця: gatewayd і Postgres checkpointer домінують у IO.
Рішення: Для негайного полегшення: налаштуйте поведінку чекпойнтів, зменшіть churn кешу або тимчасово відключіть некритичні навантаження. Для боротьби з bus-factor: задокументуйте, що таке gatewayd і хто володіє його IO-профілем.
Завдання 11: Перевірити здоров’я пулу ZFS (якщо ви використовуєте ZFS, ви повинні знати це)
cr0x@server:~$ sudo zpool status -x
all pools are healthy
Що це означає: Наразі немає відомих проблем з пулами.
Рішення: Якщо ви не регулярно бачите й не розумієте цього виводу, заплануйте навчання. ZFS не «налаштував і забув»; це «налаштував і перевіряй».
Завдання 12: Якщо ZFS нездоровий — читайте його як дерево рішень
cr0x@server:~$ sudo zpool status tank
pool: tank
state: DEGRADED
status: One or more devices has experienced an error resulting in data corruption.
action: Replace the device and run 'zpool clear'.
scan: scrub repaired 0B in 00:12:11 with 0 errors on Mon Jan 29 01:00:01 2026
config:
NAME STATE READ WRITE CKSUM
tank DEGRADED 0 0 0
mirror-0 DEGRADED 0 0 0
ata-SAMSUNG_SSD_860-1 ONLINE 0 0 0
ata-SAMSUNG_SSD_860-2 FAULTED 0 0 12
Що це означає: Член зеркала має помилки контрольної суми і FAULTED. Scrub показує 0 відновлених, але існують помилки контрольних сум: розглядайте пристрій як підозрілий.
Рішення: Замініть пошкоджений диск, підтвердіть resilver, а потім clear помилок. Найважливіше: переконайтесь, що процедура заміни в runbook-і і її може виконати не-спеціаліст під наглядом.
Завдання 13: Підтвердити, що існують scrubs і snapshoti (нудні, правильні, рятівні)
cr0x@server:~$ sudo zpool get scrubby tank
NAME PROPERTY VALUE SOURCE
tank scrubby - default
cr0x@server:~$ sudo zfs list -t snapshot | head
NAME USED AVAIL REFER MOUNTPOINT
tank/data@daily-001 128M - 1.2T -
tank/data@daily-002 130M - 1.2T -
Що це означає: У вас є знімки (добре), але scrubby не є стандартною властивістю; цей вивід каже, що scrubs тут не відслідковуються через властивість. Потрібно перевірити графік scrub десь іншим способом (cron/systemd таймери).
Рішення: Переконайтесь, що є відомий графік і алертинг для завершення scrub і помилок. Якщо scrubs «просто відбуваються», бо одна людина їх запускає вручну — це чистий ризик bus-factor.
Завдання 14: Перевірити статус реплікації/бекапу (підтвердити відновлюваність)
cr0x@server:~$ systemctl status zfs-replication.service --no-pager
● zfs-replication.service - ZFS snapshot replication
Loaded: loaded (/etc/systemd/system/zfs-replication.service; enabled)
Active: active (exited) since Mon 2026-02-02 01:00:02 UTC; 1h 22min ago
Process: 4421 ExecStart=/usr/local/sbin/replicate-tank.sh (code=exited, status=0/SUCCESS)
Що це означає: Одиниця реплікації виконувалась успішно недавно.
Рішення: Якщо успіх реплікації — це лише «status=0», додайте перевірку: подивіться останні знімки на приймаючому боці і протестуйте шлях відновлення. Довіряй, але перевіряй із доказами.
Завдання 15: Підтвердити, яку версію і конфіг ви справді запускаєте (щоб уникнути «працює на моєму ядрі»)
cr0x@server:~$ uname -a
Linux server 6.5.0-21-generic #21-Ubuntu SMP PREEMPT_DYNAMIC x86_64 GNU/Linux
cr0x@server:~$ dpkg -l | egrep 'zfs|linux-image' | head
ii linux-image-6.5.0-21-generic 6.5.0-21.21 amd64 Signed kernel image generic
ii zfsutils-linux 2.2.2-0ubuntu1 amd64 command-line tools to manage ZFS filesystems
Що це означає: Ви бачите версії ядра і ZFS. Це важливо, бо поведінка змінюється між версіями, і «племінні налаштування» часто припускають конкретну версію.
Рішення: Записуйте версії в runbook і в шаблонах інцидентів. Вимагайте canary-оновлення і план відкату для змін у стеку ядро/зберігання.
Завдання 16: Ідентифікувати cron/таймери, які знає лише одна людина
cr0x@server:~$ sudo systemctl list-timers --all | head -n 15
NEXT LEFT LAST PASSED UNIT ACTIVATES
Mon 2026-02-02 03:00:00 UTC 37min left Mon 2026-02-02 02:00:00 UTC 22min ago logrotate.timer logrotate.service
Mon 2026-02-02 04:00:00 UTC 1h 37min Mon 2026-02-02 01:00:00 UTC 1h 22min ago apt-daily-upgrade.timer apt-daily-upgrade.service
Що це означає: Таймери показують заплановану автоматизацію. Якщо ваші критичні завдання тут відсутні — або не в відомій системі оркестрації — вони можуть виконуватись вручну як ритуал.
Рішення: Конвертуйте ручні операційні кроки в таймери/джоби з логами, алертами і власністю. Завдання, яке виконується «коли хтось пам’ятає», — це баг на надійність.
Поширені помилки: симптом → корінь → виправлення
1) Симптом: «Ми не можемо деплоїти, бо лише одна людина може затвердити»
Корінь: Політика затвердження замінює інженерні контролі; ризик управляється соціально, а не технічно.
Виправлення: Замініть персональні затвердження автоматизованими перевірками (тести, policy-as-code) і вимагайте двох навчених затверджувачів у ротації. Збережіть аварійний оверрайд, але аудитуйте його.
2) Симптом: «On-call не може відновити, але експерт робить це за 10 хвилин»
Корінь: Шлях відновлення не задокументований, не протестований і, ймовірно, включає приватний контекст (приховані залежності, неявний порядок).
Виправлення: Напишіть runbook відновлення з командами й очікуваними виводами, потім проводьте квартальні тренування відновлення з не-експертами, поки експерт мовчки спостерігає і не втручається без потреби.
3) Симптом: «Сервіс стабільний; не треба його чіпати»
Корінь: Стабільність забезпечується звичками однієї людини (ручні перевірки, обережні дії), а не дизайном системи.
Виправлення: Форсуйте безпечні, невеликі зміни: canary-перезавантаження, перевірки пінувань залежностей, періодичні failover-тести. Стабільність потрібно демонструвати під контрольованою зміною.
4) Симптом: «Документи є, але ніхто їм не довіряє»
Корінь: Документи застарілі, невиконувані і написані як наратив, а не як операції.
Виправлення: Зробіть документи командо-орієнтованими: «Запустіть X, побачите Y, потім зробіть Z». Прив’яжіть їх до сторінок алертів і шаблонів інцидентів. Додайте відповідальність за документи і дати перевірки.
5) Симптом: «У нас є автоматизація, але вона крихка і лише одна людина її дебагує»
Корінь: Автоматизація — кастомна система без тестів, поганої спостережуваності й неявних припущень.
Виправлення: Сприймайте автоматизацію як продакшн-код: тести, логи, метрики і другий підтримувач. Якщо її не можна протестувати — спростіть, поки не зможете.
6) Симптом: «Ми не можемо ротувати секрети/сертифікати без даунтайму»
Корінь: Система ніколи не була проєктована для ротації; секрети вбудовані в конфіги чи код, що вимагає рестарту й ручної координації.
Виправлення: Додайте hot-reload де можливо, зменшіть розкиданість секретів, використовуйте короткоживучі креденшіали і репетируйте ротацію як реліз.
7) Симптом: «Інциденти зі зберіганням лякають і вирішуються повільно»
Корінь: Сховище має великий blast radius і низьку спостережуваність; команді бракує м’язової пам’яті щодо безпечних кроків (scrub, resilver, snapshot, restore).
Виправлення: Стандартизувати стеки зберігання; додати зрозумілі дашборди здоров’я; практикувати процедури заміни і відновлення; створити окремий плейбук для інцидентів зі зберіганням, відмінний від плейбуків додатків.
8) Симптом: «Ми завжди чекаємо, доки одна і та сама людина приєднається до інциденту»
Корінь: Лише одна людина уповноважена діяти, або всі інші бояться погіршити ситуацію.
Виправлення: Визначте права прийняття рішень (що on-call може робити без дозволу), створіть безпечні пом’якшення (shedding трафіку, feature flags) і проводьте game day-і, що заохочують навчання.
Чеклісти / покроковий план
Покроковий план зниження bus-factor за 30–60 днів
- Зробіть інвентар: сервіси, хости, критичні cron/таймери, пули зберігання, бази даних і залежності. Якщо слухає порт — йому потрібна назва і власник.
- Напишіть runbook «break glass»: як отримати доступ, як аудитується доступ, як відкотити доступ. Це різниця між стійкістю і театром.
- Створіть мінімальний інцидентний runbook для кожного сервісу:
- Що означає «здоровий» (метрики, логи, статус)?
- Топ-3 сценарії відмов і як їх безпечно пом’якшити.
- Точні команди і очікувані виводи.
- Виберіть двох неекспертів і заплануйте 60-хвилинну сесію «shadow restore», де вони виконують runbook, а експерт спостерігає.
- Уніфікуйте креденшіали: перенесіть секрети з персональних машин; вимагайте ротації; забезпечте, щоб on-call мав доступ через рольові контролі.
- Введіть безпеку змін: canary, feature flags, staged rollouts і реальний шлях відкату. Bus factor процвітає там, де відкат — міф.
- Зробіть власність явною: визначте primary/secondary власників для кожного компоненту системи. Secondary означає «може оперувати і відновлювати», а не «в копії листа».
- Додайте перевірки готовності до експлуатації для нових систем: «Хто може запустити це о 3-й ранку?» — критерій запуску, а не пропозиція.
- Проведіть щонайменше один game day, сфокусований на страшному підсистемі (зберігання, мережа, автентифікація). Мета — впевненість, а не хаос.
- Вимірюйте покращення: стежте інциденти, де експерт був потрібен; час пом’якшення при відсутності експерта; як часто використовуються і коригуються runbook-и.
Чого уникати (бо здається продуктивним, але таким не є)
- Не карайте інженера bus-factor. Він не створив стимулюючу структуру один-один. Виправляйте систему, а не цапа-відбувайла.
- Не пишіть 40-сторінковий вікі-роман. Напишіть 2-сторінковий runbook з командами й рішеннями, потім розширюйте лише за потреби.
- Не вимагайте, щоб «усі знали все». Мета — відновлюваність і операційність, а не універсальна експертиза.
- Не плутайте спільний доступ з резильєнтністю. Якщо дві людини мають один і той же пароль, ви просто подвоїли blast radius і зберегли bus factor.
Практичне «Definition of Done» для зниження ризику підсистеми
- Щонайменше дві людини можуть деплоїти, відкотити й відновити без допомоги.
- Runbook-и містять точні команди, очікувані виводи і точки прийняття рішення.
- Доступ через рольові групи з логами аудиту і періодичними рев’ю.
- Резервні копії/реплікація перевіряються відновленням, а не лише «джоб завершився».
- Щонайменше один failure injection або game day проведено за останній квартал.
Питання й відповіді
1) Чи bus factor — це просто інший термін для «ризику ключової людини»?
Так, але інженерам потрібно бачити це операційно. «Ризик ключової людини» звучить як слайд для менеджменту. «Bus factor» звучить як інцидент, що чекає на реалізацію, і це точніше.
2) Який прийнятний bus factor?
Для критичних продакшн-систем прагніть щонайменше 2 для операцій і відновлення, і 3 для тривалого розвитку. Якщо система не переживе відсутності однієї людини — вона не готова до продакшну.
3) У нас є документація. Чому bus factor все ще високий?
Тому що документація, яка не виконувана — це просто історія. Runbook-и мають включати команди, очікувані виводи і точки рішень. Також: доступ і повноваження важать так само, як і знання.
4) Чи спеціалізація неминуча для зберігання, мереж і безпеки?
Спеціалізація — ок. Єдині точки відмови — ні. Мета: «спеціалісти будують і покращують», тоді як on-call може оперувати і відновлювати безпечно за допомогою runbook-ів і огорож.
5) Як знизити bus factor без уповільнення доставки?
Ви трохи загальмуєте зараз або катастрофічно пізніше. Трюк — робити передачу знань частиною доставки: кожна зміна має оновлювати runbook, дашборди і кроки відкату.
6) Що робити, якщо інженер bus-factor відмовляється ділитися знаннями?
Іноді це контроль, іноді — вигоряння, іноді — страх втратити статус. У будь-якому разі вирішуйте структурно: зробіть спільну власність вимогою, обертайте on-call і забезпечте час для документації й тренувань.
7) Як впоратися з ситуацією «лише одна людина має креденшіали», не послаблюючи безпеку?
Використовуйте рольовий доступ, аудитований break-glass, короткоживучі токени і затвердження з логуванням. Безпека — не «одна людина володіє ключами». Безпека — це контрольований доступ із трасуванням.
8) Який найшвидший виграш?
Виберіть один критичний тип інциденту (відновлення, фейловер, ротація сертифікатів) і напишіть runbook з командами. Потім нехай не-експерт виконає його в тренуванні. Перший тренінг буде нерівним; в цьому і суть.
9) Як вимірювати покращення bus factor?
Слідкуйте, хто вирішує інциденти, скільки часу займає пом’якшення, коли експерт відсутній, як часто використовуються runbook-и і скільки сервісів мають primary/secondary власників з протестованим доступом.
10) Чи автоматизація вирішує bus factor?
Лише якщо команда може її зрозуміти і оперувати нею. Автоматизація, яку може дебажити лише одна людина, — це просто швидший спосіб застрягти.
Висновок: наступні кроки, які ви реально можете виконати
Якщо ви підозрюєте, що у вас є інженер bus-factor, то, ймовірно, так і є. Підказка — це не їхня блискучість. Це залежність команди від їхньої присутності для відновлення й змін.
Зробіть це далі, у порядку:
- Виберіть найстрашніший шлях відновлення (відновлення бази, resilver сховища, фейловер регіону) і перетворіть його на runbook з командами, виводами і рішеннями.
- Проведіть тренування, де інша людина виконує runbook. Експерт може спостерігати і робити нотатки, але не вести процес.
- Виправте доступ: переконайтесь, що on-call може зробити безпечні пом’якшення і кроки break-glass з аудитом.
- Уніфікуйте і тестуйте: canary-зміни, шляхи відкату і рутинні «нудні» перевірки як scrubs і тести відновлення.
- Зробіть власність реальною: primary і secondary власники з явними очікуваннями і часом, відведеним на передачу знань.
Надійність — це не риса характеру. Це властивість системи, яка припускає, що люди схильні помилятися, іноді будуть недоступні і не повинні бути єдиними точками відмови — незалежно від того, наскільки гарна у них історія shell.