Настройка проб готовности (Readiness) и живучести (Liveness)

KubernetesBeginner
Практиковаться сейчас

Введение

Логи, события, выполнение команд (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.