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

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

Контейнери

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

На цій сторінці міститься огляд контейнерів та образів контейнерів, а також їх використання для розробки та промислової експлуатації.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Примітка:

Якщо ви шукаєте образи контейнерів для випуску Kubernetes (наприклад, v1.37, остання мінорна версія), відвідайте розділ Завантаження 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 — назва образу із власним реєстром і теґом, відмінним від latest.
  • registry.k8s.io/pause@sha256:1ff6c18fbef2045af6b9c16bf034cc421a29027b800e4f9b68ae9b1cb3e9ae07 — назва образу з дайджестом.
  • registry.k8s.io/pause:3.5@sha256:1ff6c18fbef2045af6b9c16bf034cc421a29027b800e4f9b68ae9b1cb3e9ae07 — назва образу з теґом і дайджестом. Для завантаження використовується лише дайджест.

Оновлення образів

При першому створенні Deployment, StatefulSet, Podʼа чи іншого обʼєкта, що включає PodTemplate, а політику завантаження явно не вказано, стандартна політика завантаження всіх контейнерів у цьому Podʼі буде встановлена в IfNotPresent. Ця політика призводить до того, що kubelet пропускає завантаження образів, якщо вони вже існують.

Політика завантаження образів

imagePullPolicy для контейнера та теґ образу впливають на те, коли kubelet намагається завантажити (отримати) вказаний образ.

Ось список значень, які можна встановити для imagePullPolicy та їхній вплив:

IfNotPresent
образ завантажується лише тоді, коли він ще не присутній локально.
Always
кожного разу, коли 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ʼи (і PodTemplates) під час створення, так що робоче навантаження визначається на основі дайджесту образу, а не теґу. Це може бути корисно, якщо ви хочете переконатися, що ваші робочі навантаження запускають один і той самий код, незалежно від того, які зміни теґів відбуваються в реєстрі.

Стандартна політика завантаження образів

Коли ви (чи контролер) подаєте новий 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 хвилин).

Завантаження образу відповідно до класу середовища виконання

СТАН ФУНКЦІОНАЛУ: Alpha since Kubernetes v1.29; (стандартно вимкнено)
More information about this feature

To use this feature, you (or a cluster administrator) will need to enable the RuntimeClassInImageCriApi feature gate for all relevant components in your cluster.

See Enable Or Disable Feature Gates for more information.

У Kubernetes є альфа-підтримка для виконання завантаження образів на основі RuntimeClass Podʼа.

Якщо ви увімкнете функціональну можливість RuntimeClassInImageCriApi, kubelet вказує образи контейнерів кортежем із назви образу та обробника середовища виконання, а не лише назвою чи дайджестом образу. Ваше середовище виконання контейнерів може адаптувати свою поведінку залежно від обраного обробника. Завантаження образів на основі класу середовища виконання буде корисним для контейнерів, що використовують віртуальні машини, таких як контейнери Windows Hyper-V.

Послідовне та паралельне завантаження образів

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

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

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

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

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

Максимальна кількість паралельних завантажень образів

СТАН ФУНКЦІОНАЛУ: GA since Kubernetes v1.35

Коли 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 із жорстко закодованими назвами образів із суфіксами.

Використання приватних реєстрів

Приватні реєстри можуть вимагати автентифікації для виявлення та/або завантаження образів з них. Облікові дані можна надати кількома способами:

Ці варіанти пояснюються докладніше нижче.

Зазначення imagePullSecrets в Podʼі

Примітка:

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

У Kubernetes підтримується вказівка ключів реєстру образів контейнерів у Podʼі. Усі imagePullSecrets мають бути Secrets, які існують у тому самому Namespace, що й Pod. Ці Secrets мають бути типу kubernetes.io/dockercfg або kubernetes.io/dockerconfigjson.

Налаштування вузлів для автентифікації в приватному реєстрі

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

Для прикладу конфігурування приватного реєстру образів контейнерів дивіться завдання Завантаження образу з приватного реєстру. У цьому прикладі використовується приватний реєстр в Docker Hub.

Постачальник облікових даних Kubelet для отримання автентифікованих образів

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

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

Докладніше дивіться Налаштування постачальника облікових даних образу kubelet.

Тлумачення файлу config.json

Тлумачення config.json відрізняється між оригінальною реалізацією Docker та тлумаченням Kubernetes. У Docker ключі auths можуть вказувати тільки кореневі URL-адреси, тоді як Kubernetes дозволяє використовувати URL-адреси із шаблонами glob, а також шляхи, які відповідають префіксу. Єдиним обмеженням є те, що шаблони glob (*) повинні включати крапку (.) для кожного піддомену. Кількість піддоменів, що мають збіг, повинна дорівнювати кількості шаблонів glob (*.), наприклад:

  • *.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.example/images": { "auth": "…" },
        "*.my-registry.example/images": { "auth": "…" }
    }
}

Операції завантаження образів передають облікові дані середовищу виконання контейнерів CRI для кожного дійсного шаблону. Наприклад, такі назви образів контейнерів матимуть збіг:

  • my-registry.example/images
  • my-registry.example/images/my-image
  • my-registry.example/images/another-image
  • sub.my-registry.example/images/my-image

Однак ці назви образів контейнерів не матимуть збігу:

  • a.sub.my-registry.example/images/my-image
  • a.b.sub.my-registry.example/images/my-image

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

{
    "auths": {
        "my-registry.example/images": {
            "auth": "…"
        },
        "my-registry.example/images/subpath": {
            "auth": "…"
        }
    }
}

Тепер, якщо контейнер вказує образ my-registry.example/images/subpath/my-image, то kubelet спробує завантажити його з обох джерел автентифікації, якщо завантаження з одного з них виявиться невдалим.

Попередньо завантажені образи

Примітка:

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

Типово kubelet намагається отримати кожен образ з вказаного реєстру. Однак якщо властивість imagePullPolicy контейнера встановлена на IfNotPresent або Never, то використовується локальний образ (переважно або виключно, відповідно).

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

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

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

Примітка:

СТАН ФУНКЦІОНАЛУ: Beta since Kubernetes v1.35; (стандартно увімкнено)

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

Перевірка облікових даних під час завантаження образів

СТАН ФУНКЦІОНАЛУ: Beta since Kubernetes v1.35; (стандартно увімкнено)

Якщо увімкнено функціональну можливість KubeletEnsureSecretPulledImages, Kubernetes перевірятиме облікові дані для кожного образу, який потребує їх для завантаження, навіть якщо цей образ вже присутній на вузлі. Ця перевірка гарантує, що образи із запиту Podʼа, які не були успішно завантажені за допомогою наданих облікових даних, повинні бути повторно завантажені з реєстру. Крім того, при повторному завантаженні образів з тими самими обліковими даними, які раніше призвели до успішного завантаження образів, не потрібно повторно завантажувати їх з реєстру, а вони перевіряються локально без доступу до реєстру (за умови, що образ доступний локально). Це контролюється полем imagePullCredentialsVerificationPolicy у конфігурації Kubelet.

Ця конфігурація контролює, коли потрібно перевіряти облікові дані для завантаження образів, якщо образ вже присутній на вузлі:

  • NeverVerify: Імітує поведінку, коли цю функціональну можливість вимкнено. Якщо образ присутній локально, облікові дані для завантаження образу не перевірятимуться.
  • NeverVerifyPreloadedImages: Образи, завантажені за межами kubelet, не перевірятимуться, але всі інші образи будуть перевірятися. Це стандартна поведінка.
  • NeverVerifyAllowListedImages: Образи, завантажені поза kubelet і згадані у списку preloadedImagesVerificationAllowlist, вказаному у конфігурації kubelet, не перевірятимуться.
  • AlwaysVerify: Всі образи будуть перевірятися перед тим, як їх буде використано.

Ця перевірка застосовується до попередньо завантажених образів, образів, завантажених за допомогою Secrets рівня вузла, та образів, завантажених за допомогою Secrets рівня Podʼа.

Примітка:

У випадку ротації облікових даних, облікові дані, які було використано для завантаження образу, і надалі проходитимуть перевірку без необхідності звернення до реєстру. Нові або змінені облікові дані вимагатимуть повторного завантаження образу з реєстру.

Перше увімкнення KubeletEnsureSecretPulledImages

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

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

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

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

Це особливо корисно, якщо ви використовуєте кілька приватних реєстрів контейнерів, оскільки kubectl create secret docker-registry створює Secret, який працює лише з одним приватним реєстром.

Примітка:

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

Посилання на 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 v1.26 застарілий механізм було видалено, тому вам потрібно або:

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

Що далі

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

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

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

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

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

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

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

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

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

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

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

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

FOO_SERVICE_HOST=<хост, на якому працює сервіс>
FOO_SERVICE_PORT=<порт, на якому працює сервіс>

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

Що далі

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

СТАН ФУНКЦІОНАЛУ: GA since Kubernetes v1.20

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

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

Обґрунтування

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

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

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

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

1. Налаштуйте реалізацію CRI на вузлах

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

Конфігурація CRI

Докладніше про налаштування CRI див. у Встановлення CRI.

containerd

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

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

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

CRI-O

Обробники середовища виконання налаштовуються через конфігурацію CRI-O за шляхом /etc/crio/crio.conf. Дійсні обробники налаштовуються в таблиці crio.runtime:

[crio.runtime.runtimes.${HANDLER_NAME}]
  runtime_path = "${PATH_TO_BINARY}"

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

Планування

СТАН ФУНКЦІОНАЛУ: Beta since Kubernetes v1.16

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

Щоб гарантувати, що Podʼи потрапляють на вузли, які підтримують конкретний RuntimeClass, цей набір вузлів повинен мати спільні мітки, які потім обираються полем runtimeclass.scheduling.nodeSelector. NodeSelector RuntimeClass обʼєднується з nodeSelector Podʼа під час допуску, фактично беручи перетин множин вузлів, обраних кожним із них. Якщо виникає конфлікт, Pod буде відхилено.

Якщо підтримувані вузли мають taints, що не дають запускатися на вузлі Podʼам з іншим RuntimeClass, ви можете додати tolerations до RuntimeClass. Як і з nodeSelector, tolerations обʼєднуються з tolerations Podʼа під час допуску, фактично беручи обʼєднання множин вузлів, які толерує кожен із них.

Щоб дізнатися більше про налаштування селектора вузла і tolerations, див. Призначення Podʼів вузлам.

Накладні витрати Podʼів

СТАН ФУНКЦІОНАЛУ: GA since Kubernetes v1.24

Ви можете вказати ресурси overhead, що повʼязані із запуском Podʼа. Вказівка накладних витрат дозволяє кластеру (включаючи планувальник) враховувати це при прийнятті рішень про Podʼи та ресурси.

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

Що далі

4 - Хуки життєвого циклу контейнера

На цій сторінці описано, як контейнери, керовані kubelet, можуть використовувати фреймворк хуків життєвого циклу контейнера для запуску коду, викликаного подіями під час управління їх життєвим циклом.

Огляд

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

Хуки контейнера

Контейнерам доступні два хуки:

PostStart

Цей хук виконується відразу після створення контейнера. Він працює одночасно з ENTRYPOINT контейнера (головним процесом), що означає, що хук може виконуватися до, під час або після запуску головного процесу.

До обробника не передаються жодні параметри.

Примітка:

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

PreStop

Цей хук викликається негайно перед тим, як контейнер буде завершено через запит API або подію управління, таку як невдача проби на живучість/запуску, витіснення, конкуренція за ресурси та інші. Виклик хука PreStop не вдасться, якщо контейнер вже перебуває у стані terminated або completed, і хук повинен завершити виконання до того, як може бути відправлений сигнал TERM для зупинки контейнера. Відлік пільгового періоду припинення Podʼа починається до виконання хука PreStop, тому, незалежно від результату обробника, контейнер врешті-решт завершиться протягом пільгового періоду припинення Podʼа. Жодні параметри не передаються обробнику.

Докладний опис поведінки припинення роботи Podʼів можна знайти в Припинення роботи Podʼа.

StopSignal

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

Детальніший опис поведінки завершення за допомогою власних сигналів зупинки можна знайти в розділі Сигнали зупинки.

Реалізації обробника хуків

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

  • Exec — Виконує конкретну команду, таку як pre-stop.sh, всередині cgroups та namespaces контейнера. Ресурси, спожиті командою, зараховуються на рахунок контейнера.
  • HTTP — Виконує HTTP-запит до конкретного endpoint в контейнері.
  • Sleep — Призупиняє контейнер на вказаний час.

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

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

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

Що далі