Чому CSI драйвери Kubernetes гальмують під навантаженням
Збій монтування тому виглядає однаково зсередини й зовні: под годинами висить у ContainerCreating, kubelet чекає відповіді від драйвера, а в логах — таймаут і повторні спроби підключення.
Причина зазвичай не в застосунку: Kubernetes знімає том з вузла лише після того, як драйвер підтвердив відключення, і якщо попередня спроба не завершилася, наступна операція стає в чергу.
Ціна такого збою — не одна зависла репліка. Поки CSI драйвери Kubernetes вишиковують чергу операцій, планувальник не може розмістити поди, автоматичне масштабування не допомагає, а оновлення версії відкочується назад. Розбір інциденту починається з питання «чому том не віддався», а не «чому впав сервіс».
Далі підключаються таймаути сховища в кластері: зі зростанням кількості томів операції впираються в ліміти бекенду, і кожна наступна чекає звільнення слота.
Відмова вузла сховища перетворює це на лавину — томи не переїжджають на інший вузол, спроба підключити їх до двох вузлів одночасно блокує запуск, а відновлення перетворюється на години ручних перевірок. Розбираємо, як це закривається.
Що дає кероване сховище: ефект у строках і відмовах
Поки том під базу чи чергу заводиться вручну, новий сервіс чекає: узгодити блоковий пристрій, підключити його до вузла, прописати точку монтування в маніфесті, повторити те саме в тестовому контурі.
З драйвером том створюється із заявки на зберігання — час виділення тому падає до секунд, і той самий маніфест розгортається на будь-якому вузлі без окремих операцій і простою.
Продуктивність сховища в Kubernetes перестає бути лотереєю, коли класи описані явно: під транзакційне навантаження — блоковий клас із синхронною реплікацією, під логи й збірки — мережевий том, під спільні файли — розділювана файлова система.
Наші інженери розгортають сховище на Ceph з реплікацією і розкладають заявки за класами так, щоб важкий обхід каталогів не конкурував із записом у журнал транзакцій.
Відмовостійкість сховища перевіряється не на словах, а на перезапуску вузла: том відв'язується, под піднімається на іншому вузлі, незавершені записи розбираються за політикою.
Час відновлення сервісу задається заздалегідь — числом реплік, порядком витіснення подів і лімітами на одночасний переїзд, а не швидкістю реакції чергового вночі.
Ефект у термінах експлуатації: підготовка середовища під новий сервіс — хвилини замість годин, частка відмов під час планового обслуговування вузлів знижується до поодиноких випадків, відновлення після збою вузла передбачуване й укладається у вікно, яке команда називає сама.
Варіанти підключення сховища: порівняння підходів
Вибір починається не з моделі СХД, а з того, як застосунок звертається до даних. Блокове сховище віддає том як окремий диск — передбачувана затримка й висока швидкість запису, але том підключається до однієї ноди. Мережеве файлове сховище знімає це обмеження ціною мережевих затримок і блокувань на рівні файлів.
| Варіант | Коли підходить | Обмеження |
|---|---|---|
| Блокове (том СХД, локальний диск) | Бази даних, черги, сервіси з інтенсивним записом | Режим доступу ReadWriteOnce — том на одній ноді, переїзд пода потребує від'єднання й повторного підключення тому |
| Мережеве файлове (NFS, SMB) | Спільні каталоги, медіа, дані, які пишуть і читають кілька подів одразу | Затримки мережі, слабкі гарантії блокувань, під навантаженням канал стає вузьким місцем |
| Розподілене (Ceph) | Потрібні і блокові, і файлові томи з одного пулу, зовнішнього СХД немає | Потребує дисків на нодах і окремого обслуговування, чутливе до відмови вузлів |
| Хмарний диск (EBS, GCE PD) | Кластер повністю живе в одному хмарному середовищі | Прив'язка до зони доступності, ліміт томів на ноду, режим доступу зазвичай ReadWriteOnce |
Режим доступу до тому — не підказка, а контракт: драйвер перевіряє його під час підключення сховища до кластера, і якщо застосунок просить спільний доступ, а драйвер уміє лише одиночний, под залишиться в очікуванні й не запуститься.
Тому до вибору дивляться на кількість реплік, наявність спільного стану й вимоги до переїзду під час відмови ноди: від цього залежить, потрібен ReadWriteMany чи достатньо ReadWriteOncePod.
Порядок робіт: від аудиту кластера до передачі
Порядок робіт тут не бюрократія, а спосіб не втратити дані. Впровадження драйвера сховища в живий кластер впирається в те, що застосунки вже використовують інші класи зберігання, а частина томів прив'язана до вузлів і зон. Нижче — як ми ведемо проєкт, щоб перемикання пройшло без зупинки сервісів.
- Аудит кластера й поточного сховища: інвентар драйверів і класів зберігання, список томів і снапшотів, чутливість сервісів до затримок, стан резервних копій. На виході — карта залежностей і вузькі місця.
- Проєктування схеми: набір класів зберігання під різні профілі навантаження, режим прив'язки томів, розміщення за зонами, шифрування, квоти. Узгоджуємо план перемикання з точкою відкату.
- Впровадження драйвера сховища: контролер і вузлові компоненти, права, секрети доступу. На тестовому стенді перевіряємо створення, розширення й видалення томів.
- Міграція томів хвилями: спочатку сервіси без дисків, потім бази й черги. Копіюємо через снапшоти, старий і новий класи працюють паралельно — перемикання зворотне.
- Перевірка відмовостійкості: валимо вузол, обриваємо зв'язок зі сховищем, заміряємо, за скільки том переприкріплюється до іншого вузла і що відбувається при недоступності зони.
- Спостережуваність і регламенти: метрики й алерти щодо помилок драйвера, квот і затримок введення-виведення, інструкції для чергової зміни.
- Передача: документація щодо схеми, конфігурації, процедур міграції та відновлення, розбір із вашою командою.
Пакет передачі: конфігурації, схеми, регламенти
Роботу з налаштування сховища має сенс вважати завершеною не тоді, коли поди піднялися, а коли у вашої команди на руках є комплект, за яким черговий інженер без нашої допомоги додасть том, змінить клас зберігання або відновить дані після збою.
Нижче — те, що ми передаємо за підсумками проєкту у вигляді репозиторію з версіонуванням і вичитаних документів.
- Документація щодо сховища — опис вибраних драйверів, підтримуваних режимів доступу й типів томів, із зазначенням, які навантаження до якого класу зберігання прив'язані й чому.
- Схема розміщення томів — карта: вузол, зона доступності, клас зберігання, прив'язка навантаження; окремо зазначено, що можна переносити без простою, а що потребує зупинки.
- Політики доступу до сховища — ролі та права для сервісних облікових записів, правила монтування, обмеження на читання-запис за просторами імен.
- Регламент резервного копіювання — періодичність знімків, глибина зберігання, порядок перевірки відновлення й відповідальний за звірку.
- Маніфести й параметри конфігурації — робочі файли класів зберігання, заявок на томи й знімків у вашому репозиторії, а не в локальній папці інженера.
- Інструкція з типових операцій — підключення нового вузла, додавання класу зберігання, розширення тому, виведення вузла на обслуговування.
- Карта моніторингу й алертів — які метрики сховища збираються, за яких порогів спрацьовує повідомлення і що черговий робить далі.
- Процедура відновлення — покроковий сценарій із перевіркою на тестовому контурі, включно з відкатом до попереднього стану тому.
Такі документи старіють разом з інфраструктурою, тому в репозиторії залишаються правила їх оновлення — правка конфігурації й правка опису йдуть однією зміною.
Кейс: перенесення сховища без зупинки сервісу
Замовник — продуктова команда із самокерованим кластером: кілька десятків сервісів, стан у томах через CSI-драйвер, старий NFS-масив в основі.
Масив упирався в стелю за операціями запису: у пікові години відгук на запис зростав до секунд, нічне резервне копіювання переставало вкладатися у вікно, вичерпання місця розбирали як інцидент.
Складність була не в новому сховищі, а в уже створених томах: перестворити їх з нуля означало простій.
Поруч підняли другий клас зберігання на Ceph, увімкнули снапшоти томів і переводили сервіси групами — узгоджений снапшот, відновлення тому в новому класі, запуск подів, звірка контрольних сум, і лише потім відключення старого.
| Що вимірювали | До | Після |
|---|---|---|
| Відгук на запис у пік | зростав до секунд, черга на масиві | рівний, без сплесків |
| Простій під час перенесення томів | потрібно було б зупиняти сервіс на години | нуль, перенесення під навантаженням |
| Вікно нічного резервного копіювання | не вкладалося, частина копій переїжджала в день | вкладається із запасом |
| Інциденти через вичерпання місця | повторювалися регулярно | не повторювалися |
Відкат на кожному кроці залишався доступним: поки сервіс не підтвердив роботу, старий том не видалявся, і повернення зводилося до запуску подів на попередньому класі зберігання. Через кілька тижнів спостереження масив вивели з експлуатації — без жодного вікна простою.
Що робити, якщо в кластері Kubernetes вже розгорнуто сховище
Якщо кластер уже працює і сховище розгорнуто, міняти все «в лоб» не можна: перевстановлення драйвера рве прив'язки томів, і застосунки отримують недоступні диски.
Робочий сценарій інший — попередній CSI-драйвер продовжує обслуговувати наявні томи, поки навантаження з них не знято, а новий підключається поруч і видає нові.
Починаємо з інвентаризації: які StorageClass використовуються, скільки томів закріплено за кожним навантаженням, де потрібен спільний доступ до тому, а де достатньо одиночного.
Окремо перевіряємо снапшоти й клонування в цільового сховища — якщо їх немає, частина контурів усвідомлено залишається на попередньому драйвері, і це нормальний підсумок.
Перенесення даних без втрат іде через копію, а не перемикання «на живу»: знімаємо снапшот тому, з нього піднімаємо новий том у цільовому класі, застосунок переводимо на нього.
Для баз із реплікацією порядок зворотний — томи переносяться за репліками, запис на новий вмикається останнім, коли дані зійшлися; звірка контрольних сум до видалення старого тому обов'язкова.
Далі поетапне перемикання сховища: за просторами імен або окремими застосунками, від некритичних до критичних. Попередній клас залишається доступним, але перестає бути класом за замовчуванням — нові заявки йдуть у цільове сховище. Відкат дешевий: повертаємо попередній клас за замовчуванням, томи й драйвер на місці.
Зупиняємося там, де перемикання закриває конкретний клас відмов. Якщо сховище тримає навантаження, а привід лише «є драйвер сучасніший», переробка додасть ризик без виграшу.
Технічні сумніви: відмовостійкість, копії, сумісність
Перед стартом інженер перевіряє не те, чи підніметься том, а як сховище поводитиметься у відмові. Тому до першого встановлення CSI-драйвера ми розбираємо три сюжети: втрата зони доступності, цілісність даних після збою й сумісність із тим, що вже працює в кластері. Нижче — відповіді, які зазвичай і визначають, стартуємо ми чи ні.
Загальний принцип: драйвер не створює відмовостійкість сам — він передає кластеру те, що вміє сховище, яке лежить нижче. Репліки, снапшоти й зони налаштовуються там, а в кластері відображаються через клас зберігання й режими доступу до тому.
Що буде з томами, якщо впаде зона?
Зональні диски — EBS, GCE PD — прив'язані до однієї зони: под із таким томом не переїде до сусідньої, поки зона не повернеться. Репліковане сховище (Ceph) і мережеві експорти (NFS) віддають дані з інших зон. Тому критичні сервіси ми розводимо за зонами, а стан тримаємо там, де том доступний із кількох зон.
Як переконатися, що дані не побилися після збою?
Блокові томи перевіряємо файловою перевіркою, Ceph сам звіряє репліки фоновою перевіркою, снапшоти дають точку відновлення. Відновлення вважаємо робочим лише після прогону на стенді: розгортаємо стан зі снапшота, піднімаємо застосунок, звіряємо контрольні суми. Інакше перевірка залишається на папері.
Чи сумісно це з поточним кластером?
Драйвер ставиться поруч із наявним, старі томи продовжують читатися — перемикання йде через csi-migration. Перевіряємо версію API, доступ до вузлових служб і права на монтування хостових шляхів: у керованих кластерах частина привілеїв закрита, і це змінює схему встановлення.
Чи можна відкотитися на попереднє сховище?
Так, якщо політика повернення тому стоїть Retain, а не Delete: томи переживають видалення об'єктів кластера.
Новий драйвер працює паралельно, клас зберігання за замовчуванням змінюється без поспіху, а відкат — це повернення попереднього класу, старі томи залишаються на місці й читаються.
Обговоримо задачу: підберемо режим сховища під навантаження
Щоб повернутися з оцінкою обсягу робіт, а не із загальними формулюваннями, нам потрібні вихідні дані щодо кластера й навантаження. Чим конкретніші вхідні дані, тим точніший план впровадження: етапи, порядок виведення томів, точки перевірки й варіант відкату.
- Схема кластера: скільки вузлів, де розташовані керуючі компоненти, скільки зон доступності задіяно.
- Профіль навантаження: бази даних, черги повідомлень, файлові шари, статичні артефакти — що і з якою інтенсивністю пише на диск.
- Вимоги до доступності: чи допустимий короткочасний розрив введення-виведення під час перемикання тому на інший вузол, чи потрібна синхронна реплікація між зонами.
- Що вже використовується: Ceph, NFS, блокові диски хмари, локальні накопичувачі — і що саме в поточному варіанті не влаштовує.
- Обмеження: регламенти щодо доступів, вимоги до шифрування томів, вікна обслуговування, заборони на зовнішні сховища.
- Симптоми: зростання затримок на записі, завислі томи під час перемикання, нестача місця під образи й резервні копії.
- Хто на вашій стороні видає доступи й узгоджує зміни в промисловому контурі.
За цими даними ми оцінимо обсяг робіт, підберемо режим сховища під ваше навантаження й повернемося з планом впровадження — з етапами, відповідальними й критеріями, за якими ви приймете результат. Опишіть задачу й додайте те, що вже є: схеми, вивантаження метрик, журнали помилок. Решту уточнимо самі.







