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

Kubernetes: інтеграція з Azure Keyvault via CSI driver

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

Привіт, з вами знову Геннадій і це друга стаття про Kubernetes, Azure Key Vault та Managed Identity. Першу, про інтеграцію з Azure Managed Identity можна знайти ось тут.

У цьому тексті я хочу розповісти, як передати secrets з Azure Key Vault до вашого застосунку в Kubernetes. Та як можна достатньо просто мігрувати з використання kubernetes secrets на keyvault. Все, що ми розглянемо, працюватиме і для інших клаудів та keyvault-провайдерів.

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

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

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

Ми вже вміємо інтегрувати kubernetes та azure managed identity через workload identity, настав час навчитися працювати з CSI driver.

Azure, як і інші клауди, має сервіс зберігання секретів (паролі, різні ключі, connection strings тощо). Постає питання, як надати доступ до нього з вашого застосунку. Як завжди, є декілька способів:

  1. Application service principal — ви використовуєте звичайні client id та client secret, головний недолік client secret, як і звичайного пароля, — він довготривалий та його треба змінювати, а також його якось передавати в застосунок.
  2. Managed identity — такий собі «прозорий» доступ до ресурсів клауда з вашого застосунку. Клауд надає можливість «автоматично» отримувати access token до ресурсу для подальшого використання. Звичайно, токен має менший термін дії ніж client secret, та не потрібно менеджити його руками.

На мою думку, треба використовувати managed identity завжди, де є така можливість.

Звичайно, для кожної мови програмування та фреймворку є відповідне sdk для інтеграції з Azure Key Vault. Та ви можете знайти купу матеріалу в інтернеті на цю тему.
То нащо вам той CSI driver, якщо застосунок може сам сходити до keyvault та взяти секрети, запитаєте ви? То все зроблено для «простої» міграції.

Наприклад, як у нашому випадку: коли ми стартували, то вирішили, що будемо використовувати kubernetes secrets — швидке, просте рішення, та ще й cloud agnostic (фантомні болі від vendor lock).

Spring boot має чудовий механізм завантаження kubernetes configs та secrets:
spring.config.import=optional:configtree:/var/run/secrets/app

Кожен файл в директорії то є property:

  • file name — property name,
  • file content — property value.

Міграція на KeyVault

Але прийшов час перейти на зберігання секретів у keyvault, тож постало питання: як будемо перероблювати?
  1. Додаємо інтеграцію у застосунок: так, там все просто, але треба модифікувати купу сервісів.
    • Переваги: працює однаково як на проді, так і у девелоперів на машинах.
    • Недоліки: займає час на міграцію.
  2. Навчити kubernetes брати секрети з keyvault: додаємо зміни в одному місці, не треба модифікувати всі сервіси. Виглядає як просте рішення.
    • Переваги: швидко імплементується; ідеально для міграції.
    • Недоліки: треба щось вигадувати на девелоперських машинах.

Отже, вирішили спробувати опцію 2, бо дуже просто, але тримаємо у голові перший варіант.

Що нам потрібно:

  1. Створити keyvault.
  2. Додати azure-keyvault-secrets-provider до нашого kubernetes: туторіал ось тут.
  3. Налаштувати workload identity для kubernetes: туторіал та мій топік про це ось тут.
    • створити managed identity;
    • створити kubernetes service account;
    • зв’язати їх через federated credentials;
    • дозволити вашому managed identity доступ до keyvault.
  4. Створити новий тип «kubernetes secret»: SecretProviderClass.
  5. Додати новий csi volume до вашого поду чи деплойменту.

Нагадаю навіщо нам workload identity: це спосіб надати доступ до keyvault тільки вашим подам, точніше усьому, що використовує ваш service account.

Це краще ніж використовувати kubernetes service principal, наприклад, або зберігати azure service secret в kubernetes secrets.

Налаштування доступу вашого managed identity до Key Vault

Як додати ваш managed identity до kyvault? Вам треба додати ваш managed identity до access policy list. Це можна зробити через azure portal або командну строку:

az keyvault set-policy \
    --name "<your-keyvault-name>" \
    --object-id ${SERVICE_IDENTITY} \
    --secret-permissions set get list

Налаштування SecretProviderClass

Отже, для кожного набору secretes з keyvault ви створюєте новий ресурс у kubernetes.

Так, вам треба перерахувати імена всіх секретів з keyvault, які ви хочете прочитати. Це зручно, якщо для різних сервісів треба різні секрети.

Але майте на увазі: ваш service account має доступ до всього keyvault (якщо ви використовуєте keyvault access policy замість RBAC) тож з самого поду можна отримати доступ до всіх секретів, якщо змонтувати туди service account token.

Отже, вам потрібно вимкнути автоматичне монтування токена до поду у вашому service account за допомогою ключа: automountServiceAccountToken: false.

Повернемося до нашого SecretProviderClass:

apiVersion: secrets-store.csi.x-k8s.io/v1
kind: SecretProviderClass
metadata:
 name: test-kv-secrets
spec:
 provider: azure
 parameters:
   keyvaultName: test-kv-secrets
   clientID: "your client id here"
   tenantId: "your tenant id here"
   objects: |
     array:
       - |
         objectName: my-secret1
         objectType: secret
       - |
         objectName: my-secret2
         objectType: secret

Налаштування Secret CSI Volume

Далі монтуємо secret store volume, я покажу на прикладі пода. Вказуємо ім’я щойно створеного secret provider у полі secretProviderClass.

Після створення вашого поду, перераховані секрети будуть змонтовані як файли у директорію /var/run/secrets/app.

Також ви можете покласти їх в ENV vars через valueFrom.secretKeyRef.

kind: Pod
apiVersion: v1
metadata:
 name: busybox-secrets-store-inline
spec:
 serviceAccountName: pod-identity-sa
 containers:
   - name: busybox
     image: k8s.gcr.io/e2e-test-images/busybox:1.29
     command:
       - "/bin/sleep"
       - "10000"
     volumeMounts:
       - name: secrets-store
         mountPath: "/var/run/secrets/app"
         readOnly: true
 volumes:
   - name: secrets-store
     csi:
       driver: secrets-store.csi.k8s.io
       readOnly: true
       volumeAttributes:
         secretProviderClass: "test-kv-secrets"

Ось і все, тепер kubernetes буде отримувати секрети з вашого keyvault та монтувати їх як файли чи env var до вашого поду.

Далі ви можете, не поспішаючи, переводити вищі сервіси на використання keyvault напряму або мігрувати на використання managed identity для доступу до ресурсів замість паролів.

👍ПодобаєтьсяСподобалось1
До обраногоВ обраному0
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

Класна стаття.

Писав нещодавно якраз Helm chart і модифікував entrypoint для одного сервісу, для того, щоб ми в values могли передати один раз імена сікретів, а entrypoint скрипт парсив їх (бо в bash нема іменованих параметрів, як в PowerShell), і експортував як змінні середовища для dotnet.

Апдейт: деви переписали додатки, щоб тягнути сікрети через Azure Key Vault SDK :)

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