Що таке liveness probe
Якщо процес усередині контейнера завис (наприклад, виник Deadlock у Java-потоках або нескінченний цикл), операційна система вважає процес живим, але реальні запити він більше не...
🟢 Junior Level
30-секундна відповідь
Liveness Probe (Проба живучості) — це діагностичний механізм Kubernetes, за допомогою якого агент kubelet періодично перевіряє, чи працює застосунок усередині контейнера коректно, чи він безнадійно завис.
Якщо процес усередині контейнера завис (наприклад, виник Deadlock у Java-потоках або нескінченний цикл), операційна система вважає процес живим, але реальні запити він більше не обробляє:
- Kubelet надсилає перевірочний запит (HTTP, TCP або команду в терміналі).
- Якщо застосунок не відповідає або повертає помилку кілька разів поспіль (
failureThreshold), Kubernetes вважає контейнер мертвим і примусово перезапускає його (Self-Healing).
Наочна аналогія з життя
Liveness Probe — це перевірка пульсу пацієнта в реанімації:
- Лікар (
kubelet) кожні 10 секунд перевіряє пульс. - Якщо людина дихає і пульс є — усе гаразд, працюємо далі.
- Якщо пульс зник на 3 перевірки поспіль — лікар негайно застосовує дефібрилятор (перезапуск контейнера), щоб повернути застосунок до життя.
Базовий маніфест для Spring Boot 3 на Java 21
apiVersion: v1
kind: Pod
metadata:
name: payment-app
spec:
containers:
- name: payment-service
image: payment-service:1.0
livenessProbe:
httpGet:
path: /actuator/health/liveness # Ендпоінт Spring Boot Actuator
port: 8080
initialDelaySeconds: 30 # Пауза перед першою перевіркою (час на старт)
periodSeconds: 10 # Інтервал перевірок (кожні 10 секунд)
timeoutSeconds: 3 # Очікування відповіді не більше 3 секунд
failureThreshold: 3 # Перезапуск після 3 невдач поспіль
[!IMPORTANT] Головна мета Liveness: виявити ситуацію, коли застосунок зайшов у глухий кут і не може відновитися самостійно без повного перезапуску процесу.
🟡 Middle Level
4 механізми виконання проб
| Механізм | Як працює | Де застосовується |
|---|---|---|
httpGet |
Kubelet надсилає HTTP GET-запит. Коди 200–399 вважаються успіхом. |
Web-застосунки, REST API (Spring Boot Actuator). |
tcpSocket |
Перевіряє можливість відкрити TCP-сокет на вказаному порту. | СУБД, кеші (Redis, PostgreSQL), брокери повідомлень. |
grpc |
Викликає стандартний gRPC Health Checking Protocol. | Мікросервіси на gRPC (Kubernetes 1.24+ GA). |
exec |
Виконує команду всередині контейнера (exit 0 — успіх). |
Legacy-застосунки, перевірка створення сигнальних lock-файлів. |
Головне архітектурне правило: Liveness vs Зовнішні залежності
[!CAUTION] НІКОЛИ НЕ ПЕРЕВІРЯЙТЕ ЗОВНІШНІ ЗАЛЕЖНОСТІ (БД, KAFKA, ІНШІ СЕРВІСИ) У LIVENESS PROBE!
Що станеться, якщо включити перевірку PostgreSQL у Liveness:
- База даних PostgreSQL зазнає короткочасного перевантаження і припиняє відповідати на 15 секунд.
- Liveness-проба на всіх 50 ваших подах Java-бекенду падає з помилкою.
- Kubelet одночасно вбиває та перезапускає всі 50 подів застосунку!
- При одночасному старті 50 подів накидаються на БД, що відновлюється, з тисячами нових з’єднань пулу HikariCP, остаточно добиваючи сервер бази даних (Каскадна спіраль смерті — Cascading Death Spiral).
- Правило: Liveness Probe перевіряє ТІЛЬКИ внутрішній стан самого контейнера (пам’ять, потоки, внутрішній цикл). Перевірка зовнішніх зв’язків делегується виключно пробі готовності (Readiness Probe).
Підтримка у Spring Boot Actuator
Починаючи зі Spring Boot 2.3+ та у Spring Boot 3+, фреймворк автоматично адаптується до Kubernetes і розділяє ендпоінти:
http://localhost:8080/actuator/health/liveness— повертає статус внутрішнього стану (класLivenessState). Включає тільки локальні перевірки.http://localhost:8080/actuator/health/readiness— перевіряє готовність пулів з’єднань до БД та доступність зовнішніх ресурсів.
Увімкнення в application.yaml:
management:
health:
livenessstate:
enabled: true
readinessstate:
enabled: true
endpoint:
health:
probes:
enabled: true
🔴 Senior Level
Тандем startupProbe та livenessProbe
Історична проблема Java в Kubernetes — тривалий холодний старт (Spring Boot може ініціалізувати контекст і міграції Flyway від 40 до 90 секунд):
- Якщо поставити
initialDelaySeconds: 10, Liveness Probe вб’є здоровий под прямо під час завантаження контексту Spring. - Якщо поставити
initialDelaySeconds: 90, то при реальному зависанні застосунку в продакшені Kubelet чекатиме цілих 90 секунд перед першою реакцією.
Рішення — startupProbe:
startupProbe:
httpGet:
path: /actuator/health/liveness
port: 8080
periodSeconds: 5
failureThreshold: 30 # Дає застосунку: 30 * 5с = 150 секунд на спокійний старт!
livenessProbe:
httpGet:
path: /actuator/health/liveness
port: 8080
periodSeconds: 10
failureThreshold: 3 # Швидка реакція на зависання: 3 * 10с = 30 секунд
Поки startupProbe не завершиться успіхом, перевірки livenessProbe та readinessProbe навіть не активуються!
HotSpot Internals: Хибні спрацьовування при STW GC Паузах
Якщо збирач сміття JVM (наприклад, Parallel GC або G1 при фрагментованій пам’яті) входить у важку фазу Full GC Stop-The-World (STW):
- Усі потоки застосунку (включно з потоком HTTP-сервера Tomcat/Netty, який відповідає на Actuator) повністю заморожуються ядром JVM.
- Мережевий перевірочний пакет від Kubelet надходить у сокет хоста, але Tomcat не може сформувати HTTP-відповідь.
- Якщо таймаут проби
timeoutSeconds: 1занадто агресивний, Kubelet фіксує збій. Три такі паузи поспіль призведуть до вбивства абсолютно здорового Java-застосунку, який лише виконував очищення пам’яті! Рекомендація: значенняtimeoutSecondsдля Java-мікросервісів має становити щонайменше 3–5 секунд, а порігfailureThreshold— не менше 3.
Програмне оголошення аварії у Spring Boot 3
Розробник може програмно повідомити Kubernetes про необхідність перезапуску контейнера (наприклад, при виявленні невиправної помилки у фоновому демоні):
@Service
public class CriticalWorkerService {
private final ApplicationEventPublisher eventPublisher;
public CriticalWorkerService(ApplicationEventPublisher eventPublisher) {
this.eventPublisher = eventPublisher;
}
public void processCriticalQueue() {
try {
// обробка критичної черги
} catch (FatalCorruptionException ex) {
// Переводимо LivenessState в BROKEN -> Actuator починає віддавати HTTP 503
// Kubelet фіксує помилку і примусово перезапускає контейнер
AvailabilityChangeEvent.publish(eventPublisher, this, LivenessState.BROKEN);
}
}
}
4 Tricky Questions
1. Що станеться, якщо контейнер провалить перевірку Liveness Probe, але його специфікація містить директиву restartPolicy: Never?
Відповідь:
Kubelet НЕ перезапускатиме контейнер.
Відповідно до логіки Kubernetes, якщо restartPolicy: Never або restartPolicy: OnFailure, а процес завершився з кодом 0:
- Kubelet примусово зупинить завислий контейнер сигналом
SIGTERM, а потімSIGKILL. - Проте перестворювати його заново Kubelet не буде.
- Контейнер перейде в стан
Terminated, а весь Pod перейде в термінальну фазуFailedі залишиться в ній доти, доки контролер (Deployment) або інженер не видалить його.
2. Як детектувати взаємне блокування потоків (Deadlock) у багатопотоковому Java-застосунку за допомогою Liveness Probe?
Відповідь: Створюється кастомний індикатор здоров’я Spring Actuator з використанням системного MXBean віртуальної машини HotSpot:
@Component
public class DeadlockHealthIndicator implements HealthIndicator {
private final ThreadMXBean threadBean = ManagementFactory.getThreadMXBean();
@Override
public Health health() {
long[] deadlocked = threadBean.findDeadlockedThreads();
if (deadlocked != null && deadlocked.length > 0) {
return Health.down()
.withDetail("deadlockedThreadsCount", deadlocked.length)
.build();
}
return Health.up().build();
}
}
При виникненні взаємоблокування ендпоінт Actuator негайно поверне HTTP 503, і Kubelet перезапустить JVM, скинувши заблокований стан потоків.
3. У чому фундаментальна різниця в реакції Kubernetes на збій livenessProbe у порівнянні зі збоєм readinessProbe?
Відповідь:
- При провалі
livenessProbe: Kubernetes виконує жорстку дію — вбиває та перезапускає контейнер (Restart Container). IP-адреса пода не змінюється, але всі активні транзакції обриваються, а пам’ять скидається. - При провалі
readinessProbe: Kubernetes виконує м’яку дію — НЕ перезапускає контейнер, а лише тимчасово видаляє IP-адресу пода зі спискуEndpointsсервісу. Под продовжує жити й обробляти поточні фонові завдання, але новий вхідний трафік від користувачів на нього припиняє надходити доти, доки проба готовності знову не поверне успіх.
4. Чому виконання Liveness Probe через механізм exec (наприклад, command: ["curl", "localhost:8080/health"]) у високонавантажених системах вважається поганою практикою?
Відповідь:
При використанні exec агент Kubelet на кожне опитування (кожні 5–10 секунд) через рантайм containerd породжує новий дочірній процес операційної системи Linux усередині простору імен пода (fork + exec).
- Це створює істотний оверхед по CPU на створення структур ядра, перемикання контексту та виділення дескрипторів.
- Крім того, в образах
distrolessабо мінімалістичних образах на базі Alpine часто відсутніcurl,bashчиshз міркувань безпеки. - Використання нативного
httpGetвиконується Kubelet’ом через відкриття прямого сокета ззовні контейнера без породження зайвих процесів усередині пода.
🎯 Шпаргалка для інтерв’ю
Головне про Liveness Probe
- Призначення: перевірка життєздатності процесу; при провалі — перезапуск контейнера.
- Критичний антипатерн: перевірка зовнішніх БД/черг (призведе до лавиноподібної відмови всього кластера).
- Startup Probe: дає тривалим Java-сервісам час на ініціалізацію без небезпеки бути вбитими Liveness-пробою.
- Spring Boot 3 Actuator: стандартний ендпоінт
/actuator/health/liveness. - GC STW Pauses: таймаут
timeoutSecondsмає бути більшим за максимальну паузу Full GC (3–5 сек). - Liveness vs Readiness: Liveness вбиває процес; Readiness тимчасово виводить под із балансування сервісу.
Порівняння трьох типів проб
| Параметр | startupProbe | livenessProbe | readinessProbe |
| :— | :— | :— | :— |
| Коли виконується? | Тільки під час старту | Після успіху startup | Після успіху startup, постійно |
| Дія при збої | Вбивство контейнера | Перезапуск контейнера | Вимкнення мережевого трафіку |
| Основна мета | Дочекатися завантаження JVM | Зняти Deadlock / зависання | Дочекатися прогріву / доступності БД |
Червоні прапорці на співбесіді (Чого говорити не можна)
- ❌ «У Liveness Probe ми перевіряємо доступність PostgreSQL та Redis» — фатальна помилка, що гарантує Cascading Failure при збої БД.
- ❌ «Для Java-застосунків достатньо initialDelaySeconds: 5» — Spring Boot не встигне стартувати й потрапить у нескінченний CrashLoop.
- ❌ «Readiness та Liveness — це одне й те саме» — вони мають діаметрально протилежні цілі та дії при збої.