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

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

Зазвичай ви створюєте образ контейнера свого застосунку та розміщуєте його в реєстрі перш ніж посилатися на нього у 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

Що далі

Змінено June 20, 2024 at 12:44 PM PST: Sync changest from andygol/k8s-website (36d05bc8a1)