Files
K3S/addons/vault/README.md
Sergey Antropoff 38aaadbfb1 docs: sync addon docs with explicit external/internal service modes
Обновлена документация под новые аддоны (gitlab, redis, mongodb, kafka, kafka-ui, rabbitmq) и новую модель явного выбора зависимостей. Добавлены и унифицированы описания переключателей *_database_mode и *_redis_mode, обновлена таблица зависимостей аддонов, примеры конфигурации и список vault-секретов.
2026-04-29 23:21:04 +03:00

8.9 KiB
Raw Permalink Blame History

HashiCorp Vault

Self-hosted менеджер секретов с шифрованием, аудитом и fine-grained политиками доступа.

Установка

# Standalone (по умолчанию, 1 Pod)
make addon-vault

# HA (3 Pods с Raft, нужны минимум 3 ноды)
make addon-vault ARGS="-e vault_mode=ha"

# С авто-unseal через k8s Secret (homelab/dev)
make addon-vault ARGS="-e vault_auto_unseal_type=k8s"

# С AWS KMS авто-unseal (production)
make addon-vault ARGS="-e vault_auto_unseal_type=aws -e vault_aws_kms_region=us-east-1 -e vault_aws_kms_key_id=..."

# С Ingress
make addon-vault ARGS="-e vault_ingress_enabled=true -e vault_ingress_host=vault.example.com"

Первичная инициализация (ручной режим)

После установки Vault нужно инициализировать (только один раз):

# Инициализация (генерирует unseal keys + root token)
kubectl exec -n vault vault-0 -- vault operator init \
  -key-shares=5 \
  -key-threshold=3

# ВАЖНО: сохрани 5 unseal keys и root token в надёжное место!
# Пример вывода:
# Unseal Key 1: abc...
# Unseal Key 2: def...
# ...
# Initial Root Token: hvs.xxxxx

# Unseal (нужно подать 3 из 5 ключей)
kubectl exec -n vault vault-0 -- vault operator unseal <key1>
kubectl exec -n vault vault-0 -- vault operator unseal <key2>
kubectl exec -n vault vault-0 -- vault operator unseal <key3>

# Проверка
kubectl exec -n vault vault-0 -- vault status

Авто-unseal режимы

k8s Secret (homelab, не для production)

make addon-vault ARGS="-e vault_auto_unseal_type=k8s"

Vault автоматически инициализируется и unseal keys сохраняются в k8s Secret vault-unseal-keys. Unsealer Deployment следит за состоянием и unseals при перезапуске.

Получить root token:

kubectl get secret vault-unseal-keys -n vault \
  -o jsonpath='{.data.root_token}' | base64 -d

AWS KMS (production)

# group_vars/all/addons.yml
vault_auto_unseal_type: "aws"
vault_aws_kms_region: "us-east-1"
vault_aws_kms_key_id: "arn:aws:kms:us-east-1:..."

# group_vars/all/vault.yml
vault_aws_kms_access_key: "AKIAIOSFODNN7EXAMPLE"
vault_aws_kms_secret_key: "wJalrXUtnFEMI/K7MDENG/..."

Transit Seal (через другой Vault)

vault_auto_unseal_type: "transit"
vault_transit_address: "https://vault-primary.example.com"
vault_transit_key_name: "autounseal"
# vault.yml:
vault_transit_seal_token: "hvs.CAESIxxxxxx"

Работа с секретами

CLI (локально через port-forward)

# Port-forward
kubectl port-forward -n vault svc/vault 8200:8200 &

# Авторизация
export VAULT_ADDR=http://localhost:8200
vault login <root_token>

# Включить KV v2 engine
vault secrets enable -path=secret kv-v2

# Записать секрет
vault kv put secret/myapp/config \
  db_password="supersecret" \
  api_key="abc123"

# Прочитать секрет
vault kv get secret/myapp/config
vault kv get -field=db_password secret/myapp/config

CLI (из пода в кластере)

kubectl exec -n vault vault-0 -- env VAULT_ADDR=http://localhost:8200 \
  vault kv put secret/myapp/config db_password="supersecret"

Kubernetes Auth Method

Позволяет подам авторизоваться через их ServiceAccount токен:

# Включить kubernetes auth
vault auth enable kubernetes

# Настроить
vault write auth/kubernetes/config \
  kubernetes_host="https://kubernetes.default.svc.cluster.local:443"

# Создать политику доступа
vault policy write myapp-policy - <<EOF
path "secret/data/myapp/*" {
  capabilities = ["read"]
}
EOF

# Создать роль (привязка: namespace + serviceaccount → policy)
vault write auth/kubernetes/role/myapp-role \
  bound_service_account_names="myapp-sa" \
  bound_service_account_namespaces="myapp" \
  policies="myapp-policy" \
  ttl="1h"

Vault Agent Injector — секреты в YAML манифестах

Injector (установлен по умолчанию) автоматически монтирует секреты через sidecar по annotations.

Пример Pod с автоинжекцией секретов

apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp
  namespace: myapp
spec:
  template:
    metadata:
      annotations:
        # Включаем инжектор
        vault.hashicorp.com/agent-inject: "true"
        # Адрес Vault (по умолчанию авто-определяется)
        vault.hashicorp.com/role: "myapp-role"

        # Инжектировать секрет как файл /vault/secrets/config
        vault.hashicorp.com/agent-inject-secret-config: "secret/data/myapp/config"

        # Шаблон (опционально — форматирует вывод)
        vault.hashicorp.com/agent-inject-template-config: |
          {{- with secret "secret/data/myapp/config" -}}
          DB_PASSWORD={{ .Data.data.db_password }}
          API_KEY={{ .Data.data.api_key }}
          {{- end }}
    spec:
      serviceAccountName: myapp-sa   # должен совпадать с vault role
      containers:
        - name: app
          image: myapp:latest
          command: ["sh", "-c", "source /vault/secrets/config && ./myapp"]

Создать ServiceAccount для пода

kubectl create serviceaccount myapp-sa -n myapp

Инжекция как переменные окружения

annotations:
  vault.hashicorp.com/agent-inject: "true"
  vault.hashicorp.com/role: "myapp-role"
  vault.hashicorp.com/agent-inject-secret-env: "secret/data/myapp/config"
  vault.hashicorp.com/agent-inject-template-env: |
    {{- with secret "secret/data/myapp/config" -}}
    export DB_PASSWORD="{{ .Data.data.db_password }}"
    export API_KEY="{{ .Data.data.api_key }}"
    {{- end }}
# В контейнере:
command: ["/bin/sh", "-c", "source /vault/secrets/env && exec myapp"]

Vault в Helm чартах

Через Vault Agent (annotations в values.yaml)

# values.yaml вашего чарта
podAnnotations:
  vault.hashicorp.com/agent-inject: "true"
  vault.hashicorp.com/role: "myapp-role"
  vault.hashicorp.com/agent-inject-secret-db: "secret/data/myapp/db"
  vault.hashicorp.com/agent-inject-template-db: |
    {{- with secret "secret/data/myapp/db" -}}
    {{ .Data.data.password }}
    {{- end }}

serviceAccount:
  create: true
  name: myapp-sa

Через External Secrets Operator (рекомендуется — см. ESO README)

# Helm чарт не меняется — ESO создаёт k8s Secret автоматически
# Используй стандартный envFrom/secretRef в values.yaml
envFrom:
  - secretRef:
      name: myapp-secrets   # создан ExternalSecret → Vault

AppRole Auth (для сервисов без k8s ServiceAccount)

# Включить AppRole
vault auth enable approle

# Создать роль
vault write auth/approle/role/myservice \
  secret_id_ttl="720h" \
  token_ttl="1h" \
  token_policies="myapp-policy"

# Получить Role ID (не секретный)
vault read auth/approle/role/myservice/role-id

# Получить Secret ID (секретный, одноразовый)
vault write -f auth/approle/role/myservice/secret-id

# Авторизация через AppRole
vault write auth/approle/login \
  role_id="<role_id>" \
  secret_id="<secret_id>"

Аудит и мониторинг

# Включить аудит лог в stdout
vault audit enable file file_path=stdout

# Статус кластера (HA)
kubectl exec -n vault vault-0 -- vault operator members

# Grafana: метрики доступны если addon_prometheus_stack: true
# Дашборд: импортируй ID 12904 из Grafana.com

Полезные команды

# Статус
kubectl exec -n vault vault-0 -- vault status

# Список engines
kubectl exec -n vault vault-0 -- vault secrets list

# Список auth methods
kubectl exec -n vault vault-0 -- vault auth list

# Seal (экстренная блокировка)
kubectl exec -n vault vault-0 -- vault operator seal

# Raft cluster (HA)
kubectl exec -n vault vault-0 -- vault operator raft list-peers

Официальные ресурсы