Kubernetes: Liveness та Readiness Probes – Best practices

Автор |  13/11/2023
 

Кілька корисних порад по використанню Liveness та Readiness Probes в Kubernetes – різниця між ними, та як правильно налаштовувати ці перевірки.

Якщо зовсім коротко, то:

  • livenessProbe: використовується Kubernetes, щоб знати, коли потрібно виконати restart поду
  • readinessProbe: використовується Kubernetes, щоб знати, коли контейнер готовий приймати трафік, тобто – коли відповідний Kubernetes Service може додавати цей под до своїх роутів
  • startupProbe: використовується Kubernetes, щоб знати, коли контейнер запустився і готовий до виконання перевірок з livenessProbe та readinessProbe
    • livenessProbe та readinessProbe почнуть виконуватись тільки після успішної перевірки startupProbe

Отже, livenessProbe використовується для визначення чи живий процес в поді, тоді як readinessProbe – чи готовий сервіс в поді приймати трафік, а startupProbe – коли починати виконувати livenessProbe та readinessProbe.

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

І в кцінці буде ще кілька посилань.

livenessProbe

livenessProbe потрібна коли, наприклад, процесс застряг в deadlock і не може виконувати свої задачі. Інший приклад – якщо процес увійшов в infinite loop і використовує 100% CPU, при цьому не маючи змоги обробляти запити від клієнтів, бо він все ще підключений до лоад-балансінгу в мережі Kubernetes.

У випадку, коли у вас є readinessProbe, але немає livenessProbe – то такий под буде відключений від трафіку, але залишиться в статусі Running, і буде продовжувати займати ресурси CPU/Memory.

Запити до livenessProbe виконуються процесом kubelet на тій самій WorkerNode, де працює конейтенер, і після рестарту под буде створено на тій самій WorkerNode

Процес в конейнері має зупинятись з кодом помилки 

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

livenessProbe використовується тільки для перевірки статусу самого процесу в контейнері.

Розділяйте Liveness та Readiness Probes

Розповсюджена практика використання одного ендпоінту для livenessProbe та readinessProbe, але для livenessProbe задавати вище значення failureThreshold, тобто – раніше відключати від трафіку і клієнтів, і якщо “діло зовсім погано” – то виконувати рестарт.

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

Уникайте залежностей

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

Замість цього, ви можете створити окремий ендпоінт для системи моніторингу, і виконувати такі перевірки там – задля алертів і дашбордів в Grafana.

Крім того, процес в контейнері не має падати, якщо не може отримати доступ до сервісу, від якого він залежить. Натомість, він має виконувати retry конекту, бо Kubernetes очікує, що поди можуть бути запущені в будь-якому порядку.

Корректна обробка SIGTERM

Процес в контейнері має коректно оброблювати сигнал SIGTERM – саме він відправляється від kubelet до контейнерів, коли їх треба перезапустити. Якщо на SIGTERM відповіді не було (бо процес “вісить”) – буде виконано SIGKILL.

Або процес може сприймати SIGTERM як SIGKILL, і зупинятись не закривши відкриті TCP-конекти – див. Kubernetes: NGINX/PHP-FPM graceful shutdown – избавляемся от 502 ошибок.

readinessProbe

readinessProbe потрібні, щоб не надсилати запити до подів, які ще запустились.

Наприклад, якщо процес старту вашого поду займає 2 хвилини (якийсь bootsrap процесу, особливо якщо це JVM, або завантаження якогось cache в пам’ять), а ви не маєте readinessProbe – то Kubernetes почне відправляти запроси, як тільки под перейде в статус Running, і вони будуть фейлитись.

Перевірка залежностей

На відміну від livenessProbe, в readinessProbe може бути сенс в перевірці доступності сервісів, від яких залежить под, бо у випадку коли сервіс не може виконати запит від клієнта, бо в нього немає конекта до бази даних – то пускати трафік на цей под не треба.

Втім пам’ятайте, що readinessProbe виконується постійно (кожні 15 секунд по дефолту), і на кожну таку перевірку буде виконуватись окремий запрос до бази даних.

Але в цілому це залежить від самого вашого застосунку. Наприклад, якщо ви можете віддавати відповіді з якогось локального кешу, то под може продовжувати роботу, а на виконання запитів з Write-операціями – повертати помилку 503.

startupProbe

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

Наприклад, може бути корисним перевірити підключення до бази даних коли ви деплоїте новую версію Helm-чарту і маєте Kubernetes Deployment з Rolling Update, але в новій версії маєте помилку в URL або паролі до серверу бази даних.

Також startupProbe може бути корисна, щоб не збільшувати параметр initialDelaySeconds для livenessProbe та readinessProbe , а натомість вікласти їх запуск допоки не завершиться перевірка startupProbe, бо якщо livenessProbe при старті контейнера не встигне виконатись – то Kubernetes виконає рестарт поду, хоча він ще “прогрівається”.

Типи перевірок

В кожній Probe можемо використовувати перевірки по:

  • exec: виконати команду всередені контейнеру
  • httpGet: виконати запит HTTP GET
  • tcpSocket: відкрити TCP connect на порт
  • grpc: виконати запит gRPC на TCP порт

Параметри для Probes

Всі Probes мають параметри, якві дозволяють точно налаштувати час виконання перевірок:

  • initialDelaySeconds: затримка між стартом контейнеру та початком виконання перевірок
  • periodSeconds: як часто після initialDelaySeconds робити запити на перевірку стану
  • timeoutSeconds: як довго чекати відповіді на запит
  • failureThreshold: скільки має бути failed відповідей, щоб вважати перевірку не пройденою (або – скільки раз повторювати перевірку, перш ніж виконати рестарт поду або відключення від мережі)
  • successThreshold: аналогічно, але щоб вважати перевірку пройденою

Корисні посилання