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

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

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

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 (або, у нашому випадку, на будь-який секрет) у своєму imagePullSecrets. Коли Kubelet намагається запустити pod, він дотримується політики IfNotPresent. Kubelet бачить, що образ Foo вже присутній локально, і надасть образ Foo для Pod B. Pod B може запустити образ, навіть якщо він не надав облікових даних, які б дозволили йому спочатку отримати образ.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Коли майбутні поди, заплановані на той самий вузол, запитують раніше витягнутий приватний образ:

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

Спробуйте

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

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

Що далі?

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

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

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

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

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