diff --git a/charts/miroir/examples/eso-external-secret.yaml b/charts/miroir/examples/eso-external-secret.yaml new file mode 100644 index 0000000..a7413ad --- /dev/null +++ b/charts/miroir/examples/eso-external-secret.yaml @@ -0,0 +1,40 @@ +# Example: ExternalSecret for Miroir secrets via External Secrets Operator (ESO) +# Pulls from OpenBao KV v2 at kv/search/miroir using the openbao-backend ClusterSecretStore. +# +# Prerequisites: +# - External Secrets Operator installed in the cluster +# - ClusterSecretStore "openbao-backend" configured for OpenBao access +# - KV secrets populated at kv/search/miroir with properties: +# master_key, node_master_key, admin_api_key, redis_password +# +# Usage: +# kubectl apply -f examples/eso-external-secret.yaml +apiVersion: external-secrets.io/v1beta1 +kind: ExternalSecret +metadata: + name: miroir-secrets +spec: + refreshInterval: 1h + secretStoreRef: + name: openbao-backend + kind: ClusterSecretStore + target: + name: miroir-secrets + creationPolicy: Owner + data: + - 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 + - secretKey: redis-password + remoteRef: + key: kv/search/miroir + property: redis_password diff --git a/charts/miroir/templates/_helpers.tpl b/charts/miroir/templates/_helpers.tpl index 814a2d3..882b9c7 100644 --- a/charts/miroir/templates/_helpers.tpl +++ b/charts/miroir/templates/_helpers.tpl @@ -172,6 +172,9 @@ cdc: {{- if eq (include "miroir.redisEnabled" .) "true" }} redis_bytes: {{ .Values.miroir.cdc.buffer.redis_bytes | default 1073741824 }} {{- end }} + {{- if eq (include "miroir.cdcPvcEnabled" .) "true" }} + pvc_path: /data/cdc + {{- end }} {{- end }} {{- end -}} @@ -182,11 +185,23 @@ Return "true" if Redis is enabled, "false" otherwise. {{- if .Values.redis.enabled -}}true{{- else -}}false{{- end -}} {{- end -}} +{{/* +Redis auth secret name. +*/}} +{{- define "miroir.redisSecretName" -}} +{{- if .Values.redis.auth.existingSecret -}} +{{- .Values.redis.auth.existingSecret -}} +{{- else -}} +{{- include "miroir.fullname" . }}-redis-secret +{{- end -}} +{{- end -}} + {{/* Return "true" if CDC PVC should be created, "false" otherwise. +PVC is rendered when cdc.buffer.primary=="pvc" or cdc.buffer.overflow=="pvc". */}} {{- define "miroir.cdcPvcEnabled" -}} -{{- if .Values.cdcPvc.enabled -}}true{{- else -}}false{{- end -}} +{{- if and .Values.miroir.cdc (or (eq .Values.miroir.cdc.buffer.primary "pvc") (eq .Values.miroir.cdc.buffer.overflow "pvc")) -}}true{{- else -}}false{{- end -}} {{- end -}} {{/* diff --git a/charts/miroir/templates/miroir-deployment.yaml b/charts/miroir/templates/miroir-deployment.yaml index 08de087..d79de2a 100644 --- a/charts/miroir/templates/miroir-deployment.yaml +++ b/charts/miroir/templates/miroir-deployment.yaml @@ -86,6 +86,13 @@ spec: key: adminApiKey - name: RUST_LOG value: {{ .Values.miroir.logLevel | default "info" }} + {{- if and (eq (include "miroir.redisEnabled" .) "true") .Values.redis.auth.enabled }} + - name: MIROIR_REDIS_PASSWORD + valueFrom: + secretKeyRef: + name: {{ include "miroir.redisSecretName" . }} + key: redis-password + {{- end }} volumeMounts: - name: config mountPath: /config @@ -94,7 +101,7 @@ spec: mountPath: /data {{- if eq (include "miroir.cdcPvcEnabled" .) "true" }} - name: cdc-buffer - mountPath: /cdc + mountPath: /data/cdc {{- end }} livenessProbe: httpGet: diff --git a/charts/miroir/templates/miroir-pvc.yaml b/charts/miroir/templates/miroir-pvc.yaml index 12c8a08..b718a29 100644 --- a/charts/miroir/templates/miroir-pvc.yaml +++ b/charts/miroir/templates/miroir-pvc.yaml @@ -1,6 +1,6 @@ {{/* Miroir CDC Buffer PVC -Only rendered when cdcPvc.enabled=true +Only rendered when cdc.buffer.primary=="pvc" or cdc.buffer.overflow=="pvc" */}} {{- if eq (include "miroir.cdcPvcEnabled" .) "true" }} apiVersion: v1 @@ -15,8 +15,8 @@ spec: - ReadWriteOnce resources: requests: - storage: {{ .Values.cdcPvc.size | default "5Gi" }} - {{- if .Values.cdcPvc.storageClass }} - storageClassName: {{ .Values.cdcPvc.storageClass }} + storage: {{ .Values.miroir.cdc.buffer.pvc_size | default "10Gi" }} + {{- if .Values.miroir.cdc.buffer.pvc_storage_class }} + storageClassName: {{ .Values.miroir.cdc.buffer.pvc_storage_class }} {{- end }} {{- end }} diff --git a/charts/miroir/templates/miroir-redis-secret.yaml b/charts/miroir/templates/miroir-redis-secret.yaml new file mode 100644 index 0000000..eb0d97b --- /dev/null +++ b/charts/miroir/templates/miroir-redis-secret.yaml @@ -0,0 +1,15 @@ +{{/* +Redis auth secret (auto-generated when redis.auth.enabled and no existingSecret) +*/}} +{{- if and (eq (include "miroir.redisEnabled" .) "true") .Values.redis.auth.enabled (not .Values.redis.auth.existingSecret) }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ include "miroir.fullname" . }}-redis-secret + labels: + {{- include "miroir.labels" . | nindent 4 }} + app.kubernetes.io/component: redis +type: Opaque +data: + redis-password: {{ randAlphaNum 32 | b64enc }} +{{- end }} diff --git a/charts/miroir/templates/redis-deployment.yaml b/charts/miroir/templates/redis-deployment.yaml index 735072a..d246054 100644 --- a/charts/miroir/templates/redis-deployment.yaml +++ b/charts/miroir/templates/redis-deployment.yaml @@ -1,5 +1,5 @@ {{/* -Redis Deployment (only when taskStore.backend=redis) +Redis Deployment (only when redis.enabled=true) */}} {{- if eq (include "miroir.redisEnabled" .) "true" }} apiVersion: apps/v1 @@ -40,6 +40,19 @@ spec: - name: redis containerPort: 6379 protocol: TCP + {{- if .Values.redis.auth.enabled }} + env: + - name: REDIS_PASSWORD + valueFrom: + secretKeyRef: + name: {{ include "miroir.redisSecretName" . }} + key: redis-password + {{- end }} + args: + {{- if .Values.redis.auth.enabled }} + - --requirepass + - $(REDIS_PASSWORD) + {{- end }} {{- if .Values.redis.persistence.enabled }} volumeMounts: - name: data @@ -47,12 +60,24 @@ spec: {{- end }} livenessProbe: exec: - command: ["redis-cli", "ping"] + command: + - redis-cli + {{- if .Values.redis.auth.enabled }} + - -a + - $(REDIS_PASSWORD) + {{- end }} + - ping initialDelaySeconds: 5 periodSeconds: 10 readinessProbe: exec: - command: ["redis-cli", "ping"] + command: + - redis-cli + {{- if .Values.redis.auth.enabled }} + - -a + - $(REDIS_PASSWORD) + {{- end }} + - ping initialDelaySeconds: 3 periodSeconds: 5 resources: diff --git a/charts/miroir/values.schema.json b/charts/miroir/values.schema.json index 2981825..eec4424 100644 --- a/charts/miroir/values.schema.json +++ b/charts/miroir/values.schema.json @@ -43,7 +43,26 @@ }, "nodeSelector": { "type": "object" }, "tolerations": { "type": "array" }, - "affinity": { "type": "object" } + "affinity": { "type": "object" }, + "cdc": { + "type": "object", + "properties": { + "enabled": { "type": "boolean" }, + "emit_ttl_deletes": { "type": "boolean" }, + "emit_internal_writes": { "type": "boolean" }, + "buffer": { + "type": "object", + "properties": { + "primary": { "type": "string", "enum": ["memory", "pvc", "redis"] }, + "overflow": { "type": "string", "enum": ["drop", "pvc", "redis"] }, + "pvc_size": { "type": "string" }, + "pvc_storage_class": { "type": "string" }, + "memory_bytes": { "type": "integer", "minimum": 0 }, + "redis_bytes": { "type": "integer", "minimum": 0 } + } + } + } + } } }, "taskStore": { @@ -193,17 +212,16 @@ "type": { "type": "string" }, "port": { "type": "integer", "minimum": 1, "maximum": 65535 } } + }, + "auth": { + "type": "object", + "properties": { + "enabled": { "type": "boolean" }, + "existingSecret": { "type": "string" } + } } } }, - "cdcPvc": { - "type": "object", - "properties": { - "enabled": { "type": "boolean" }, - "size": { "type": "string" }, - "storageClass": { "type": "string" } - } - }, "search_ui": { "type": "object", "properties": { diff --git a/charts/miroir/values.yaml b/charts/miroir/values.yaml index 0510b01..a66f1ca 100644 --- a/charts/miroir/values.yaml +++ b/charts/miroir/values.yaml @@ -28,6 +28,16 @@ miroir: nodeSelector: {} tolerations: [] affinity: {} + cdc: + enabled: true + emit_ttl_deletes: false + emit_internal_writes: false + buffer: + primary: memory # memory | pvc | redis + overflow: drop # drop | pvc | redis + pvc_size: 10Gi + pvc_storage_class: "" + memory_bytes: 67108864 taskStore: backend: sqlite # sqlite | redis @@ -109,7 +119,7 @@ redis: enabled: false # dev default: enable for production image: repository: redis - tag: 7-alpine + tag: 7.4-alpine pullPolicy: IfNotPresent replicas: 1 podAnnotations: {} @@ -126,17 +136,14 @@ redis: affinity: {} persistence: enabled: true - size: 1Gi + size: 5Gi storageClass: "" service: type: ClusterIP port: 6379 - -# PVC for CDC buffer (when cdc.buffer.primary=pvc or overflow=pvc) -cdcPvc: - enabled: false - size: 5Gi - storageClass: "" + auth: + enabled: true + existingSecret: "" # auto-generated as -redis-secret when empty; password comes from K8s Secret or ESO # Prometheus Operator integration (plan §10 + §14.9) serviceMonitor: