Files
K3S/addons/external-secrets/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

294 lines
9.1 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# External Secrets Operator (ESO)
Синхронизирует секреты из внешних хранилищ (HashiCorp Vault, AWS Secrets Manager, GCP Secret Manager и др.) в нативные Kubernetes Secrets.
**Когда использовать ESO вместо Vault Agent Injector:**
- Нужны стандартные k8s Secrets (`secretRef`, `envFrom`) — Helm чарты не менять
- Секреты нужны до старта пода (init containers, admission webhooks)
- Нужна синхронизация между namespace
- Нет желания добавлять Vault annotations в каждый Deployment
## Установка
```bash
# Базовая установка (настрой ClusterSecretStore вручную после)
make addon-external-secrets
# Сразу с настроенным ClusterSecretStore → Vault (если AppRole уже создан)
make addon-external-secrets ARGS="-e external_secrets_vault_role_id=<role-id>"
```
## Настройка AppRole в Vault
ESO использует AppRole для аутентификации в Vault. Выполни один раз:
```bash
# 1. Port-forward к Vault
kubectl port-forward -n vault svc/vault 8200:8200 &
export VAULT_ADDR=http://localhost:8200
vault login <root_token>
# 2. Включить AppRole auth (если ещё не включён)
vault auth enable approle
# 3. Создать политику для ESO (read-only на все секреты)
vault policy write eso-policy - <<EOF
path "secret/data/*" {
capabilities = ["read"]
}
path "secret/metadata/*" {
capabilities = ["read", "list"]
}
EOF
# 4. Создать AppRole роль
vault write auth/approle/role/eso-role \
secret_id_ttl="0" \
token_ttl="1h" \
token_max_ttl="24h" \
token_policies="eso-policy"
# 5. Получить Role ID (публичный, вставить в addons.yml)
vault read -field=role_id auth/approle/role/eso-role/role-id
# → Скопируй в external_secrets_vault_role_id в group_vars/all/addons.yml
# 6. Получить Secret ID (секретный, вставить в vault.yml)
vault write -f -field=secret_id auth/approle/role/eso-role/secret-id
# → Скопируй в vault_eso_approle_secret_id в group_vars/all/vault.yml
# 7. Применить ClusterSecretStore
make addon-external-secrets ARGS="-e external_secrets_vault_role_id=<role-id>"
```
## Проверка подключения
```bash
# Статус ClusterSecretStore (должен быть Valid)
kubectl get clustersecretstore vault-backend
# Подробности
kubectl describe clustersecretstore vault-backend
```
## Использование в YAML манифестах
### Простой ExternalSecret — синхронизация одного секрета
```yaml
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: myapp-db-secret
namespace: myapp
spec:
refreshInterval: 1h # как часто синхронизировать
secretStoreRef:
name: vault-backend # ClusterSecretStore
kind: ClusterSecretStore
target:
name: myapp-db-credentials # имя k8s Secret который будет создан
creationPolicy: Owner # ESO управляет Secret (авто-удаление)
data:
- secretKey: DB_PASSWORD # ключ в k8s Secret
remoteRef:
key: myapp/database # путь в Vault: secret/data/myapp/database
property: password # поле внутри секрета
- secretKey: DB_USER
remoteRef:
key: myapp/database
property: username
```
После применения ESO создаст k8s Secret `myapp-db-credentials`.
### Использование в Deployment (через envFrom)
```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp
namespace: myapp
spec:
template:
spec:
containers:
- name: app
image: myapp:latest
envFrom:
- secretRef:
name: myapp-db-credentials # создан ExternalSecret выше
# ИЛИ выборочно:
env:
- name: DATABASE_PASSWORD
valueFrom:
secretKeyRef:
name: myapp-db-credentials
key: DB_PASSWORD
```
### Весь секрет целиком (все поля из Vault)
```yaml
spec:
dataFrom:
- extract:
key: myapp/config # все поля из secret/data/myapp/config станут ключами в k8s Secret
```
### ExternalSecret с template (форматирование)
```yaml
spec:
target:
name: myapp-connection-string
template:
data:
DATABASE_URL: "postgresql://{{ .username }}:{{ .password }}@postgres:5432/mydb"
dataFrom:
- extract:
key: myapp/database
```
## Использование в Helm чартах
### Способ 1: ExternalSecret в том же Helm чарте
```yaml
# templates/external-secret.yaml
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: {{ include "myapp.fullname" . }}-secrets
namespace: {{ .Release.Namespace }}
spec:
refreshInterval: {{ .Values.secrets.refreshInterval | default "1h" }}
secretStoreRef:
name: vault-backend
kind: ClusterSecretStore
target:
name: {{ include "myapp.fullname" . }}-secrets
creationPolicy: Owner
dataFrom:
- extract:
key: {{ .Values.secrets.vaultPath }} # задаётся в values.yaml
```
```yaml
# values.yaml
secrets:
vaultPath: "myapp/production/config"
refreshInterval: "30m"
# Deployment использует стандартный envFrom:
envFrom:
- secretRef:
name: "{{ include "myapp.fullname" . }}-secrets"
```
### Способ 2: ESO как внешняя зависимость (рекомендуется)
Секреты создаются заранее через отдельный ExternalSecret, Helm чарт просто ссылается на k8s Secret:
```bash
# 1. Создать ExternalSecret (один раз, в GitOps репозитории)
kubectl apply -f external-secret.yaml
# 2. Установить Helm чарт — он найдёт уже существующий Secret
helm install myapp ./mychart --set existingSecret=myapp-db-credentials
```
```yaml
# values.yaml чарта
existingSecret: "" # если задан — используется, иначе chart создаёт свой
# templates/deployment.yaml
{{- if .Values.existingSecret }}
envFrom:
- secretRef:
name: {{ .Values.existingSecret }}
{{- end }}
```
### Способ 3: ArgoCD + ESO
```yaml
# argocd Application
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: myapp
spec:
source:
helm:
values: |
# Секреты создаются ESO автоматически — чарт просто ссылается
envFrom:
- secretRef:
name: myapp-vault-secrets
```
## PushSecret — запись секретов в Vault из k8s
ESO поддерживает обратную синхронизацию (k8s → Vault):
```yaml
apiVersion: external-secrets.io/v1alpha1
kind: PushSecret
metadata:
name: push-to-vault
namespace: myapp
spec:
refreshInterval: 10s
secretStoreRefs:
- name: vault-backend
kind: ClusterSecretStore
selector:
secret:
name: my-local-secret # существующий k8s Secret
data:
- match:
secretKey: password
remoteRef:
remoteKey: myapp/config
property: password
```
## Управление несколькими SecretStore
### Namespace-scoped SecretStore (для разных Vault paths/политик)
```yaml
apiVersion: external-secrets.io/v1beta1
kind: SecretStore
metadata:
name: vault-myapp # только для namespace myapp
namespace: myapp
spec:
provider:
vault:
server: "http://vault.vault.svc.cluster.local:8200"
path: "myapp" # ограниченный путь
version: "v2"
auth:
appRole:
path: "approle"
roleId: "<myapp-role-id>"
secretRef:
name: vault-approle-myapp
key: secretId
```
## Мониторинг
Если `addon_prometheus_stack: true`, метрики ESO доступны в Grafana:
- `external_secrets_sync_calls_total` — количество синхронизаций
- `external_secrets_sync_call_errors_total` — ошибки
- Дашборд: импортируй Grafana Dashboard ID 21045
```bash
# Статус всех ExternalSecrets в кластере
kubectl get externalsecrets --all-namespaces
# Подробности (условие Ready/SecretSynced)
kubectl describe externalsecret myapp-db-secret -n myapp
```
## Официальные ресурсы
- Официальный сайт: [https://external-secrets.io/](https://external-secrets.io/)
- Официальная документация: [https://external-secrets.io/latest/](https://external-secrets.io/latest/)
- Версии Helm chart / ПО: [https://artifacthub.io/packages/helm/external-secrets-operator/external-secrets](https://artifacthub.io/packages/helm/external-secrets-operator/external-secrets)