Ця сторінка надає загальний огляд init-контейнерів: спеціалізованих контейнерів, які запускаються перед запуском контейнерів застосунків в Podʼі. Init-контейнери можуть містити утиліти або сценарії налаштування, які відсутні в образі застосунку.
Ви можете вказати init-контейнери в специфікації Podʼа разом із масивом containers (який описує контейнери застосунку).
У Kubernetes sidecar-контейнер — це контейнер, який запускається перед основним контейнером застосунку і продовжує працювати. Цей документ стосується init-контейнерів — контейнерів, які виконуються до завершення під час ініціалізації Podʼа.
У Podʼі може бути кілька контейнерів, які виконують застосунки, але також може бути один чи кілька init-контейнерів, які виконуються до того, як стартують контейнери застосунків.
Init-контейнери точно такі самі, як і звичайні контейнери, за винятком того, що:
Якщо init-контейнер Podʼа зазнає збою, kubelet повторно перезапускає цей init-контейнер, доки він не завершиться успішно. Однак якщо restartPolicy Podʼа дорівнює Never, і init-контейнер зазнає збою під час запуску цього Podʼа, Kubernetes вважає весь Pod невдалим.
Щоб вказати init-контейнер для Podʼа, додайте поле initContainers у специфікацію Podʼа, у вигляді масиву обʼєктів container (аналогічно полю containers застосунку та його вмісту). Дивіться Container в
довідці API для отримання докладнішої інформації.
Статус init-контейнерів повертається у полі .status.initContainerStatuses у вигляді масиву статусів контейнерів (аналогічно полю .status.containerStatuses).
Init-контейнери підтримують всі поля та можливості контейнерів застосунків, включаючи обмеження ресурсів, томи та налаштування безпеки. Однак запити та обмеження ресурсів для init-контейнера обробляються по-іншому, як описано в розділі Спільне використання ресурсів всередині контейнерів.
Звичайні init-контейнери (іншими словами, виключаючи sidecar-контейнери) не підтримують поля lifecycle, livenessProbe, readinessProbe чи startupProbe. Init-контейнери повинні успішно завершити свою роботу перед тим, як Pod може бути готовий; sidecar-контейнери продовжують працювати протягом життєвого циклу Podʼа і підтримують деякі проби. Дивіться sidecar-контейнер для отримання додаткової інформації про ці контейнери.
Якщо ви вказали кілька init-контейнерів для Podʼа, kubelet виконує кожен такий контейнер послідовно. Кожен init-контейнер повинен успішно завершити свою роботу, перш ніж може бути запущено наступний. Коли всі init-контейнери завершать свою роботу, kubelet ініціалізує контейнери застосунків для Podʼа та запускає їх як зазвичай.
Init-контейнери запускаються і завершують свої завдання до того, як розпочнеться робота основного контейнера застосунку. На відміну від sidecar-контейнерів, init-контейнери не продовжують працювати паралельно з основними контейнерами.
Init-контейнери запускаються і завершують свою роботу послідовно, і основний контейнер не починає свою роботу, доки всі init-контейнери успішно не завершать свою роботу.
Init-контейнери не підтримують lifecycle, livenessProbe, readinessProbe чи startupProbe, у той час, як sidecar-контейнери підтримують всі ці проби, щоб керувати своїм життєвим циклом.
Init-контейнери використовують ті самі ресурси (CPU, памʼять, мережу), що й основні контейнери застосунків, але не взаємодіють з ними напряму. Однак вони можуть використовувати спільні томи для обміну даними.
Оскільки init-контейнери мають образи, окремі від контейнерів застосунків, вони мають кілька переваг для коду, повʼязаного із запуском:
FROM іншого образу лише для використання інструменту, такого як sed, awk, python чи dig під час налаштування.Ось кілька ідей, як використовувати init-контейнери:
Очікування на створення Service, використовуючи команду оболонки у вигляді одного рядка, наприклад:
for i in {1..100}; do sleep 1; if nslookup myservice; then exit 0; fi; done; exit 1
Реєстрація Podʼа на віддаленому сервері зі значеннями, отриманими з Downward API за допомогою команди, подібної цій:
curl -X POST http://$MANAGEMENT_SERVICE_HOST:$MANAGEMENT_SERVICE_PORT/register -d 'instance=$(<POD_NAME>)&ip=$(<POD_IP>)'
Очікування певного часу перед запуском контейнера застосунку за допомогою команди, подібної цій:
sleep 60
Клонування репозиторію Git у том
Додавання значень у файл конфігурації та виклик інструменту шаблонування для динамічного створення файлу конфігурації для основного контейнера застосунку. Наприклад, додайте значення POD_IP у конфігурацію та створіть основний файл конфігурації застосунку за допомогою Jinja.
У цьому прикладі визначається простий Pod, який має два init-контейнери. Перший чекає на myservice, а другий — на mydb. Як тільки обидва init-контейнери завершаться, Pod запускає контейнер застосунку зі свого розділу spec.
apiVersion: v1
kind: Pod
metadata:
name: myapp-pod
labels:
app.kubernetes.io/name: MyApp
spec:
containers:
- name: myapp-container
image: busybox:1.28
command: ['sh', '-c', 'echo The app is running! && sleep 3600']
initContainers:
- name: init-myservice
image: busybox:1.28
command: ['sh', '-c', "until nslookup myservice.$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace).svc.cluster.local; do echo waiting for myservice; sleep 2; done"]
- name: init-mydb
image: busybox:1.28
command: ['sh', '-c', "until nslookup mydb.$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace).svc.cluster.local; do echo waiting for mydb; sleep 2; done"]
Ви можете запустити цей Pod, виконавши:
kubectl apply -f myapp.yaml
Вивід буде подібний до цього:
pod/myapp-pod created
І перевірте його статус за допомогою:
kubectl get -f myapp.yaml
Вивід буде подібний до цього:
NAME READY STATUS RESTARTS AGE
myapp-pod 0/1 Init:0/2 0 6m
або докладніше:
kubectl describe -f myapp.yaml
Вивід буде подібний до цього:
Name: myapp-pod
Namespace: default
[...]
Labels: app.kubernetes.io/name=MyApp
Status: Pending
[...]
Init Containers:
init-myservice:
[...]
State: Running
[...]
init-mydb:
[...]
State: Waiting
Reason: PodInitializing
Ready: False
[...]
Containers:
myapp-container:
[...]
State: Waiting
Reason: PodInitializing
Ready: False
[...]
Events:
FirstSeen LastSeen Count From SubObjectPath Type Reason Message
--------- -------- ----- ---- ------------- -------- ------ -------
16s 16s 1 {default-scheduler } Normal Scheduled Successfully assigned myapp-pod to 172.17.4.201
16s 16s 1 {kubelet 172.17.4.201} spec.initContainers{init-myservice} Normal Pulling pulling image "busybox"
13s 13s 1 {kubelet 172.17.4.201} spec.initContainers{init-myservice} Normal Pulled Successfully pulled image "busybox"
13s 13s 1 {kubelet 172.17.4.201} spec.initContainers{init-myservice} Normal Created Created container init-myservice
13s 13s 1 {kubelet 172.17.4.201} spec.initContainers{init-myservice} Normal Started Started container init-myservice
Щоб переглянути логи init-контейнерів у цьому Podʼі, виконайте:
kubectl logs myapp-pod -c init-myservice # Огляд першого init-контейнера
kubectl logs myapp-pod -c init-mydb # Огляд другого init-контейнера
На цей момент ці init-контейнери будуть чекати виявлення Services з назвами mydb та myservice.
Ось конфігурація, яку ви можете використовувати для того, щоб ці Services зʼявилися:
---
apiVersion: v1
kind: Service
metadata:
name: myservice
spec:
ports:
- protocol: TCP
port: 80
targetPort: 9376
---
apiVersion: v1
kind: Service
metadata:
name: mydb
spec:
ports:
- protocol: TCP
port: 80
targetPort: 9377
Щоб створити Services mydb та myservice:
kubectl apply -f services.yaml
Вивід буде подібний до цього:
service/myservice created
service/mydb created
Потім ви побачите, що ці init-контейнери завершаться, і Pod myapp-pod переходить у стан Running:
kubectl get -f myapp.yaml
Вивід буде подібний до цього:
NAME READY STATUS RESTARTS AGE
myapp-pod 1/1 Running 0 9m
Цей простий приклад повинен дати вам натхнення для створення ваших власних init-контейнерів. У розділі Що далі є посилання на більш детальний приклад.
Під час запуску Podʼа kubelet затримує виконання init-контейнерів, доки мережа та сховище не будуть готові. Після цього kubelet виконує init-контейнери Podʼа в порядку, в якому вони зазначені в специфікації Podʼа.
Кожен init-контейнер має успішно завершитися перед тим, як буде запущений наступний контейнер. Якщо контейнер не вдалося запустити через помилку середовища виконання або він завершується з помилкою, його перезапускають згідно з політикою перезапуску Podʼа (restartPolicy). Однак якщо політика перезапуску Podʼа (restartPolicy) встановлена на Always, init-контейнери використовують політику перезапуску OnFailure.
Pod не може бути Ready, поки всі init-контейнери не завершаться успішно. Порти init-контейнерів не агрегуються в Service. Pod, що ініціалізується, перебуває в стані Pending, але повинен мати умову Initialized, встановлену на false.
Якщо Pod перезапускається або був перезапущений, всі init-контейнери мають виконатися знову.
Зміни в специфікації init-контейнерів обмежуються полем образу контейнера. Безпосередня зміна поля image init-контейнера не призводить до перезапуску Podʼа або його перестворення. Якщо Pod ще не було запущено, ці зміни можуть вплинути на те, як він завантажиться.
Для шаблону Podʼа ви зазвичай можете змінити будь-яке поле init-контейнера; наслідки цієї зміни залежать від того, де використовується шаблон Podʼа.
Оскільки init-контейнери можуть бути перезапущені, повторно виконані або виконані заново, код init-контейнерів повинен бути ідемпотентним. Зокрема, код, що записує дані в будь-який том emptyDir, має бути підготовлений до того, що файл виводу вже може існувати.
Init-контейнери мають усі поля контейнера застосунку. Проте Kubernetes забороняє використання readinessProbe, оскільки init-контейнери не можуть визначати готовність окремо від завершення. Це забезпечується під час валідації.
Використовуйте activeDeadlineSeconds в Podʼі, щоб запобігти нескінченним збоям init-контейнерів. Активний крайній термін охоплює init-контейнери. Однак рекомендується використовувати activeDeadlineSeconds лише якщо команди розгортають свій застосунок як Job, оскільки activeDeadlineSeconds впливає навіть після завершення роботи init-контейнера. Pod, який вже працює правильно, буде завершено через activeDeadlineSeconds, якщо ви його налаштуєте.
Назва кожного контейнера застосунку та init-контейнера в Podʼі має бути унікальною; для контейнера, назва якого збігається з назвою іншого, буде згенеровано помилку валідації.
З урахуванням порядку виконання init-контейнерів, sidecar-контейнерів і контейнерів застосунків застосовуються такі правила використання ресурсів:
Квоти та обмеження застосовуються на основі ефективного запиту та обмеження Podʼа.
У Linux розподіл ресурсів для контрольних груп (cgroups) рівня Podʼа ґрунтується на ефективному запиті та обмеженні Podʼа, так само як і для планувальника.
Pod може перезапускатися, що призводить до повторного виконання init-контейнерів, з таких причин:
restartPolicy встановлено в Always, що примушує до перезапуску, а запис про завершення init-контейнера було втрачено через збір сміття.Pod не буде перезапущено, коли змінюється образ init-контейнера, або запис про завершення init-контейнера було втрачено через збір сміття. Це стосується Kubernetes v1.20 і пізніших версій. Якщо ви використовуєте старішу версію Kubernetes, ознайомтеся з документацією версії, яку ви використовуєте.
Дізнайтеся більше про таке: