Це багатосторінковий друкований вигляд цього розділу. Натисність щоб друкувати.

Повернутися до звичайного перегляду сторінки.

Контейнери

Технологія для упаковки застосунку разом з його залежностями оточення виконання.

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

Контейнери відокремлюють застосунки від базової інфраструктури хоста Це полегшує розгортання в різних хмарних або ОС-середовищах.

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

Образи контейнерів

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

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

Середовище виконання контейнерів

Основний компонент, який дозволяє Kubernetes ефективно запускати контейнери. Він відповідає за керування виконанням і життєвим циклом контейнерів у середовищі Kubernetes.

Kubernetes підтримує середовища виконання контейнерів, такі як containerd, CRI-O, та будь-яку іншу реалізацію Kubernetes CRI (інтерфейс виконання контейнерів).

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

Ви також можете використовувати RuntimeClass для запуску різних Podʼів з однаковим контейнером, але з різними налаштуваннями.

1 - Образ контейнера

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

Зазвичай ви створюєте образ контейнера свого застосунку та розміщуєте його в реєстрі перш ніж посилатися на нього у Pod.

Ця сторінка надає огляд концепції образів контейнерів.

Назви образів

Образам контейнерів зазвичай дається назва, така як 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 ефективним, якщо реєстр доступний. Ваше середовище виконання контейнерів може помітити, що шари образів вже існують на вузлі, так що їх не потрібно знову завантажувати.

Щоб переконатися, що 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 контейнера в 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]
У Kubernetes є альфа-підтримка для виконання завантаження образів на основі класу середовища виконання контейнерів Pod.

Якщо ви увімкнете feature gate 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.

Тлумачення файлу 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, який працює лише з одним приватним реєстром.

Посилання на 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 на рівні вузла. Облікові дані обʼєднанні.

Сценарії використання

Існує кілька рішень для конфігурації приватних реєстрів. Ось деякі типові сценарії використання та рекомендовані рішення.

  1. Кластер, в якому використовуються лише непроприєтарні (наприклад, відкриті) образи. Немає потреби приховувати образи.
    • Використовуйте відкриті образи з відкритого реєстру.
      • Конфігурація не потрібна.
      • Деякі постачальники хмари автоматично кешують або дзеркалюють відкриті образи, що підвищує доступність та скорочує час їх отримання.
  2. Кластер, в якому використовуються деякі проприєтарні образи, які повинні бути невидимими для інших компаній, але доступними для всіх користувачів кластера.
    • Використовуйте приватний реєстр.
      • Можлива ручна конфігурація на вузлах, які повинні мати доступ до приватного реєстру.
    • Або запустіть внутрішній приватний реєстр за вашим фаєрволом з відкритим доступом на читання.
      • Не потрібна конфігурація Kubernetes.
    • Використовуйте сервіс реєстрації образів контейнерів, який контролює доступ до образів.
      • Він працюватиме краще з автомасштабуванням кластера, ніж ручна конфігурація вузла.
    • Або на кластері, де зміна конфігурації вузла незручна, використовуйте imagePullSecrets.
  3. Кластер із проприєтарними образами, кілька з яких вимагають строгого контролю доступу.
    • Переконайтеся, що контролер доступу AlwaysPullImages активний. У противному випадку всі Podʼи потенційно мають доступ до всіх образів.
    • Перемістіть конфіденційні дані в ресурс "Secret", а не додавайте їх в образ.
  4. Багатокористувацький кластер, де кожен орендар потребує власного приватного реєстру.
    • Переконайтеся, що контролер доступу 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.30 він відсутній, тому вам потрібно або:

  • налаштувати постачальника облікових записів kubelet на кожному вузлі
  • вказати облікові дані для отримання образів, використовуючи imagePullSecrets та принаймні один Secret

Що далі

2 - Середовище контейнера

Ця сторінка описує ресурси, доступні контейнерам в середовищі контейнера.

Середовище контейнера

Середовище контейнера Kubernetes надає кілька важливих ресурсів контейнерам:

  • Файлову систему, яка є комбінацією образу та одного чи декількох томів.
  • Інформацію про сам контейнер.
  • Інформацію про інші обʼєкти в кластері.

Інформація про контейнер

hostname контейнера є імʼям Pod, в якому він працює. Воно доступне через команду hostname або виклик функції gethostname у бібліотеці libc.

Імʼя та простір імен Pod доступні як змінні середовища через downward API.

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

Інформація про кластер

Список всіх служб, які були активні при створенні контейнера, доступний цьому контейнеру як змінні середовища. Цей список обмежений службами в межах того ж простору імен, що й новий Pod контейнера, та службами керування Kubernetes.

Для служби з імʼям foo, яка повʼязана з контейнером із імʼям bar, визначаються наступні змінні:

FOO_SERVICE_HOST=<хост, на якому працює служба>
FOO_SERVICE_PORT=<порт, на якому працює служба>

Служби мають виділені IP-адреси які доступні для контейнера через DNS, якщо увімкнено надбудову DNS.

Що далі

3 - Клас виконання

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

Ця сторінка описує ресурс RuntimeClass та механізм вибору середовища виконання.

RuntimeClass — це функція для вибору конфігурації середовища виконання контейнерів. Конфігурація середовища виконання контейнерів використовується для запуску контейнерів у Pod.

Мотивація

Ви можете встановити різне значення RuntimeClass для різних Pod, щоб забезпечити баланс між продуктивністю та безпекою. Наприклад, якщо частина вашого завдання вимагає високого рівня підтвердження захищеності інформації, ви можете вибрати планування цих Pod так, щоб вони працювали в середовищі виконання контейнерів, яке використовує апаратну віртуалізацію. Таким чином ви скористаєтеся додатковою ізоляцією альтернативного середовища коштом деякого додаткового навантаження.

Ви також можете використовувати RuntimeClass для запуску різних Pod з однаковим середовищем виконання, але з різними налаштуваннями.

Налаштування

  1. Налаштуйте впровадження CRI на вузлах (залежить від середовища виконання).
  2. Створіть відповідні ресурси RuntimeClass.

1. Налаштуйте впровадження CRI на вузлах

Конфігурації, доступні через RuntimeClass, залежать від конкретної реалізації інтерфейсу контейнера (CRI). Для отримання інструкцій щодо налаштування перегляньте відповідну документацію (нижче) для вашої реалізації CRI.

Кожна конфігурація має відповідний 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 для кластера, ви можете вказати 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.

containerd

Обробники Runtime налаштовуються через конфігурацію containerd за шляхом /etc/containerd/config.toml. Дійсні обробники налаштовуються в розділі runtimes:

[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.${HANDLER_NAME}]

Докладніше див. у документації з конфігурації containerd:

CRI-O

Обробники 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" є функцією бета-рівня типово увімкненою через feature gate PodLifecycleSleepAction.

Виконання обробника хука

Коли викликається хук управління життєвим циклом контейнера, система управління Kubernetes виконує обробник відповідно до дії хука, httpGet, tcpSocket та sleep виконуються процесом kubelet, а exec виконується в контейнері.

Виклики обробників хуків синхронні в межах контексту Pod, який містить контейнер. Це означає, що для хука PostStart, ENTRYPOINT контейнера та хук викликаються асинхронно. Однак якщо хук займає занадто багато часу або блокується, контейнер не може досягти стану 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

Що далі