03:17. На дашборді зелено, ваш пейджер говорить «ні», а генеральний директор каже «але ми на преміум‑шарі хмари». Тим часом користувачі дивляться на спінери, ніби це ностальгійне хобі.
До 2026 року ми додали AI‑копілотів, «serverless для всього», NVMe скрізь, service mesh, eBPF і стільки керованих сервісів, що ними можна обклеїти ангар. Проте відмови досі римуються з тими, що були в 2006: переповнені черги, невідповідні припущення, заперечення ємності й «оптимізації», що здаються блискучими, поки не трапиться перший серйозний інцидент.
Чому 2026 видається знайомим: ті ж фізичні закони, новий маркетинг
Більшість «нових» проблем надійності — це старі проблеми в іншому вбранні. Основні обмеження не змінилися:
- Теорія черг усе ще керує вашим дата‑центром. Коли завантаження наближається до 100%, латентність експоненційно зростає. Не лінійно. Вибухоподібно.
- Хвостова латентність усе ще домінує над досвідом користувача. Ваш медіан може бути чудовим, тоді як p99 — фактично в пеклі.
- Сховище — це спільна доля stateful‑систем. Чи це керована база, Kubernetes PersistentVolume або саморобний ZFS‑пул — не вдасться «мікросервісити» I/O у безкінечність.
- Мережі досі втратні й змінні. Ви можете загорнути їх у gRPC, QUIC, mesh і політики, але фізика має останнє слово.
- Люди досі роблять припущення. І припущення ламаються при 2× масштабу, 10× навантаженні або в найневдалий момент.
«Поворот 2026 року» в тому, що складність тепер продається як безпека. Якщо ви використовуєте керований сервіс, то певно хтось інший вирішив за вас надійність. Якщо додаєте ще один рівень абстракції, то система нібито стає простішою. Якщо дашборд зелений — продакшн у порядку. Жодне з цього не гарантується. Це просто способи делегувати розуміння.
Ось перефразована ідея, яку часто приписують Richard Cook: Складні системи відмовляють складно, і розуміння нормальної роботи — ключ до розуміння відмов.
Це не поетика. Це операційна порада: припиніть вивчати лише відмови; вивчайте, як все працює у звичайний вівторок. Саме там ховаються ваші реальні запасні межі.
Одне правило для 2026: якщо ви не можете пояснити, де знаходиться черга, ви не знаєте, чому латентність висока.
Дев’ять фактів і контекст історії (що пояснюють сьогоднішнє)
- RAID не зник; він перемістився. Багато «хмарних дисків» усе ще побудовані на дзеркалуванні/ерейзер‑кодуванні плюс кешування, просто не на вашій серверній RAID‑карті.
- Маркетинг IOPS вводив команди в оману десятиліттями. Мільйон 4k‑читаїв — це не те саме, що тисяча 1MB‑записів, а «до» продуктивності не означає гарантії.
- Підсилення записів (write amplification) старіше за SSD. Файлові системи, бази даних і лінійно‑журнальні дизайни завжди платили послідовними записами за роботу з компактуванням пізніше.
- Помилкова віра, що «безстанність вирішує stateful‑біль», повторюється. Люди розбивають сервіси, залишаючи одну спільну базу даних, а потім дивуються, чому база стала новим монолітом.
- Хвостова латентність стала мейнстрімом у 2010‑х. До того багато команд вимірювали середні значення й дивувалися скаргам користувачів. Тепер ми вимірюємо p99 і все одно дивуємося — бо досі не керуємо чергами.
- Контейнери не ліквідували шумних сусідів; вони їх індустріалізували. cgroups обмежують CPU й пам’ять, але спільне сховище й мережеві шляхи все ще пов’язують навантаження.
- «Нарешті консистентні» системи все ще мають витрати консистентності. Повторні спроби, узгодження та компактування можуть перенести біль у фон, поки він не вийде на передній план.
- NVMe зменшив латентність, але збільшив швидкість відмови. Коли система може генерувати навантаження швидше, вона також може швидше переповнити залежності.
- Ретроспективи інцидентів часто надто ввічливі. Справжня коренева причина часто звучить як «ми вірили в властивість, яка ніколи не була істинною», але записується як «транзитна латентність».
Блискуче пакування: де тепер ховаються старі режими відмов
1) «Керований» не означає «обмежений»
Керовані бази та диски чудові, поки ви не починаєте ставитися до них як до магії. Вони все ще мають:
- системи кредитів I/O і поведінку «burst»
- вікна обслуговування і фонові компактування
- мульти‑тенантну конкуренцію
- ліміти, які ви не помітите, доки їх не перевищите
У 2026 найпоширеніший шаблон відмов у керованих сервісах, який я бачу — це м’яке тротлінг. Немає очевидного піку 5xx. Немає драматичного «вимкнення». Лише повільне ковзання в таймаути, коли латентність зростає, а повторні спроби множаться. Сервіс «up». Ваш SLO — ні.
2) Обсервабельність покращилася — і одночасно погіршилася
У нас більше телеметрії, ніж будь-коли: розподілені трасування, профілі, мережева видимість на основі eBPF, метрики сховища, глибина черги, сигнали насичення. І все ж команди провалюються, бо їхня обсервабельність некурована.
Якщо ваш on‑call має мислено поєднувати 14 дашбордів і переводити шість різних перцентилів у одне рішення — у вас немає обсервабельності. У вас музей.
3) Кеш усе ще найнебезпечніша «фіча продуктивності»
Кеші хороші. Надмірна самовпевненість у кешах — ні. У 2026 класичні відмови все ще відбуваються:
- cache stampede після інвалідації
- вилучення під час стрибка трафіку
- посилення «гарячого ключа» від одного популярного об’єкта
- роботи з прогрівання кешу, що тихо DDoS‑лять базу
Жарт №1: Кеш — це як спільний офісний холодильник: усім подобається, поки хтось не принесе рибу в п’ятницю після обіду.
4) «Просто додайте retry» залишається антипатерном надійності
Повторні спроби — це податок за невизначеність. Вони можуть врятувати, якщо обмежені й з джитером. Вони також можуть стати причиною катастрофи. У 2026 retries часто сховані в SDK, service mesh і клієнтських бібліотеках — тож ви думаєте, що у вас один запит, а залежності бачать три.
Бюджети повторних спроб і circuit breaker — не «приємності». Вони — різниця між транзитним сплеском і тотальним каскадом.
5) Сховище — місце, куди йде оптимізм продуктивності
Stateful‑системи не стали менш важливими. Вони стали більш централізованими. Можна мати 200 мікросервісів, але все одно залишаться:
- кілька баз даних, що мають значення
- шина повідомлень, яка має значення
- об’єктне сховище, на яке всі опираються
- рівень persistent volume, що тихо визначає ваш p99
Коли вони насичуються, решта архітектури стає декоративною.
Три міні‑історії з виробничих боїв
Міні‑історія 1: Інцидент через хибне припущення
Вони мігрували клієнтський API з VM у Kubernetes. Та сама аплікація, та сама база, «більш стійка платформа». Новий кластер використовував CSI‑драйвер на основі мережевого блочного сховища. Ніхто не панікував, бо в даташиті вендора було вказано, що тип тома — «висока продуктивність».
Хибне припущення було тонким: команда вірила, що латентність сховища буде стабільною, поки середні IOPS залишаються нижче опублікованого ліміту. Але їхнє робоче навантаження не було середнім. Це були стрибкоподібні записи, fsync‑інтенсивні, чутливі до хвостової латентності. Під час піку блочний пристрій почав показувати періодичні сплески латентності — від одинакx мілісекунд до сотень. Не постійно, але достатньо, щоб порушити дедлайни запитів.
Першим симптомом не були алерти сховища. Це були таймаути аплікації й сплеск повторних спроб. Це подвоїло швидкість записів, що збільшило глибину черги на шарі сховища й ще більше підняло латентність. Система «самопідсилювалася» в інцидент, не втративши при цьому статусу «up».
Коли нарешті витягли метрики на рівні ноди, вони побачили: зростання iowait, але лише на підмножині нод. Розподіл планування був нерівномірний; кілька нод мали кілька stateful‑подів, прив’язаних близько одна до одної, що «били» по одному й тому самому шляху до сховища.
Виправлення було непретензійним: задати явну pod anti‑affinity для stateful‑навантажень, налаштувати таймаути клієнтів із джитером для повторних спроб і переключити том бази на клас із передбачуваною латентністю (і заплатити за це). Найважливіше — оновити рукопис: «Опубліковані IOPS не є гарантією латентності».
Міні‑історія 2: Оптимізація, що обернулась проти нас
Платформ‑команда захотіла скоротити витрати хмари. Вони помітили, що інстанси бази недовантажені по CPU. Тож вони зменшили CPU і пам’ять, очікуючи ту ж пропускну здатність. Це спрацювало в стенді. Воно навіть працювало тиждень у проді.
Потім настав місячний звітний цикл і звичні jobs з репортингу. База почала інтенсивніше чекпоинтитись. Маючи менше пам’яті, кеш‑буфер крутився сильніше. Маючи менше CPU, фонове обслуговування конкурувало з foreground‑запитами. Латентність зросла.
Хтось «оптимізував» аплікацію, збільшивши розмір connection pool, щоб зменшити видимі черги. Це підняло конкурентність на базі, що збільшило lock contention і write amplification. p50 покращився для кількох ендпоінтів. p99 накрився.
Відкат був не лише про продуктивність. Це була втрата операційної ясності. Система стала нестабільною так, що кожен дашборд виглядав «досить правдоподібно». CPU не був завантажений. Диск не був забитий. Мережа не була завантажена. Все просто… повільніше.
Вони відкотили зменшення ресурсів, зменшили розміри пулів і ввели admission control: якщо черга зростає, скидати навантаження або деградувати функції замість «протискання». Урок вдарив по суті: коли оптимізуєш за середніми, зазвичай платиш у хвостах.
Міні‑історія 3: Нудна, але правильна практика, що врятувала день
Середній SaaS мав репутацію «занадто обережних». Вони робили квартальні drills відновлення. Не стендові вправи — реальні відновлення в ізольованому середовищі з верифікацією на рівні аплікації. Люди сміялися над цим, поки це не знадобилося.
Інженер виконав рутинне розширення сховища на хості з ZFS‑базованою базою. Зміна була коректна, але існувала окрема, не пов’язана проблема: один диск у дзеркалі тихо кидав помилки, що ще не перетнули поріг тривоги. Під час resilver‑у частота помилок зросла. Пул деградував. База почала логувати I/O‑помилки.
Вони оголосили інцидент рано — до того, як симптоми корупції даних дісталися клієнтів. Оскільки команда регулярно практикувала відновлення, питання не було «чи можемо ми відновити?», а «який шлях відновлення найшвидший і найbezпечніший?». Вони переключились на теплий репліку, ізолювали деградований пул і відновили постраждалі дані на новому сховищі для перевірки.
Пост‑інцидентний огляд не був драматичним. Він був майже нудним. І в цьому суть: «нудна» практика drills відновлення перетворила потенційний екзистенційний інцидент на контрольоване впорядковане завдання з кількома годинами зниження продуктивності.
Жарт №2: Нічого не зміцнює команду так, як drill відновлення — крім неперевіреного відновлення під час відмови, яке згуртовує так само, як корабельна аварія.
План швидкої діагностики: знайти вузьке місце за хвилини
Це план, який я хотів би бачити надлаштованим біля чергового столу. Не тому, що він витончений, а тому, що він послідовний. Порядок має значення.
Перше: підтвердьте, що у вас проблема латентності, а не коректності
- Чи таймаутяться запити або повертають помилки?
- Чи p95/p99 зростає, а p50 залишається стабільним? Це сигнал черги або контенції.
- Чи лише один ендпоінт падає? Ймовірно залежність або hotspot із блокуванням.
Друге: ідентифікуйте обмежений ресурс за допомогою підходу «USE»
Для кожного шару (аплікація, нода, сховище, мережа, база) перевірте:
- Utilization: близько ліміту?
- Saturation: глибина черги, час очікування, backpressure?
- Errors: таймаути, ретрансміти, помилки диска, тротлінг?
Третє: шукайте чергу
Черга рідко там, де ви її очікуєте. У 2026 вона часто ховається в:
- клієнтських connection pool
- retry у service mesh
- пул thread‑ів і async‑екзекуторів
- ядровому блок‑шарі (avgqu‑sz)
- чергах контролера сховища
- очікуваннях блокувань у базі
- партиціях message broker
Четверте: зупиніть кровотечу діями з обмеженням
Обирайте дії, що зворотні й передбачувані:
- зменшити конкуренцію (connection pool, worker threads)
- відключити нефундаментальні jobs (аналітика, імпорт батчів)
- збільшувати таймаути лише разом із зменшенням retry
- маршрутизація трафіку від гарячого шард‑у/зони
- тимчасово скидати навантаження через feature flags
П’яте: виправляйте причини, а не симптоми
Після стабілізації: усуньте приховану зв’язку. Якщо два навантаження конкурують — ізолюйте їх. Якщо латентність сховища змінна — купіть передбачуваність або змініть шаблон доступу. Якщо retries створюють бурю — введіть бюджети і backoff.
Практичні завдання: команди, виходи та рішення (12+)
Це не «іграшкові» команди. Це те, що ви запускаєте, коли продакшн повільний і потрібні відповіді без написання дисертації. Кожне завдання включає: команду, що означає вихід, і рішення, яке з нього випливає.
Завдання 1: Підтвердити load average проти CPU‑тиску
cr0x@server:~$ uptime
03:22:18 up 41 days, 7:10, 2 users, load average: 18.42, 16.90, 12.11
Значення: Високий load average може бути викликаний runnable‑задачами на CPU або задачами, заблокованими на I/O. Сам по собі load не каже, що саме.
Рішення: Не масштабуйте CPU навмання. Наступним кроком перевірте iowait і чергу виконання.
Завдання 2: Перевірити iowait та steal CPU
cr0x@server:~$ mpstat -P ALL 1 3
Linux 6.5.0 (db-01) 02/02/2026 _x86_64_ (16 CPU)
03:22:31 CPU %usr %nice %sys %iowait %irq %soft %steal %idle
03:22:32 all 12.10 0.00 4.20 38.50 0.00 0.40 0.10 44.70
03:22:33 all 11.80 0.00 4.10 40.20 0.00 0.30 0.10 43.50
03:22:34 all 13.00 0.00 4.50 39.70 0.00 0.30 0.10 42.40
Значення: ~40% iowait кричить «латентність або насичення сховища». Низький steal свідчить, що це не гіпервізор, що краде CPU.
Рішення: Рухайтесь швидко до перевірки черги диска/латентності; масштабування CPU цього не виправить.
Завдання 3: Визначити, який блочний пристрій шкодить
cr0x@server:~$ iostat -xz 1 3
Linux 6.5.0 (db-01) 02/02/2026 _x86_64_ (16 CPU)
avg-cpu: %user %nice %system %iowait %steal %idle
12.4 0.0 4.3 39.5 0.1 43.7
Device r/s w/s rkB/s wkB/s rrqm/s wrqm/s %util await svctm
nvme0n1 120.0 880.0 6144.0 32768.0 0.0 120.0 98.5 42.30 0.85
Значення: %util ~98% плюс await ~42ms вказує, що пристрій насичений або має високу латентність. svctm ненадійний на сучасних ядрах; орієнтуйтесь на await і util.
Рішення: Підтвердьте глибину черги і чи викликано латентність навантаженням або тротлінгом пристрою.
Завдання 4: Перевірити здоров’я NVMe і помилки носія
cr0x@server:~$ sudo nvme smart-log /dev/nvme0
Smart Log for NVME device:nvme0 namespace-id:ffffffff
critical_warning : 0x00
temperature : 43 C
available_spare : 100%
percentage_used : 2%
media_errors : 0
num_err_log_entries : 0
warning_temp_time : 0
critical_comp_time : 0
Значення: Немає помилок носія, невеликий знос. Це відводить підозру від «диск помирає» і вказує на «диск перевантажений» або «латентність в іншому рівні стеку».
Рішення: Шукайте поведінку файлової системи/зберігання, синхронні записи та checkpoint‑и бази.
Завдання 5: Знайти топ‑споживачів I/O за процесом
cr0x@server:~$ sudo iotop -oPa
Total DISK READ: 6.01 M/s | Total DISK WRITE: 33.12 M/s
PID PRIO USER DISK READ DISK WRITE SWAPIN IO> COMMAND
2411 be/4 postgres 1.20 M/s 18.50 M/s 0.00 % 62.10 % postgres: checkpointer
2388 be/4 postgres 0.80 M/s 9.10 M/s 0.00 % 31.40 % postgres: wal writer
3102 be/4 app 0.20 M/s 2.10 M/s 0.00 % 7.20 % java -jar api.jar
Значення: Dominування checkpointer і WAL writer свідчить про тиск записів і активність checkpoint, що часто пов’язано з пам’яттю або піками записів.
Рішення: Зменшити стрибки записів (батчинг), налаштувати checkpoint або додати запас IOPS/латентності. Розглянути виділення WAL на окремий пристрій.
Завдання 6: Перевірити простір файлової системи та інодний тиск
cr0x@server:~$ df -h /var/lib/postgresql
Filesystem Size Used Avail Use% Mounted on
/dev/nvme0n1p2 900G 812G 42G 96% /var/lib/postgresql
Значення: 96% заповнення — запах проблем продуктивності на деяких ФС і ризик раптових режимів відмов (autovacuum bloat, логи, тимчасові файли).
Рішення: Звільніть місце зараз; потім зробіть capacity‑алерти з «днями до заповнення», а не лише відсотками.
Завдання 7: Перевірити тиск блочної черги на рівні ядра
cr0x@server:~$ cat /proc/diskstats | egrep 'nvme0n1 '
259 0 nvme0n1 112233 0 987654 12000 998877 0 776655 54000 0 62000 66000 0 0 0 0
Значення: diskstats сам по собі — сирі дані. Його використовують для кореляції з iostat або для підтвердження, що I/O відбувається, коли вищі‑рівневі метрики брехливі.
Рішення: Якщо аплікація каже «idle», але diskstats сильно інкрементується — ваша обсервабельність щось пропускає (sidecar, хостові процеси, бекапи).
Завдання 8: Визначити TCP‑ретрансміти та втрати (мережево‑індукована латентність)
cr0x@server:~$ ss -s
Total: 1542 (kernel 0)
TCP: 1123 (estab 980, closed 77, orphaned 0, timewait 25)
Transport Total IP IPv6
RAW 0 0 0
UDP 12 10 2
TCP 1046 1002 44
INET 1058 1012 46
FRAG 0 0 0
Значення: Це лише обсяг з’єднань. Корисно для виявлення неконтрольованих кількостей з’єднань або TIMEWAIT‑штормів.
Рішення: Якщо estab різко зростає, підозрюйте misconfig pooling або поведінку лоад‑балансера; далі переходьте до метрик ретрансмітів.
cr0x@server:~$ netstat -s | egrep -i 'retrans|segments retransmited|listen|reset'
3420 segments retransmited
217 resets received for embryonic SYN_RECV sockets
Значення: Ретрансміти сильно корелюють з хвостовою латентністю. SYN_RECV‑ресети можуть вказувати на перевантаження або SYN‑флуд, але також на агресивні таймаути.
Рішення: Якщо ретрансміти зростають під час інциденту, розглядайте мережу як фактор‑вкладник у вузьке місце, а не лише «те, що між сервісами».
Завдання 9: Kubernetes: знайти нерівномірне розміщення подів (noisy neighbor через scheduling)
cr0x@server:~$ kubectl get pods -n prod -o wide | egrep 'db|cache'
db-0 1/1 Running 0 14d 10.2.3.14 node-a
db-1 1/1 Running 0 14d 10.2.5.21 node-c
cache-0 1/1 Running 0 14d 10.2.3.51 node-a
cache-1 1/1 Running 0 14d 10.2.3.52 node-a
Значення: Кілька важких stateful‑подів на node‑a. Класична проблема «ми не хотіли їх прив’язувати разом».
Рішення: Додати pod anti‑affinity і/або topology spread constraints. Розглянути taints для вузлів, що важкі по сховищу.
Завдання 10: Kubernetes: перевірити клас persistent volume і режим доступу
cr0x@server:~$ kubectl get pvc -n prod db-data-db-0 -o yaml | egrep 'storageClassName|accessModes|resources'
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 500Gi
storageClassName: standard
Значення: «standard» часто означає спільний бекенд із вибухоподібною поведінкою. ReadWriteOnce також означає обмеження на failover і переселення.
Рішення: Якщо p99 — бізнес‑вимога, використовуйте storage class, розроблений для передбачуваної латентності, і тестуйте його під реалістичним fsync‑навантаженням.
Завдання 11: База даних: знайти очікування блокувань, що виглядають як «рандомна повільність»
cr0x@server:~$ psql -U postgres -d appdb -c "select now(), wait_event_type, wait_event, count(*) from pg_stat_activity where wait_event is not null group by 1,2,3 order by 4 desc;"
now | wait_event_type | wait_event | count
------------------------------+-----------------+---------------+-------
2026-02-02 03:25:10.112+00 | Lock | transactionid | 37
2026-02-02 03:25:10.112+00 | IO | DataFileRead | 12
Значення: Багато сесій, що чекають на transactionid locks, вказує на конкуренцію (довгі транзакції, «гарячі» рядки). Є також деякі I/O‑очікування.
Рішення: Завбити/помʼякшити довгу транзакцію, якщо безпечно; зменшити конкуренцію; виправити шаблон «гарячого рядка». Не кидайте просто сховище у відповідь на lock contention.
Завдання 12: База даних: перевірити тиск чекпоінтів (приклад PostgreSQL)
cr0x@server:~$ psql -U postgres -d appdb -c "select checkpoints_timed, checkpoints_req, buffers_checkpoint, checkpoint_write_time, checkpoint_sync_time from pg_stat_bgwriter;"
checkpoints_timed | checkpoints_req | buffers_checkpoint | checkpoint_write_time | checkpoint_sync_time
------------------+-----------------+--------------------+-----------------------+----------------------
1200 | 980 | 98765432 | 83423456 | 1223344
Значення: Високі checkpoints_req можуть означати, що система змушена робити чекпоінти через обсяг WAL, що може викликати сплески I/O.
Рішення: Налаштуйте параметри чекпоінтів, зменшіть піки записів і переконайтеся, що WAL і дані лежать на сховищі, яке витримає такий рівень записів.
Завдання 13: ZFS: виявити стан пулу і підказки латентності чит/запис
cr0x@server:~$ sudo zpool status
pool: tank
state: DEGRADED
status: One or more devices has experienced an error resulting in data corruption.
action: Replace the device and restore the pool from backup if necessary.
scan: scrub repaired 0B in 02:31:12 with 0 errors on Sun Feb 1 03:10:01 2026
config:
NAME STATE READ WRITE CKSUM
tank DEGRADED 0 0 0
mirror-0 DEGRADED 0 0 0
sda ONLINE 0 0 0
sdb UNAVAIL 5 12 0
Значення: DEGRADED плюс недоступний член — це не «почекаємо». Це негайно змінює продуктивність і ризик.
Рішення: Замініть пристрій зараз і уникайте важких обслуговувань (компактацій), поки відновлення надлишковості не завершиться.
Завдання 14: Тиск пам’яті Linux (кеш проти thrash‑відновлення)
cr0x@server:~$ free -h
total used free shared buff/cache available
Mem: 64Gi 52Gi 1.2Gi 1.1Gi 11Gi 3.0Gi
Swap: 0B 0B 0B
Значення: Лише 3Gi доступно — ознака тиску на відновлення; продуктивність сховища може погіршуватися, коли ядро постійно евіктить і рефолить сторінки.
Рішення: Додати запас пам’яті, зменшити churn кешу або ізолювати пам’ятевмісткі сайдкари. Уникати аргументів типу «маємо free в buff/cache, тож все гаразд» під час інцидентів.
Завдання 15: Виявити runaway retries на клієнті (рейт + помилка)
cr0x@server:~$ sudo journalctl -u api.service -n 20 --no-pager
Feb 02 03:24:51 api-01 api[3102]: WARN upstream timeout talking to payments, retry=1
Feb 02 03:24:51 api-01 api[3102]: WARN upstream timeout talking to payments, retry=2
Feb 02 03:24:52 api-01 api[3102]: WARN upstream timeout talking to payments, retry=3
Feb 02 03:24:52 api-01 api[3102]: ERROR request failed after retries
Значення: Повторні спроби відбуваються швидко й ймовірно синхронізовані між запитами. Це може стати retry‑штормом.
Рішення: Додати jittered exponential backoff, обмежити кількість спроб і розглянути circuit breaker, щоб зберегти залежність і власну чергу.
Поширені помилки: симптом → корінь → виправлення
1) «Все повільніше», але CPU в нормі
Симптоми: p99 піднімається, CPU виглядає помірковано, дашборди не показують нічого зашкалюючого.
Корінь: Прихована черга: очікування на сховище, lock‑и, мережеві ретрансміти або насичення connection pool.
Виправлення: Вимірюйте насичення напряму (iostat await/%util, DB wait events, ретрансміти). Зменшіть конкуренцію й retries; ізолюйте гарячі компоненти.
2) Масштабування аплікації робить усе гірше
Симптоми: Більше подів/інстансів підвищує кількість помилок і латентність.
Корінь: Спільна залежність насичена (БД, кеш, диск). Більше клієнтів створює більше конкуренції і черг.
Виправлення: Масштабуйте вузьке місце, а не клієнтів. Додайте admission control і backpressure. Обмежте конкурентність на кордоні залежності.
3) «Та це NVMe, не може бути диском»
Симптоми: iowait сплески, fsync‑латентність бази, але пристрій «швидкий».
Корінь: NVMe теж може насититися; також термальне тротлінг, поведінка прошивки або write amplification від checkpoint/компактації.
Виправлення: Перевірте iostat await/%util, nvme smart‑log і шаблони навантаження (checkpoint/компактація). За потреби відокремте WAL/лог від даних.
4) Kubernetes робить stateful‑навантаження «таємно» нестабільними
Симптоми: Лише деякі поди повільні; реседжулінг змінює поведінку; ноди різняться.
Корінь: Нерівномірне розміщення, спільні ресурси ноди, відмінності шляху до сховища або варіації PV‑бекенду.
Виправлення: Topology spread, anti‑affinity, виділені пулі нод і явні storage class, протестовані під fsync‑навантаженням.
5) Інвалідація кешу спричиняє відмови
Симптоми: Після деплою або flush кешу навантаження на БД зростає; таймаути; повільне відновлення.
Корінь: Stampede: багато викликів одночасно промахуються по кешу й штурмують оригінал.
Виправлення: Request coalescing, stale‑while‑revalidate, jittered TTL і rate limiting до origin. Ніколи не робіть «flush all» під час піку.
6) Бекапи «працюють», поки не знадобляться
Симптоми: Завдання бекапу успішні; відновлення провалюється або неповне; RTO — фантазія.
Корінь: Неперевірені відновлення, відсутня аплікаційна верифікація або бекапи, що фіксують неконсистентний стан.
Виправлення: Заплановані drills відновлення з перевірками; документуйте шлях відновлення як деплой.
7) «Ми збільшили таймаути і стало стабільно» (тимчасово)
Симптоми: Таймаути зменшились, але загальна латентність і використання ресурсів зростають, і наступний сплеск гірший.
Корінь: Таймаути виконували роль запобіжного клапана. Їх збільшили — це дозволило чергам рости, підвищивши хвостову латентність і використання пам’яті.
Виправлення: Тримайте дедлайни реалістичними. Зменшуйте конкурентність, впроваджуйте backpressure і пріоритезацію. Таймаути — не інструмент налаштування продуктивності.
Чеклісти / покроковий план: будувати системи, які не повторюють історію
Покроково: перед тим як приймати наступну блискучу платформу
- Запишіть інваріанти, які ви припускаєте. Наприклад: «латентність сховища стабільна при навантаженні X». Потім протестуйте саме це твердження.
- Визначайте SLO у перцентилях. Якщо ви визначаєте лише середні, ви інженерите під неправильну реальність.
- Знаходьте чергу на кожному шарі. Пул потоків аплікації, клієнтські пули, партиції брокера, ядрові черги, черги сховища.
- Бюджетуйте retries. На кожен ендпоінт і залежність. Зробіть механічно складним створення retry‑штормів.
- Доведете відновлення, а не лише бекап. Drills відновлення з верифікацією, за розкладом, з відповідальністю команди.
- Плануйте ємність для хвостів. Майте запас, щоб періоди стрибків не штовхали завантаження у «латентний обрив».
- Розділяйте навантаження за доменом відмов. Noisy neighbor — не теоретична проблема; це рахунок, який ви заплатите пізніше з процентами.
- Віддавайте перевагу передбачуваній продуктивності над піковою. Стабільна латентність рятує від інцидентів частіше, ніж «до 1M IOPS».
Операційний чекліст: при розгортанні «покращень продуктивності»
- Чи можна швидко відкотити без міграції даних?
- Чи тестували ви з продукційоподібною конкурентністю та обсягом даних?
- Чи вимірювали ви p95/p99 і рівні помилок, а не лише пропускну здатність?
- Чи тестували ви відмову: залежність у повільному режимі, а не лише повністю down?
- Чи узгоджені таймаути й retries між сервісами?
- Чи перевіряли ви поведінку кешу під інвалідацією та холодним стартом?
- Чи підтвердили ви продуктивність storage class під fsync‑інтенсивним навантаженням?
Архітектурні рішення, які старіють краще (і чому)
- Admission control: запобігає колапсу при перевантаженні. Якщо залежність витримує N, примусово дотримуйтеся N.
- Ізоляція стану: виділені ноди/диски для баз і черг. Спільна доля — реальна.
- Явні бюджети: бюджети retry, error, capacity. Вони перетворюють «надію» на числа.
- Рунбуки, що вказують чергу: «Перевірити iostat await» краще, ніж «розбиратися з продуктивністю».
- Лоад‑тести, що включають фонову роботу: компактування, checkpointing, vacuum, бекапи. Те, що реально відбувається.
Поширені питання
1) Чому ті самі відмови повторюються, навіть з кращими інструментами?
Бо інструменти не змінюють стимули. Команди досі випускають фічі швидше, ніж будують розуміння, а складність усе ще ховає черги. Краща телеметрія навіть може підвищувати впевненість і знижувати усвідомлення.
2) Яка найсуттєвіша пастка надійності у 2026?
Віра, що «керований» означає передбачувану продуктивність і ясні режими відмов. Керовані сервіси можуть бути відмінними, але їхні межі часто м’які, мульти‑тенантні й важко видимі.
3) Чи завжди p99 — правильна метрика?
Ні, але зазвичай вона ближча до болю користувача, ніж середні. Використовуйте p50 для типової поведінки, p95/p99 — для черг, і error rate — для коректності. Якщо у вас жорсткі дедлайни (платежі, пошук, авторизація), хвіст — це ваш продукт.
4) Як визначити, чи це сховище або база?
Перевірте обидва рівні: node‑рівневий iowait/iostat для насичення пристрою і db‑wait events/lock‑и для контенції. Насичення сховища часто показує високий await/%util; DB‑контенція — очікування блокувань і довгі транзакції. Вони можуть підсилювати одне одного.
5) Чому додавання реплік або подів інколи підвищує латентність?
Бо це збільшує контенцію на спільних залежностях і накладні витрати синхронізації. Більше викликачів означає більше retries, більше lock‑ів, більше churn‑у кешу і більше фонової роботи. Масштабуйте вузьке місце і обмежуйте клієнтів.
6) Чи погані retries?
Ні. Погані — необмежені retries. Використовуйте exponential backoff з джитером, обмежуйте спроби і проектуйте retry‑бюджет, щоб повільна залежність не була заблокована в смерть.
7) Який швидкий спосіб помітити приховану чергу?
Шукайте зростання p99 при стабільному p50, зростання iowait, збільшення DB waiters або збільшення ретрансмітів. Потім знайдіть, де накопичується час очікування: пул потоків, connection pool, диск‑черга або lock.
8) Як планувати ємність у світі стрибкоподібних навантажень і autoscaling?
Плануйте для найповільнішої залежності, а не для найпростіших шарів, що масштабуються. Autoscaling допомагає CPU‑bound stateless‑рівням. Воно не масштабує вашу базу, lock‑и або мережевий шар автоматично.
9) Яка найменш оцінена «нудна» практика?
Drills відновлення з верифікацією. Не «маємо снапшоти», а «ми відновлювали, запускали перевірки цілісності і заміряли час». Це перетворює екзистенційний ризик на передбачувану процедуру.
Висновок: кроки, які можна зробити цього тижня
Індустрія в 2026 не страждає від нестачі інновацій. Їй не вистачає скромності щодо старих обмежень. Блискуче пакування реальне — кращі продукти, швидший апарат, розумніша автоматизація — але фізика не підписувала ваш ребрендинг.
Зробіть три речі цього тижня:
- Напишіть рукопис «де черга?» для ваших двох найважливіших шляхів користувача. Включіть точно команди, які ви будете запускати (як наведені вище), і які рішення вони зумовлюють.
- Встановіть одне SLO, що змусить вас бачити хвости (p95/p99) і прив’яжіть його до бюджету залежностей (retries, concurrency або headroom‑у ємності).
- Проведіть drill відновлення, що включає верифікацію аплікації, а не лише відновлення даних. Заміряйте час. Запишіть кроки. Виправте те, що було «племінним знанням».
Якщо ви це зробите, інциденти все одно будуть. Усі з ними стикаються. Але ви припините платити за ті самі двічі — спочатку в часі простою, а потім у здивуванні.