Сучасна диджитал-освіта для дітей — безоплатне заняття в GoITeens ×
Mazda CX 30
×

Kubernetes: як впровадити інтеграцію з Azure Managed Identity

Усі статті, обговорення, новини про DevOps — в одному місці. Підписуйтеся на DOU | DevOps!

Привіт, мене звати Геннадій, я займаюся розробкою вже 16 років та обожнюю Java. У цьому тексті я хочу розповісти як інтегрувати Kubernetes з Azure Managed Identity за допомогою Workload Identity (pods identity). Також ми розглянемо варіант конфігурації Workload Identity без зайвих компонентів як Mutating Admission Webhook та купи annotations та labels.

Рішення універсальне, тож буде працювати і для інших клаудів.

Задача, яку вирішуємо

Почну з опису задачі яку ми вирішуємо: маємо десяток сервісів на Spring boot, які працюють в Kubernetes в Azure. Зараз різні паролі та api keys зберігаються в Kubernetes secrets та монтуються у pod. Ми хочемо зберігати їх в azure keyvault та зробити цей перехід максимально простим. У майбутньому, позбутися паролів та перейти на managed identity для доступу до ресурсів у клауді.

Отже, наше рішення виглядає так:

  1. перенести секрети до key vault;
  2. надати доступ Kubernetes (а точніше вашому pod) до keyvault;
  3. налаштувати Kubernetes монтувати секрети з keyvault до нашого pod за допомогою CSI driver (тема для наступного топіку).

Тож перша проблема, яку треба вирішити: як надати доступ до keyvault без зберігання нового пароля (service secret) в Kubernetes secrets? Для цього в клауді існує Managed Identity.

Отже, навчімось інтегрувати Kubernetes з Azure Managed Identity за допомогою Workload Identity. Та сконфігуруємо його без зайвих додаткових компонентів.

Опис буде для платформи Azure, але все те саме буде актуальне і для інших клауд-провайдерів.

Про managed identity

В усіх клаудах так чи інакше є managed identity — такий собі «прозорий» доступ до ресурсів клауду з вашого застосунку. Замість доступу за звичними username/password, ви дозволяєте вашій VM мати доступ до бази, наприклад.

В клауді реєструється managed identity (акаунт для вашого сервісу), йому надається доступ до ресурсу (база даних, keyvault, черга та інше), а потім призначаєте це identity на вашу VM.

Далі ви отримуєте access token з well-known metadata url та використовуєте його для доступу до ресурсу (в azure це «>http://169.254.169.254/metadata/identity/oauth2/token»).

Навіщо нам с тим всім заморочуватися? Головна причина — нам не потрібно турбуватися про пароль: його складність, як передавати його в застосунок, як там його зберігати, як його змінювати (password rotation).

Все це бере на себе клауд: access token має обмежений термін придатності та автоматично змінюється.

Про workload identity

Все це було створено для VM та працювало поки не з’явився Kubernetes. На кожній VM може працювати багато різних pods, отже не можна надати доступ до бази для VM.

Тож було дві спроби вирішення задачі:

Перша спроба: Azure active directory pod identity (aad-pod-identity). Вже застарілий, тож не будем гаяти час на нього.

Друга спроба: Workload Identity — універсальне рішення для всіх клауд-провайдерів. У цьому рішенні Kubernetes це наче зовнішній клауд, якому «довіряє» наш клауд. Тепер ми можемо використовувати service account tokens з Kubernetes для доступу до ресурсів клауду. У самому клауді kubernetes service account зіставляється з cloud identity і далі клауд використовує вже його (в azure це зроблено через federated credentials).

  1. github
  2. azure
  3. gce
  4. aws

В документації ось така діаграма описує весь процес:

Як це виглядає для нашого застосунку:

  1. Kubernetes монтує service account token в наш pod.
  2. Наш застосунок, використовуючи цей змонтований kubernetes service account token, отримує cloud access token.
  3. Далі використовуємо цей cloud access token для доступу до ресурсів.

В мережі купа статей про це, та навіть офіційна дока також норм:

  1. Installation.
  2. Quick Start.

Тож я не хочу переповідати інфу з інтернету, але розповім про налаштування компонентів workload identity та який мінімальний набір вам потрібен.

Конфігурація workload identity

Отже, аби workload identity працювало, вам потрібно:

  1. увімкнути OIDC Issuer UR feature у нашому Kubernetes;
  2. створити kubernetes service account;
  3. створити managed identity in azure;
  4. додати federated credentials до створеного managed identity;
    • вказуємо наш OIDC Issuer UR;
    • вказуємо наш service account name;
  5. додати kubernetes service account token до нашого pod за допомогою projected volume.

У туторіалі ви побачите, що вам потрібен ще Mutating Admission Webhook та купа annotations та labels на ваш service account та pod.

Але це зовсім не обов’язково. Я не хочу додавати зайвий софт до мого продакшену, бо його треба менеджети — конфігурувати, моніторити та оновлювати. І якщо ми можемо уникнути цього, то це треба робить.

Спочатку треба зрозуміти, що воно робить. Ось тут код вебхука на github.

Все, що він робить — автоматично додає деякі параметри до вашого pod:

  1. монтує projected volume з service account token;
  2. додає env vars;
    • AZURE_CLIENT_ID,
    • AZURE_TENANT_ID,
    • AZURE_FEDERATED_TOKEN_FILE — шлях до файлу куди змонтований kubernetes service account token.

Отже, все це ми можемо зробити руцями для нашого pod, це не забирає багато часу.

І якщо ми не використовуємо mutating admission webhook, то можна не додавати ті всі annotations and labels до нашого service account та pod. То все треба, щоб webhook знайшов наш service account та pod. Почитати тут.

Отже, приклад з туторіалу без використання webhook буде виглядати так:

Service account:

apiVersion: v1
kind: ServiceAccount
metadata:
 name: pod-identity-sa
 namespace: default

Msal pod: тестова програма з туторіалу, яка читає secret з azure keyvault (зазирніть в туторіал)

kind: Pod
apiVersion: v1
metadata:
 name: quick-start
spec:
 serviceAccountName: pod-identity-sa
 containers:
   - name: oidc
     image: ghcr.io/azure/azure-workload-identity/msal-go
     env:
       # standard msal env vars, added manually
       - name: AZURE_CLIENT_ID
         value: ${AZURE_CLIENT_ID}
       - name: AZURE_TENANT_ID
         value: ${AZURE_TENANT_ID}
       - name: AZURE_FEDERATED_TOKEN_FILE
         value: /var/run/secrets/tokens/pod-identity-sa
       # special env vars for test app
       - name: AZURE_AUTHORITY_HOST
         value: https://login.microsoftonline.com/
       - name: KEYVAULT_URL
         value: ${KEYVAULT_URL}
       - name: SECRET_NAME
         value: ${KEYVAULT_SECRET_NAME}
     volumeMounts:
       - name: sa-token
         mountPath: /var/run/secrets/tokens
 volumes:
   - name: sa-token
     projected:
       sources:
         - serviceAccountToken:
             path: pod-identity-sa
             audience: api://AzureADTokenExchange

Metadata proxy sidecar

Якщо ви мігруєте з VM та ваш застосунок все ще використовує well-known metadata url, то вам допоможе sidecar container з proxy, який перехопить запит до metadata url та виконає запит до azure api:

  1. як додати workload-identity/proxy init container та sidecar;
  2. код proxy можна подивитись на github.

Знову, його можна додати руками або mutating admission webhook може це зробити для нас.

Kubernetes service account token projection

Головне питання — чи оновлюється токен у вашому pod автоматично, коли він експайриться? Так, він оновлюється автоматично, у вашому застосунку вам треба моніторити оновлення файлу та читати токен з нього кожного разу як він знадобився, а не зберігати в пам’яті.

👍ПодобаєтьсяСподобалось6
До обраногоВ обраному4
LinkedIn
Дозволені теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter
Дозволені теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter

Доброго дня, чи правильно зрозумів , що це нові технології які дозволяють прибрати старий шлях наприклад через secret sync котрий дублює ключі з AKV на k8s?

worload identiity — це про доступ до ресурсів azure за допомогою kubernetes service account. тобто вам більше не треба зберігати пароль від keyvault або service account secret в kubernetes.
в офф прикладі у них є апка яка використовує azure msal lib (є для всіх мов) аби отримати ключ із keyvault.

відповідь на ваше запитання про secret sync — новий спосіб це secret store csi driver(збираюсь дописати статтю про нього). офф дока — azure keyvault csi driver. Воно не копіює секрети до kubernetes secrets, а монтує їх у под.

аби воно працювало треба куберу надати доступ до keyvault, є дві опціі: service account secret або managed identity (via worload identity).
як раз для цього і писав цю статтю

Підписатись на коментарі