Kubernetes — это мощная платформа для оркестрации контейнеров, которая автоматизирует развертывание, масштабирование и управление приложениями. Одной из ключевых задач в управлении контейнерами является обеспечение их работоспособности и готовности к обработке запросов. В Kubernetes существуют механизмы, известные как пробы (Probes): Liveness, Readiness и Startup. С их помощью Kubernetes отслеживает состояние контейнеров и принимает решения о перезапуске, маршрутизации трафика или ожидании завершения инициализации. В этой статье мы подробно рассмотрим каждую из проб, их настройку, типичные ошибки при использовании и лучшие практики. Для каждой пробы будет приведен практический пример.
Мы будем рассматривать практическую часть, для которой нам понадобится кластер Kubernetes. Арендовать готовый кластер можно с помощью сервиса Kubernetes в облаке. Для работы с сервисами достаточно одной master-ноды и одной worker-ноды с минимальной конфигурацией.
tech
Пробы в Kubernetes — это диагностические проверки, которые выполняет компонент kubelet
(агент запущенный на каждом узле Kubernetes) выполняет для оценки состояния контейнеров. Они помогают определить, работает ли контейнер корректно, готов ли он принимать сетевой трафик, завершил ли он процесс инициализации. Без таких проверок Kubernetes не может точно знать, находится ли приложение в рабочем состоянии, что может привести к сбоям в обслуживании или некорректной маршрутизации запросов к приложению.
В Kubernetes существует три основных вида проб, каждый из которых решает свою задачу:
Liveness Probe проверяет, «жив» ли контейнер, то есть работает ли он корректно. Если проверка не проходит, Kubernetes автоматически перезапустит контейнер.
Readiness Probe определяет, готов ли контейнер принимать входящий сетевой трафик. Если контейнер не готов, он исключается из балансировки нагрузки.
Startup Probe используется для приложений, которым требуется длительное время на запуск, чтобы избежать преждевременного перезапуска или исключения из маршрутизации.
Проверки необходимы для обеспечения отказоустойчивости и стабильности приложений. В частности они позволяют:
Автоматически перезапускать зависшие контейнеры.
Исключать из обработки запросов контейнеры, которые временно не готовы принимать сетевой трафик.
Контролировать запуск приложений с долгой инициализацией.
Снижать вероятность ошибок, связанных с некорректной маршрутизацией трафика.
Проверки поддерживают три механизма выполнения:
HTTP: Отправка HTTP-запроса к эндпоинту контейнера. Код ответа в диапазоне 200–399 считается успешным.
TCP: Проверка открытия TCP-соединения на указанном порту.
Command: Выполнение команды внутри контейнера. Код возврата 0 означает успех.
Теперь рассмотрим каждый тип проверки подробнее.
Liveness Probe определяет, работает ли запущенный контейнер корректно. Если проверка не проходит, Kubernetes считает контейнер нерабочим и автоматически выполняет его перезапуск. Это полезно в ситуациях, когда приложение зависает, потребляет слишком много ресурсов или сталкивается с внутренней ошибкой, но при этом процесс внутри контейнера продолжает работать.
Kubelet периодически выполняет проверку, указанную в конфигурации Liveness Probe. Если проверка завершается неудачно (например, HTTP-запрос возвращает код 500 или команда возвращает ненулевой код в качестве ответа), Kubernetes увеличивает счетчик неудачных попыток. После достижения порога (указывается в параметре failureThreshold
) контейнер будет перезапущен автоматически.
Ниже перечислены параметры, которые используются при настройке Liveness пробы:
initialDelaySeconds
: Задержка перед первой проверкой после запуска контейнера. Указывается в секундах.
periodSeconds
: Интервал между проверками. Указывается в секундах.
timeoutSeconds
: Время ожидания ответа на проверку. Указывается в секундах.
successThreshold
: Минимальное количество успешных проверок для признания контейнера «работоспособным» (обычно указывается значение 1).
failureThreshold
: Количество неудачных проверок, после которых контейнер считается «неживым».
Рассмотрим использование Liveness Probe на практике. Для этого воспользуемся манифестом ниже:
---
apiVersion: v1
kind: Namespace
metadata:
name: test-liveness-probe
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: test-liveness-probe-http
namespace: test-liveness-probe
spec:
replicas: 1
selector:
matchLabels:
app: nginx-liveness
template:
metadata:
labels:
app: nginx-liveness
spec:
containers:
- name: nginx--test-container
image: nginx:1.26.0
livenessProbe:
httpGet:
path: /
port: 80
initialDelaySeconds: 15
periodSeconds: 10
timeoutSeconds: 3
failureThreshold: 3
В указанной конфигурации используется образ с веб-сервером Nginx и задана liveness-проба, которая периодически выполняет HTTP-запрос к корневому эндпоинту /
на 80 порту для контроля работоспособности приложения. Первая проверка начинается через 15 секунд после запуска контейнера (initialDelaySeconds
) и выполняется каждые 10 секунд (periodSeconds
). Если при выполнении HTTP-запроса к эндпоинту /healthz
возвращается код ответа в диапазоне 200–399, то проверка считается успешной. Однако если три последовательные проверки (failureThreshold
) завершаются неудачно, контейнер будет перезапущен автоматически.
Сохраняем конфигурацию выше в файл с именем test-liveness-probe.yaml
и применяем:
kubectl apply -f test-liveness-probe.yaml
Проверим, что под успешно запустился:
kubectl get pods -n test-liveness-probe
Как можно увидеть на скриншоте выше, под успешно запустился и находится в статусе Running
.
Теперь проверим работоспособность пробы. Для этого воспользуемся командой для проверки логов пода при помощи команды:
kubectl logs test-liveness-probe-http-6bf85d548b-xc9lf -n test-liveness-probe
Не забудьте поменять имя пода с test-liveness-probe-http-6bf85d548b-xc9lf
на другое, которое будет отображено при выполнении команды kubectl get po -n test-liveness-probe
.
Как можно увидеть на скриншоте ниже, проба отправляет запрос каждые 10 секунд и успешно получает ответ:
Теперь проверим, как поведет себя под, если мы поменяем на несуществующий эндпоинт. Для этого меняем эндпоинт в ранее использованной конфигурации:
livenessProbe:
httpGet:
path: /nonexistent
port: 80
Сохраняем изменения в конфигурацию и применяем:
kubectl apply -f test-liveness-probe.yaml
Проверим статус пода:
kubectl get pods -n test-liveness-probe
Под запущен, однако обратите внимание на столбец RESTARTS
, в котором отображаются перезапуска пода. В данном случае под перезапускался два раза и будет перезапускаться далее. Это связано с заданными параметрами Liveness-пробы — если три последовательные проверки завершаются неудачно, контейнер будет перезапускаться автоматически.
Liveness-пробу полезно использовать в следующих случаях:
Приложение зависает без завершения процесса (например, из-за возникновения deadlock).
Контейнер потребляет ресурсы, но не выполняет полезную работу.
Нужно гарантировать, что приложение всегда находится в рабочем состоянии.
Readiness Probe определяет, готов ли контейнер принимать входящий сетевой трафик. Если проверка не проходит, Kubernetes исключает контейнер из маршрутизации (например, из объекта типа Service или Ingress), но при этом не перезапускает контейнер. Это позволяет временно изолировать контейнер, который не готов обрабатывать запросы, например, во время обновления базы данных или загрузки кэша.
Kubelet выполняет проверку аналогично Liveness Probe. Если проверка завершается успешно, контейнер считается готовым и Kubernetes включает его в маршрутизацию трафика. Если проверка не проходит, контейнер исключается из маршрутизации, но продолжает работать.
Readiness-проба использует те же параметры, что и в Liveness-пробе. Однако их значения могут отличаться.
Рассмотрим использование Readiness Probe на практике. Для этого воспользуемся манифестом ниже, в котором приведен пример конфигурации с использованием TCP-проверки:
apiVersion: v1
kind: Namespace
metadata:
name: test-readiness-probe
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-test-deployment
namespace: test-readiness-probe
labels:
app: nginx
spec:
replicas: 1
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx-web-server
image: nginx:1.14.2
ports:
- containerPort: 80
readinessProbe:
httpGet:
path: /
port: 80
initialDelaySeconds: 5
periodSeconds: 10
timeoutSeconds: 3
successThreshold: 1
failureThreshold: 3
В данной конфигурации мы используем образ с веб-сервером Nginx. Проверка выполняется каждые 10 секунд на порт 80 (порт по умолчанию для Nginx). Если проверка на порту 80 не проходит три раза подряд, контейнер исключается из маршрутизации. Первая проверка начинается через 5 секунд после запуска.
Сохраняем конфигурацию выше в файл с именем test-readiness-probe.yaml
и применяем:
kubectl apply -f test-readiness-probe.yaml
Проверим, что под успешно запустился:
kubectl get pods -n test-readiness-probe
Как можно увидеть на скриншоте выше, под успешно запустился и находится в статусе Running
.
Теперь проверим работоспособность пробы при сбое. Для этого «сломаем» контейнер, подключившись к поду и удалив индексный файл index.html
:
kubectl exec -it nginx-deployment-5c8b8b9669-q8vrh -n test-readiness-probe -- rm /usr/share/nginx/html/index.html
Далее проверим статус пода:
kubectl get pods -n test-readiness-probe
Как можно увидеть на скриншоте выше, под будет помечен как неготовый (0/1
в столбце READY
). Проверим события пода при помощи команды kubectl describe
:
kubectl describe pod nginx-deployment-5c8b8b9669-q8vrh -n test-readiness-probe
В разделе Events
появилось сообщение о том, что Readiness не смогла пройти проверку и возвращает в ответ ошибку 403.
Для того чтобы под снова смог принимать входящий трафик, достаточно его удалить при помощи команды:
kubectl delete pod nginx-deployment-5c8b8b9669-q8vrh -n test-readiness-probe
Далее проверяем статус пода:
kubectl get pods -n test-readiness-probe
Под снова готов к работе и может принимать входящий сетевой трафик.
Readiness-пробу полезно использовать в следующих случаях:
Приложение требует времени на инициализацию (например, загрузка конфигурации или данных, особенно актуально при работе с СУБД, т.к. им обычно требуется время на запуск).
Контейнер временно не может обрабатывать запросы (например, во время миграции базы данных или обновления СУБД).
Нужно исключить из маршрутизации контейнеры, которые находятся в состоянии перегрузки, чтобы они не принимали входящий трафик.
Startup Probe предназначена для приложений, которым требуется больше времени на запуск. Она позволяет Kubernetes дождаться завершения инициализации контейнера, прежде чем начинать Liveness- или Readiness-проверки. Без Startup Probe медленное приложение может быть перезапущено из-за неудачных Liveness-проверок, даже если оно еще не завершило запуск.
Startup Probe выполняется до тех пор, пока не завершится успешно или не превысит порог неудачных попыток. После успешного завершения проверки Kubernetes начинает выполнять Liveness и Readiness Probes (при условии, что они настроены). Если проверка не проходит, контейнер будет перезагружен.
Startup-проба использует параметры, аналогичные другим пробам, но часто имеют более высокие значения в параметрах initialDelaySeconds
и failureThreshold
, чтобы учесть длительный запуск приложения.
Рассмотрим использование Startup Probe на практике. Для этого подготовим конфигурацию для приложения, которое долго инициализируется:
apiVersion: v1
kind: Namespace
metadata:
name: test-startup-probe
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: startup-demo
namespace: test-startup-probe
spec:
replicas: 1
selector:
matchLabels:
app: startup-demo
template:
metadata:
labels:
app: startup-demo
spec:
containers:
- name: demo-container
image: nginx:alpine
ports:
- containerPort: 80
lifecycle:
postStart:
exec:
command: ["/bin/sh", "-c", "sleep 30 && touch /usr/share/nginx/html/ready"]
startupProbe:
exec:
command: ["cat", "/usr/share/nginx/html/ready"]
failureThreshold: 10
periodSeconds: 5
livenessProbe:
httpGet:
path: /
port: 80
initialDelaySeconds: 5
periodSeconds: 5
readinessProbe:
httpGet:
path: /
port: 80
initialDelaySeconds: 5
periodSeconds: 5
В приведенной выше конфигурации запускается контейнер на основе образа с веб-сервером Nginx, который имитирует медленный запуск. Для управления состоянием контейнера используются три пробы Kubernetes:
cat /usr/share/nginx/html/ready
каждые 5 секунд (periodSeconds: 5
). Если файл ready
существует и доступен (команда завершается успешно), то контейнер считается запущенным. Проба повторяется до 10 раз (failureThreshold: 10
), что дает максимум 50 секунд на успешный запуск. Если все попытки неудачны, контейнер перезапускается./
) по порту 80 каждые 5 секунд (periodSeconds: 5
) после начальной задержки в 5 секунд (initialDelaySeconds: 5
). Если сервер возвращает код ответа в диапазоне 200–399, проба успешна. В противном случае контейнер считается неработоспособным и перезапускается./
по порту 80 каждые 5 секунд (periodSeconds: 5
) после задержки в 5 секунд (initialDelaySeconds: 5
). Если запрос успешен (код ответа 200–399), контейнер включается в балансировку для обработки трафика. Если проба не проходит, контейнер исключается из балансировки, но не перезапускается.Сохраняем конфигурацию в файл с именем test-startup-probe.yaml
и применяем:
kubectl apply -f test-startup-probe.yaml
Проверим статус пода:
kubectl get pods -n test-startup-probe
Как можно заметить на скриншоте выше, под запущен, но не готов к работе (0/1
в столбце READY
). В первые 30 секунд (из-за sleep 30
в postStart
) под будет в статусе Running
, но не Ready
, так как startupProbe
ожидает появления файла /usr/share/nginx/html/ready
. После 30 секунд у пода будет готов к работе:
Startup-проба полезна для:
Приложений, которые обладают длительной инициализацией (например, загрузка больших моделей машинного обучения).
Контейнеров, которые подключаются к внешним сервисам при старте.
Использование неправильных значений
Маленькие значения в параметрах periodSeconds
или timeoutSeconds
могут привести к ложным срабатываниям из-за временных задержек. Необходимо устанавливать разумные значения (например, periodSeconds: 10
, timeoutSeconds: 3
).
Отсутствие эндпоинтов для проверки
Если в приложение не заданы эндпоинты (например, /healthz
или /ready
), то HTTP-проверки будут завершаться неудачно. Реализуйте соответствующие эндпоинты в самом приложении при его разработке.
Перегрузка контейнера
Частые проверки могут нагружать приложение, особенно если они выполняют сложные операции. Используйте легковесные проверки, например, TCP вместо HTTP, если этого достаточно.
Игнорирование Startup Probe
Без использования Startup Probe медленные приложения могут быть перезапущены из-за неудачных Liveness-проверок. Необходимо использовать и правильно настроить Startup Probe для приложений с длительным запуском.
Разделяйте Liveness- и Readiness-пробы
Liveness Probe должна проверять, работает ли приложение, а Readiness Probe — готово ли оно принимать сетевой трафик. Например, Liveness может проверять наличие процесса, а Readiness — доступность внешних зависимостей.
Используйте Startup Probe для медленных приложений
Если приложение требует более 10–15 секунд на запуск, настройте Startup Probe, чтобы избежать преждевременных перезапусков.
Реализуйте легковесные проверки
HTTP-проверки должны возвращать минимальный объем данных, чтобы снизить нагрузку на приложение. TCP-проверки предпочтительны, если достаточно проверки доступности порта.
Учитывайте зависимости
Если приложение зависит от базы данных или другого сервиса, настройте Readiness Probe для проверки доступности этих зависимостей.
Надежные VPS/VDS для ваших проектов
Liveness, Readiness и Startup Probes в Kubernetes — это критически важные параметры, которые позволяют контролировать состояние контейнеров, автоматически перезапускать неисправные экземпляры, исключать неподготовленные из маршрутизации и давать время на инициализацию медленным приложениям. Правильная настройка проверок требует понимания работы приложения и тщательного подбора параметров.
Использование проб в Kubernetes не только повышает стабильность приложений, но и упрощает управление инфраструктурой, позволяя автоматизировать реакции на сбои и изменения состояния.