1 - Образ контейнера
Образ контейнера представляє бінарні дані, які інкапсулюють застосунок та всі його програмні залежності. Образи контейнерів — це виконувані пакунки програмного забезпечення, які можуть працювати окремо і роблять дуже чітко визначені припущення щодо свого середовища виконання.
Зазвичай ви створюєте образ контейнера свого застосунку та розміщуєте його в реєстрі
перш ніж посилатися на нього у Pod.
Ця сторінка надає огляд концепції образів контейнерів.
Примітка:
Якщо ви шукаєте образи контейнерів для випуску Kubernetes (наприклад, v1.31, остання мінорна версія), відвідайте розділ
Завантаження Kubernetes.
Назви образів
Образам контейнерів зазвичай дається назва, така як pause
, example/mycontainer
або kube-apiserver
. Образ також може містити імʼя хосту реєстру; наприклад: fictional.registry.example/imagename
, а також, можливо, номер порту; наприклад: fictional.registry.example:10443/imagename
.
Якщо ви не вказуєте імʼя хосту реєстру, Kubernetes вважає, що ви маєте на увазі публічний реєстр образів Docker. Ви можете змінити цю поведінку, вказавши стандартний реєстр образів у налаштуваннях середовища виконання контейнерів.
Після частини назви образу ви можете додати теґ або даджест (так само, якщо ви використовуєте команди типу docker
чи podman
). Теґи дозволяють ідентифікувати різні версії одного ряду образів. Даджест — унікальний ідентифікатор конкретної версії образу. Даджести є хешами, які визначаються вмістом образу, і вони не змінюються. Теґи можна змініювати, так щоб вони вказували на різні версії образу, даджйести залишаються незмінними.
Теґи образів складаються з малих і великих літер, цифр, підкреслень (_
), крапок (.
) та тире (-
). Довжина теґу може бути до 128 символів. Теґ має відповідати наступному шаблону: [a-zA-Z0-9_][a-zA-Z0-9._-]{0,127}
. Дізнатись більше та знайти інші регулярні вирази для перевірки можна в OCI Distribution Specification. Якщо ви не вказуєте теґ, Kubernetes вважає, що ви маєте на увазі теґ latest
.
Хеш-сума образу складається з назви алгоритму хешу (наприклад, sha256
) і значення хешу. Наприклад: sha256:1ff6c18fbef2045af6b9c16bf034cc421a29027b800e4f9b68ae9b1cb3e9ae07
Додаткову інформацію про формат хешів можна знайти в OCI Image Specification.
Деякі приклади імен образів, які може використовувати Kubernetes:
busybox
— Тільки назва образу, без теґу або хеша. Kubernetes використовує загальний реєстр Docker і теґ latest. (Те саме, що і docker.io/library/busybox:latest
)busybox:1.32.0
— назва образу з теґом. Kubernetes використовує загальний реєстр Docker. (Те саме, що і docker.io/library/busybox:1.32.0
)registry.k8s.io/pause:latest
— назва образу з власного реєстру і теґом latest.registry.k8s.io/pause:3.5
— назва образу з власного реєстру і теґом, який не є останнім.registry.k8s.io/pause@sha256:1ff6c18fbef2045af6b9c16bf034cc421a29027b800e4f9b68ae9b1cb3e9ae07
— назва образу з хешем.registry.k8s.io/pause:3.5@sha256:1ff6c18fbef2045af6b9c16bf034cc421a29027b800e4f9b68ae9b1cb3e9ae07
— назва образу з теґом і хешем. Тільки хеш буде використаний для завантаження.
Оновлення образів
При першому створенні Deployment, StatefulSet, Pod чи іншого обʼєкта, що включає шаблон Pod, стандартна політика завантаження всіх
контейнерів у цьому Pod буде встановлена в IfNotPresent
, якщо вона не вказана явно. Ця політика призводить до того, що kubelet пропускає завантаження образів, якщо вони вже існують.
Політика завантаження образів
imagePullPolicy
для контейнера та теґ образу впливають на те, коли kubelet намагається завантажити (стягнути) вказаний образ.
Ось список значень, які можна встановити для imagePullPolicy
та їхні ефекти:
IfNotPresent
- образ завантажується лише тоді, коли він ще не присутній локально.
Always
- кожен раз, коли kubelet запускає контейнер, kubelet зверетається до реєстру образів для пошуку відповідності між назвою та образом (digest). Якщо у kubelet є образ контейнера з цим точним хешем в кеші локально, kubelet використовує свій кеш образів; в іншому випадку kubelet завантажує образ зі знайденим хешем та використовує його для запуску контейнера.
Never
- kubelet не намагається отримати образ. Якщо образ вже присутній локально, kubelet намагається запустити контейнер; в іншому випадку запуск закінчується невдачею. Див. попередньо завантажені образи для отримання деталей.
Семантика кешування базового постачальника образів робить навіть imagePullPolicy: Always
ефективним, якщо реєстр доступний. Ваше середовище виконання контейнерів може помітити, що шари образів вже існують на вузлі, так що їх не потрібно знову завантажувати.
Примітка:
Ви повинні уникати використання теґу :latest
при розгортанні контейнерів в промисловому оточені, оскільки важко відстежити, яка версія образів запущена, і складніше виконати відкат.
Замість цього використовуйте інший значущий теґ, такий як v1.42.0
і/або хеш.
Щоб переконатися, що Pod завжди використовує ту саму версію образів контейнерів, ви можете вказати хеш образів; замініть <image-name>:<tag>
на <image-name>@<digest>
(наприклад, image@sha256:45b23dee08af5e43a7fea6c4cf9c25ccf269ee113168c19722f87876677c5cb2
).
При використанні теґів образів, якщо реєстр образів змінив код, який представляє теґ вашого образу, ви могли б отримати суміш Podʼів, що запускають старий і новий код. Дайджест образу унікально ідентифікує конкретну версію образу, тому Kubernetes запускає один і той же код кожного разу, коли він запускає контейнер із вказаним імʼям образу та дайджестом. зазначення образу за допомогою дайджесту виправляє код, який ви запускаєте, так що зміна в реєстрі не може призвести до такого змішаного використання версій.
Є сторонні контролери допуску що змінюють Pod (і шаблони pod), коли вони створюються, так що робоче навантаження визначається на основі хешу образу, а не теґу. Це може бути корисно, якщо ви хочете переконатися, що всі ваші робочі навантаження запускають один і той самий код, незалежно від того, які зміни теґів відбуваються в реєстрі.
Стандартні політики завантаження образів
Коли ви (чи контролер) подаєте новий Pod серверу API, ваш кластер встановлює поле imagePullPolicy
при виконанні певних умов:
- якщо ви опускаєте поле
imagePullPolicy
та вказуєте хеш для образів контейнерів, imagePullPolicy
автоматично встановлюється в IfNotPresent
. - якщо ви опускаєте поле
imagePullPolicy
та теґ для образів контейнерів є :latest
, imagePullPolicy
автоматично встановлюється в Always
; - якщо ви опускаєте поле
imagePullPolicy
та не вказуєте теґ для образів контейнерів, imagePullPolicy
автоматично встановлюється в Always
; - якщо ви опускаєте поле
imagePullPolicy
та вказуєте теґ для образів контейнерів, який не є :latest
, imagePullPolicy
автоматично встановлюється в IfNotPresent
.
Примітка:
Значення imagePullPolicy
контейнера завжди встановлюється при першому створенні обʼєкта і не оновлюється, якщо теґ чи хеш образів пізніше зміниться.
Наприклад, якщо ви створите Deployment з образом, теґ якого не є :latest
, і пізніше оновите образ цього Deployment до теґу :latest
, поле imagePullPolicy
не зміниться на Always
. Вам слід вручну змінити політику завантаження для будь-якого обʼєкта після його початкового створення.
Обовʼязкове завантаження образів
Якщо ви хочете завжди виконувати завантаження, ви можете зробити одне з наступного:
- Встановіть
imagePullPolicy
контейнера в Always
. - Опустіть
imagePullPolicy
і використовуйте :latest
як теґ для образів; Kubernetes встановить політику в Always
при подачі Pod. - Опустіть
imagePullPolicy
та теґ для використання образів; Kubernetes встановить політику в Always
при подачі Pod. - Увімкніть контролер допуску AlwaysPullImages.
ImagePullBackOff
Коли kubelet починає створювати контейнери для Pod за допомогою середовища виконання контейнерів, можливо, контейнер перебуває у стані Waiting з причини ImagePullBackOff
.
Статус ImagePullBackOff
означає, що контейнер не може запуститися через те, що Kubernetes не може завантажити образ контейнера (з причин, таких як невірне імʼя образу або спроба завантаження з приватного реєстру без imagePullSecret
). Частина BackOff
вказує на те, що Kubernetes буде продовжувати пробувати завантажити образ зі збільшенням інтервалів між спробами.
Kubernetes збільшує інтервал між кожною спробою до тих пір, поки не досягне вбудованого обмеження, яке становить 300 секунд (5 хвилин).
Завантаження образу відповідно до класу середовища виконання
СТАН ФУНКЦІОНАЛУ:
Kubernetes v1.29 [alpha]
(стандартно увімкнено: false)
У Kubernetes є альфа-підтримка для виконання завантаження образів на основі класу середовища виконання контейнерів Pod.
Якщо ви увімкнете функціональну можливість RuntimeClassInImageCriApi
, kubelet вказує образи контейнерів кортежем (назва образу, обробник), а не лише назва чи хешем образу. Ваше середовище виконання контейнерів може адаптувати свою поведінку залежно від обраного обробника. Завантаження образів на основі класу середовища виконання буде корисним для контейнерів, що використовують віртуальні машини, таких як контейнери Windows Hyper-V.
Послідовне та паралельне завантаження образів
Типово kubelet завантажує образи послідовно. Іншими словами, kubelet надсилає лише один запит на завантаження образу до служби образів одночасно. Інші запити на завантаження образів мають чекати, поки завершиться обробка того, який знаходиться в процесі.
Вузли приймають рішення про завантаження образу незалежно один від одного. Навіть коли ви використовуєте послідовні запити на завантаження образів, два різні вузли можуть завантажувати один і той самий образ паралельно.
Якщо ви хочете увімкнути паралельне завантаження образів, ви можете встановити поле serializeImagePulls
у значення false у конфігурації kubelet. Зі значенням serializeImagePulls
встановленим у false, запити на завантаження образів будуть надсилатись до служби образів негайно, і кілька образів буде завантажено одночасно.
При увімкненні паралельного завантаження образів, будь ласка, переконайтеся, що служба образів вашого середовища виконання контейнерів може обробляти паралельне завантаження образів.
Kubelet ніколи не завантажує кілька образів паралельно від імені одного Pod. Наприклад, якщо у вас є Pod із контейнером ініціалізації та контейнером застосунку, завантаження образів для цих двох контейнерів не буде виконуватись паралельно. Однак якщо у вас є два Podʼи, які використовують різні образи, kubelet завантажує образи паралельно для цих двох різних Podʼів, коли увімкнено паралельне завантаження образів.
Максимальна кількість паралельних завантажень образів
СТАН ФУНКЦІОНАЛУ:
Kubernetes v1.27 [alpha]
Коли serializeImagePulls
встановлено в значення false, kubelet стандартно не обмежує максимальну кількість образів, які завантажуються одночасно. Якщо ви хочете обмежити кількість паралельних завантажень образів, ви можете встановити поле maxParallelImagePulls
у конфігурації kubelet. Зі значенням maxParallelImagePulls
в n, тільки n образів можуть завантажуватися одночасно, і будь-яке завантаження образу за межами n буде чекати, поки завершиться принаймні одне завантаження образу, яке вже триває.
Обмеження кількості паралельних завантажень образів допоможе уникнути зайвого використання пропускної здатності мережі або дискових операцій вводу/виводу, коли увімкнено паралельне завантаження образів.
Ви можете встановити maxParallelImagePulls
на позитивне число, яке більше або рівне 1. Якщо ви встановите maxParallelImagePulls
більше або рівне 2, ви повинні встановити serializeImagePulls
в значення false. Kubelet не буде запущено з недійсними налаштуваннями maxParallelImagePulls
.
Мультиархітектурні образи з індексами образів
Окрім надання бінарних образів, реєстр контейнерів також може обслуговувати індекс образу контейнера. Індекс образу може посилатися на кілька маніфестів образу для версій контейнера, специфічних для архітектури. Ідея полягає в тому, що ви можете мати імʼя для образу (наприклад: pause
, example/mycontainer
, kube-apiserver
) та дозволити різним системам отримувати правильний бінарний образ для використання на їхній архітектурі машини.
Сам Kubernetes зазвичай називає образи контейнерів із суфіксом -$(ARCH)
. З метою забезпечення сумісності з попередніми версіями, будь ласка, генеруйте старіші образи із суфіксами. Ідея полягає в тому, щоб створити, наприклад, образ pause
, який має маніфест для всіх архітектур, та скажімо pause-amd64
, який є сумісним з попередніми конфігураціями або файлами YAML, які можуть містити жорстко закодовані образи із суфіксами.
Використання приватних реєстрів
Приватні реєстри можуть вимагати ключі для читання образів з них. Облікові дані можна надати кількома способами:
- Налаштування вузлів для автентифікації в приватному реєстрі
- всі Podʼи можуть читати будь-які налаштовані приватні реєстри
- вимагає конфігурації вузла адміністратором кластера
- Постачальник облікових даних Kubelet для динамічного отримання облікових даних для приватних реєстрів
- kubelet може бути налаштований для використання втулка від постачальника облікових даних для відповідного приватного реєстру.
- Попередньо завантажені образи
- всі Podʼи можуть використовувати будь-які образи, кешовані на вузлі
- вимагає доступу до кореня на всіх вузлах для налаштування
- Вказання ImagePullSecrets на Pod
- лише Podʼи, які надають власні ключі, можуть отримувати доступ до приватного реєстру
- Постачальник специфічний для вендора або локальні розширення
- якщо ви використовуєте власну конфігурацію вузла, ви (або ваш постачальник хмари) можете реалізувати власний механізм автентифікації вузла в реєстрі контейнерів.
Ці варіанти пояснюються докладніше нижче.
Налаштування вузлів для автентифікації в приватному реєстрі
Конкретні інструкції щодо встановлення облікових даних залежать від середовища виконання контейнерів та реєстру, який ви вибрали для використання. Вам слід звертатися до документації щодо вашого рішення для отримання найточнішої інформації.
Для прикладу конфігурування приватного реєстру образів контейнерів дивіться завдання Завантаження образу з приватного реєстру. У цьому прикладі використовується приватний реєстр в Docker Hub.
Постачальник облікових даних Kubelet для витягування автентифікованих образів
Примітка:
Цей підхід добре підходить, коли kubelet повинен динамічно отримувати облікові дані реєстру. Зазвичай використовується для реєстрів, наданих хмарними провайдерами, де токени автентифікації мають обмежений термін дії.Ви можете налаштувати kubelet для виклику бінарного втулка, щоб динамічно отримувати облікові дані реєстру для образу контейнера. Це найнадійніший та універсальний спосіб отримання облікових даних для приватних реєстрів, але також вимагає конфігурації kubelet для його увімкнення.
Докладніше дивіться Налаштування постачальника облікових даних образу kubelet.
Тлумачення файлу config.json
Тлумачення config.json
відрізняється між оригінальною реалізацією Docker та тлумаченням Kubernetes. У Docker ключі auths
можуть вказувати тільки кореневі URL-адреси, тоді як Kubernetes дозволяє використовувати глобальні URL-адреси, а також шляхи, які відповідають префіксу. Єдиним обмеженням є те, що глобальні шаблони (*
) повинні включати крапку (.
) для кожного піддомену. Кількість піддоменів, що мають збіг, повинна дорівнювати кількості глобальних шаблонів (*.
), наприклад:
*.kubernetes.io
не збігатиметься з kubernetes.io
, але збігатиметься з abc.kubernetes.io
*.*.kubernetes.io
не збігатиметься з abc.kubernetes.io
, але збігатиметься з abc.def.kubernetes.io
prefix.*.io
збігатиметься з prefix.kubernetes.io
*-good.kubernetes.io
збігатиметься з prefix-good.kubernetes.io
Це означає, що файл config.json
, подібний до цього, є дійсним:
{
"auths": {
"my-registry.io/images": { "auth": "…" },
"*.my-registry.io/images": { "auth": "…" }
}
}
Операції отримання образів тепер будуть передавати облікові дані CRI контейнеру для кожного дійсного шаблону. Наприклад, образи контейнера,
вказані нижче, успішно збігатимуться:
my-registry.io/images
my-registry.io/images/my-image
my-registry.io/images/another-image
sub.my-registry.io/images/my-image
Але не:
a.sub.my-registry.io/images/my-image
a.b.sub.my-registry.io/images/my-image
Kubelet виконує операції отримання образів послідовно для кожного знайденого облікового запису. Це означає, що можливі кілька записів у config.json
для різних шляхів:
{
"auths": {
"my-registry.io/images": {
"auth": "…"
},
"my-registry.io/images/subpath": {
"auth": "…"
}
}
}
Тепер, якщо контейнер вказує образ my-registry.io/images/subpath/my-image
,
то kubelet спробує завантажити його з обох джерел автентифікації, якщо завантеження з одного з них виявиться невдалим.
Попередньо завантажені образи
Примітка:
Цей підхід підходить, якщо ви можете контролювати конфігурацію вузла. Він не буде надійно працювати, якщо ваш постачальник хмари управляє вузлами та автоматично їх замінює.Типово kubelet намагається отримати кожен образ з вказаного реєстру. Однак якщо властивість imagePullPolicy
контейнера встановлена на IfNotPresent
або Never
,
то використовується локальний образ (переважно або виключно, відповідно).
Якщо ви хочете покладатися на попередньо завантажені образи як заміну автентифікації в реєстрі, вам слід переконатися, що всі вузли кластера мають однакові попередньо завантажені образи.
Це може бути використано для попереднього завантаження певних образів для швидкості або як альтернатива автентифікації в приватному реєстрі.
Всі Podʼи матимуть доступ на читання до будь-яких попередньо завантажених образів.
Вказання ImagePullSecrets для Pod
Примітка:
Це рекомендований підхід для запуску контейнерів на основі образів з приватних реєстрів.Kubernetes підтримує вказання ключів реєстру образів контейнерів для Pod. imagePullSecrets
повинні бути всі в тому ж просторі імен, що й Pod. Зазначені Secrets повинні бути типу kubernetes.io/dockercfg
або kubernetes.io/dockerconfigjson
.
Створення Secret з Docker-конфігом
Вам потрібно знати імʼя користувача, пароль реєстру та адресу електронної пошти клієнта для автентифікації в реєстрі, а також його імʼя хосту. Виконайте наступну команду, підставивши відповідні значення замість написів у верхньому регістрі:
kubectl create secret docker-registry <name> \
--docker-server=DOCKER_REGISTRY_SERVER \
--docker-username=DOCKER_USER \
--docker-password=DOCKER_PASSWORD \
--docker-email=DOCKER_EMAIL
Якщо у вас вже є файл облікових даних Docker, ніж використовувати вищезазначену
команду, ви можете імпортувати файл облікових даних як Secrets Kubernetes. Створення Secret на основі наявних облікових даних Docker пояснює, як це зробити.
Це особливо корисно, якщо ви використовуєте кілька приватних реєстрів контейнерів, оскільки kubectl create secret docker-registry
створює Secret, який працює лише з одним приватним реєстром.
Примітка:
Podʼи можуть посилатися лише на ключі реєстру образів у своєму власному просторі імен, так що цей процес слід виконати один раз для кожного простору імен.Посилання на imagePullSecrets для Pod
Тепер ви можете створювати Podʼи, які посилаються на цей secret, додавши розділ imagePullSecrets
до визначення Pod. Кожен елемент у масиві imagePullSecrets
може посилатися тільки на Secret у тому ж просторі імен.
Наприклад:
cat <<EOF > pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: foo
namespace: awesomeapps
spec:
containers:
- name: foo
image: janedoe/awesomeapp:v1
imagePullSecrets:
- name: myregistrykey
EOF
cat <<EOF >> ./kustomization.yaml
resources:
- pod.yaml
EOF
Це слід робити для кожного Podʼа, який використовує приватний реєстр.
Однак налаштування цього поля можна автоматизувати, встановивши imagePullSecrets в ресурс ServiceAccount.
Перевірте Додавання ImagePullSecrets до облікового запису служби для докладних інструкцій.
Ви можете використовувати це разом із .docker/config.json
на рівні вузла. Облікові дані обʼєднанні.
Сценарії використання
Існує кілька рішень для конфігурації приватних реєстрів. Ось деякі типові сценарії використання та рекомендовані рішення.
- Кластер, в якому використовуються лише непроприєтарні (наприклад, відкриті) образи. Немає потреби приховувати образи.
- Використовуйте відкриті образи з відкритого реєстру.
- Конфігурація не потрібна.
- Деякі постачальники хмари автоматично кешують або дзеркалюють відкриті образи, що підвищує доступність та скорочує час їх отримання.
- Кластер, в якому використовуються деякі проприєтарні образи, які повинні бути невидимими для інших компаній, але доступними для всіх користувачів кластера.
- Використовуйте приватний реєстр.
- Можлива ручна конфігурація на вузлах, які повинні мати доступ до приватного реєстру.
- Або запустіть внутрішній приватний реєстр за вашим фаєрволом з відкритим доступом на читання.
- Не потрібна конфігурація Kubernetes.
- Використовуйте сервіс реєстрації образів контейнерів, який контролює доступ до образів.
- Він працюватиме краще з автомасштабуванням кластера, ніж ручна конфігурація вузла.
- Або на кластері, де зміна конфігурації вузла незручна, використовуйте
imagePullSecrets
.
- Кластер із проприєтарними образами, кілька з яких вимагають строгого контролю доступу.
- Переконайтеся, що контролер доступу AlwaysPullImages активний. У противному випадку всі Podʼи потенційно мають доступ до всіх образів.
- Перемістіть конфіденційні дані в ресурс "Secret", а не додавайте їх в образ.
- Багатокористувацький кластер, де кожен орендар потребує власного приватного реєстру.
- Переконайтеся, що контролер доступу AlwaysPullImages активний. У противному випадку всі Podʼи всіх орендарів потенційно мають доступ до всіх образів.
- Запустіть приватний реєстр з обовʼязковою авторизацією.
- Створіть обліковий запис реєстру для кожного орендара, розмістіть його в Secret та внесіть Secret в кожний простір імен орендаря.
- Орендар додає цей Secret до imagePullSecrets кожного простору імен.
Якщо вам потрібен доступ до декількох реєстрів, ви можете створити Secret для кожного реєстру.
Застарілий вбудований постачальник облікових даних kubelet
У старших версіях Kubernetes kubelet мав пряму інтеграцію з обліковими даними хмарного постачальника. Це давало йому можливість динамічно отримувати облікові дані для реєстрів образів.
Існувало три вбудовані реалізації інтеграції облікових записів kubelet: ACR (Azure Container Registry), ECR (Elastic Container Registry) та GCR (Google Container Registry).
Докладніше про застарілий механізм можна прочитати в документації версії Kubernetes, яку ви використовуєте. У версіях Kubernetes від v1.26 до v1.31 він відсутній, тому вам потрібно або:
- налаштувати постачальника облікових записів kubelet на кожному вузлі
- вказати облікові дані для отримання образів, використовуючи
imagePullSecrets
та принаймні один Secret
Що далі
3 - Клас виконання
СТАН ФУНКЦІОНАЛУ:
Kubernetes v1.20 [stable]
Ця сторінка описує ресурс RuntimeClass та механізм вибору середовища виконання.
RuntimeClass — це функція для вибору конфігурації середовища виконання контейнерів. Конфігурація середовища виконання контейнерів використовується для запуску контейнерів у Pod.
Мотивація
Ви можете встановити різне значення RuntimeClass для різних Pod, щоб забезпечити баланс між продуктивністю та безпекою. Наприклад, якщо частина вашого завдання вимагає високого рівня підтвердження захищеності інформації, ви можете вибрати планування цих Pod так, щоб вони працювали в середовищі виконання контейнерів, яке використовує апаратну віртуалізацію. Таким чином ви скористаєтеся додатковою ізоляцією альтернативного середовища коштом деякого додаткового навантаження.
Ви також можете використовувати RuntimeClass для запуску різних Pod з однаковим середовищем виконання, але з різними налаштуваннями.
Налаштування
- Налаштуйте впровадження CRI на вузлах (залежить від середовища виконання).
- Створіть відповідні ресурси RuntimeClass.
Конфігурації, доступні через RuntimeClass, залежать від конкретної реалізації інтерфейсу контейнера (CRI). Для отримання інструкцій щодо налаштування перегляньте відповідну документацію (нижче) для вашої реалізації CRI.
Примітка:
Стандартно RuntimeClass передбачає однорідну конфігурацію вузла в усьому кластері (що означає, що всі вузли налаштовані однаковим чином щодо контейнерних середовищ). Щоб підтримувати різнорідні конфігурації вузлів, див.
Планування нижче.
Кожна конфігурація має відповідний handler
, на який посилається RuntimeClass. Handler повинен бути дійсним імʼям DNS-мітки.
2. Створіть відповідні ресурси RuntimeClass
Кожна конфігурація, налаштована на кроці 1, повинна мати асоційованій handler
, який ідентифікує конфігурацію. Для кожного handler створіть обʼєкт RuntimeClass.
Ресурс RuntimeClass наразі має всього 2 значущі поля: імʼя RuntimeClass (metadata.name
) та handler (handler
). Визначення обʼєкта виглядає наступним чином:
# RuntimeClass визначений у групі API node.k8s.io
apiVersion: node.k8s.io/v1
kind: RuntimeClass
metadata:
# Імʼя, за яким буде викликано RuntimeClass.
# RuntimeClass - ресурс без простору імен.
name: myclass
# Імʼя відповідної конфігурації CRI
handler: myconfiguration
Імʼя обʼєкта RuntimeClass повинно бути дійсним імʼям DNS-піддомену.
Примітка:
Рекомендується обмежити операції запису RuntimeClass (create/update/patch/delete), щоб вони були доступні тільки адміністраторам кластера. Це, як правило, типове значення. Докладніше див.
Огляд авторизації.
Використання
Після налаштування RuntimeClass для кластера, ви можете вказати runtimeClassName
в специфікації Pod, щоб використовувати його. Наприклад:
apiVersion: v1
kind: Pod
metadata:
name: mypod
spec:
runtimeClassName: myclass
# ...
Це доручить kubelet використовувати названий RuntimeClass для запуску цього Podʼа. Якщо зазначений RuntimeClass не існує або CRI не може виконати відповідний handler, Pod увійде в термінальну фазу Failed
. Шукайте відповідну подію для отримання повідомлення про помилку.
Якщо runtimeClassName
не вказано, буде використовуватися стандартний обробник, що еквівалентно поведінці при вимкненні функції RuntimeClass.
Конфігурація CRI
Докладніше про налаштування CRI див. в Інсталяції CRI.
Обробники Runtime налаштовуються через конфігурацію containerd за шляхом
/etc/containerd/config.toml
. Дійсні обробники налаштовуються в розділі runtimes:
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.${HANDLER_NAME}]
Докладніше див. у документації з конфігурації containerd:
Обробники Runtime налаштовуються через конфігурацію CRI-O за шляхом /etc/crio/crio.conf
. Дійсні обробники налаштовуються в таблиці crio.runtime:
[crio.runtime.runtimes.${HANDLER_NAME}]
runtime_path = "${PATH_TO_BINARY}"
Докладніше див. у документації з конфігурації CRI-O.
Планування
СТАН ФУНКЦІОНАЛУ:
Kubernetes v1.16 [beta]
Зазначаючи поле scheduling
для RuntimeClass, ви можете встановити обмеження, щоб
забезпечити, що Podʼи, які працюють із цим RuntimeClass, плануються на вузли, які його підтримують. Якщо scheduling
не встановлено, припускається, що цей RuntimeClass підтримується всіма вузлами.
Щоб гарантувати, що Podʼи потрапляють на вузли, які підтримують конкретний RuntimeClass, цей набір вузлів повинен мати спільні мітки, які потім обираються полем runtimeclass.scheduling.nodeSelector
. NodeSelector RuntimeClass обʼєднується з nodeSelector Pod під час допуску, фактично беручи перетин множини вузлів, обраних кожним.
Якщо підтримувані вузли позначені, щоб завадити запуску інших Podʼів з іншим RuntimeClass на вузлі, ви можете додати tolerations
до RuntimeClass. Як із nodeSelector
, tolerations обʼєднуються з tolerations Pod у доступі, фактично беручи обʼєднання множини вузлів, які влаштовують всіх.
Щоб дізнатися більше про налаштування селектора вузла і tolerations, див. Призначення Podʼів вузлам.
Надмірність Pod
СТАН ФУНКЦІОНАЛУ:
Kubernetes v1.24 [stable]
Ви можете вказати ресурси overhead, що повʼязані із запуском Pod. Вказівка надмірності дозволяє кластеру (включаючи планувальник) враховувати це при прийнятті рішень про Podʼи та ресурси.
Надмірність Podʼа визначається через поле overhead
в RuntimeClass. За допомогою цього поля ви можете вказати надмірність запуску Podʼів, що використовують цей RuntimeClass, та забезпечити облік цих надмірностей в Kubernetes.
Що далі
4 - Хуки життєвого циклу контейнера
На цій сторінці описано, як контейнери, керовані kubelet, можуть використовувати фреймворк хука життєвого циклу контейнера для запуску коду, викликаного подіями під час управління їх життєвим циклом.
Огляд
Аналогічно багатьом фреймворкам програмування, які мають хуки життєвого циклу компонентів, таким як Angular, Kubernetes надає контейнерам хуки життєвого циклу. Ці хуки дозволяють контейнерам бути в курсі подій у своєму циклі управління та виконувати код, реалізований в обробнику, коли відповідний хук життєвого циклу виконується.
Хуки контейнера
До контейнерів виносяться два хуки:
PostStart
Цей хук виконується негайно після створення контейнера. Однак немає гарантії, що хук виконається до ENTRYPOINT контейнера. До обробника не передаються параметри.
PreStop
Цей хук викликається негайно перед тим, як контейнер буде завершено через запит API або подію управління, таку як невдача проби на живучість/запуску, передумови, конфлікт ресурсів та інші. Звернення до хука PreStop
не вдасться, якщо контейнер вже перебуває у стані завершення або виконання, і хук повинен завершити виконання до того, як може бути відправлений сигнал TERM для зупинки контейнера. Відлік пільгового періоду припинення Pod починається до виконання хуку PreStop
, тому, незалежно від результату обробника, контейнер врешті-решт закінчиться протягом пільгового періоду припинення Pod. Жодні параметри не передаються обробнику.
Докладний опис поведінки припинення роботи Podʼів можна знайти в Припинення роботи Podʼа.
Реалізації обробника хуків
Контейнери можуть мати доступ до хука, реалізувавши та реєструючи обробник для цього хука. Існують три типи обробників хука, які можна реалізувати для контейнерів:
- Exec — Виконує конкретну команду, таку як
pre-stop.sh
, всередині cgroups та namespaces контейнера. Ресурси, спожиті командою, зараховуються на рахунок контейнера. - HTTP — Виконує HTTP-запит до конкретного endpoint в контейнері.
- Sleep — Призупиняє контейнер на вказаний час. Обробник "Sleep" є функцією бета-рівня типово увімкненою через функціональну можливість
PodLifecycleSleepAction
.
Виконання обробника хука
Коли викликається хук управління життєвим циклом контейнера, система управління Kubernetes виконує обробник відповідно до дії хука, httpGet
, tcpSocket
та sleep
виконуються процесом kubelet, а exec
виконується в контейнері.
Виклик обробника хука PostStart
ініціюється при створенні контейнера, тобто точка входу контейнера ENTRYPOINT і хук PostStart
спрацьовують одночасно. Однак, якщо хук PostStart
виконується занадто довго або зависає, це може завадити контейнеру перейти у стан running
.
Хуки PreStop
не викликаються асинхронно від сигналу зупинки контейнера; хук повинен завершити своє виконання до того, як може бути відправлений сигнал TERM. Якщо хук PreStop
затримується під час виконання, фаза Pod буде Terminating
, і залишиться такою, поки Pod не буде вбито після закінчення його terminationGracePeriodSeconds
. Цей період припинення роботи застосовується до загального часу, необхідного як для виконання хука PreStop
, так і для зупинки контейнера. Якщо, наприклад, terminationGracePeriodSeconds
дорівнює 60, і хук займає 55 секунд для завершення, а контейнер зупиняється нормально через 10 секунд після отримання сигналу, то контейнер буде вбитий перш, ніж він зможе завершити роботу, оскільки terminationGracePeriodSeconds
менше, ніж загальний час (55+10), необхідний для цих двох подій.
Якщо хук PostStart
або PreStop
не вдасться, він вбиває контейнер.
Користувачам слід робити свої обробники хуків якомога легкими. Проте є випадки, коли довгострокові команди мають сенс, наприклад, коли потрібно зберегти стан перед зупинкою контейнера.
Гарантії доставки хуків
Постачання хука призначено бути принаймні одноразовим, що означає, що хук може бути викликано кілька разів для будь-якої події, такої як для PostStart
чи PreStop
. Це залежить від реалізації хука.
Як правило, здійснюються лише разові доставки. Якщо, наприклад, приймач HTTP-хука не працює і не може приймати трафік, спроба повторно надіслати не відбувається. Однак у деяких рідкісних випадках може статися подвійна доставка. Наприклад, якщо kubelet перезапускається посеред надсилання хука, хук може бути повторно відправлений після того, як kubelet повернеться.
Налагодження обробників хуків
Логи обробника хука не відображаються в подіях Pod. Якщо обробник відмовляється з будь-якої причини, він розсилає подію. Для PostStart
це подія FailedPostStartHook
, а для PreStop
це подія FailedPreStopHook
. Щоб згенерувати подію FailedPostStartHook
, змініть lifecycle-events.yaml файл, щоб змінити команду postStart на "badcommand" та застосуйте його. Ось приклад виводу події, який ви побачите після виконання kubectl describe pod lifecycle-demo
:
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 7s default-scheduler Successfully assigned default/lifecycle-demo to ip-XXX-XXX-XX-XX.us-east-2...
Normal Pulled 6s kubelet Successfully pulled image "nginx" in 229.604315ms
Normal Pulling 4s (x2 over 6s) kubelet Pulling image "nginx"
Normal Created 4s (x2 over 5s) kubelet Created container lifecycle-demo-container
Normal Started 4s (x2 over 5s) kubelet Started container lifecycle-demo-container
Warning FailedPostStartHook 4s (x2 over 5s) kubelet Exec lifecycle hook ([badcommand]) for Container "lifecycle-demo-container" in Pod "lifecycle-demo_default(30229739-9651-4e5a-9a32-a8f1688862db)" failed - error: command 'badcommand' exited with 126: , message: "OCI runtime exec failed: exec failed: container_linux.go:380: starting container process caused: exec: \"badcommand\": executable file not found in $PATH: unknown\r\n"
Normal Killing 4s (x2 over 5s) kubelet FailedPostStartHook
Normal Pulled 4s kubelet Successfully pulled image "nginx" in 215.66395ms
Warning BackOff 2s (x2 over 3s) kubelet Back-off restarting failed container
Що далі