Рекомендації щодо конфігурації Kubernetes

Конфігурація — це одна з тих речей у Kubernetes, яка здається незначною, доки не стає важливою. Конфігурація лежить в основі кожного робочого навантаження Kubernetes. Відсутня лапка, неправильна версія API або неправильно розміщений відступ YAML можуть зіпсувати все розгортання.

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

Цей блог створено на основі оригінальної сторінки "Кращі практики конфігурації", яка розвивалася завдяки участі багатьох членів спільноти Kubernetes.

Загальні практики конфігурації

Використовуйте останню стабільну версію API

Kubernetes швидко розвивається. Старі API з часом стають застарілими і перестають працювати. Тому, коли ви визначаєте ресурси, переконайтеся, що ви використовуєте останню стабільну версію API. Ви завжди можете перевірити це за допомогою

kubectl api-resources

Цей простий крок вбереже вас від майбутніх проблем із сумісністю.

Зберігайте конфігурацію в системі контролю версій

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

Використовуйте YAML, а не JSON для створення конфігурацій

Використовуйте YAML, а не JSON для створення файлів конфігурації. Технічно обидва формати працюють, але YAML простіший для сприйняття. Він чіткіший, менш захаращений і широко використовується в спільноті.

YAML має деякі підступні пастки з булевими значеннями: використовуйте тільки true або false. Не пишіть yes, no, on або off. Вони можуть працювати в одній версії YAML, але не працювати в іншій. Щоб бути впевненим, беріть в лапки все, що виглядає як булеве значення (наприклад, "yes").

Зберігайте конфігурацію простою та мінімальною

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

Якщо ваші Deployment, Service та ConfigMap належать до одного застосунка, розмістіть їх в одному файлі маніфесту. Так легше відстежувати зміни та застосовувати їх як єдине ціле. Приклад цієї синтаксичної конструкції дивіться у файлі Guestbook all-in-one.yaml.

Ви навіть можете застосувати цілі теки за допомогою:

kubectl apply -f configs/

Одна команда — і все, що знаходиться в цій теці, розгортається.

Додайте корисні анотації

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

Найкориснішим коментарем є kubernetes.io/description. Він схожий на звичайний коментар, але копіюється в API, щоб усі могли його бачити навіть після розгортання.

Управління робочими навантаженнями: Pods, Deployments та Jobs

Поширеною помилкою на початку роботи з Kubernetes є безпосереднє створення Podʼів. Podʼи працюють, але вони не переплановують себе, якщо щось йде не так.

Naked Pods (Pods, які не управляються контролером, таким як Deployment або StatefulSet) підходять для тестування, але в реальних умовах їх використання є ризикованим.

Чому? Тому що якщо вузол, на якому розміщений цей Pod, вийде з ладу, Pod також вийде з ладу, і Kubernetes не відновить його автоматично.

Використовуйте Deployments для застосунків, які повинні завжди працювати

Розгортання (Deployment), яке створює ReplicaSet для забезпечення постійної доступності необхідної кількості Podʼів і визначає стратегію заміни Podʼів (наприклад, RollingUpdate), майже завжди є кращим варіантом, ніж безпосереднє створення Podʼів. Ви можете розгорнути нову версію, а якщо щось не спрацює, миттєво повернути попередню.

Використовуйте Job для завдань, які повинні бути завершені

Job (/docs/concepts/workloads/controllers/job/) ідеально підходить, коли вам потрібно виконати щось один раз, а потім зупинити, наприклад, міграцію бази даних або пакетну обробку завдань. Він повторить спробу, якщо podʼи зазнають збою, і повідомить про успішне виконання, коли все буде готово.

Конфігурація Services та мережа

Services — це спосіб, у який ваші робочі навантаження спілкуються між собою всередині (а іноді й поза межами) вашого кластера. Без них ваші podʼи існують, але не можуть ні з ким звʼязатися. Подбаємо про те, щоб цього не сталося.

Створіть Services перед робочими навантаженнями, які їх використовують

Коли Kubernetes запускає Pod, він автоматично вводить змінні середовища для наявних Services. Отже, якщо Pod залежить від Service, створіть Service перед відповідними робочими навантаженнями бекенду (Deployments або StatefulSets) і перед будь-якими робочими навантаженнями, які потребують доступу до нього.

Наприклад, якщо існує Service з назвою foo, всі контейнери отримають у своєму початковому середовищі такі змінні:

FOO_SERVICE_HOST=<хост, на якому працює Service>
FOO_SERVICE_PORT=<порт, на якому працює Service>

Виявлення на основі DNS не має цієї проблеми, але все одно варто дотримуватися цієї хорошої звички.

Використання DNS для виявлення Service

Якщо ваш кластер має надбудову DNS (як і більшість), кожен Service автоматично отримує запис DNS. Це означає, що ви можете отримати до нього доступ за назвою, а не за IP-адресою:

curl http://my-service.default.svc.cluster.local

Це одна з тих функцій, які роблять мережу Kubernetes такою чарівною.

Уникайте використання hostPort та hostNetwork, якщо це не є абсолютно необхідним

Іноді ви можете побачити такі опції в маніфестах:

hostPort: 8080
hostNetwork: true

Але ось у чому справа: Вони привʼязують ваші Podʼи до конкретних вузлів, що ускладнює їх планування та масштабування. Оскільки кожна комбінація <hostIP, hostPort, protocol> повинна бути унікальною. Якщо ви не вкажете hostIP та protocol явно, Kubernetes буде використовувати 0.0.0.0 як типовий hostIP та TCP як типовий protocol. Якщо ви не займаєтеся відлагодженням або створенням чогось на зразок мережевого втулка, уникайте їх.

Якщо вам потрібен лише локальний доступ для тестування, спробуйте kubectl port-forward:

kubectl port-forward deployment/web 8080:80

Докладнішу інформацію див. у розділі Використання переадресації портів для доступу до застосунків у кластері. Або, якщо вам дійсно потрібен зовнішній доступ, використовуйте type: NodePort Service. Це безпечніший, природний для Kubernetes спосіб.

Використовуйте headless Services для внутрішнього виявлення

Іноді ви не хочете, щоб Kubernetes балансував трафік. Ви хочете спілкуватися безпосередньо з кожним Podʼом. Саме тут на допомогу приходять headless Services.

Ви створюєте їх, встановивши clusterIP: None. Замість однієї IP-адреси DNS надає вам список усіх IP-адрес Podʼа, що ідеально підходить для застосунків, які самостійно керують зʼєднаннями.

Ефективна робота з мітками

Мітки — це пари ключ/значення, які прикріплюються до обʼєктів, таких як Podʼи. Мітки допомагають організовувати, шукати та групувати ресурси. Самі по собі вони нічого не роблять, але завдяки їм все інше, від Services до Deployments, працює злагоджено.

Використовуйте семантичні мітки

Хороші мітки допомагають зрозуміти, що до чого, навіть через кілька місяців. Визначте та використовуйте мітки, які ідентифікують семантичні атрибути вашого застосунку або розгортання. Наприклад:

labels:
  app.kubernetes.io/name: myapp
  app.kubernetes.io/component: web
  tier: frontend
  phase: test
  • app.kubernetes.io/name : що це за застосунок
  • tier : до якого шару він належить (frontend/backend)
  • phase : на якому етапі він знаходиться (test/prod)

Потім ви можете використовувати ці мітки для створення потужних селекторів. Наприклад:

kubectl get pods -l tier=frontend

Це відобразить список усіх фронтенд-подів у вашому кластері, незалежно від того, з якого розгортання вони походять. По суті, ви не вказуєте імена подів вручну, а лише описуєте, що вам потрібно. Приклади такого підходу дивіться в застосунку guestbook.

Використовуйте загальні мітки Kubernetes

Kubernetes фактично рекомендує набір загальних міток. Це стандартизований спосіб називати обʼєкти у різних робочих навантаженнях або проєктах. Дотримання цієї домовленості робить ваші маніфести чіткішими, а це означає, що такі інструменти, як Headlamp, dashboard або сторонні системи моніторингу, можуть автоматично розуміти, що саме працює.

Маніпулювання мітками для відлагодження

Оскільки контролери (такі як ReplicaSets або Deployments) використовують мітки для управління Podʼами, ви можете видалити мітку, щоб тимчасово «відʼєднати» Pod.

Приклад:

kubectl label pod mypod app-

Частина app- видаляє ключ мітки app. Після цього контролер більше не буде керувати цим Podʼом. Це схоже на ізоляцію для перевірки, «режим карантину» для налагодження. Щоб інтерактивно видаляти або додавати мітки, використовуйте kubectl label.

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

Корисні поради щодо kubectl

Ці невеликі поради значно полегшують роботу з декількома файлами маніфесту або кластерами.

Застосування цілих текстових файлів

Замість того, щоб застосовувати файл за файлом, застосуйте цілу теку:

# Використання серверного застосування також є гарною практикою.
kubectl apply -f configs/ --server-side

Ця команда шукає файли .yaml, .yml та .json у цій теці та застосовує їх усі разом. Це швидше, чистіше та допомагає групувати елементи за застосунками.

Використовуйте селектори міток для отримання або видалення ресурсів

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

kubectl get pods -l app=myapp
kubectl delete pod -l phase=test

Це особливо корисно в конвеєрах CI/CD, де потрібно динамічно очищати тестові ресурси.

Швидке створення Deployments і Services

Для швидких експериментів не завжди потрібно писати маніфест. Ви можете запустити Deployment прямо з CLI:

kubectl create deployment webapp --image=nginx

Потім експонуйте його як Service:

kubectl expose deployment webapp --port=80

Це чудово підходить, коли ви просто хочете щось протестувати перед написанням повних маніфестів. Також дивіться приклад у статті Використання Service для доступу до застосунку в кластері.

Підсумок

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

А що найкраще? Чисті конфігурації залишаються читабельними. Навіть через кілька місяців ви або будь-хто з вашої команди зможете поглянути на них і точно зрозуміти, що відбувається.