Kubernetes
Kubernetes — це цикл керування з API перед ним. Ви не наказуєте йому запустити контейнер: ви записуєте бажаний стан, а контролери постійно звіряють цей запис із тим, що працює насправді, і діють на різницю — завжди, а не один раз. Кожен обʼєкт, який він пропонує, і кожна його несподівана поведінка походять звідси. На цій сторінці — сам цикл, кілька обʼєктів, що справді важать, чому ліміти ресурсів і перевірки здоровʼя спричиняють більшість інцидентів у проді й коли все це вам справді потрібне.
- Ви оголошуєте
- Стан, а не команду
- Контролери
- Зводять постійно
- Більшість інцидентів
- Ліміти й проби
Цикл керування, а не виконавець команд
Ментальна модель, від якої все решта стає на місце, — це термостат. Ви не наказуєте термостату ввімкнути опалення: ви кажете йому потрібну температуру, а він міряє й діє, доки кімната не збіжиться, — і далі міряє. Kubernetes працює так само. Ви подаєте обʼєкт, що описує, як має бути, сервер API його зберігає, а контролер крутиться завжди: прочитати бажаний стан, прочитати дійсний стан, подіяти на різницю.
Саме тому видалення Pod руками не дає нічого тривкого: Deployment досі каже «три репліки», тож контролер помічає дві й робить третю. Саме тому застосувати той самий маніфест двічі нешкідливо: ви повторили факт, а не видали другу вказівку. І саме тому цікаве питання під час інциденту — ніколи не «чи виконалася команда», а «у що кластер зараз вірить як у належне і що йому заважає». Відповідь — у статусі обʼєкта та його подіях, і це перше місце, куди варто дивитися, і останнє, куди дивляться.
Обʼєкти, які вам справді потрібні
Поверхня API величезна, а робочий набір малий. Шість обʼєктів покривають більшість того, що потрібно сервісу, і кожен існує тому, що якийсь контролер зводить його з чимось.
Pod
Один чи кілька контейнерів, що ділять мережеву адресу й можуть ділити том. Найменше, що планується, — і те, що ніколи не створюють напряму.
Deployment
Каже, скільки однакових Pod має існувати і з якого образу. Веде поступові оновлення й відкати. Саме це ви й пишете.
Service
Стала назва й адреса перед змінним набором Pod. Pod приходять і зникають з новими адресами; Service — ні.
Ingress
Маршрутизує зовнішній HTTP-трафік до Service за хостом і шляхом і завершує TLS. Одна точка входу замість однієї на сервіс.
ConfigMap і Secret
Конфігурація й облікові дані, подані до Pod як змінні чи файли. Secret закодовано в base64, а не зашифровано, — вмикайте шифрування у спокої.
StatefulSet
Для Pod, яким потрібні стала ідентичність і власне сховище. Потрібен базам — і привід спитати, чи хочете ви їх тут узагалі.
Service вартий ще одного речення, бо саме тут живе плутанина з іменами. Усередині кластера Service дає вам DNS-імʼя, що розвʼязується у сталу віртуальну адресу, а трафік до неї розподіляється між тими Pod, які зараз збігаються з його селектором. Ця непрямість і є причиною, чому Pod можна замінити будь-якої миті, нічого більше не переналаштовуючи, — і вона ж є причиною, чому «Pod працює, але до нього ніхто не достукається» майже завжди означає селектор, що не збігається з мітками Pod.
Звідки беруться інциденти
Два налаштування спричиняють більше проблем у проді, ніж усе решта разом, і обидва виглядають як шаблонний текст. Перше — ресурси. Запит (request) — це те, що планувальник резервує, вирішуючи, на який вузол Pod влазить; ліміт — це стеля, що діє під час роботи. Задайте запити замалими — і вузол перепідписаний, тож Pod приземляються там, де немає куди рости. Задайте зависокими — і платите за потужність, якою ніхто не користується. Не задайте зовсім — і планувальник вгадує, а так один сервіс і починає морити сусідів на тому самому вузлі.
Два ліміти поводяться по-різному, коли в них упираються, і плутанина між ними коштує годин. Перевищення ліміту памʼяті призводить до того, що ядро вбиває процес: Pod показує OOMKilled, перезапускається, і стектрейсу немає, бо жодного винятку не виникало. Перевищення ліміту CPU не вбиває нічого: процес пригальмовують, тож симптом — це затримка, що росте під навантаженням без жодної помилки, і на це витрачають день, звинувачуючи базу. Памʼять убиває, CPU гальмує: це речення економить той день, за який його інакше вивчають.
| Проба | На що відповідає | Що стається, коли падає |
|---|---|---|
| Readiness | Чи може цей Pod прийняти трафік прямо зараз? | Його виводять із Service і лишають працювати. Безпечна — і та, за якою варто тягтися першою. |
| Liveness | Чи цей процес заклинило без надії на відновлення? | Контейнер убивають і перезапускають. Потужна — і звична причина аварії, завданої самому собі. |
| Startup | Чи закінчив стартувати застосунок, що довго вантажиться? | Інші проби відкладають, доки вона не пройде: так повільний старт перестає бути циклом перезапусків. |
Як це виявляється в реальній поставці
Чесне питання — чи потрібен він вам узагалі, і відповідь «так» звучить рідше, ніж підказує галузева розмова. Kubernetes купує вам планування по багатьох машинах, самозцілення, поступові оновлення й один декларативний інтерфейс для команд, кожна з яких тримає кілька сервісів. Платите ви за це постійною експлуатаційною поверхнею: оновлення, мережа, класи сховищ, контроль доступу — і клас збоїв, чия причина не у вашому коді, а в платформі. Три сервіси на двох машинах дістануть більшість переваг від середовища контейнерів і балансувальника за частку вартості, а керована платформа, що ховає панель керування, — середній варіант, який варто розглянути до будь-якої з крайнощів.
Якщо ви все ж його тримаєте, практика, що окупається найшвидше, — тримати маніфести в репозиторії й давати чомусь їх застосовувати, а не давати людям виконувати команди проти кластера. Тоді кластер має історію, придатну до перегляду, відкат стає ревертом, а різниця між тим, що має працювати, і тим, що працює, стає видимою, а не переказаною. Шаблонізація — Helm, Kustomize чи будь-хто з їхніх нащадків — заслуговує на місце тієї миті, коли ті самі маніфести існують для кожного середовища, і перестає заслуговувати тієї миті, коли ніхто не може сказати, що ці шаблони породжують.
Про навантаження зі станом: платформа вміє тримати базу, і питання в тому, чи має. StatefulSet із постійними томами дає вам ідентичність і сховище, що переживають перепланування, — і дає ще й відповідальність за бекапи, перемикання при збої, оновлення версій та власні режими збою шару сховища, і все це поверх планувальника, спроєктованого рухати речі. Команди, що так тримають власні бази, зазвичай мають людину, чия це робота. Командам, які такої не мають, зазвичай краще служать керована база й кластер, що тримає лише роботу без стану.
Де це вироджується
- Узяти його на три сервіси на двох машинах: експлуатаційна ціна є, вигоди немає.
- Проба liveness із залежністю на шляху: повільна база перетворюється на бурю перезапусків у всьому кластері.
- Відсутність запитів ресурсів: планувальник вгадує, і один сервіс морить сусідів.
- Пошук стектрейсу для перезапуску
OOMKilled, якого ніколи не було, бо вбивало ядро. - Зміни через
kubectl editна живому кластері, які наступне застосування тихо викидає. - Секрети, закомічені як маніфести: закодовані base64 й помилково взяті за зашифровані.
- Service, чий селектор не збігається з мітками Pod: здоровий Pod не дістає нічого.
- Власна база в кластері, де ніхто не володіє бекапами, перемиканням при збої й сховищем.
- Шаблони поверх шаблонів, аж поки ніхто не може сказати, що саме застосовується.
Коли це застосовувати
Застосовуйте, коли
- Багато сервісів на багатьох машинах, де планування й самозцілення — це робота, яку інакше робили б руками.
- Кілька команд, яким потрібен один декларативний інтерфейс і один набір гарантій для розгортання.
- Навантаження, чий попит коливається настільки, що масштабування реплік є рутинною подією.
- Організації, що вже на ньому, де керована панель керування знімає більшість експлуатаційних витрат.
Уникайте, коли
- Мала кількість сервісів на малій кількості машин, де вистачає середовища виконання й балансувальника.
- Команди, де нікому володіти платформою: кластер стає найменш зрозумілою річчю у проді.
- Бази зі станом — якщо тільки хтось справді не володіє бекапами, перемиканням і шаром сховища.
- Як спосіб дістати переносимість між хмарами: керовані додатки навколо кластера тихо її забирають.
Було корисно?
Поділіться з тим, хто працює над тією ж задачею.