Kubernetes v1.35: Кращий спосіб передачі токенів службових облікових записів до драйверів CSI
Якщо ви підтримуєте драйвер CSI, який використовує токени службових облікових записів, Kubernetes v1.35 приносить удосконалення, про яке вам варто знати. З моменту введення функції TokenRequests, токени службових облікових записів, запитувані драйверами CSI, передавалися їм через поле volume_context. Хоча це працювало, це не ідеальне місце для конфіденційної інформації, і ми бачили випадки, коли токени випадково реєструвалися в драйверах CSI.
Kubernetes v1.35 вводить рішення бета-версії для вирішення цієї проблеми:
Опція драйвера CSI для токенів службових облікових записів через поле Secrets.
Це дозволяє драйверам CSI отримувати токени службових облікових записів
через поле secrets у NodePublishVolumeRequest,
яке є відповідним місцем для конфіденційних даних у специфікації CSI.
Розуміння поточного підходу
Коли драйвери CSI використовують функцію TokenRequests, вони можуть запитувати токени службових облікових записів для ідентифікації робочого навантаження, налаштовуючи поле TokenRequests у специфікації CSIDriver. Ці токени передаються драйверам як частина мапи атрибутів тому, використовуючи ключ csi.storage.k8s.io/serviceAccount.tokens.
Поле volume_context працює, але воно не призначене для конфіденційних даних. Через це виникають кілька викликів:
По-перше, інструмент protosanitizer, який використовують драйвери CSI, не розглядає контекст тому як конфіденційний, тому токени службових облікових записів можуть потрапити до журналів, коли реєструються gRPC-запити. Це сталося з CVE-2023-2878 у Secrets Store CSI Driver та CVE-2024-3744 у Azure File CSI Driver.
По-друге, кожен драйвер CSI, який хоче уникнути цієї проблеми, повинен реалізовувати власну логіку санітізації, що призводить до неузгодженості між драйверами.
Специфікація CSI вже має поле secrets у NodePublishVolumeRequest, яке призначене саме для такого роду конфіденційної інформації. Проблема полягає в тому, що ми не можемо просто змінити місце, де ми розміщуємо токени, без порушення роботи поточних драйверів CSI, які очікують їх у контексті тому.
Як працює механізм увімкнення
Kubernetes v1.35 вводить механізм увімкнення, який дозволяє драйверам CSI вибирати, як вони отримують токени службових облікових записів. Таким чином, поточні драйвери продовжують працювати як і раніше, а інші драйвери можуть перейти до більш відповідного поля secrets, коли будуть готові.
Драйвери CSI можуть встановити нове поле у своїй специфікації CSIDriver:
#
# УВАГА: це приклад конфігурації.
# Не використовуйте це для власного кластера!
#
apiVersion: storage.k8s.io/v1
kind: CSIDriver
metadata:
name: example-csi-driver
spec:
# ... наявні поля ...
tokenRequests:
- audience: "example.com"
expirationSeconds: 3600
# Нове поле для опції доставки через secrets
serviceAccountTokenInSecrets: true # стандартно false
Поведінка залежить від поля serviceAccountTokenInSecrets:
Коли встановлено false (стандартно), токени розміщуються у VolumeContext з ключем csi.storage.k8s.io/serviceAccount.tokens, як і сьогодні.
Коли встановлено true, токени розміщуються лише у полі Secrets з тим самим ключем.
Про бета-реліз
Функціональна можливість CSIServiceAccountTokenSecrets стандартно увімкнена як для kubelet, так і для kube-apiserver. Оскільки поле serviceAccountTokenInSecrets стандартно має значення false, увімкнення функціональної можливості не змінює жодної поточної поведінки. Усі драйвери продовжують отримувати токени через контекст тому, якщо вони явно не оберуться. Це пояснює, чому ми почувалися комфортно, починаючи з бета-версії, а не альфа.
Посібник для авторів драйверів CSI
Якщо ви підтримуєте драйвер CSI, який використовує токени службових облікових записів, ось як запровадити цю функцію.
Додавання резервної логіки
Спочатку оновіть код вашого драйвера, щоб перевіряти обидва місця на наявність токенів. Це робить ваш драйвер сумісним з обома підходами, старим і новим:
const serviceAccountTokenKey = "csi.storage.k8s.io/serviceAccount.tokens"
func getServiceAccountTokens(req *csi.NodePublishVolumeRequest) (string, error) {
// Перевірити поле secrets спочатку (нова поведінка, коли драйвер обирається)
if tokens, ok := req.Secrets[serviceAccountTokenKey]; ok {
return tokens, nil
}
// Резерв до контексту тому (поточна поведінка)
if tokens, ok := req.VolumeContext[serviceAccountTokenKey]; ok {
return tokens, nil
}
return "", fmt.Errorf("service account tokens not found")
}
Ця резервна логіка є зворотньо сумісною та безпечною для випуску в будь-якій версії драйвера, навіть до оновлення кластерів до v1.35.
Послідовність розгортання
Автори драйверів CSI повинні дотримуватися певної послідовності при прийнятті цієї функції, щоб уникнути порушення наявних томів.
Підготовка драйвера (може відбутися будь-коли)
Ви можете почати підготовку вашого драйвера прямо зараз, додавши резервну логіку, яка перевіряє як поле secrets, так і контекст тому на наявність токенів. Ця зміна коду є зворотньо сумісною та безпечною для випуску в будь-якій версії драйвера, навіть до оновлення кластерів до v1.35. Ми заохочуємо вас додати цю логіку раніше, випускати релізи та навіть робити зворотні портування до гілок обслуговування, де це можливо.
Оновлення кластера та увімкнення функції
Після того, як ваш драйвер має резервну логіку, ось безпечний порядок розгортання для увімкнення функції в кластері:
- Завершити оновлення kube-apiserver до 1.35 або пізнішої версії
- Завершити оновлення kubelet до 1.35 або пізнішої версії на всіх вузлах
- Переконатися, що версія драйвера CSI з резервною логікою розгорнута (якщо не зроблено в фазі підготовки)
- Повністю завершити розгортання DaemonSet драйвера CSI на всіх вузлах
- Оновити ваш маніфест CSIDriver, щоб встановити
serviceAccountTokenInSecrets: true
Важливі обмеження
Найважливіше, що потрібно памʼятати, — це час. Якщо ваш DaemonSet драйвера CSI та обʼєкт CSIDriver знаходяться в одному маніфесті або чарті Helm, вам потрібно два окремі оновлення. Спочатку розгорніть нову версію драйвера з резервною логікою, зачекайте завершення розгортання DaemonSet, потім оновіть специфікацію CSIDriver, щоб встановити serviceAccountTokenInSecrets: true.
Також не оновлюйте CSIDriver перед тим, як усі поди драйвера будуть розгорнуті. Якщо ви це зробите, монтування томів зазнають невдачі на вузлах, які все ще працюють зі старою версією драйвера, оскільки ті поди перевіряють лише контекст тому.
Чому це важливо
Прийняття цієї функції допомагає в кількох аспектах:
- Це усуває ризик випадкового реєстрації токенів службових облікових записів як частини контексту тому в gRPC-запитах
- Вона використовує призначене поле специфікації CSI для конфіденційних даних, що є правильним
- Інструмент
protosanitizerавтоматично правильно обробляє поле secrets, тому вам не потрібні специфічні для драйвера обхідні шляхи - Це опціонально, тому ви можете мігрувати у власному темпі без порушення наявних розгортань
Заклик до дії
Ми (Kubernetes SIG Storage) заохочуємо авторів драйверів CSI прийняти цю функцію та надати відгуки про досвід міграції. Якщо у вас є думки щодо дизайну API або виникають будь-які проблеми під час прийняття, будь ласка, зверніться до нас у каналі #csi на Kubernetes Slack (для запрошення відвідайте https://slack.k8s.io/).
Ви можете стежити за KEP-5538 щоб відстежувати прогрес у наступних релізах Kubernetes.