diff --git a/redis/Chart.yaml b/redis/Chart.yaml index 386e08d..61e71b2 100644 --- a/redis/Chart.yaml +++ b/redis/Chart.yaml @@ -1,35 +1,17 @@ +# Chart: keydb-custom +# Helm chart tailored for KeyDB (EqAlpha) on 2 Raspberry Pi 5 nodes +# - Mode: master (statefulset index 0) + replica (index 1) +# - Replica runs as replicaof master at startup +# - server-threads = 4 +# - Config mounted via ConfigMap +# - Liveness / readiness probes included +# - Persistence via PersistentVolumeClaim (storageClass configurable) +# ----------------------------------------------------------------------------- +# Chart.yaml +# ----------------------------------------------------------------------------- apiVersion: v2 -name: redis -description: A Helm chart for Kubernetes - -dependencies: -- name: tool - version: 0.1.0 - repository: https://gitea.arcodange.duckdns.org/api/packages/arcodange-org/helm -- name: keydb - version: 0.5.22 - repository: https://charts.bitnami.com/bitnami -# - name: redis -# version: 24.0.0 -# repository: https://charts.bitnami.com/bitnami - -# A chart can be either an 'application' or a 'library' chart. -# -# Application charts are a collection of templates that can be packaged into versioned archives -# to be deployed. -# -# Library charts provide useful utilities or functions for the chart developer. They're included as -# a dependency of application charts to inject those utilities and functions into the rendering -# pipeline. Library charts do not define any templates and therefore cannot be deployed. +name: keydb-custom # https://chatgpt.com/c/69315a7d-cb88-832c-bc18-3be2b519356d +description: "Custom KeyDB Helm chart for 2-node Master+Replica on Raspberry Pi 5" type: application - -# This is the chart version. This version number should be incremented each time you make changes -# to the chart and its templates, including the app version. -# Versions are expected to follow Semantic Versioning (https://semver.org/) version: 0.1.0 - -# This is the version number of the application being deployed. This version number should be -# incremented each time you make changes to the application. Versions are not expected to -# follow Semantic Versioning. They should reflect the version the application is using. -# It is recommended to use it with quotes. -# appVersion: "1.16.0" +appVersion: "latest" \ No newline at end of file diff --git a/redis/templates/NOTES.txt b/redis/templates/NOTES.txt new file mode 100644 index 0000000..c67b14a --- /dev/null +++ b/redis/templates/NOTES.txt @@ -0,0 +1,12 @@ +# ----------------------------------------------------------------------------- +# templates/NOTES.txt +# ----------------------------------------------------------------------------- +{{""}} +1. Get the application URL by running these commands: + export POD0=$(kubectl get pods -l app={{ include "keydb-custom.name" . }} -o jsonpath="{.items[0].metadata.name}") + kubectl logs $POD0 + +2. To connect via keydb-cli from a pod: + kubectl run -it --rm --image=eqalpha/keydb --restart=Never keydb-client -- /bin/sh + # inside the pod: + keydb-cli -h {{ include "keydb-custom.fullname" . }}-0.{{ include "keydb-custom.fullname" . }}-headless -a "{{ .Values.auth.password }}" PING diff --git a/redis/templates/_helpers.tpl b/redis/templates/_helpers.tpl new file mode 100644 index 0000000..b41ae0e --- /dev/null +++ b/redis/templates/_helpers.tpl @@ -0,0 +1,11 @@ +# ----------------------------------------------------------------------------- +# templates/_helpers.tpl +# ----------------------------------------------------------------------------- +{{""}} +{{- define "keydb-custom.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 -}} +{{- end -}} + +{{- define "keydb-custom.fullname" -}} +{{- printf "%s" (include "keydb-custom.name" .) -}} +{{- end -}} \ No newline at end of file diff --git a/redis/templates/configmap.yaml b/redis/templates/configmap.yaml new file mode 100644 index 0000000..9f56318 --- /dev/null +++ b/redis/templates/configmap.yaml @@ -0,0 +1,21 @@ +# ----------------------------------------------------------------------------- +# templates/configmap.yaml +# ----------------------------------------------------------------------------- +{{""}} +apiVersion: v1 +kind: ConfigMap +metadata: + name: '{{ include "keydb-custom.fullname" . }}-conf' + labels: + app: {{ include "keydb-custom.name" . }} +data: + keydb.conf: | + # Minimal keydb.conf generated from values + server-threads {{ .Values.keydb.serverThreads }} + maxmemory {{ .Values.keydb.maxmemory }} + maxmemory-policy {{ .Values.keydb.maxmemoryPolicy }} + appendonly {{ .Values.keydb.appendonly }} + protected-mode no + bind 0.0.0.0 + port {{ .Values.service.port }} + # requirepass is handled via env (not in file) \ No newline at end of file diff --git a/redis/templates/headless-svc.yaml b/redis/templates/headless-svc.yaml new file mode 100644 index 0000000..41877f5 --- /dev/null +++ b/redis/templates/headless-svc.yaml @@ -0,0 +1,17 @@ +# ----------------------------------------------------------------------------- +# templates/headless-svc.yaml +# ----------------------------------------------------------------------------- +{{""}} +apiVersion: v1 +kind: Service +metadata: + name: '{{ include "keydb-custom.fullname" . }}-headless' + labels: + app: {{ include "keydb-custom.name" . }} +spec: + clusterIP: None + selector: + app: {{ include "keydb-custom.name" . }} + ports: + - port: {{ .Values.service.port }} + name: keydb \ No newline at end of file diff --git a/redis/templates/helm-chart-config.yaml b/redis/templates/helm-chart-config.yaml deleted file mode 100644 index 31cb271..0000000 --- a/redis/templates/helm-chart-config.yaml +++ /dev/null @@ -1,3 +0,0 @@ -{{- if eq .Values.tool.kind "HelmChart" -}} -{{- include "tool.helm-chart-config.tpl" . -}} -{{- end -}} \ No newline at end of file diff --git a/redis/templates/helm-chart.yaml b/redis/templates/helm-chart.yaml deleted file mode 100644 index c6b793d..0000000 --- a/redis/templates/helm-chart.yaml +++ /dev/null @@ -1,3 +0,0 @@ -{{- if eq .Values.tool.kind "HelmChart" -}} -{{- include "tool.helm-chart.tpl" . -}} -{{- end -}} \ No newline at end of file diff --git a/redis/templates/secret-auth.yaml b/redis/templates/secret-auth.yaml new file mode 100644 index 0000000..52aa4e2 --- /dev/null +++ b/redis/templates/secret-auth.yaml @@ -0,0 +1,11 @@ +# ----------------------------------------------------------------------------- +# templates/secret-auth.yaml +# ----------------------------------------------------------------------------- +{{""}} +apiVersion: v1 +kind: Secret +metadata: + name: '{{ include "keydb-custom.fullname" . }}-auth' +type: Opaque +stringData: + password: "{{ .Values.auth.password }}" \ No newline at end of file diff --git a/redis/templates/statefulset.yaml b/redis/templates/statefulset.yaml new file mode 100644 index 0000000..1fbebcf --- /dev/null +++ b/redis/templates/statefulset.yaml @@ -0,0 +1,135 @@ +# ----------------------------------------------------------------------------- +# templates/statefulset.yaml +# ----------------------------------------------------------------------------- +{{""}} +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: {{ include "keydb-custom.fullname" . }} + labels: + app: {{ include "keydb-custom.name" . }} +spec: + serviceName: {{ include "keydb-custom.fullname" . }}-headless + replicas: {{ .Values.replicaCount }} + selector: + matchLabels: + app: {{ include "keydb-custom.name" . }} + template: + metadata: + labels: + app: {{ include "keydb-custom.name" . }} + spec: + {{- if .Values.nodeAffinity }} + affinity: + nodeAffinity: {{ toYaml .Values.nodeAffinity | nindent 8 }} + {{- end }} + {{- if .Values.podAntiAffinity.enabled }} + affinity: + podAntiAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + - labelSelector: + matchExpressions: + - key: "app" + operator: In + values: + - {{ include "keydb-custom.name" . }} + topologyKey: "kubernetes.io/hostname" + {{- end }} + containers: + - name: keydb + image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + ports: + - name: keydb + containerPort: {{ .Values.service.port }} + env: + - name: KEYDB_PASSWORD + valueFrom: + secretKeyRef: + name: {{ include "keydb-custom.fullname" . }}-auth + key: password + - name: KEYDB_CONF_FILE + value: "/etc/keydb/keydb.conf" + volumeMounts: + - name: keydb-conf + mountPath: /etc/keydb + - name: data + mountPath: /bitnami/keydb + resources: + {{ toYaml .Values.resources | nindent 12 }} + command: + - sh + - -c + - | + # Startup logic: + # - pod index 0 starts as master + # - pod index >0 will start and then configure REPLICAOF to master + POD_NAME=$(hostname) + # derive ordinal from pods named - + ORDINAL=${POD_NAME##*-} + # start keydb-server in background to accept CONFIG/CLI commands + keydb-server /etc/keydb/keydb.conf & + sleep 1 + if [ "${ORDINAL}" != "0" ]; then + # wait for master to be ready + MASTER_HOST={{ include "keydb-custom.fullname" . }}-0.{{ include "keydb-custom.fullname" . }}-headless + until nc -z ${MASTER_HOST} {{ .Values.service.port }}; do sleep 1; done + # configure replication (use CLI to set replicaof) + if [ -n "$KEYDB_PASSWORD" ]; then + keydb-cli -a "$KEYDB_PASSWORD" REPLICAOF ${MASTER_HOST} {{ .Values.service.port }} + else + keydb-cli REPLICAOF ${MASTER_HOST} {{ .Values.service.port }} + fi + echo "Configured replicaof ${MASTER_HOST}:{{ .Values.service.port }}" + # tail logs (block) to keep container running + wait + else + # master: block on server process + wait + fi + readinessProbe: + {{- if .Values.readinessProbe.enabled }} + exec: + command: + - sh + - -c + - | + # quick PING check + if [ -n "$KEYDB_PASSWORD" ]; then + keydb-cli -a "$KEYDB_PASSWORD" PING > /dev/null 2>&1 && exit 0 || exit 1 + else + keydb-cli PING > /dev/null 2>&1 && exit 0 || exit 1 + fi + initialDelaySeconds: {{ .Values.readinessProbe.initialDelaySeconds }} + periodSeconds: {{ .Values.readinessProbe.periodSeconds }} + timeoutSeconds: {{ .Values.readinessProbe.timeoutSeconds }} + {{- end }} + livenessProbe: + {{- if .Values.livenessProbe.enabled }} + exec: + command: + - sh + - -c + - | + if [ -n "$KEYDB_PASSWORD" ]; then + keydb-cli -a "$KEYDB_PASSWORD" PING > /dev/null 2>&1 && exit 0 || exit 1 + else + keydb-cli PING > /dev/null 2>&1 && exit 0 || exit 1 + fi + initialDelaySeconds: {{ .Values.livenessProbe.initialDelaySeconds }} + periodSeconds: {{ .Values.livenessProbe.periodSeconds }} + timeoutSeconds: {{ .Values.livenessProbe.timeoutSeconds }} + {{- end }} + volumes: + - name: keydb-conf + configMap: + name: {{ include "keydb-custom.fullname" . }}-conf + volumeClaimTemplates: + - metadata: + name: data + spec: + accessModes: {{ toYaml .Values.persistence.accessModes | nindent 8 }} + resources: + requests: + storage: {{ .Values.persistence.size }} + storageClassName: "{{ .Values.persistence.storageClass }}" \ No newline at end of file diff --git a/redis/values.redis.yaml b/redis/values.redis.yaml deleted file mode 100644 index 36ec21c..0000000 --- a/redis/values.redis.yaml +++ /dev/null @@ -1,18 +0,0 @@ -redis: &redis_config - architecture: replication - global: - defaultStorageClass: local-path - sentinel: - enabled: true - master: - resourcesPreset: &resources small - replica: - resourcesPreset: *resources - -tool: - # kind: 'SubChart' or 'HelmChart', if subchart then uncomment Chart.yaml dependency, else comment and use tool library with helm chart template - kind: 'SubChart' - repo: https://charts.bitnami.com/bitnami - chart: redis - version: 24.0.0 - values: *redis_config diff --git a/redis/values.yaml b/redis/values.yaml index a147204..6de30b1 100644 --- a/redis/values.yaml +++ b/redis/values.yaml @@ -1,26 +1,59 @@ -keydb: &keydb_config - image: - registry: docker.io - repository: eqalpha/keydb # Remplace l'image Redis par KeyDB - tag: latest - pullPolicy: IfNotPresent - global: - defaultStorageClass: local-path - security: - allowInsecureImages: true - architecture: replication - auth: - password: redisarcodange - master: - resourcesPreset: &resources small - replica: - activeReplica: true - resourcesPreset: *resources +# ----------------------------------------------------------------------------- +# values.yaml +# ----------------------------------------------------------------------------- +# Default values - adjust to your environment +replicaCount: 2 -tool: - # kind: 'SubChart' or 'HelmChart', if subchart then uncomment Chart.yaml dependency, else comment and use tool library with helm chart template - kind: 'SubChart' - repo: https://charts.bitnami.com/bitnami - chart: keydb - version: 0.5.22 - values: *keydb_config +image: + repository: eqalpha/keydb + tag: latest + pullPolicy: IfNotPresent + +service: + port: 6379 + headless: true + +auth: + enabled: true + password: "redisarcodange" + +keydb: + serverThreads: 4 + maxmemory: "70%" + maxmemoryPolicy: "allkeys-lru" + appendonly: "no" + +persistence: + enabled: true + accessModes: + - ReadWriteOnce + size: 1Gi + storageClass: "local-storage" # set to your storageClass: longhorn, local-path, etc. + +resources: + requests: + cpu: "300m" + memory: "512Mi" + limits: + cpu: "1200m" + memory: "1Gi" + +nodeAffinity: {} + +podAntiAffinity: + enabled: true + +securityContext: + enabled: false + +livenessProbe: + enabled: true + initialDelaySeconds: 30 + periodSeconds: 10 + timeoutSeconds: 5 + +readinessProbe: + enabled: true + initialDelaySeconds: 5 + periodSeconds: 5 + timeoutSeconds: 2 \ No newline at end of file