Налаштування проб життєздатності, готовності та запуску

Ця сторінка показує, як налаштувати проби життєздатності, готовності та запуску для контейнерів.

Kubelet використовує проби життєздатності для визначення моменту перезапуску контейнера. Наприклад, проби життєздатності можуть виявити проблеми, коли застосунок працює, але не може досягти результату. Перезапуск контейнера в такому стані може допомогти зробити застосунок більш доступним, попри помилки.

Загальний шаблон для проб життєздатності — використовувати той самий недорогу HTTP-точку доступу, що й для проб готовності, але з більшим значенням failureThreshold. Це гарантує, що Pod може спостерігатись як не готовий впродовж певного часу перед тим, як примусово завершити його роботу.

Kubelet використовує проби готовності для визначення моменту, коли контейнер готовий приймати трафік. Pod вважається готовим, коли всі його контейнери готові. Одним з використань цього сигналу є контроль за тим, які Podʼи використовуються як бекенди для Service. Коли Pod не готовий, його видаляють з балансувальників навантаження Serviceʼів.

Kubelet використовує проби запуску для визначення моменту запуску застосунку контейнера. Якщо така проба налаштована, проби життєздатності та готовності не починають працювати, поки вона не успішна, щоб переконатися, що ці проби не перешкоджають запуску застосунку. Це може бути використано для впровадження перевірки життєздатності для повільних контейнерів, що дозволяє уникати їхнього вимкнення kubelet перед тим, як вони будуть готові до роботи.

Перш ніж ви розпочнете

Вам треба мати кластер Kubernetes, а також інструмент командного рядка kubectl має бути налаштований для роботи з вашим кластером. Рекомендується виконувати ці настанови у кластері, що має щонайменше два вузли, які не виконують роль вузлів управління. Якщо у вас немає кластера, ви можете створити його, за допомогою minikube або використовувати одну з цих пісочниць:

Визначте команду життєздатності

Багато застосунки, що працюють протягом тривалого часу, зрештою переходять у непрацездатний стан і не можуть відновитися, крім як знову бути перезапущеними. Kubernetes надає проби життєздатності для виявлення та виправлення таких ситуацій.

У цьому завданні ви створите Pod, який запускає контейнер на основі образу registry.k8s.io/busybox. Ось файл конфігурації для Podʼа:

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

У файлі конфігурації можна побачити, що у Podʼа є один Container. Поле periodSeconds вказує, що kubelet повинен виконувати пробу життєздатності кожні 5 секунд. Поле initialDelaySeconds повідомляє kubelet, що він повинен зачекати 5 секунд перед виконанням першої проби. Для виконання проби kubelet виконує команду cat /tmp/healthy у цільовому контейнері. Якщо команда успішно виконується, вона повертає 0, і kubelet вважає контейнер живим і справним. Якщо команда повертає ненульове значення, kubelet примусово зупиняє контейнер і перезапускає його.

Під час запуску контейнера виконується ця команда:

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

Протягом перших 30 секунд життя контейнера існує файл /tmp/healthy. Таким чином, протягом перших 30 секунд команда cat /tmp/healthy повертає код успіху. Після 30 секунд cat /tmp/healthy повертає код невдачі.

Створіть Pod:

kubectl apply -f https://k8s.io/examples/pods/probe/exec-liveness.yaml

Протягом 30 секунд перегляньте події Podʼа:

kubectl describe pod liveness-exec

Виведений текст показує, що жодна проба життєздатності ще не зазнав невдачі:

Type    Reason     Age   From               Message
----    ------     ----  ----               -------
Normal  Scheduled  11s   default-scheduler  Successfully assigned default/liveness-exec to node01
Normal  Pulling    9s    kubelet, node01    Pulling image "registry.k8s.io/busybox"
Normal  Pulled     7s    kubelet, node01    Successfully pulled image "registry.k8s.io/busybox"
Normal  Created    7s    kubelet, node01    Created container liveness
Normal  Started    7s    kubelet, node01    Started container liveness

Після 35 секунд знову перегляньте події Podʼа:

kubectl describe pod liveness-exec

У нижній частині виводу є повідомлення про те, що проби життєздатності зазнали невдачі, і непрацездатні контейнери були примусово зупинені та перезапущені.

Type     Reason     Age                From               Message
----     ------     ----               ----               -------
Normal   Scheduled  57s                default-scheduler  Successfully assigned default/liveness-exec to node01
Normal   Pulling    55s                kubelet, node01    Pulling image "registry.k8s.io/busybox"
Normal   Pulled     53s                kubelet, node01    Successfully pulled image "registry.k8s.io/busybox"
Normal   Created    53s                kubelet, node01    Created container liveness
Normal   Started    53s                kubelet, node01    Started container liveness
Warning  Unhealthy  10s (x3 over 20s)  kubelet, node01    Liveness probe failed: cat: can't open '/tmp/healthy': No such file or directory
Normal   Killing    10s                kubelet, node01    Container liveness failed liveness probe, will be restarted

Почекайте ще 30 секунд та перевірте, що контейнер був перезапущений:

kubectl get pod liveness-exec

Виведений текст показує, що RESTARTS було збільшено. Зауважте, що лічильник RESTARTS збільшується, як тільки непрацездатний контейнер знову переходить у стан виконання:

NAME            READY     STATUS    RESTARTS   AGE
liveness-exec   1/1       Running   1          1m

Визначення HTTP-запиту життєздатності

Ще один вид проб життєздатності використовує HTTP GET-запит. Ось файл конфігурації для Podʼа, який запускає контейнер на основі образу registry.k8s.io/e2e-test-images/agnhost.

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

У файлі конфігурації можна побачити, що у Podʼа є один контейнер. Поле periodSeconds вказує, що kubelet повинен виконувати пробу життєздатності кожні 3 секунди. Поле initialDelaySeconds повідомляє kubelet, що він повинен зачекати 3 секунди перед виконанням першої проби. Для виконання проби kubelet надсилає HTTP GET-запит на сервер, який працює в контейнері та слухає порт 8080. Якщо обробник для шляху /healthz сервера повертає код успіху, kubelet вважає контейнер живим і справним. Якщо обробник повертає код невдачі, ubelet примусово зупиняє контейнер і перезапускає його.

Будь-який код, більший або рівний 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 зупинить та перезапустить контейнер.

Щоб спробувати перевірку стану справності через HTTP, створіть Pod:

kubectl apply -f https://k8s.io/examples/pods/probe/http-liveness.yaml

Через 10 секунд перегляньте події Podʼа, щоб перевірити, що проби життєздатності зазнали невдачі, і контейнер був перезапущений:

kubectl describe pod liveness-http

У випусках після v1.13 налаштування локального HTTP-проксі не впливають на пробу життєздатності через HTTP.

Визначення проби життєздатності через TCP-сокет

Третій тип проби життєздатності використовує TCP сокет. З цією конфігурацією kubelet спробує відкрити зʼєднання з вашим контейнером на вказаному порту. Якщо він може встановити зʼєднання, контейнер вважається справним, якщо ні — це вважається невдачею.

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

Як можна побачити, конфігурація для перевірки TCP досить схожа на перевірку через HTTP. У цьому прикладі використовуються як проби готовності, так і життєздатності. Kubelet надішле першу пробу готовності через 15 секунд після запуску контейнера. Ця проба спробує підʼєднатися до контейнера goproxy на порту 8080. Якщо проба вдається, Pod буде позначений як готовий. Kubelet буде продовжувати виконувати цю перевірку кожні 10 секунд.

Крім проби готовності, ця конфігурація включає пробу життєздатності. Kubelet запустить першу пробу життєздатності через 15 секунд після запуску контейнера. Аналогічно проби готовності, це спроба підʼєднатися до контейнера goproxy на порту 8080. Якщо проба життєздатності не вдається, контейнер буде перезапущено.

Щоб спробувати перевірку життєздатності через TCP, створіть Pod:

kubectl apply -f https://k8s.io/examples/pods/probe/tcp-liveness-readiness.yaml

Через 15 секунд перегляньте події Podʼа, щоб перевірити, що проби життєздатності:

kubectl describe pod goproxy

Визначення проби життєздатності через gRPC

СТАН ФУНКЦІОНАЛУ: Kubernetes v1.27 [stable]

Якщо ваш застосунок реалізує Протокол gRPC перевірки стану справності, цей приклад показує, як налаштувати Kubernetes для його використання для перевірок життєздатності застосунку. Так само ви можете налаштувати проби готовності та запуску.

Ось приклад маніфесту:

apiVersion: v1
kind: Pod
metadata:
  name: etcd-with-grpc
spec:
  containers:
  - name: etcd
    image: registry.k8s.io/etcd:3.5.1-0
    command: [ "/usr/local/bin/etcd", "--data-dir",  "/var/lib/etcd", "--listen-client-urls", "http://0.0.0.0:2379", "--advertise-client-urls", "http://127.0.0.1:2379", "--log-level", "debug"]
    ports:
    - containerPort: 2379
    livenessProbe:
      grpc:
        port: 2379
      initialDelaySeconds: 10

Для використання проби gRPC має бути налаштований port. Якщо ви хочете розрізняти проби різних типів та проби для різних функцій, ви можете використовувати поле service. Ви можете встановити service у значення liveness та вказати вашій точці доступу gRPC перевірки стану справності відповідати на цей запит інакше, ніж коли ви встановлюєте service у значення readiness. Це дозволяє використовувати ту саму точку доступу для різних видів перевірки стану справності контейнера замість прослуховування двох різних портів. Якщо ви хочете вказати свою власну назву сервісу та також вказати тип проби, Kubernetes рекомендує використовувати імʼя, яке складається з цих двох частин. Наприклад: myservice-liveness (використовуючи - як роздільник).

Проблеми конфігурації (наприклад: неправильний порт чи Service, нереалізований протокол перевірки стану справності) вважаються невдачею проби, подібно до проб через HTTP та TCP.

Щоб спробувати перевірку життєздатності через gRPC, створіть Pod за допомогою наступної команди. У наведеному нижче прикладі, Pod etcd налаштований для використання проби життєздатності через gRPC.

kubectl apply -f https://k8s.io/examples/pods/probe/grpc-liveness.yaml

Через 15 секунд перегляньте події Podʼа, щоб перевірити, що перевірка життєздатності не зазнала невдачі:

kubectl describe pod etcd-with-grpc

При використанні проби через gRPC, є кілька технічних деталей, на які варто звернути увагу:

  • Проби запускаються для IP-адреси Podʼа або його імені хосту. Обовʼязково налаштуйте вашу кінецеву точку gRPC для прослуховування IP-адреси Podʼа.
  • Проби не підтримують жодних параметрів автентифікації (наприклад, -tls).
  • Немає кодів помилок для вбудованих проб. Усі помилки вважаються невдачами проби.
  • Якщо ExecProbeTimeout feature gate встановлено у false, grpc-health-probe не дотримується налаштування timeoutSeconds (яке стандартно становить 1 с), тоді як вбудована проба зазнає невдачі через тайм-аут.

Використання іменованого порту

Ви можете використовувати іменований port для проб HTTP та TCP. Проби gRPC не підтримують іменовані порти.

Наприклад:

ports:
- name: liveness-port
  containerPort: 8080

livenessProbe:
  httpGet:
    path: /healthz
    port: liveness-port

Захист контейнерів, що повільно запускаються за допомогою проб запуску

Іноді вам доводиться мати справу з застарілими застосунками, які можуть вимагати додаткового часу запуску при їх першій ініціалізації. У таких випадках може бути складно налаштувати параметри проби життєздатності без компромісів щодо швидкої відповіді на затримки, які мотивували використання такої проби. Суть у тому, щоб налаштувати пробу запуску з тою самою командою, перевіркою через HTTP або TCP, з failureThreshold * periodSeconds, достатньо довгим, щоб покрити найгірший випадок щодо часу запуску.

Отже, попередній приклад стане:

ports:
- name: liveness-port
  containerPort: 8080

livenessProbe:
  httpGet:
    path: /healthz
    port: liveness-port
  failureThreshold: 1
  periodSeconds: 10

startupProbe:
  httpGet:
    path: /healthz
    port: liveness-port
  failureThreshold: 30
  periodSeconds: 10

Завдяки пробі запуску застосунок матиме максимум 5 хвилин (30 * 10 = 300 с), щоб завершити свій запуск. Як тільки проба запуску вдалася один раз, проба життєздатності бере роль на себе, щоб забезпечити швидку відповідь на затримки роботи контейнера. Якщо проба запуску ніколи не вдається, контейнер буде зупинений після 300 с і підпадатиме під restartPolicy Podʼа.

Визначення проб готовності

Іноді застосунки тимчасово не можуть обслуговувати трафік. Наприклад, застосунок може потребувати завантаження великих даних або конфігураційних файлів під час запуску, або залежати від зовнішніх служб після запуску. У таких випадках ви не хочете примусово припиняти роботу застосунку, але ви також не хочете надсилати йому запити. Kubernetes надає проби готовності для виявлення та помʼякшення таких ситуацій. Pod з контейнерами, які повідомляють, що вони не готові, не отримують трафіку через Service Kubernetes.

Проби готовності налаштовуються аналогічно пробам життєздатності. Єдина відмінність полягає в тому, що ви використовуєте поле readinessProbe замість поля livenessProbe.

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

Конфігурація для проб готовності через HTTP та TCP також залишається ідентичною конфігурації пробам життєздатності.

Проби готовності та життєздатності можуть використовуватися паралельно для того самого контейнера. Використання обох може забезпечити, що трафік не досягне контейнера, який не готовий до нього, та що контейнери будуть перезапускатися у разі виникнення несправностей.

Налаштування проб

Проби мають кілька полів, які можна використовувати для більш точного керування поведінкою перевірок запуску, життєздатності та готовності:

  • initialDelaySeconds: Кількість секунд після запуску контейнера, перед тим як будуть запущені перевірки запуску, життєздатності або готовності. Якщо визначено пробу запуску, проби життєздатності та готовності не починаються, поки проба запуску не вдалася. Якщо значення periodSeconds більше, ніж initialDelaySeconds, то значення initialDelaySeconds буде проігнороване. Стандартно — 0 секунд. Мінімальне значення — 0.
  • periodSeconds: Як часто (у секундах) виконувати пробу. Стандартно — 10 секунд. Мінімальне значення — 1.
  • timeoutSeconds: Кількість секунд, після яких проба завершиться по тайм-ауту. Стандартно — 1 секунда. Мінімальне значення — 1.
  • successThreshold: Мінімальна послідовна кількість успіхів для того, щоб проба вважалася успішною після невдачі. Стандартно — 1. Має бути 1 для проб життєздатності та запуску. Мінімальне значення — 1.
  • failureThreshold: Після того, як проба не вдається failureThreshold разів поспіль, Kubernetes вважає, що загальна перевірка невдала: контейнер не готовий/справний. У випадку проби запуску або життєздатності, якщо принаймні failureThreshold проб зазнали невдачі, Kubernetes розглядає контейнер як несправний та виконує перезапуск для цього конкретного контейнера. Kubelet дотримується налаштування terminationGracePeriodSeconds для цього контейнера. Для невдалих проб готовності kubelet продовжує запускати контейнер, який не пройшов перевірку, і також продовжує запускати додаткові проби; через те, що перевірка не пройшла, kubelet встановлює умову Ready для Podʼа у значення false.
  • terminationGracePeriodSeconds: налаштуйте період-допуск для kubelet, щоб чекати між тригером вимкнення невдалих контейнерів та примусовим зупиненням контейнера середовищем виконання. Стандартно — значення успадковується від рівня Podʼа для terminationGracePeriodSeconds (якщо не вказано, то 30 секунд), а мінімальне значення — 1. Див. terminationGracePeriodSeconds на рівні проби для більш детальної інформації.

HTTP проби

HTTP проби мають додаткові поля, які можна встановити в httpGet:

  • host: Імʼя хосту для підключення, стандартно — IP-адреса Podʼа. Ймовірно, ви захочете встановити "Host" в httpHeaders замість цього.
  • scheme: Схема для підключення до хосту (HTTP або HTTPS). Стандартно — "HTTP".
  • path: Шлях до доступу на HTTP сервері. Стандартно — "/".
  • httpHeaders: Власні заголовки, що встановлюються у запиті. HTTP дозволяє повторювані заголовки.
  • port: Імʼя або номер порту для доступу до контейнера. Номер повинен бути в діапазоні від 1 до 65535.

Для HTTP проби kubelet надсилає HTTP-запит на вказаний порт та шлях, щоб виконати перевірку. Kubelet надсилає пробу до IP-адреси Podʼа, якщо адреса не перевизначена необовʼязковим полем host у httpGet. Якщо поле scheme встановлено ​​на HTTPS, kubelet надсилає запит HTTPS, пропускаючи перевірку сертифіката. У більшості сценаріїв ви не хочете встановлювати поле host. Ось один сценарій, коли ви його встановлюєте. Припустимо, що контейнер слухає на 127.0.0.1, а поле hostNetwork Podʼа встановлене ​​на true. Тоді host у httpGet повинен бути встановлений ​​на 127.0.0.1. Якщо ваш Pod спирається на віртуальні хости, що, ймовірно, є більш поширеним випадком, ви не повинні використовувати host, але краще встановити заголовок Host в httpHeaders.

Для HTTP проби kubelet надсилає два заголовки запиту, крім обовʼязкового заголовка Host:

  • User-Agent: Стандартне значення — kube-probe/1.30, де 1.30 — версія kubelet.
  • Accept: Стандартне значення — */*.

Ви можете перевизначити стандартне значення цих двох заголовків, визначивши httpHeaders для проби. Наприклад:

livenessProbe:
  httpGet:
    httpHeaders:
      - name: Accept
        value: application/json

startupProbe:
  httpGet:
    httpHeaders:
      - name: User-Agent
        value: MyUserAgent

Ви також можете видалити ці два заголовки, визначивши їх з порожнім значенням.

livenessProbe:
  httpGet:
    httpHeaders:
      - name: Accept
        value: ""

startupProbe:
  httpGet:
    httpHeaders:
      - name: User-Agent
        value: ""

TCP проби

Для TCP-проби kubelet встановлює зʼєднання проби на вузлі, а не в Podʼі, що означає, що ви не можете використовувати імʼя сервісу в параметрі host, оскільки kubelet не може його розпізнати.

terminationGracePeriodSeconds на рівні проб

СТАН ФУНКЦІОНАЛУ: Kubernetes 1.25 [stable]

У версіях 1.25 і вище користувачі можуть вказувати terminationGracePeriodSeconds на рівні проби в рамках специфікації проби. Коли одночасно встановлені terminationGracePeriodSeconds на рівні Podʼа і на рівні проби, kubelet використовуватиме значення на рівні проби.

При встановленні terminationGracePeriodSeconds слід звернути увагу на наступне:

  • Kubelet завжди враховує поле terminationGracePeriodSeconds на рівні проби, якщо воно присутнє в Podʼі.

  • Якщо у вас є поточні Podʼи, де поле terminationGracePeriodSeconds встановлене і ви більше не бажаєте використовувати індивідуальні терміни відповідного завершення роботи для пробт, вам слід видалити ці Podʼи.

Наприклад:

spec:
  terminationGracePeriodSeconds: 3600  # на рівні Podʼа
  containers:
  - name: test
    image: ...

    ports:
    - name: liveness-port
      containerPort: 8080

    livenessProbe:
      httpGet:
        path: /healthz
        port: liveness-port
      failureThreshold: 1
      periodSeconds: 60
      # Перевизначити `terminationGracePeriodSeconds` на рівні Podʼа #
      terminationGracePeriodSeconds: 60

terminationGracePeriodSeconds на рівні проби не може бути встановлене для проб готовності. Воно буде відхилене API-сервером.

Що далі

Також ви можете прочитати API-посилання на:

Змінено June 20, 2024 at 12:44 PM PST: Sync changest from andygol/k8s-website (36d05bc8a1)