Конфигурация проверки работоспособности контейнера Kubernetes

задняя часть Kubernetes
Конфигурация проверки работоспособности контейнера Kubernetes

Это 7-й день моего участия в August Update Challenge, проверьте подробности события, проверьте подробности события:​Испытание августовского обновления

1. Введение

В этой статье описывается, как настроить контейнерliveness,readiness,startupзонд.

kubeletиспользоватьlivenessУзнайте, когда перезапустить контейнер. Например,livenessЗонды могут обнаруживать взаимоблокировки (приложение работает, но не может продолжить выполнение последующих шагов). Перезапуск контейнера в таком случае помогает сделать приложение более удобным для использования в случае возникновения проблем.

kubeletиспользоватьreadinessЗонды знают, когда контейнеры готовы, и могут начать принимать трафик запросов, а под считается готовым, когда готовы все контейнеры внутри пода. Одним из способов использования такого сигнала является контроль того, какой под является бэкэндом для службы. Когда Pod не готов, он будет удален из балансировщика нагрузки Сервиса.

kubeletиспользоватьstartupЗонды могут определить, когда запущен контейнер приложения. Если вы настроите этот тип зонда, вы можете контролировать запуск контейнера, прежде чем продолжить.livenessиreadinessУбедитесь, что эти проверки активности и готовности не мешают запуску приложения. Это можно использовать для проверки жизнеспособности контейнеров с медленным запуском, предотвращая их уничтожение до того, как они начнут работать.

2 Определите пробу живучести

Многие долго работающие приложения в конечном итоге переходят в отключенное состояние, которое невозможно восстановить, если не перезапустить. Kubernetes предоставляетlivenessдетекторы для обнаружения и исправления ситуации.

Создайте под, который запускаетk8s.gcr.io/busyboxКонтейнер изображения. Файл конфигурации выглядит следующим образом. имя файла:exec-liveness.yaml

apiVersion: v1
kind: Pod
metadata:
  labels:
    test: liveness
  name: liveness-exec
spec:
  containers:
  - name: liveness
    image: k8s.gcr.io/busybox
    args:
    - /bin/sh
    - -c
    - touch /tmp/healthy; sleep 30; rm -rf /tmp/healthy; sleep 600
    livenessProbe:
      exec:
        command:
        - cat
        - /tmp/healthy
      initialDelaySeconds: 5
      periodSeconds: 5

В конфигурационном файле видно, что в поде только один контейнер.periodSecondsПоле указывает, что kubelet должен выполнять проверку жизнеспособности каждые 5 секунд.initialDelaySecondsполе говоритkubeletВы должны подождать 5 секунд перед выполнением первого зонда. kubelet выполняет команды в контейнереcat /tmp/healthyтестировать. Если команда выполняется успешно и возвращаемое значение равно 0, kubelet считает контейнер живым и работоспособным. Если эта команда вернет ненулевое значение, kubelet уничтожит контейнер и перезапустит его. Выполните команду следующим образом

/bin/sh -c "touch /tmp/healthy; sleep 30; rm -rf /tmp/healthy; sleep 600"

В течение первых 30 секунд жизни этого контейнера/tmp/healthyФайл существует. Выполнение заказаcat /tmp/healthyБудет возвращен код успеха. Через 30 секунд выполните командуcat /tmp/healthyОн возвращает код ошибки.

Создать модуль

# kubectl apply -f /root/k8s-example/probe/exec-liveness.yaml

Через 30 секунд просмотрите события для модуля.

kubectl describe pod liveness-exec

Вывод показывает, что сбоев активных датчиков еще нет.

Events:
  Type    Reason     Age        From                 Message
  ----    ------     ----       ----                 -------
  Normal  Scheduled  <unknown>  default-scheduler    Successfully assigned default/liveness-exec to k8s-node04
  Normal  Pulled     22s        kubelet, k8s-node04  Container image "k8s.gcr.io/busybox" already present on machine
  Normal  Created    22s        kubelet, k8s-node04  Created container liveness
  Normal  Started    22s        kubelet, k8s-node04  Started container liveness

Через 30 секунд посмотрите на события Pod:

kubectl describe pod liveness-exec

Внизу вывода есть сообщение о том, что liveness probe не удалось, контейнер был убит и пересобран.

Events:
  Type     Reason     Age               From                 Message
  ----     ------     ----              ----                 -------
  Normal   Scheduled  <unknown>         default-scheduler    Successfully assigned default/liveness-exec to k8s-node04
  Normal   Pulled     47s               kubelet, k8s-node04  Container image "k8s.gcr.io/busybox" already present on machine
  Normal   Created    47s               kubelet, k8s-node04  Created container liveness
  Normal   Started    47s               kubelet, k8s-node04  Started container liveness
  Warning  Unhealthy  5s (x3 over 15s)  kubelet, k8s-node04  Liveness probe failed: cat: can't open '/tmp/healthy': No such file or directory
  Normal   Killing    5s                kubelet, k8s-node04  Container liveness failed liveness probe, will be restarted

Подождите еще 30 секунд и убедитесь, что контейнер был перезапущен:

kubectl get pod liveness-exec
NAME            READY   STATUS    RESTARTS   AGE
liveness-exec   1/1     Running   2          3m10s

Еще раз проверьте сведения о ресурсе Pod:

kubectl describe pod liveness-exec

Вывод выглядит следующим образом, и контейнер успешно перезапускается.

Events:
  Type     Reason     Age                 From                 Message
  ----     ------     ----                ----                 -------
  Normal   Scheduled  <unknown>           default-scheduler    Successfully assigned default/liveness-exec to k8s-node04
  Warning  Unhealthy  35s (x6 over 2m)    kubelet, k8s-node04  Liveness probe failed: cat: can't open '/tmp/healthy': No such file or directory
  Normal   Killing    35s (x2 over 110s)  kubelet, k8s-node04  Container liveness failed liveness probe, will be restarted
  Normal   Pulled     5s (x3 over 2m32s)  kubelet, k8s-node04  Container image "k8s.gcr.io/busybox" already present on machine
  Normal   Created    5s (x3 over 2m32s)  kubelet, k8s-node04  Created container liveness
  Normal   Started    5s (x3 over 2m32s)  kubelet, k8s-node04  Started container liveness

3. Определите интерактивный интерфейс HTTP-запроса

другой типlivenessМетод обнаружения заключается в использовании HTTP-запроса GET. Ниже приведен файл конфигурации для пода, который запускаетk8s.gcr.io/livenessКонтейнер изображения.

Создать модуль

apiVersion: v1
kind: Pod
metadata:
  labels:
    test: liveness
  name: liveness-http
spec:
  containers:
  - name: liveness
    image: k8s.gcr.io/liveness
    args:
    - /server
    livenessProbe:
      httpGet:
        path: /healthz
        port: 8080
        httpHeaders:
        - name: X-Custom-Header
          value: Awesome
      initialDelaySeconds: 3
      periodSeconds: 3

В конфигурационном файле в поде только один контейнер.periodSecondsПоле указывает, что kubelet должен выполнять проверку каждые 3 секунды.initialDelaySecondsПоле сообщает kubelet, что он должен подождать 3 секунды, прежде чем выполнять первый тест. Kubelet отправит службу, работающую в контейнере (служба будет прослушивать порт 8080).HTTP GETЗапрос на выполнение зондирования. если служба/healthzОбработчик под путем возвращает код успеха. Кубелет считает контейнер здоровым и живым. Если обработчик вернет код ошибки, kubelet уничтожит контейнер и перезапустит его.

Любой код возврата больше или равен 200 и меньше 400 указывает на успех, другие коды возврата указывают на сбой.

Вы можете увидеть исходный код сервиса здесьserver.go.

В течение первых 10 секунд существования контейнера/healthzОбработчик возвращает код состояния 200. Затем обработчик возвращает код состояния 500.

http.HandleFunc("/healthz", func(w http.ResponseWriter, r *http.Request) {
    duration := time.Now().Sub(started)
    if duration.Seconds() > 10 {
        w.WriteHeader(500)
        w.Write([]byte(fmt.Sprintf("error: %v", duration.Seconds())))
    } else {
        w.WriteHeader(200)
        w.Write([]byte("ok"))
    }
})

Kubelet начинает выполнять проверки работоспособности через 3 секунды после запуска контейнера. Так что первые несколько проверок здоровья прошли успешно. Но через 10 секунд проверка работоспособности не проходит и kubelet убивает контейнер и перезапускает его.

# kubectl apply -f /root/k8s-example/probe/http-liveness.yaml

Через 10 секунд просмотрите события Pod, чтобы обнаружить, что проверка живучести не удалась, и контейнер был перезапущен.

Events:
  Type     Reason     Age              From                 Message
  ----     ------     ----             ----                 -------
  Normal   Scheduled  <unknown>        default-scheduler    Successfully assigned default/liveness-http to k8s-node01
  Normal   Pulled     17s              kubelet, k8s-node01  Container image "k8s.gcr.io/liveness" already present on machine
  Normal   Created    17s              kubelet, k8s-node01  Created container liveness
  Normal   Started    16s              kubelet, k8s-node01  Started container liveness
  Warning  Unhealthy  1s (x2 over 4s)  kubelet, k8s-node01  Liveness probe failed: HTTP probe failed with statuscode: 500

4 Определите определение живучести TCP

третий типlivenessЗондирование использует сокеты TCP. По конфигурации kubelet попытается установить сокетное соединение с контейнером на указанном порту. Если связь может быть установлена, контейнер считается исправным, если нет — контейнер считается проблемным.

Создайте под. имя файла:tcp-liveness-readiness.yaml

apiVersion: v1
kind: Pod
metadata:
  name: goproxy
  labels:
    app: goproxy
spec:
  containers:
  - name: goproxy
    image: k8s.gcr.io/goproxy:0.1
    ports:
    - containerPort: 8080
    readinessProbe:
      tcpSocket:
        port: 8080
      initialDelaySeconds: 5
      periodSeconds: 10
    livenessProbe:
      tcpSocket:
        port: 8080
      initialDelaySeconds: 15
      periodSeconds: 20

Конфигурация проверки TCP очень похожа на проверку HTTP. В следующем примере используются детекторы готовности и живучести. Kubelet отправит первую проверку готовности через 5 секунд после запуска контейнера. Это попытается подключиться к порту 8080 контейнера goproxy. Если проверка прошла успешно, Pod будет помечен как готовый, а kubelet будет продолжать запускать проверку каждые 10 секунд.

КромеreadinessProbe, эта конфигурация включает в себяlivenessзонд. Kubelet запустится в первый раз через 15 секунд после запуска контейнера.livenessзонд. какreadinessКак и зонд, он попытается подключиться к порту 8080 контейнера goproxy. Если обнаружение живучести не удается, контейнер будет перезапущен.

# kubectl apply -f /root/k8s-example/probe/tcp-liveness-readiness.yaml

Через 15 секунд проверьте живучесть, просмотрев события Pod:

# kubectl describe pod goproxy

Используйте именованные порты

Именованные порты контейнера можно использовать для определения живучести HTTP или TCP.

ports:
- name: liveness-port
  containerPort: 8080
  hostPort: 8080
​
livenessProbe:
  httpGet:
    path: /healthz
    port: liveness-port

5 Защита контейнеров с медленным запуском с помощью зондов запуска

Иногда существуют существующие приложения, которым требуется больше времени для инициализации при запуске. Чтобы не влиять на быстрый отклик и не вызывать взаимоблокировку обнаружения, в этом случае установитеlivenessПараметры зондирования сложны. Хитрость заключается в использовании команды для установкиstartupОбнаружение для обнаружения HTTP или TCP можно установить, установивfailureThreshold * periodSecondsпараметры, чтобы убедиться, что есть достаточно времени, чтобы справиться с плохой ситуацией времени запуска.

Итак, предыдущий пример становится:

ports:
- name: liveness-port
  containerPort: 8080
  hostPort: 8080
​
livenessProbe:
  httpGet:
    path: /healthz
    port: liveness-port
  failureThreshold: 1
  periodSeconds: 10
​
startupProbe:
  httpGet:
    path: /healthz
    port: liveness-port
  failureThreshold: 30
  periodSeconds: 10

к счастьюstartupзонд, приложение будет иметь больше всего5 分钟(30 * 10 = 300s)время для завершения его запуска. однаждыstartupПосле успешного обнаружения задача обнаружения в реальном времени возьмет на себя обнаружение контейнера, что может быстро отреагировать на тупиковую ситуацию контейнера. еслиstartupЗонд не удался, контейнер убит через 300 секунд, и согласноrestartPolicyчтобы установить состояние Pod.

6 определенийreadlinessдетектор

Иногда приложения временно не могут предоставлять услуги связи. Например, приложению может потребоваться загрузить большой файл данных или конфигурации при запуске или зависеть от ожидания внешней службы после запуска. В этом случае не хочется ни убивать приложение, ни отправлять ему запрос. Kubernetes предоставляет тесты готовности для обнаружения и смягчения таких ситуаций. Pod, в котором находится контейнер, сообщает информацию, которая еще не готова, и не принимает пропускKubernetes Serviceдвижение.

Примечание. Зонд готовности продолжает работать в течение всего срока службы контейнера.

Конфигурация зонда готовности аналогична конфигурации зонда живучести. Единственная разница заключается в использованииreadinessProbeполе, а не лivenessProbeполе.

readinessProbe:
  exec:
    command:
    - cat
    - /tmp/healthy
  initialDelaySeconds: 5
  periodSeconds: 5

HTTP и TCPreadlinessКонфигурация детектора такжеlivenessКонфигурация детектора та же.

readlinessиlivenessЗонды можно использовать параллельно на одном и том же контейнере. Использование обоих гарантирует, что трафик не отправляется в контейнеры, которые не готовы, и контейнеры перезапускаются в случае сбоя.

7 Настройте детектор

Зонды имеют ряд полей конфигурации, которые можно использовать для точного управления поведением обнаружения живости и готовности:

  • InitialDelaySeconds: количество секунд ожидания после запуска контейнера до инициализации детекторов живости и готовности.По умолчанию 0 секунд, а минимальное значение равно 0.
  • PeriodSeconds: интервал времени (в секундах) для выполнения тестов. По умолчанию 10 секунд. Минимальное значение равно 1.
  • timeoutSeconds: сколько секунд ждать после истечения времени ожидания зонда. Значение по умолчанию — 1 секунда. Минимальное значение равно 1.
  • SuccessThreshold: минимальное количество последовательных успешных попыток, при котором зонд считается успешным после сбоя. Значение по умолчанию — 1. Это значение должно быть равно 1 для зондов живучести. Минимальное значение равно 1.
  • failureThreshold: количество повторных попыток для Kubernetes, когда модуль запускается и обнаруживает сбой. Отказ в случае проверки живучести означает перезапуск контейнера. Заброшенные Поды в случае обнаружения готовности помечаются как не готовые. Значение по умолчанию — 3. Минимальное значение равно 1.

HTTP-зонды можно найти по адресуhttpGetНастройте дополнительные поля на:

  • хост: имя хоста, используемое для подключения, по умолчанию используется IP-адрес пода. Вместо этого также можно установить «Host» в заголовке HTTP.
  • схема: используется для установки метода подключения к хосту (HTTP или HTTPS). По умолчанию используется HTTP.
  • путь: путь для доступа к службе HTTP.
  • httpHeaders: Пользовательские заголовки HTTP в запросе. Поля заголовка HTTP разрешено дублировать.
  • порт: номер порта или имя порта для доступа к контейнеру. Если число должно быть между 1 и 65535.

Для HTTP-зондов kubelet отправляет HTTP-запрос по указанному пути и порту для выполнения зонда. пока неhttpGetсерединаhostустановлено, в противном случае kubelet по умолчанию отправляет зонды на IP-адрес пода. еслиschemeЕсли в поле указано значение HTTPS, kubelet будет пропускать проверку сертификата и отправлять HTTPS-запросы. В большинстве случаев настройка не требуетсяhostполе. Необходимо установитьhostПолевые сценарии, предполагающие, что контейнер прослушивает127.0.0.1, и Pod'shostNetworkполе установлено наtrue. ТакhttpGetсерединаhostполе должно быть установлено в127.0.0.1. Вероятно, более распространенным случаем является то, что если Pod использует виртуальный хост, вам не следует устанавливатьhostполе, но должно быть вhttpHeadersУстановите Хост.

Для зонда kubelet устанавливает соединение зонда на узле (не внутри пода), что означает, что вы не можетеhostконфигурация параметровservice name, потому что kubelet не может разрешитьservice name.