Ця стаття була опублікована більше року тому. Старіші статті можуть містити застарілу інформацію. Перевірте, чи інформація на цій сторінці не втратила актуальності з моменту її публікації.

Kubernetes v1.33: Image Pull Policy працює так, як ви завжди вважали!

Image Pull Policy працює так, як ви завжди вважали!

Деякі речі в Kubernetes дивують, і поведінка imagePullPolicy може бути однією з них. Враховуючи, що Kubernetes — це насамперед про запуск Podʼів, може бути дивним дізнатися, що вже більш як 10 років існує застереження щодо обмеження доступу Podʼів до автентифікованих образів у вигляді issue 18787! Дуже приємно, коли вдається розвʼязати проблему десятирічної давнини.

Примітка:

У цьому блозі ми часто будемо використовувати термін «облікові дані Podʼа». У цьому контексті цей термін, як правило, інкапсулює автентифікаційні дані, які доступні для Podʼів, щоб автентифікувати отримання образу контейнера.

IfNotPresent, навіть якщо я не повинен його мати

Суть проблеми в тому, що стратегія imagePullPolicy: IfNotPresent робила саме те, що в ній сказано, і нічого більше. Створімо сценарій. Почнемо з того, що Pod A у Просторі імен X заплановано на Вузол 1 і йому потрібен образ Foo з приватного репозиторію. Для отримання матеріалу для автентифікації образів Pod посилається на Secret 1 у своєму imagePullSecrets. Secret 1 містить необхідні облікові дані для отримання образів з приватного реєстру. Kubelet використає облікові дані з Secret 1, надані Pod A, і отримає образ контейнера Foo з реєстру. Це передбачувана (і безпечна) поведінка.

Але тепер все стає цікавіше. Якщо Pod B у Просторі імен Y також заплановано на Вузол 1, трапляються неочікувані (і потенційно небезпечні) речі. Pod B може посилатися на той самий приватний образ, визначаючи політику отримання образу IfNotPresent. Pod B не посилається на Secret 1 (або, у нашому випадку, на будь-який Secret) у своєму imagePullSecrets. Коли Kubelet намагається запустити Pod, він дотримується політики IfNotPresent. Kubelet бачить, що образ Foo вже присутній локально, і надасть образ Foo для Pod B. Pod B може запустити образ, навіть якщо він не надав облікових даних, які б дозволили йому спочатку отримати образ.

Ілюстрація процесу, коли два Podʼи намагаються отримати доступ до приватного образу, перший — з секретом, другий — без нього

Використання приватного образу, отриманого іншим Podʼом

Хоча IfNotPresent не повинен завантажувати образ Foo, якщо він вже присутній на вузлі, це неправильна позиція безпеки — дозволяти всім Podʼам, запланованим на вузлі, мати доступ до раніше отриманих приватних образів, хоча ці Podʼи ніколи не були уповноважені на отримання образу.

IfNotPresent, але тільки якщо я повинен його мати

У Kubernetes v1.33 ми, SIG Auth і SIG Node, нарешті почали вирішувати цю (дійсно стару) проблему і робити перевірку правильно! Основна очікувана поведінка не змінилася. Якщо образ відсутній, Kubelet спробує отримати його. Для цього будуть використані облікові дані, які надаються кожним Podʼом. Це відповідає поведінці до версії 1.33.

Якщо образ присутній, поведінка Kubelet зміниться. Тепер Kubelet перевірятиме облікові дані Podʼів перед тим, як дозволити Podʼу використовувати образ.

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

Ніколи не завантажувати, а використовувати, якщо дозволено

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

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

Завжди завантажувати, якщо це дозволено

Політика imagePullPolicy: Always завжди працювала належним чином. Кожного разу, коли запитується образ, запит надсилається до реєстру, і реєстр виконує перевірку автентифікації.

У минулому примусове застосування політики завантаження образів Always через допуск (admission) Podʼів було єдиним способом гарантувати, що ваші приватні образи контейнерів не будуть повторно використані іншими Podʼами на вузлах, які вже завантажили образи.

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

Як це все працює

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

Процес першого запиту образу виглядає так:

  1. На вузлі заплановано Pod, який запитує образ з приватного реєстру.
  2. Образ відсутній на вузлі.
  3. Kubelet робить запис про намір отримати образ.
  4. Kubelet бере облікові дані з Secret Kubernetes, на який Pod посилається як на секрет для отримання образу, і використовує їх для отримання образу з приватного реєстру.
  5. Після того, як образ успішно отримано, Kubelet робить запис про успішне отримання. Цей запис містить деталі про використані облікові дані (у вигляді хешу), а також Secret, з якого вони походять.
  6. Kubelet видаляє початковий запис про наміри.
  7. Kubelet зберігає запис про успішне завантаження для подальшого використання.

Коли майбутні Podʼи, заплановані на той самий вузол, запитують раніше завантажений приватний образ:

  1. Kubelet перевіряє облікові дані, які надає для завантаження новий Pod.
  2. Якщо хеш цих облікових даних або вихідний Secret облікових даних збігається з хешем або вихідним Secret, які були записані для попереднього успішного завантаження, Podʼу дозволяється використовувати раніше завантажений образ.
  3. Якщо облікові дані або їхній вихідний Secret не знайдено у записах успішних завантажень для цього образу, Kubelet спробує використати ці нові облікові дані для запиту завантаження з віддаленого реєстру, запускаючи потік авторизації.

Спробуйте

У Kubernetes v1.33 ми випустили альфа-версію цієї можливості. Щоб випробувати її, увімкніть функціональну можливість KubeletEnsureSecretPulledImages для ваших Kubelet версії 1.33.

Ви можете дізнатися більше про цю можливість та додаткові опціональні налаштування на сторінці концепції про образи в офіційній документації Kubernetes.

Що далі?

У наступних випусках ми збираємося:

  1. Зробити так, щоб ця можливість працювала разом з Projected service account tokens for Kubelet image credential providers, який додає нове, специфічне для робочого навантаження джерело облікових даних для завантаження образів.
  2. Написати набір бенчмарків, щоб виміряти продуктивність цієї можливості та оцінити вплив будь-яких майбутніх змін.
  3. Реалізувати рівень кешування у памʼяті, щоб нам не потрібно було читати файли для кожного запиту на отримання образів.
  4. Додати підтримку закінчення терміну дії облікових даних, таким чином змушуючи раніше підтверджені облікові дані проходити повторну автентифікацію.

Як долучитися

Ознайомитись з KEP-2535 — це чудовий спосіб глибше зрозуміти ці зміни.

Якщо ви зацікавлені в подальшій участі, звʼяжіться з нами у каналі #sig-auth-authenticators-dev в Kubernetes Slack (щоб отримати запрошення, відвідайте https://slack.k8s.io/). Ви також можете приєднатися до зустрічей SIG Auth, що відбуваються раз на два тижні, кожної другої середи.