Ответ
Я интегрировал Vault в Kubernetes для безопасного управления секретами, используя два основных подхода в production-среде.
1. Vault Agent Injector (для статических секретов): Это sidecar-контейнер, который автоматически внедряет секреты в под как файлы или переменные окружения.
- Установка через Helm:
helm install vault hashicorp/vault --set "server.ha.enabled=true" --set "injector.enabled=true" - Конфигурация через аннотации в манифесте пода:
apiVersion: v1 kind: Pod metadata: name: my-app annotations: vault.hashicorp.com/agent-inject: 'true' vault.hashicorp.com/role: 'myapp-role' # Роль Kubernetes для аутентификации vault.hashicorp.com/agent-inject-secret-db-creds: 'database/creds/my-role' vault.hashicorp.com/agent-inject-template-db-creds: | {{- with secret "database/creds/my-role" -}} {{ .Data.username }} {{ .Data.password }} {{- end }} spec: serviceAccountName: my-app-sa # ServiceAccount, привязанный к роли Vault containers: - name: app image: my-app:latest
2. CSI Provider (для динамических секретов): Идеально подходит для баз данных, где нужны кратковременные учетные данные. Секреты монтируются как том и автоматически обновляются.
- Включение CSI Provider:
helm install vault hashicorp/vault --set "csi.enabled=true" - Создание
SecretProviderClass:apiVersion: secrets-store.csi.x-k8s.io/v1 kind: SecretProviderClass metadata: name: db-dynamic-creds spec: provider: vault parameters: vaultAddress: "http://vault-active.vault.svc.cluster.local:8200" roleName: "db-admin" objects: | - objectPath: "database/creds/my-dynamic-role" secretKey: "password"
Ключевые настройки для продакшена, которые я выполнял:
- Аутентификация через Kubernetes ServiceAccount: Настраивал в Vault
kubernetesauth method, связывая K8s namespaces и service accounts с политиками Vault. - High Availability (HA): Запускал Vault в HA-режиме с Consul или Integrated Storage (Raft).
- TLS и mTLS: Настраивал внутренний и внешний TLS для всего трафика, включая взаимную аутентификацию между Vault и injector/CSI.
- Политики с наименьшими привилегиями: Тщательно прорабатывал политики Vault, выдавая приложениям доступ только к конкретным путям секретов.
Ответ 18+ 🔞
Э, слушай, история про то, как я Vault в кубер прикручивал. Ёпта, это отдельная сага, чувак. В общем, сидишь такой, думаешь: «Э бошка, думай!» Как секреты в продакшене хранить, чтобы не было потом «хиросимы и нигерсраки», если какой-нибудь «пидарас шерстяной» в кластер проберётся. Ну, Vault — штука мощная, но и возни с ним, бля, овердохуища.
Вот смотри, я юзал два основных подхода, чтобы не быть «распиздяем».
1. Vault Agent Injector (для статичных секретиков типа ключей API). Это такая «мартышлюшка»-сайдкар, которая тебе в под лезет и тихонько подкладывает секреты прямо в файлы или переменные окружения. Удобно, ёбать копать. Ставится через Helm — раз плюнуть.
helm install vault hashicorp/vault
--set "server.ha.enabled=true"
--set "injector.enabled=true"
А потом в манифесте своего пода навешиваешь аннотации, и он всё делает сам. Главное — ServiceAccount правильно привязать к роли в Vault, а то будет «доверия ебать ноль».
apiVersion: v1
kind: Pod
metadata:
name: my-app
annotations:
vault.hashicorp.com/agent-inject: 'true'
vault.hashicorp.com/role: 'myapp-role'
vault.hashicorp.com/agent-inject-secret-db-creds: 'database/creds/my-role'
vault.hashicorp.com/agent-inject-template-db-creds: |
{{- with secret "database/creds/my-role" -}}
{{ .Data.username }}
{{ .Data.password }}
{{- end }}
spec:
serviceAccountName: my-app-sa
containers:
- name: app
image: my-app:latest
2. CSI Provider (для динамических секретов, типа паролей от БД, которые живут пять минут). Вот это, бля, вообще песня! Для баз данных — то, что доктор прописал. Секреты монтируются как том и сами по себе обновляются, как только срок жизни подходит к концу. Чувствуешь разницу? Не нужно приложение перезапускать. Включил — и забыл.
helm install vault hashicorp/vault
--set "csi.enabled=true"
Потом создаёшь SecretProviderClass, где указываешь, что и куда монтировать. Смотри, как просто:
apiVersion: secrets-store.csi.x-k8s.io/v1
kind: SecretProviderClass
metadata:
name: db-dynamic-creds
spec:
provider: vault
parameters:
vaultAddress: "http://vault-active.vault.svc.cluster.local:8200"
roleName: "db-admin"
objects: |
- objectPath: "database/creds/my-dynamic-role"
secretKey: "password"
А теперь, чувак, самое важное — что я в продакшене настраивал, чтобы не «накрыться медным тазом».
- Аутентификация через ServiceAccount: В Vault включаешь
kubernetesauth method и начинаешь вязать K8s неймспейсы и service accounts с политиками Vault. Чтобы приложение изdefaultне могло достучаться до секретов изproduction. Иначе — пиздец. - High Availability (HA): Запускать Vault в одном экземпляре — это, прости, «мудя» полная. Обязательно в HA-режиме, либо с Consul, либо со своим Raft storage. Чтобы если одна нода легла — остальные работали.
- TLS и mTLS: Это святое, бля. Весь трафик — и внешний, и внутренний — должен шифроваться. А между Vault и его инжектором/CSI-провайдером я ещё и mTLS настроил, взаимную аутентификацию. Чтобы никакой левый «хуй с горы» не мог притвориться инжектором и стырить все пароли.
- Политики с наименьшими привилегиями: Вот тут мозги надо включать. В Vault политики пишешь так, чтобы приложение могло читать ТОЛЬКО свой конкретный путь. Не
database/*, а строгоdatabase/creds/my-app-role. Иначе получится «во все дыры давалка» — любая скомпрометированная поделка получит доступ ко всему. «Подозрение ебать чувствую», когда вижу широкие политики.
В общем, работа не для слабаков. Но когда всё взведено и работает, а ты знаешь, что твои секреты в безопасности — это, бля, такое чувство, «сам от себя охуел». Главное — не расслабляться и следить за обновлениями, а то «будет вам хиросима».