Чтение секретов из кода и CSI
Когда хочется обойтись без Agent: приложение само ходит в Vault, либо секреты монтируются томом через CSI.
Прямая интеграция — приложение само логинится в Vault клиентской библиотекой и читает секреты; CSI-провайдер монтирует секреты как файлы тома средствами Kubernetes.
Vault Agent удобен, но иногда приложение работает с Vault напрямую: для гибкости, в не-k8s среде или при единичном чтении на старте. Разберём оба подхода.
Чтение из кода: общий паттерн
Логика одинакова в любом языке: настроить адрес и токен (или залогиниться), прочитать путь, достать поле. Псевдокод на Python (это иллюстрация API, не запускается в браузере):
import hvac # официальный Python-клиент Vault
client = hvac.Client(url="https://vault.internal:8200")
# логин через AppRole
client.auth.approle.login(
role_id=ROLE_ID,
secret_id=SECRET_ID,
)
# чтение динамических кред БД
resp = client.read("database/creds/readonly")
db_user = resp["data"]["username"]
db_pass = resp["data"]["password"]
connect_to_db(db_user, db_pass)
Ключевой момент — секреты получают при старте, не зашивают в образ. Для динамических кредов приложение должно ещё уметь обновлять их до истечения аренды (или отдать это Agent).
Где взять токен в коде
Самое сложное в прямом подходе — первичная аутентификация (secret zero). Варианты: AppRole с SecretID через response wrapping, Kubernetes auth по ServiceAccount-токену пода, облачная identity (AWS/GCP) ВМ. Хардкодить токен нельзя — это возвращает исходную проблему.
CSI: секреты как том
Secrets Store CSI Driver — другой подход в Kubernetes: секреты монтируются в под как файлы тома, без sidecar. Описывается ресурсом SecretProviderClass:
apiVersion: secrets-store.csi.x-k8s.io/v1
kind: SecretProviderClass
metadata:
name: orders-db
spec:
provider: vault
parameters:
roleName: "orders"
vaultAddress: "https://vault.internal:8200"
objects: |
- objectName: "db-password"
secretPath: "secret/data/orders/db"
secretKey: "password"
Под монтирует такой том, и секрет появляется файлом по пути монтирования. Приложение снова просто читает файл.
Как работает под капотом и выбор подхода
CSI-драйвер при монтировании тома логинится в Vault (через k8s auth) и пишет запрошенные секреты в tmpfs-том пода. Отличие от Injector: нет постоянного sidecar — обновление секретов зависит от ротации тома и устроено иначе, чем непрерывное продление Agent. Поэтому для динамических кредов с активным продлением чаще выбирают Agent/Injector, а CSI удобен для статических секретов и единообразного монтирования.
| Подход | Когда |
| код напрямую (hvac и др.) | не-k8s, гибкость, единичное чтение |
| Vault Agent / Injector | динамика, продление аренды, без правки кода |
| CSI Driver | статика как том, k8s-нативное монтирование |
Частые ошибки
- Хардкодить токен в коде/образе — secret zero не решён, утечёт вместе с артефактом.
- Читать секреты один раз и держать вечно для динамики — креды протухнут.
- Ждать от CSI поведения Agent по непрерывному продлению аренды — это разные модели.
Итог
- Из кода: залогиниться (AppRole/k8s/облако) и прочитать секреты при старте, не хардкодя токен.
- CSI Driver монтирует секреты файлами тома без sidecar — удобно для статики.
- Для динамических кредов с продлением аренды обычно выбирают Agent/Injector.