Налаштування StorageClass Kubernetes: динамічне виділення томів

Томи не створюються вчасно, поди зависають у Pending, а релізи зсуваються. Ми налаштовуємо StorageClass Kubernetes під ключ: динамічне виділення томів, режими доступу, квоти та політики. Скорочуємо час на підготовку інфраструктури та прибираємо ручні операції.
Часті запитання

Поди зависають у Pending: де ламається Kubernetes StorageClass

Розгортання виглядає здоровим: маніфести застосовано, сервіс створено, але поди висять у Pending і не рухаються. У подіях поду — FailedScheduling із посиланням на незадоволений запит на том, у контролера — помилка виділення тому. Застосунок при цьому не падає: він просто не запускається, бо Kubernetes не віддає йому сховище.

Причина майже завжди в конфігурації класу зберігання. Якщо в StorageClass виставлено режим негайного прив'язування, том створюється до того, як планувальник вибрав вузол, — і легко потрапляє в зону, де потрібного диска немає або він несумісний із цим вузлом.

За відкладеного прив'язування том виділяється під конкретний вузол, і зависле розгортання часто означає, що под нікуди поставити, а не що сховище недоступне.

Окрема гілка — розбіжність запиту й класу: PVC посилається на ім'я, якого в кластері немає, на клас без позначки класу за замовчуванням або просить режим доступу, який драйвер не вміє віддавати.

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

Діагностика тут передбачувана: дивимося події PVC і поду, звіряємо ім'я класу, режим прив'язування та політику повернення, перевіряємо, що драйвер зареєстровано і у вибраній зоні є вільна ємність.

Далі завдання не в тому, щоб розбудити один завислий под, а в тому, щоб привести політики зберігання до ладу — розбираємо, як це закривається.

Що дає динамічний провіжинінг томів у кластері

Динамічний провіжинінг томів будується на одній зв'язці: StorageClass описує клас сховища та політику його звільнення, а PersistentVolumeClaim у маніфесті застосунку просто посилається на цей клас.

Далі контролер сховища сам створює том, прив'язує його до запиту й підключає до поду. Ручний крок «замовити диск, дочекатися виділення, вписати ідентифікатор у специфікацію й передеплоїти» зникає з процесу повністю — том з'являється за секунди, а не за години узгоджень.

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

Масштабування навантаження отримує той самий ефект: у разі зростання кількості реплік StatefulSet кожен новий под автоматично створює том із класу й монтує його, не потребуючи ручної роботи на кожну копію.

Клас відмов виду «том не виділено», «запит висить в очікуванні», «диск прив'язано не до тієї зони» зникає з експлуатації, бо їх закриває контролер, а не черговий інженер.

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

Якщо в кластері вже описано StorageClass із політиками збереження даних, нові запити використовують їх як є — сумісність зі старими маніфестами зберігається, змінювати розмітку сховища не потрібно.

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

Усе інше — створення, прив'язування, монтування — відбувається автоматично, а радіус відмови звужується до одного запиту замість ланцюжка ручних кроків.

Порівняння режимів виділення та прив'язування томів

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

Статичний провіжинінг дає повний контроль над тим, куди потраплять дані, динамічний — прибирає ручну роботу на кожен новий сервіс.

На прив'язування томів впливає не лише режим, а й політика переробки тому: після видалення запиту носій або повертається в пул, або зберігається як є, або видаляється разом із томом. Від цього залежить і можливість відкату, і те, як швидко зростає обсяг сховища.

Коли який режим доречний

Варіант Коли підходить Обмеження
Статичне виділення Дані переживають кластер: бази, архіви, томи із зовнішнім життєвим циклом Томи створюються вручну, пул потрібно тримати із запасом, прив'язування за іменем крихке
Динамічне через клас за замовчуванням Однотипне навантаження без вимог до профілю носія Усі запити отримують один профіль; його зміна зачіпає весь кластер, а не одну команду
Іменовані класи під профілі Різні вимоги: швидкі диски під транзакції, ємні — під логи й аналітику Більше об'єктів у супроводі, для кожного класу своя політика переробки

Окремо варто відзначити відкладене прив'язування: том створюється лише тоді, коли под уже розміщено на вузлі. Інакше в кластері з кількома зонами носій може опинитися не в тій зоні, і под зависне в очікуванні, а діагностика такого стану займає години. Розбираємо, як вибрати режим під профіль навантаження і не втратити дані під час відкату.

Як ми налаштовуємо Kubernetes StorageClass: етапи робіт

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

  1. Аудит томів Kubernetes: збираємо PVC і PV за просторами імен, дивимося драйвер, політику звільнення, режим прив'язування, фактичну утилізацію та топологію вузлів. На виході — таблиця навантажень із вимогами до затримки, спільного доступу та інтенсивності введення-виведення.
  2. Проєктування схеми класів: виділяємо 3–5 профілів — швидкі томи для баз даних, ємні для логів, архівні з холодним шаром — і закріплюємо за кожним свій StorageClass із явними параметрами.
  3. Налаштування StorageClass: задаємо політику звільнення, дозвіл на розширення, відкладене прив'язування для томів у кількох зонах і граничні розміри, щоб один PVC не витягнув увесь пул.
  4. Підготовка й переведення навантажень: призначаємо клас за замовчуванням, переносимо наявні томи зміною класу через перестворення або знімки — без тривалої зупинки сервісів.
  5. Перевірка на стенді: проганяємо відмову вузла, вичерпання квоти, розширення тому на живому навантаженні та відкат на попередній клас. Фіксуємо, як поводиться планувальник у кожному сценарії.
  6. Впровадження сховища в продуктив і передача команді: розкочуємо за просторами імен, віддаємо схему класів, регламент запитів на томи та інструкції для чергової зміни.

Політики доступу, квоти та об'єкти в кластері

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

  • Описи кожного StorageClass: призначення, параметри (режим прив'язування тому, політика повернення даних у разі видалення запиту, тип диска) і клас навантаження, під який його заведено — розробник вибирає клас за описом, а не навмання.
  • Політики доступу: розмежування прав за ролями — хто створює й редагує класи, хто лише запитує томи, хто читає статус; окремі ролі для сервісних облікових записів.
  • Квоти просторів імен: ResourceQuota і LimitRange на кожен простір — межа за сумарним обсягом сховища, кількістю запитів і розміром одного тому. У разі вичерпання квоти команда отримує зрозумілу помилку, а не зависле завдання.
  • Правила життєвого циклу томів: які класи зберігають дані після видалення запиту, які звільняють; як забрати том на розбір інциденту.
  • Регламент обслуговування: порядок додавання класу або редагування параметрів, перевірка на стенді, вікно застосування змін, точки відкату.
  • Документація щодо кластера: схема розміщення, перелік класів, маніфести та їхня історія в системі контролю версій, журнал змін.
  • Моніторинг і оповіщення: які метрики за запитами томів і вільним місцем знімаються, за яких порогів надходить повідомлення.
  • Передача команді: розбір з інженерами замовника, прогін типових сценаріїв, контакти для ескалації на час супроводу.

Кейс: прибрали зависання томів на піковому навантаженні

До проєкту томи в кластері видавалися вручну: за запитом інженер створював диск і підкладав його в маніфест, а поди чекали своєї черги. На пікових розпродажах черга зростала, частина подів залишалася в стані Pending до ранку, і розділ каталогу був недоступний.

Планувальник Kubernetes допомогти не міг — без StorageClass йому нічим прив'язати том, тому черговий розбирав такі інциденти вночі, руками.

Що змінили

Описали StorageClass під профілі навантаження: швидкий клас за замовчуванням для баз і черг, холодний — для логів і вивантажень.

Увімкнули динамічний провіжинінг, прив'язування тому до зони поду, allowVolumeExpansion для росту тому без перестворення та reclaimPolicy Retain для критичних даних — том більше не йде разом із запитом.

Зверху поставили квоти на розмір запиту, щоб один под не виїдав пул повністю, і знімки тому перед релізом для швидкого відкату.

Метрики до і після

Показник До Після
Томи в Pending на піку до 18% запитів нуль
Видача тому 4-6 хвилин, на піку — десятки секунди
Ручні операції чергового 10-12 на тиждень 0
Інциденти через сховище 3-4 на місяць 0 за пів року

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

Що робити, якщо том уже створено статично

Поле storageClassName у наявного PVC незмінне — відредагувати його на живому кластері не вийде.

Тому перехід на динамічний провіжинінг роблять не правкою маніфесту, а міграцією: створюється StorageClass із потрібним драйвером і політикою повернення, готується новий PVC, дані переносяться, і лише потім навантаження перемикається на новий том.

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

Якщо знімків немає, піднімається друга репліка, яка наповнює новий том, поки сервіс відповідає на трафік.

Перевикористати старий том як є не вийде: статичний PV прив'язано до конкретного PVC. StatefulSet не підхопить чужий PVC автоматично — правиться volumeClaimTemplates, а поди замінюються по одному з перевіркою, що репліка наздогнала та дані на новому томі консистентні.

Старий том залишається змонтованим для відкату, поки нова схема не відпрацює під навантаженням повний цикл.

На живому кластері не можна змінювати accessModes і прив'язку до класу у PVC, а розмір — лише у бік збільшення і лише якщо розширення увімкнено в StorageClass; частина драйверів робить це на льоту, іншим потрібен перезапуск поду.

Політику повернення ресурсів задають у StorageClass до створення тому: правити її на працюючому PV ризиковано — видалення PVC забере дані, на які ще посилається застосунок.

Технічні сумніви перед стартом робіт

Сумніви зазвичай не про Kubernetes як такий, а про те, як конкретний клас ляже на наявне сховище, томи й права команд. Нижче — питання, які інженерні команди задають перед стартом найчастіше.

Клас спрацюється з нашим сховищем?

StorageClass — це профіль, а роботу з диском виконує драйвер сховища. На розборі дивимося, які режими доступу він підтримує і як поводиться під час зміни вузла, і піднімаємо тестовий клас на ізольованому контурі — до будь-яких правок у продуктивному середовищі.

Що станеться з уже наявними томами?

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

Окремо стежимо за класом за замовчуванням: поки позначка стоїть, усі томи без явної вказівки потрапляють саме до нього.

Чому не можна обійтися одним класом на все?

Обмеження задає драйвер: один том — один вузол, спільний доступ, поведінка під час видалення знятого запиту. Тому класи дроблять за профілями. Універсальний клас або не дає потрібного режиму, або видаляє дані там, де їх потрібно було зберегти.

Які права доступу потрібні командам?

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

Обговоримо завдання: що підготувати до розмови

Щоб обговорити завдання предметно, корисно мати на руках поточну картину зберігання та вимоги до неї. Ми не просимо оформлювати повноцінне технічне завдання — достатньо переліку нижче, і за ним уже збирається оцінка робіт і план впровадження.

  • Поточна схема класів: які StorageClass оголошено в кластері, який позначено як використовуваний за замовчуванням, які політики повернення тому задано і куди дівається фізичний диск після видалення запиту.
  • Профілі навантаження: які сервіси пишуть послідовно (логи, архіви), яким потрібен випадковий запис (бази даних), а яким достатньо мережевого диска — від цього залежить тип провіжинінгу та режим прив'язування тому до вузла.
  • Вимоги до доступу: чи потрібен одночасний запис із кількох вузлів, чи є жорстка прив'язка до зони доступності, якими правами володіють команди та простори імен.
  • Робота зі зростанням і копіями: чи допускається розширення тому на льоту, чи робляться знімки, як влаштовано резервні копії та відновлення з них.
  • Порядок перевірки результату: на якому тестовому контурі звіряємо поведінку, за якими сценаріями — створення тому, переїзд навантаження, звільнення диска після видалення, відмова вузла.
  • Режим експлуатації: вікна робіт, вимоги до відмовостійкості, хто з боку замовника приймає зміни та підписує перехід на нову схему.

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

Наші компетенції:

Останні роботи

  • Розробка сайту компанії B2B ADVANCE
    Розробка сайту компанії B2B ADVANCE
    1542
  • Розробка веб-додатків для компанії FEEDME
    Розробка веб-додатків для компанії FEEDME
    1394
  • Розробка веб-сайту для компанії БЕЛФІНГРУП
    Розробка веб-сайту для компанії БЕЛФІНГРУП
    1081
  • Розробка інтернет магазину для компанії FURNORO
    Розробка інтернет магазину для компанії FURNORO
    1369
  • Розробка логотипу компанії B2B Advance
    Розробка логотипу компанії B2B Advance
    816
  • Розробка веб-додатків для компанії Enviok
    Розробка веб-додатків для компанії Enviok
    1141