7 типових помилок Kubernetes (і як я навчився їх уникати)

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

1. Оминання запитів на ресурси та обмежень

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

Контекст: У Kubernetes запити та обмеження ресурсів є критично важливими для ефективного управління кластерами. Запити ресурсів гарантують, що планувальник зарезервує відповідну кількість CPU та памʼяті для кожного пода, гарантуючи, що він має необхідні ресурси для роботи. Обмеження ресурсів обмежують кількість CPU та памʼяті, яку може використовувати под, запобігаючи тому, щоб жоден окремий под не споживав надмірні ресурси та потенційно не позбавляв інші поди ресурсів. Коли запити та обмеження ресурсів не встановлені:

  1. Нестача ресурсів: Поди можуть отримувати недостатньо ресурсів, що призводить до зниження продуктивності або збоїв. Це відбувається тому, що Kubernetes планує поди на основі цих запитів. Без них планувальник може розмістити занадто багато подів на одному вузлі, що призводить до конкуренції за ресурси та вузьких місць у продуктивності.
  2. Привласнення ресурсів: З іншого боку, без обмежень под може споживати більше, ніж йому належить, впливаючи на продуктивність і стабільність інших подів на тому ж вузлі. Це може призвести до таких проблем, як виселення або знищення інших подів за допомогою Out-Of-Memory (OOM) killer через брак доступної памʼяті.

Як уникнути цього:

  • Почніть з помірних requests (наприклад, 100m CPU, 128Mi памʼяті) і подивіться, як ваш застосунок поводиться.
  • Моніторте реальне використання та уточнюйте свої значення; HorizontalPodAutoscaler може допомогти автоматизувати масштабування на основі метрик.
  • Слідкуйте за kubectl top pods або вашим інструментом логування/моніторингу, щоб підтвердити, що ви не перевищуєте або недопостачаєте ресурси.

Перевірка життям: На початку я ніколи не думав про обмеження памʼяті. Здавалося, що все гаразд на моєму локальному кластері. Потім, у більшому середовищі, Pods отримали OOMKilled зліва і справа. Урок засвоєно. Для отримання детальних інструкцій щодо налаштування запитів і обмежень ресурсів для ваших контейнерів, будь ласка, зверніться до Призначення ресурсів памʼяті для контейнерів і подів (частина офіційної документації Kubernetes).

2. Недооцінка перевірок життєздатності та готовності

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

Контекст: Перевірки життєздатності, готовності та запуску — це механізми, які Kubernetes використовує для моніторингу стану контейнерів та їх доступності.

  • Liveness probes визначають, чи все ще працює застосунок. Якщо перевірка життєздатності не проходить, контейнер перезапускається.
  • Readiness probes контролюють, чи готовий контейнер обслуговувати трафік. Поки перевірка готовності не пройде, контейнер видаляється з точок доступу Service.
  • Startup probes допомагають відрізнити тривалі часи запуску від фактичних збоїв.

Як уникнути цього:

  • Додайте просту HTTP livenessProbe, щоб перевірити точку доступу справності (наприклад, /healthz), щоб Kubernetes міг перезапустити контейнер, якщо він перестане відповідати.
  • Використовуйте readinessProbe, щоб забезпечити, те що трафік не досягає вашого застосунку, поки він не буде готовий.
  • Зберігайте перевірки простими. Надто складні перевірки можуть створити хибні сповіщення та непотрібні перезапуски.

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

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

3. «Ми просто переглянемо журнали контейнерів» (відомі останні слова)

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

Як уникнути цього:

  • Централізуйте журнали за допомогою інструментів CNCF, таких як Fluentd або Fluent Bit, щоб агрегувати вихідні дані з усіх Podʼів.
  • Використовуйте OpenTelemetry для унфікованого перегляду журналів, метрик і (за потреби) трейсів. Це дозволяє виявляти кореляції між подіями інфраструктури та поведінкою на рівні застосунків.
  • Поєднуйте журнали з метриками Prometheus, щоб відстежувати дані на рівні кластера разом із журналами застосунків. Якщо вам потрібне розподілене трасування, розгляньте проекти CNCF, такі як Jaeger.

Перевірка життям: Коли я вперше втратив журнали Pod через швидкий перезапуск, я зрозумів, наскільки ненадійним може бути «kubectl logs» сам по собі. З того часу я налаштував належний конвеєр для кожного кластера, щоб уникнути втрати важливих підказок.

4. Однакове ставлення до оточень розробки та промислової експлуатації

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

Як уникнути цього:

  • Використовуйте оверлеї або kustomize, щоб підтримувати спільну базу, налаштовуючи запити ресурсів, репліки або конфігурацію для кожного середовища.
  • Витягніть специфічну для середовища конфігурацію в ConfigMaps і / або Secrets. Ви можете використовувати спеціалізований інструмент, такий як Sealed Secrets, для управління конфіденційними даними.
  • Плануйте масштабування в промисловому середовищі. Ваш кластер розробки, ймовірно, може обійтися мінімальними ресурсами CPU/памʼяті, але промислове середовище може потребувати значно більше.

Перевірка життям: Одного разу я збільшив replicaCount з 2 до 10 у невеликому середовищі розробки, просто щоб «перевірити». Я швидко вичерпав ресурси і півдня витратив на подолання наслідків. Ой.

5. Коли старі речі залишаються на місці

Пастка: У кластері залишаються невикористані або застарілі ресурси, такі як Deployments, Services, ConfigMaps або PersistentVolumeClaims. Це часто відбувається тому, що Kubernetes не видаляє ресурси автоматично, якщо не вказано явно, і немає вбудованого механізму для відстеження приналежності або терміну придатності. З часом ці забуті обʼєкти можуть накопичуватися, споживаючи ресурси кластера, збільшуючи витрати на хостинг у хмарі та створюючи операційну плутанину, особливо коли застарілі Services або LoadBalancers продовжують маршрутизувати трафік.

Як уникнути цього:

  • Позначте все мітками з метою або власником. Таким чином, ви зможете легко знайти ресурси, які вам більше не потрібні.
  • Регулярно перевіряйте свій кластер: запустіть kubectl get all -n <namespace>, щоб побачити, що насправді працює, і підтвердити, що все це так має бути.
  • Використовуйте збір сміття в Kubernetes: документація K8s показує, як автоматично видаляти залежні обʼєкти.
  • Використовуйте автоматизацію політики: Інструменти, такі як Kyverno, можуть автоматично видаляти або блокувати застарілі ресурси після певного періоду, або впроваджувати політики життєвого циклу, щоб вам не доводилося памʼятати про кожен окремий крок очищення.

Перевірка життям: Після хакатону я забув знести “test-svc”, привʼязаний до зовнішнього балансувальника навантаження. Три тижні потому я зрозумів, що платив за цей балансувальник навантаження весь цей час. Facepalm.

6. Занадто глибоке занурення в мережу занадто рано

Пастка: Впровадження розширених мережевих рішень, таких як сервісні мережі, власні втулки CNI або міжкластерна комунікація, до повного розуміння рідних мережевих примітивів Kubernetes. Це часто трапляється, коли команди реалізують такі функції, як маршрутизація трафіку, спостережуваність або mTLS, використовуючи зовнішні інструменти, не освоївши спочатку, як працює основна мережа Kubernetes: включаючи Pod-to-Pod комунікацію, ClusterIP сервіси, DNS-резолюцію та базову обробку вхідного трафіку. В результаті проблеми, повʼязані з мережею, стають важчими для усунення, особливо коли оверлеї вводять додаткові абстракції та точки відмови.

Як уникнути цього:

  • Почніть з малого: Deployment, Service та базовий контролер вхідного трафіку, наприклад, на основі NGINX (наприклад, Ingress-NGINX).
  • Переконайтеся, що ви розумієте, як трафік проходить у кластері, як працює виявлення сервісів і як налаштована DNS.
  • Переходьте до повноцінної мережі або розширених функцій CNI лише тоді, коли це дійсно необхідно, оскільки складна мережа додає накладні витрати.

Перевірка життям: Я спробував Istio на невеликому внутрішньому застосунку, а потім витратив більше часу на налагодження самого Istio, ніж на сам застосунок. Врешті-решт, я відступив, видалив Istio, і все запрацювало нормально.

7. Занадто легковажне ставлення до безпеки та RBAC

Пастка: Розгортання робочих навантажень з ненадійними конфігураціями, такими як запуск контейнерів від імені користувача root, використання теґу обрахів latest, відключення контекстів безпеки або призначення надто широких ролей RBAC, таких як cluster-admin. Ці практики зберігаються, оскільки Kubernetes не забезпечує суворі стандартні налаштування безпеки, а платформа розроблена для гнучкості, а не для жорстких обмежень. Без явних політик безпеки кластери можуть залишатися вразливими до ризиків, таких як втеча контейнерів, несанкціоноване підвищення привілеїв або випадкові зміни в промисловому середовищі через незафіксовані образи.

Як уникнути цього:

  • Використовуйте RBAC для визначення ролей і дозволів у Kubernetes. Хоча RBAC є стандартним і найширше підтримуваним механізмом авторизації, Kubernetes також дозволяє використовувати альтернативні авторизатори. Для більш складних або зовнішніх потреб у політиці розгляньте рішення, такі як OPA Gatekeeper (на основі Rego), Kyverno або користувацькі вебхуки з використанням мов політики, таких як CEL або Cedar.
  • Привʼяжіть образи до конкретних версій (більше ніякого :latest!). Це допоможе вам знати, що насправді розгорнуто.
  • Розгляньте Pod Security Admission (або інші рішення, такі як Kyverno), щоб забезпечити використання контейнерів без прав root, файлових систем лише для читання тощо.

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

І на останок

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

Щасливої подорожі!