Введение
Логи, события, выполнение команд (exec) и перенаправление портов (port-forwarding) помогают вам проверять состояние приложения. Пробы (probes) позволяют Kubernetes непрерывно контролировать приложение. Проба готовности (readiness probe) отвечает на вопрос: «Должен ли этот Pod принимать трафик?». Проба живучести (liveness probe) отвечает на вопрос: «Нужно ли перезапустить этот контейнер?».
В этой лабораторной работе вы настроите пробы готовности и живучести по отдельности. Сначала вы создадите приложение, которое становится готовым (Ready) только после создания конечной точки /ready. Затем вы создадите другое приложение с пробой живучести, удалите его файл проверки работоспособности с помощью kubectl exec и понаблюдаете, как Kubernetes перезапустит контейнер.
Подготовка пространства имен для практики с пробами
На этом этапе вы подготовите чистое пространство имен (namespace) для работы с пробами.
Начните работу в директории /home/labex/project. В ней вы будете хранить манифесты для проб.
mkdir -p /home/labex/project
cd /home/labex/project
Убедитесь, что API-сервер Kubernetes доступен. Если виртуальная машина только что запустилась и узел еще не готов, подождите несколько секунд и выполните команду снова.
kubectl get nodes --request-timeout=5s
Ожидаемый вывод:
NAME STATUS ROLES AGE VERSION
labex-v135 Ready control-plane ... v1.35...
Дождитесь, пока Pod сетевого плагина кластера перейдет в состояние Ready. Пробы и сервисы зависят от корректной работы сети Pod'ов.
kubectl wait --namespace kube-system --for=condition=Ready pod -l k8s-app=calico-node --timeout=120s
Ожидаемый вывод:
pod/calico-node-... condition met
Создайте пространство имен с именем ckad-prep-probes и установите его в качестве текущего:
kubectl create namespace ckad-prep-probes
kubectl config set-context --current --namespace=ckad-prep-probes
Проверьте текущее пространство имен:
kubectl config view --minify --output 'jsonpath={..namespace}'; echo
Ожидаемый вывод:
ckad-prep-probes
Настройка пробы готовности (Readiness Probe)
На этом этапе вы настроите пробу готовности и убедитесь, что сервис использует только готовые к работе Pod'ы.
Контейнер запускает HTTP-сервер немедленно, но создает файл /www/ready через несколько секунд. Проба готовности выполняет GET /ready на порту 8080. Пока этот путь не существует, Pod может находиться в состоянии Running, но не Ready, и сервис не должен направлять на него трафик.
Создайте файл readiness-web.yaml:
cat > readiness-web.yaml <<'EOF'
apiVersion: apps/v1
kind: Deployment
metadata:
name: readiness-web
spec:
replicas: 2
selector:
matchLabels:
app: readiness-web
template:
metadata:
labels:
app: readiness-web
spec:
terminationGracePeriodSeconds: 0
containers:
- name: web
image: busybox:1.36
command:
- /bin/sh
- -c
- |
mkdir -p /www
echo readiness-ok > /www/index.html
(sleep 12; echo ready > /www/ready) &
httpd -f -p 8080 -h /www
ports:
- containerPort: 8080
readinessProbe:
httpGet:
path: /ready
port: 8080
initialDelaySeconds: 1
periodSeconds: 2
failureThreshold: 1
---
apiVersion: v1
kind: Service
metadata:
name: readiness-web
spec:
selector:
app: readiness-web
ports:
- port: 80
targetPort: 8080
EOF
Примените манифест и посмотрите на состояние Pod'ов вскоре после создания:
kubectl apply -f readiness-web.yaml
sleep 3
kubectl get pods -l app=readiness-web
Ожидаемый вывод может показать Pod'ы, которые запущены (Running), но еще не готовы (Ready):
NAME READY STATUS RESTARTS AGE
readiness-web-... 0/1 Running 0 ...
Дождитесь завершения развертывания (Deployment):
kubectl rollout status deployment/readiness-web --timeout=120s
Ожидаемый вывод:
deployment "readiness-web" successfully rolled out
Проверьте конечные точки сервиса через EndpointSlice. После того как проба готовности пройдет успешно, у сервиса должно быть две готовые конечные точки.
kubectl get endpointslice -l kubernetes.io/service-name=readiness-web
Ожидаемый вывод включает:
NAME ADDRESSTYPE PORTS ENDPOINTS
readiness-web-... IPv4 8080 ... + 1 more...
Создайте клиентский Pod и протестируйте сервис:
kubectl run probe-client --image=busybox:1.36 --restart=Never --command -- sleep 3600
kubectl wait --for=condition=Ready pod/probe-client --timeout=120s
kubectl exec probe-client -- wget -qO- http://readiness-web
Ожидаемый вывод:
readiness-ok
Настройка пробы живучести (Liveness Probe)
На этом этапе вы настроите пробу живучести, которая проверяет наличие файла работоспособности.
Проба живучести определяет, должен ли Kubernetes перезапустить контейнер. В этом примере используется проба типа exec, которая выполняет команду test -f /tmp/healthy внутри контейнера. Контейнер создает этот файл при запуске, поэтому изначально он считается работоспособным.
Создайте файл liveness-web.yaml:
cat > liveness-web.yaml <<'EOF'
apiVersion: apps/v1
kind: Deployment
metadata:
name: liveness-web
spec:
replicas: 1
selector:
matchLabels:
app: liveness-web
template:
metadata:
labels:
app: liveness-web
spec:
terminationGracePeriodSeconds: 0
containers:
- name: web
image: busybox:1.36
command:
- /bin/sh
- -c
- |
touch /tmp/healthy
mkdir -p /www
echo liveness-ok > /www/index.html
httpd -f -p 8080 -h /www
ports:
- containerPort: 8080
livenessProbe:
exec:
command:
- test
- -f
- /tmp/healthy
initialDelaySeconds: 3
periodSeconds: 3
failureThreshold: 1
EOF
Примените манифест и дождитесь развертывания:
kubectl apply -f liveness-web.yaml
kubectl rollout status deployment/liveness-web --timeout=120s
Ожидаемый вывод включает:
deployment.apps/liveness-web created
deployment "liveness-web" successfully rolled out
Сохраните имя Pod'а и подтвердите наличие файла работоспособности:
LIVE_POD="$(kubectl get pods -l app=liveness-web -o jsonpath='{.items[0].metadata.name}')"
echo "$LIVE_POD"
kubectl exec "$LIVE_POD" -- test -f /tmp/healthy
echo "health file exists"
Ожидаемый вывод включает имя Pod'а и:
health file exists
Опишите Pod и найдите конфигурацию пробы живучести:
kubectl describe pod "$LIVE_POD" | grep -A3 'Liveness:'
Ожидаемый вывод включает:
Liveness: exec [test -f /tmp/healthy] delay=3s timeout=1s period=3s
Инициирование перезапуска по состоянию живучести
На этом этапе вы удалите файл работоспособности и увидите, как проба живучести перезапустит контейнер.
Объект Pod может оставаться прежним, в то время как контейнер внутри него перезапускается. Именно поэтому вы будете следить за счетчиком перезапусков контейнера, а не ожидать появления нового имени Pod'а.
Сохраните текущее имя Pod'а:
LIVE_POD="$(kubectl get pods -l app=liveness-web -o jsonpath='{.items[0].metadata.name}')"
echo "$LIVE_POD"
Удалите файл работоспособности изнутри контейнера:
kubectl exec "$LIVE_POD" -- rm /tmp/healthy
Следите за счетчиком перезапусков, пока он не станет больше нуля. Проба живучести запускается каждые три секунды, поэтому это может занять некоторое время.
for i in $(seq 1 20); do
RESTARTS="$(kubectl get pod "$LIVE_POD" -o jsonpath='{.status.containerStatuses[0].restartCount}')"
echo "restart-count=$RESTARTS"
if [ "$RESTARTS" != "0" ]; then
break
fi
sleep 3
done
Ожидаемый вывод в конечном итоге включает:
restart-count=1
После перезапуска контейнера команда запуска снова создает файл /tmp/healthy. Убедитесь, что файл восстановлен:
kubectl exec "$LIVE_POD" -- test -f /tmp/healthy
echo "health file recreated"
Ожидаемый вывод:
health file recreated
Прочитайте события Pod'а и найдите информацию о сбое пробы живучести:
kubectl describe pod "$LIVE_POD" | sed -n '/Events:/,$p'
Ожидаемый вывод включает:
Warning Unhealthy ... Liveness probe failed
Normal Killing ... Container web failed liveness probe
Резюме
Вы настроили обе основные пробы приложения. Проба готовности контролировала момент подключения Pod'ов к конечным точкам сервиса, а проба живучести перезапустила контейнер после удаления файла работоспособности. Вы также изучили EndpointSlice, описания Pod'ов, счетчики перезапусков и события, чтобы связать конфигурацию проб с наблюдаемым поведением Kubernetes.


