Налаштування проб життєздатності, готовності та запуску
Ця сторінка показує, як налаштувати проби життєздатності, готовності та запуску для контейнерів.
Для отримання додаткової інформації про проби див. Проби життєздатності, готовності та запуску
Kubelet використовує проби життєздатності для визначення моменту перезапуску контейнера. Наприклад, проби життєздатності можуть виявити проблеми, коли застосунок працює, але не може досягти результату. Перезапуск контейнера в такому стані може допомогти зробити застосунок більш доступним, попри помилки.
Загальний шаблон для проб життєздатності — використовує ту саму недорогу HTTP-точку доступу, що й для проб готовності, але з більшим значенням failureThreshold. Це гарантує, що Pod може спостерігатись як не готовий впродовж певного часу перед тим, як примусово завершити його роботу.
Kubelet використовує проби готовності для визначення моменту, коли контейнер готовий приймати трафік. Одним з використань цього сигналу є контроль за тим, які Podʼи використовуються як бекенди для Service. Pod вважається готовим, коли його стан Ready
є true. Коли Pod не готовий, його видаляють з балансувальників навантаження Serviceʼів. Стан Ready
у Pod є false, коли стан Ready
у його Node не є true, коли один з readinessGates
Pod є хибним, або коли принаймні один з його контейнерів не готовий.
Kubelet використовує проби запуску для визначення моменту запуску застосунку контейнера. Якщо така проба налаштована, проби життєздатності та готовності не починають працювати, поки вона не успішна, щоб переконатися, що ці проби не перешкоджають запуску застосунку. Це може бути використано для впровадження перевірки життєздатності для повільних контейнерів, що дозволяє уникати їхнього вимкнення kubelet перед тим, як вони будуть готові до роботи.
Увага:
Проби життєздатності можуть бути потужним засобом відновлення після відмов застосунків, але їх слід використовувати обережно. Проби життєздатності повинні бути налаштовані ретельно, щоб вони дійсно вказували на незворотню відмову застосунку, наприклад, на застрягання.Примітка:
Неправильна реалізація проб життєздатності може призвести до каскадних відмов. Це призводить до перезапуску контейнера при великому навантаженні; невдалих запитів клієнтів через зменшення масштабованості вашого застосунку; та збільшеного навантаження на інші Podʼи через невдалі Podʼи. Розумійте різницю між пробами готовності та життєздатності та коли застосовувати їх для вашого застосунку.Перш ніж ви розпочнете
Вам треба мати кластер 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. Якщо проба на життєздатність не спрацює, контейнер буде перезапущено. Kubelet продовжить виконувати цю перевірку кожні 10 секунд.
Крім проби життєздатності, ця конфігурація включає пробу готовності. Kubelet запустить першу пробу готовності через 15 секунд після запуску контейнера. Аналогічно проби життєздатності, це спроба підʼєднатися до контейнера goproxy
на порту 8080. Якщо проба пройде успішно, Pod буде позначений як готовий і отримає трафік від сервісів. Якщо перевірка готовності не вдасться, то Pod буде позначений як не готовий і не отримає трафік від жодного з сервісів.
Щоб спробувати перевірку життєздатності через 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
(використовуючи -
як роздільник).
Примітка:
На відміну від проб HTTP або TCP, ви не можете вказати порт перевірки стану справності за іменем, але не можете налаштувати власне імʼя для хосту.Проблеми конфігурації (наприклад: неправильний порт чи 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.
Примітка:
Проби готовності працюють у контейнері протягом його всього життєвого циклу.Увага:
Проби готовності та життєздатності не залежать одна від одної для успішного виконання. Якщо ви хочете зачекати перед виконанням проби готовності, вам слід використовуватиinitialDelaySeconds
або startupProbe
.Проби готовності налаштовуються аналогічно пробам життєздатності. Єдина відмінність полягає в тому, що ви використовуєте поле readinessProbe
замість поля livenessProbe
.
readinessProbe:
exec:
command:
- cat
- /tmp/healthy
initialDelaySeconds: 5
periodSeconds: 5
Конфігурація для проб готовності через HTTP та TCP також залишається ідентичною конфігурації пробам життєздатності.
Проби готовності та життєздатності можуть використовуватися паралельно для того самого контейнера. Використання обох може забезпечити, що трафік не досягне контейнера, який не готовий до нього, та що контейнери будуть перезапускатися у разі виникнення несправностей.
Налаштування проб
Проби мають кілька полів, які можна використовувати для більш точного керування поведінкою перевірок запуску, життєздатності та готовності:
initialDelaySeconds
: Кількість секунд після запуску контейнера, перед тим як будуть запущені перевірки запуску, життєздатності або готовності. Якщо визначено пробу запуску, проби життєздатності та готовності не починаються, поки проба запуску не вдалася. Якщо значенняperiodSeconds
більше, ніжinitialDelaySeconds
, то значенняinitialDelaySeconds
буде проігнороване. Стандартно — 0 секунд. Мінімальне значення — 0.periodSeconds
: Як часто (у секундах) виконувати пробу. Стандартно — 10 секунд. Мінімальне значення — 1. Поки контейнер не має статусу Ready,ReadinessProbe
може бути виконаний у час, відмінний від налаштованого інтервалуperiodSeconds
. Це робиться для того, щоб пришвидшити готовність Podʼа.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.31
, де1.31
— версія 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: ""
Примітка:
Коли kubelet перевіряє Pod за допомогою HTTP, він виконує переадресацію тільки в тому випадку, якщо переадресація відбувається на той самий хост. Якщо kubelet отримує 11 або більше переадресувань під час перевірки, проба вважається успішною і створюється відповідна подія:
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 29m default-scheduler Successfully assigned default/httpbin-7b8bc9cb85-bjzwn to daocloud
Normal Pulling 29m kubelet Pulling image "docker.io/kennethreitz/httpbin"
Normal Pulled 24m kubelet Successfully pulled image "docker.io/kennethreitz/httpbin" in 5m12.402735213s
Normal Created 24m kubelet Created container httpbin
Normal Started 24m kubelet Started container httpbin
Warning ProbeWarning 4m11s (x1197 over 24m) kubelet Readiness probe warning: Probe terminated redirects
Якщо kubelet отримує переадресацію, де імʼя хосту відрізняється від запиту, результат проби вважається успішним, і kubelet створює подію для повідомлення про збій переадресації.
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-посилання на:
- Pod, і зокрема: