feat(helm): add CDC buffer config and ESO example (P8.7)

Add CDC configuration section to values.yaml with buffer settings:
- primary: memory|redis|pvc (default memory)
- overflow: redis|pvc|drop (default redis)
- pvc_size: 10Gi (when primary or overflow is pvc)
- memory_bytes: 64MiB, redis_bytes: 1GiB

Add cdcPvcEnabled helper to _helpers.tpl to conditionally render
the CDC PVC template when cdc.buffer.primary or overflow is "pvc".

Convert examples/eso-external-secret.yaml from raw K8s manifest
to Helm values file demonstrating ESO integration:
- eso.enabled: true
- eso.secretStoreRef configuration
- Optional flags for previous JWT, shared key, Redis password

Acceptance:
- With cdc.buffer.overflow: pvc → PVC manifest rendered
- With default values → no PVC manifest rendered
- redis.enabled: true → redis-deployment.yaml rendered
- ESO example demonstrates openbao-backend integration

Closes: miroir-qjt.7
This commit is contained in:
jedarden 2026-05-24 13:20:32 -04:00
parent 041cb5a2a8
commit 0dd26016b5
3 changed files with 66 additions and 79 deletions

View file

@ -1,86 +1,42 @@
# ExternalSecret for Miroir — full secret inventory (plan §9)
# Example: External Secrets Operator (ESO) integration for Miroir
# Plan §6 ESO integration: pulling secrets from OpenBao rather than baking into values.yaml
#
# Pulls from OpenBao KV v2 at kv/search/miroir via the openbao-backend
# ClusterSecretStore. Every key in the inventory is mapped below.
# This example assumes:
# - ESO is installed in the cluster (https://external-secrets.io/)
# - A ClusterSecretStore named "openbao-backend" exists
# - OpenBao has secrets at kv/search/miroir
#
# Prerequisites:
# - External Secrets Operator installed in the cluster
# - ClusterSecretStore "openbao-backend" configured for OpenBao access
# - KV secrets populated at kv/search/miroir
#
# Secret inventory:
# ┌───────────────────────────────┬──────────────────────────────────────────┬─────────────────────────────────────┐
# │ OpenBao key │ Consumer │ Rotation │
# ├───────────────────────────────┼──────────────────────────────────────────┼─────────────────────────────────────┤
# │ master_key │ miroir-proxy (MIROIR_MASTER_KEY) │ Manual / infrequent │
# │ node_master_key │ miroir-proxy → Meilisearch nodes │ Admin-scoped child key (P10.2) │
# │ admin_api_key │ Operators, miroir-ctl │ Rotate with admin_session_seal_key │
# │ admin_session_seal_key │ miroir-proxy (ADMIN_SESSION_SEAL_KEY) │ P10.4 │
# │ search_ui_jwt_secret │ miroir-proxy (SEARCH_UI_JWT_SECRET) │ P10.3 dual-secret overlap │
# │ search_ui_jwt_secret_previous │ miroir-proxy — only during rotation │ Ephemeral; absent outside rotation │
# │ search_ui_shared_key │ miroir-proxy + host apps (shared_key) │ Only in shared_key auth mode │
# │ redis_password │ miroir-proxy (MIROIR_REDIS_PASSWORD) │ Optional; only if redis_auth_enabled│
# └───────────────────────────────┴──────────────────────────────────────────┴─────────────────────────────────────┘
#
# Not managed by this ExternalSecret (infrastructure, not Miroir scope):
# - meilisearch_master_key → Meilisearch startup (planned-maintenance)
# - ghcr_credentials → Kaniko build pipeline (iad-ci)
# - github_token → gh CLI (iad-ci)
#
# Usage:
# kubectl apply -f examples/eso-external-secret.yaml
#
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: miroir-secrets
spec:
refreshInterval: 1h
# Install this example:
# helm install miroir ./charts/miroir -f examples/eso-external-secret.yaml
eso:
enabled: true
secretStoreRef:
name: openbao-backend
kind: ClusterSecretStore
target:
name: miroir-secrets
creationPolicy: Owner
data:
# ── Critical secrets (always required) ──────────────────────────────
- secretKey: masterKey
remoteRef:
key: kv/search/miroir
property: master_key
- secretKey: nodeMasterKey
remoteRef:
key: kv/search/miroir
property: node_master_key
- secretKey: adminApiKey
remoteRef:
key: kv/search/miroir
property: admin_api_key
secretPath: kv/search/miroir
refreshInterval: 1h
# Optional: include previous JWT secret for key rotation (plan §9)
includePreviousJwt: true
# Optional: include shared key for search_ui auth mode "shared_key"
includeSharedKey: false
# Optional: include Redis password when using the chart's Redis deployment
includeRedisPassword: false
# ── Admin session sealing (P10.4) ──────────────────────────────────
- secretKey: adminSessionSealKey
remoteRef:
key: kv/search/miroir
property: admin_session_seal_key
# When eso.enabled is true, the chart's ExternalSecret templates render
# and create K8s Secrets populated from OpenBao. Set existingSecret to
# the ESO-generated Secret name so the Deployment references it.
miroir:
existingSecret: "" # Defaults to "<release-name>-miroir-secret" from ESO
# ── Search UI JWT (P10.3 dual-secret overlap) ──────────────────────
- secretKey: searchUiJwtSecret
remoteRef:
key: kv/search/miroir
property: search_ui_jwt_secret
- secretKey: searchUiJwtSecretPrevious
remoteRef:
key: kv/search/miroir
property: search_ui_jwt_secret_previous
# ── Shared-key auth mode (only when search_ui.auth.mode=shared_key) ─
- secretKey: searchUiSharedKey
remoteRef:
key: kv/search/miroir
property: search_ui_shared_key
# ── Redis auth (only when redis.auth.enabled=true) ─────────────────
- secretKey: redis-password
remoteRef:
key: kv/search/miroir
property: redis_password
# Example minimal values for a functional deployment with ESO:
# miroir:
# shards: 64
# replicationFactor: 2
# taskStore:
# backend: sqlite
# path: /data/miroir-tasks.db
# admin_ui:
# enabled: true
# redis:
# enabled: false # Set true for HA multi-replica deployments

View file

@ -55,6 +55,13 @@ Redis enabled
{{- eq .Values.miroir.taskStore.backend "redis" }}
{{- end }}
{{/*
CDC PVC enabled — only rendered when cdc.buffer.primary=="pvc" or cdc.buffer.overflow=="pvc" (plan §13.13)
*/}}
{{- define "miroir.cdcPvcEnabled" -}}
{{- or (eq .Values.miroir.cdc.buffer.primary "pvc") (eq .Values.miroir.cdc.buffer.overflow "pvc") }}
{{- end }}
{{/*
Service Account Name
*/}}

View file

@ -163,6 +163,30 @@ miroir:
# Existing secret with keys: masterKey, nodeMasterKey, adminApiKey
existingSecret: ""
# CDC (Change Data Capture) configuration (plan §13.13)
cdc:
enabled: false
emit_ttl_deletes: false
emit_internal_writes: false
sinks: []
# Example sink configurations:
# - type: webhook
# url: https://internal/cdc
# batch_size: 100
# batch_flush_ms: 1000
# include_body: false
# retry_max_s: 3600
# - type: nats
# url: nats://nats.messaging.svc:4222
# subject_prefix: miroir.cdc
buffer:
primary: memory # memory | redis | pvc
memory_bytes: 67108864 # 64 MiB — fits within §14.2 per-pod budget
overflow: redis # redis | pvc | drop
redis_bytes: 1073741824 # 1 GiB per-pod budget in Redis for overflow
pvc_size: 10Gi # Size of PVC when primary or overflow is pvc
pvc_storage_class: "" # Empty uses default storage class
# Redis deployment (when taskStore.backend=redis)
redis:
enabled: false