From 8866047a59dd9f0f1797f278e2586d0b3566b390 Mon Sep 17 00:00:00 2001 From: Julio Caicedo Date: Sun, 30 Nov 2025 16:58:12 -0500 Subject: [PATCH] feat: Refactor health check scripts, add configurable volume permissions, and implement sentinel startup wait for master DNS. --- Chart.yaml | 21 +++- templates/_helpers.tpl | 24 ++-- templates/configmap.yaml | 7 -- templates/health-configmap.yaml | 177 +++++----------------------- templates/master/application.yaml | 18 +-- templates/pre-upgrade-job.yaml | 146 ++++++++++++++++------- templates/replica/statefulset.yaml | 8 +- templates/sentinel/statefulset.yaml | 32 ++++- values.yaml | 68 ++++++----- 9 files changed, 230 insertions(+), 271 deletions(-) diff --git a/Chart.yaml b/Chart.yaml index 9237a3c..eed7ce5 100644 --- a/Chart.yaml +++ b/Chart.yaml @@ -2,7 +2,7 @@ apiVersion: v2 name: valkey description: Valkey is an open source, high-performance data structure server compatible with Redis. It supports strings, hashes, lists, sets, and sorted sets. type: application -version: 0.1.24 +version: 0.2.0 appVersion: "9.0.0" annotations: artifacthub.io/signKey: | @@ -17,15 +17,24 @@ annotations: url: https://github.com/start-codex/valkey-helm-chart artifacthub.io/images: | - name: valkey - image: docker.io/valkey/valkey:9.0.0 - - name: os-shell - image: docker.io/alpine:3.22.2 + image: cgr.dev/chainguard/valkey:latest + - name: wolfi-base + image: cgr.dev/chainguard/wolfi-base:latest - name: redis-exporter image: docker.io/oliver006/redis_exporter:v1.80.0 - name: kubectl - image: docker.io/alpine/k8s:1.31.13 - artifacthub.io/containsSecurityUpdates: "false" + image: cgr.dev/chainguard/kubectl:latest + artifacthub.io/containsSecurityUpdates: "true" artifacthub.io/prerelease: "false" + artifacthub.io/changes: | + - kind: security + description: Switch to Chainguard images for zero CVE (valkey, kubectl, wolfi-base) + - kind: changed + description: Update container user from 999 to 65532 (Chainguard default) + - kind: changed + description: Simplify health check scripts for distroless compatibility + - kind: changed + description: Update pre-upgrade hook to work without shell keywords: - valkey - redis diff --git a/templates/_helpers.tpl b/templates/_helpers.tpl index c5c143e..a464e2b 100644 --- a/templates/_helpers.tpl +++ b/templates/_helpers.tpl @@ -269,11 +269,9 @@ Return the Valkey configuration Return if Valkey authentication is enabled */}} {{- define "valkey.auth.enabled" -}} -{{- if .Values.auth.enabled }} -{{- true }} -{{- else }} -{{- false }} -{{- end }} +{{- if .Values.auth.enabled -}} +true +{{- end -}} {{- end }} {{/* @@ -429,11 +427,9 @@ Return the Valkey password Return true if TLS is enabled */}} {{- define "valkey.tls.enabled" -}} -{{- if .Values.tls.enabled }} - {{- true -}} -{{- else }} - {{- false -}} -{{- end }} +{{- if .Values.tls.enabled -}} +true +{{- end -}} {{- end }} {{/* @@ -484,11 +480,9 @@ Return the path to the CA cert file Return if metrics are enabled */}} {{- define "valkey.metrics.enabled" -}} -{{- if .Values.metrics.enabled }} - {{- true -}} -{{- else }} - {{- false -}} -{{- end }} +{{- if .Values.metrics.enabled -}} +true +{{- end -}} {{- end -}} {{/* diff --git a/templates/configmap.yaml b/templates/configmap.yaml index 84ebb44..11932a4 100644 --- a/templates/configmap.yaml +++ b/templates/configmap.yaml @@ -22,13 +22,6 @@ data: {{- if .Values.sentinel.enabled }} sentinel.conf: | {{- .Values.sentinel.configuration | nindent 4 }} - sentinel monitor valkey-master {{ include "valkey.master.serviceName" . }} {{ include "valkey.port" . }} {{ .Values.sentinel.quorum }} - sentinel down-after-milliseconds valkey-master {{ .Values.sentinel.downAfterMilliseconds }} - sentinel failover-timeout valkey-master {{ .Values.sentinel.failoverTimeout }} - sentinel parallel-syncs valkey-master {{ .Values.sentinel.parallelSyncs }} - {{- if include "valkey.auth.enabled" . }} - sentinel auth-pass valkey-master $VALKEY_PASSWORD - {{- end }} {{- end }} {{- end }} {{- end }} \ No newline at end of file diff --git a/templates/health-configmap.yaml b/templates/health-configmap.yaml index e935d9e..55a53cb 100644 --- a/templates/health-configmap.yaml +++ b/templates/health-configmap.yaml @@ -12,190 +12,67 @@ metadata: {{- end }} data: ping_readiness_local.sh: |- - #!/bin/bash - + #!/usr/bin/bash [[ -n "$VALKEY_PASSWORD" ]] && export REDISCLI_AUTH="$VALKEY_PASSWORD" - response=$( - timeout -s 15 $1 \ - valkey-cli \ - -h localhost \ -{{- if .Values.tls.enabled }} - -p {{ .Values.tls.port | default 6380 }} \ - --tls \ - {{- if .Values.tls.caCertFilename }} - --cacert {{ include "valkey.tls.caCertFilename" . }} \ - {{- end }} - {{- if .Values.tls.authClients }} - --cert {{ include "valkey.tls.certFilename" . }} \ - --key {{ include "valkey.tls.certKeyFilename" . }} \ - {{- end }} -{{- else }} - -p 6379 \ -{{- end }} - ping - ) - if [ "$?" -eq "124" ]; then - echo "Timed out" - exit 1 - fi + response=$(valkey-cli -h localhost -p {{ if .Values.tls.enabled }}{{ .Values.tls.port | default 6380 }}{{ else }}6379{{ end }} ping 2>&1) if [ "$response" != "PONG" ]; then echo "$response" exit 1 fi ping_liveness_local.sh: |- - #!/bin/bash - + #!/usr/bin/bash [[ -n "$VALKEY_PASSWORD" ]] && export REDISCLI_AUTH="$VALKEY_PASSWORD" - response=$( - timeout -s 15 $1 \ - valkey-cli \ - -h localhost \ -{{- if .Values.tls.enabled }} - -p {{ .Values.tls.port | default 6380 }} \ - --tls \ - {{- if .Values.tls.caCertFilename }} - --cacert {{ include "valkey.tls.caCertFilename" . }} \ - {{- end }} - {{- if .Values.tls.authClients }} - --cert {{ include "valkey.tls.certFilename" . }} \ - --key {{ include "valkey.tls.certKeyFilename" . }} \ - {{- end }} -{{- else }} - -p 6379 \ -{{- end }} - ping - ) - if [ "$?" -eq "124" ]; then - echo "Timed out" - exit 1 - fi - responseFirstWord=$(echo $response | head -n1 | awk '{print $1;}') - if [ "$response" != "PONG" ] && [ "$responseFirstWord" != "LOADING" ] && [ "$responseFirstWord" != "MASTERDOWN" ]; then - echo "$response" - exit 1 + response=$(valkey-cli -h localhost -p {{ if .Values.tls.enabled }}{{ .Values.tls.port | default 6380 }}{{ else }}6379{{ end }} ping 2>&1) + if [ "$response" = "PONG" ] || [[ "$response" == LOADING* ]] || [[ "$response" == MASTERDOWN* ]]; then + exit 0 fi + echo "$response" + exit 1 {{- if eq .Values.architecture "sentinel" }} ping_sentinel.sh: |- - #!/bin/bash - + #!/usr/bin/bash {{- if .Values.auth.sentinel }} [[ -f $VALKEY_PASSWORD_FILE ]] && export VALKEY_PASSWORD="$(< "${VALKEY_PASSWORD_FILE}")" [[ -n "$VALKEY_PASSWORD" ]] && export VALKEYCLI_AUTH="$VALKEY_PASSWORD" {{- end }} - response=$( - timeout -s 15 $1 \ - valkey-cli \ - -h localhost \ -{{- if (include "valkey.tls.enabled" .) }} - -p $VALKEY_SENTINEL_TLS_PORT_NUMBER \ - --tls \ - {{- if .Values.tls.caCertFilename }} - --cacert "$VALKEY_SENTINEL_TLS_CA_FILE" \ - {{- end }} - {{- if .Values.tls.authClients }} - --cert "$VALKEY_SENTINEL_TLS_CERT_FILE" \ - --key "$VALKEY_SENTINEL_TLS_KEY_FILE" \ - {{- end }} -{{- else }} - -p $VALKEY_SENTINEL_PORT \ -{{- end }} - ping - ) - if [ "$?" -eq "124" ]; then - echo "Timed out" - exit 1 - fi + SENTINEL_PORT=${VALKEY_SENTINEL_PORT:-26379} + response=$(valkey-cli -h localhost -p $SENTINEL_PORT ping 2>&1) if [ "$response" != "PONG" ]; then echo "$response" exit 1 fi - parse_sentinels.awk: |- - /ip/ {FOUND_IP=1} - /port/ {FOUND_PORT=1} - /runid/ {FOUND_RUNID=1} - !/ip|port|runid/ { - if (FOUND_IP==1) { - IP=$1; FOUND_IP=0; - } - else if (FOUND_PORT==1) { - PORT=$1; - FOUND_PORT=0; - } else if (FOUND_RUNID==1) { - printf "\nsentinel known-sentinel {{ .Values.sentinel.masterSet }} %s %s %s", IP, PORT, $0; FOUND_RUNID=0; - } - } -{{- end }} ping_readiness_master.sh: |- - #!/bin/bash - + #!/usr/bin/bash [[ -f $VALKEY_MASTER_PASSWORD_FILE ]] && export VALKEY_MASTER_PASSWORD="$(< "${VALKEY_MASTER_PASSWORD_FILE}")" [[ -n "$VALKEY_MASTER_PASSWORD" ]] && export VALKEYCLI_AUTH="$VALKEY_MASTER_PASSWORD" - response=$( - timeout -s 15 $1 \ - valkey-cli \ - -h $VALKEY_MASTER_HOST \ - -p $VALKEY_MASTER_PORT_NUMBER \ -{{- if (include "valkey.tls.enabled" .) }} - --tls \ - {{- if .Values.tls.caCertFilename }} - --cacert {{ include "valkey.tls.caCertFilename" . }} \ - {{- end }} - {{- if .Values.tls.authClients }} - --cert {{ include "valkey.tls.certFilename" . }} \ - --key {{ include "valkey.tls.certKeyFilename" . }} \ - {{- end }} -{{- end }} - ping - ) - if [ "$?" -eq "124" ]; then - echo "Timed out" - exit 1 - fi + response=$(valkey-cli -h $VALKEY_MASTER_HOST -p $VALKEY_MASTER_PORT_NUMBER ping 2>&1) if [ "$response" != "PONG" ]; then echo "$response" exit 1 fi ping_liveness_master.sh: |- - #!/bin/bash - + #!/usr/bin/bash [[ -f $VALKEY_MASTER_PASSWORD_FILE ]] && export VALKEY_MASTER_PASSWORD="$(< "${VALKEY_MASTER_PASSWORD_FILE}")" [[ -n "$VALKEY_MASTER_PASSWORD" ]] && export VALKEYCLI_AUTH="$VALKEY_MASTER_PASSWORD" - response=$( - timeout -s 15 $1 \ - valkey-cli \ - -h $VALKEY_MASTER_HOST \ - -p $VALKEY_MASTER_PORT_NUMBER \ -{{- if (include "valkey.tls.enabled" .) }} - --tls \ - {{- if .Values.tls.caCertFilename }} - --cacert {{ include "valkey.tls.caCertFilename" . }} \ - {{- end }} - {{- if .Values.tls.authClients }} - --cert {{ include "valkey.tls.certFilename" . }} \ - --key {{ include "valkey.tls.certKeyFilename" . }} \ - {{- end }} -{{- end }} - ping - ) - if [ "$?" -eq "124" ]; then - echo "Timed out" - exit 1 - fi - responseFirstWord=$(echo $response | head -n1 | awk '{print $1;}') - if [ "$response" != "PONG" ] && [ "$responseFirstWord" != "LOADING" ]; then - echo "$response" - exit 1 + response=$(valkey-cli -h $VALKEY_MASTER_HOST -p $VALKEY_MASTER_PORT_NUMBER ping 2>&1) + if [ "$response" = "PONG" ] || [[ "$response" == LOADING* ]]; then + exit 0 fi + echo "$response" + exit 1 ping_readiness_local_and_master.sh: |- + #!/usr/bin/bash script_dir="$(dirname "$0")" exit_status=0 - "$script_dir/ping_readiness_local.sh" $1 || exit_status=$? - "$script_dir/ping_readiness_master.sh" $1 || exit_status=$? + "$script_dir/ping_readiness_local.sh" || exit_status=$? + "$script_dir/ping_readiness_master.sh" || exit_status=$? exit $exit_status ping_liveness_local_and_master.sh: |- + #!/usr/bin/bash script_dir="$(dirname "$0")" exit_status=0 - "$script_dir/ping_liveness_local.sh" $1 || exit_status=$? - "$script_dir/ping_liveness_master.sh" $1 || exit_status=$? + "$script_dir/ping_liveness_local.sh" || exit_status=$? + "$script_dir/ping_liveness_master.sh" || exit_status=$? exit $exit_status -{{- end }} \ No newline at end of file +{{- end }} +{{- end }} diff --git a/templates/master/application.yaml b/templates/master/application.yaml index 6c6e06e..ebf0c92 100644 --- a/templates/master/application.yaml +++ b/templates/master/application.yaml @@ -65,7 +65,7 @@ spec: image: {{ .Values.volumePermissions.image.registry }}/{{ .Values.volumePermissions.image.repository }}:{{ .Values.volumePermissions.image.tag }} imagePullPolicy: {{ .Values.volumePermissions.image.pullPolicy }} command: - - /bin/bash + - /bin/sh - -ec - | chown -R {{ .Values.podSecurityContext.runAsUser }}:{{ .Values.podSecurityContext.fsGroup }} /data @@ -85,7 +85,7 @@ spec: securityContext: {{- toYaml .Values.securityContext | nindent 12 }} command: - - /bin/bash + - /usr/bin/bash args: - -c - | @@ -94,9 +94,9 @@ spec: # Copy config and add requirepass cp /etc/valkey/valkey.conf /tmp/valkey.conf echo "requirepass $VALKEY_PASSWORD" >> /tmp/valkey.conf - valkey-server /tmp/valkey.conf + exec valkey-server /tmp/valkey.conf {{- else }} - valkey-server /etc/valkey/valkey.conf + exec valkey-server /etc/valkey/valkey.conf {{- end }} env: {{- if .Values.auth.enabled }} @@ -118,7 +118,7 @@ spec: failureThreshold: 3 exec: command: - - sh + - /usr/bin/bash - -c - /health/ping_liveness_local.sh 5 readinessProbe: @@ -129,7 +129,7 @@ spec: failureThreshold: 3 exec: command: - - sh + - /usr/bin/bash - -c - /health/ping_readiness_local.sh 1 {{- if eq .Values.architecture "sentinel" }} @@ -147,8 +147,8 @@ spec: - name: valkey-data mountPath: /data - name: config - mountPath: /opt/valkey/etc/valkey.conf - subPath: valkey.conf + mountPath: /etc/valkey/valkey.conf + subPath: {{ if eq .Values.architecture "sentinel" }}master.conf{{ else }}valkey.conf{{ end }} - name: tmp mountPath: /tmp {{- if .Values.metrics.enabled }} @@ -233,7 +233,7 @@ spec: defaultMode: 0755 - name: config configMap: - name: {{ if eq .Values.architecture "sentinel" }}{{ printf "%s-master" (include "valkey.fullname" .) }}{{ else }}{{ include "valkey.fullname" . }}{{ end }} + name: {{ include "valkey.fullname" . }} - name: tmp emptyDir: {} {{- if or (and (eq .Values.architecture "sentinel") .Values.master.persistence.enabled) (and (ne .Values.architecture "sentinel") .Values.standalone.persistence.enabled) }} diff --git a/templates/pre-upgrade-job.yaml b/templates/pre-upgrade-job.yaml index 298efe0..6d69eab 100644 --- a/templates/pre-upgrade-job.yaml +++ b/templates/pre-upgrade-job.yaml @@ -13,6 +13,7 @@ metadata: "helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded spec: backoffLimit: 3 + ttlSecondsAfterFinished: 60 template: metadata: name: {{ include "valkey.fullname" . }}-pre-upgrade @@ -24,53 +25,108 @@ spec: serviceAccountName: {{ include "valkey.fullname" . }}-pre-upgrade securityContext: runAsNonRoot: true - runAsUser: 65534 - fsGroup: 65534 + runAsUser: 65532 + fsGroup: 65532 + initContainers: + {{- if eq .Values.architecture "sentinel" }} + # Delete master StatefulSet + - name: delete-master + image: {{ .Values.preUpgradeHook.image.registry }}/{{ .Values.preUpgradeHook.image.repository }}:{{ .Values.preUpgradeHook.image.tag }} + imagePullPolicy: {{ .Values.preUpgradeHook.image.pullPolicy }} + args: + - delete + - statefulset + - {{ include "valkey.fullname" . }}-master + - --namespace={{ .Release.Namespace }} + - --cascade=orphan + - --ignore-not-found=true + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + readOnlyRootFilesystem: true + runAsNonRoot: true + runAsUser: 65532 + {{- if .Values.preUpgradeHook.resources }} + resources: {{- toYaml .Values.preUpgradeHook.resources | nindent 12 }} + {{- end }} + # Delete replica StatefulSet + - name: delete-replica + image: {{ .Values.preUpgradeHook.image.registry }}/{{ .Values.preUpgradeHook.image.repository }}:{{ .Values.preUpgradeHook.image.tag }} + imagePullPolicy: {{ .Values.preUpgradeHook.image.pullPolicy }} + args: + - delete + - statefulset + - {{ include "valkey.fullname" . }}-replica + - --namespace={{ .Release.Namespace }} + - --cascade=orphan + - --ignore-not-found=true + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + readOnlyRootFilesystem: true + runAsNonRoot: true + runAsUser: 65532 + {{- if .Values.preUpgradeHook.resources }} + resources: {{- toYaml .Values.preUpgradeHook.resources | nindent 12 }} + {{- end }} + # Delete sentinel StatefulSet + - name: delete-sentinel + image: {{ .Values.preUpgradeHook.image.registry }}/{{ .Values.preUpgradeHook.image.repository }}:{{ .Values.preUpgradeHook.image.tag }} + imagePullPolicy: {{ .Values.preUpgradeHook.image.pullPolicy }} + args: + - delete + - statefulset + - {{ include "valkey.fullname" . }}-sentinel + - --namespace={{ .Release.Namespace }} + - --cascade=orphan + - --ignore-not-found=true + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + readOnlyRootFilesystem: true + runAsNonRoot: true + runAsUser: 65532 + {{- if .Values.preUpgradeHook.resources }} + resources: {{- toYaml .Values.preUpgradeHook.resources | nindent 12 }} + {{- end }} + {{- else }} + # Delete standalone StatefulSet + - name: delete-standalone + image: {{ .Values.preUpgradeHook.image.registry }}/{{ .Values.preUpgradeHook.image.repository }}:{{ .Values.preUpgradeHook.image.tag }} + imagePullPolicy: {{ .Values.preUpgradeHook.image.pullPolicy }} + args: + - delete + - statefulset + - {{ include "valkey.fullname" . }} + - --namespace={{ .Release.Namespace }} + - --cascade=orphan + - --ignore-not-found=true + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + readOnlyRootFilesystem: true + runAsNonRoot: true + runAsUser: 65532 + {{- if .Values.preUpgradeHook.resources }} + resources: {{- toYaml .Values.preUpgradeHook.resources | nindent 12 }} + {{- end }} + {{- end }} containers: - - name: pre-upgrade + # Final container just to complete the job successfully + - name: complete image: {{ .Values.preUpgradeHook.image.registry }}/{{ .Values.preUpgradeHook.image.repository }}:{{ .Values.preUpgradeHook.image.tag }} imagePullPolicy: {{ .Values.preUpgradeHook.image.pullPolicy }} - command: - - /bin/sh - - -c - - | - set -e - echo "=== Valkey Pre-Upgrade Hook ===" - echo "Checking for existing StatefulSets to clean up..." - - NAMESPACE="{{ .Release.Namespace }}" - - # Lista de StatefulSets a verificar segĂșn la arquitectura - STATEFULSETS="" - - {{- if or (eq .Values.architecture "standalone") (eq .Values.architecture "sentinel") }} - # Master/Standalone StatefulSet - {{- if eq .Values.architecture "sentinel" }} - STATEFULSETS="${STATEFULSETS} {{ include "valkey.fullname" . }}-master" - {{- else }} - STATEFULSETS="${STATEFULSETS} {{ include "valkey.fullname" . }}" - {{- end }} - {{- end }} - - {{- if eq .Values.architecture "sentinel" }} - # Replica StatefulSet - STATEFULSETS="${STATEFULSETS} {{ include "valkey.fullname" . }}-replica" - # Sentinel StatefulSet - STATEFULSETS="${STATEFULSETS} {{ include "valkey.fullname" . }}-sentinel" - {{- end }} - - for STS_NAME in ${STATEFULSETS}; do - if kubectl get statefulset "${STS_NAME}" -n "${NAMESPACE}" >/dev/null 2>&1; then - echo "Found StatefulSet: ${STS_NAME}" - echo "Deleting StatefulSet ${STS_NAME} with --cascade=orphan to preserve pods and PVCs..." - kubectl delete statefulset "${STS_NAME}" -n "${NAMESPACE}" --cascade=orphan - echo "StatefulSet ${STS_NAME} deleted successfully (pods and PVCs preserved)" - else - echo "StatefulSet ${STS_NAME} not found, skipping..." - fi - done - - echo "=== Pre-upgrade cleanup completed successfully ===" + args: + - version + - --client=true securityContext: allowPrivilegeEscalation: false capabilities: @@ -78,7 +134,7 @@ spec: - ALL readOnlyRootFilesystem: true runAsNonRoot: true - runAsUser: 65534 + runAsUser: 65532 {{- if .Values.preUpgradeHook.resources }} resources: {{- toYaml .Values.preUpgradeHook.resources | nindent 12 }} {{- end }} diff --git a/templates/replica/statefulset.yaml b/templates/replica/statefulset.yaml index 30a729a..2629b07 100644 --- a/templates/replica/statefulset.yaml +++ b/templates/replica/statefulset.yaml @@ -73,11 +73,11 @@ spec: image: {{ include "valkey.volumePermissions.image" . }} imagePullPolicy: {{ .Values.volumePermissions.image.pullPolicy | quote }} command: - - /bin/bash + - /bin/sh args: - -ec - | - chown -R 1001:1001 /data + chown -R {{ .Values.podSecurityContext.runAsUser }}:{{ .Values.podSecurityContext.fsGroup }} /data {{- if .Values.volumePermissions.containerSecurityContext.enabled }} securityContext: {{- omit .Values.volumePermissions.containerSecurityContext "enabled" | toYaml | nindent 12 }} {{- end }} @@ -177,7 +177,7 @@ spec: failureThreshold: {{ .Values.replica.livenessProbe.failureThreshold }} exec: command: - - sh + - /usr/bin/bash - -c - /health/ping_liveness_local.sh 5 readinessProbe: @@ -188,7 +188,7 @@ spec: failureThreshold: {{ .Values.replica.readinessProbe.failureThreshold }} exec: command: - - sh + - /usr/bin/bash - -c - /health/ping_readiness_local.sh 1 {{- end }} diff --git a/templates/sentinel/statefulset.yaml b/templates/sentinel/statefulset.yaml index 9e2f9a6..15ea416 100644 --- a/templates/sentinel/statefulset.yaml +++ b/templates/sentinel/statefulset.yaml @@ -73,9 +73,29 @@ spec: securityContext: {{- omit .Values.sentinel.containerSecurityContext "enabled" | toYaml | nindent 12 }} {{- end }} command: - - valkey-sentinel + - /usr/bin/bash args: - - /etc/valkey/sentinel.conf + - -c + - | + # Wait for master service to be resolvable + until getent hosts {{ include "valkey.master.serviceName" . }}; do + echo "Waiting for master DNS to be resolvable..." + sleep 1 + done + # Get master IP (getent returns "IP hostname", we need only IP) + MASTER_LINE=$(getent hosts {{ include "valkey.master.serviceName" . }}) + MASTER_IP=${MASTER_LINE%% *} + echo "Master resolved to: $MASTER_IP" + # Copy config to /tmp and add sentinel monitor with resolved IP + cp /etc/valkey/sentinel.conf /tmp/sentinel.conf + echo "sentinel monitor {{ .Values.sentinel.masterSet }} $MASTER_IP {{ include "valkey.port" . }} {{ .Values.sentinel.quorum }}" >> /tmp/sentinel.conf + echo "sentinel down-after-milliseconds {{ .Values.sentinel.masterSet }} {{ .Values.sentinel.downAfterMilliseconds }}" >> /tmp/sentinel.conf + echo "sentinel failover-timeout {{ .Values.sentinel.masterSet }} {{ .Values.sentinel.failoverTimeout }}" >> /tmp/sentinel.conf + echo "sentinel parallel-syncs {{ .Values.sentinel.masterSet }} {{ .Values.sentinel.parallelSyncs }}" >> /tmp/sentinel.conf + {{- if (include "valkey.auth.enabled" .) }} + echo "sentinel auth-pass {{ .Values.sentinel.masterSet }} $VALKEY_PASSWORD" >> /tmp/sentinel.conf + {{- end }} + exec valkey-sentinel /tmp/sentinel.conf env: - name: VALKEY_SENTINEL_ENABLED value: "yes" @@ -158,7 +178,7 @@ spec: failureThreshold: {{ .Values.sentinel.livenessProbe.failureThreshold }} exec: command: - - sh + - /usr/bin/bash - -c - /health/ping_sentinel.sh 5 readinessProbe: @@ -169,7 +189,7 @@ spec: failureThreshold: {{ .Values.sentinel.readinessProbe.failureThreshold }} exec: command: - - sh + - /usr/bin/bash - -c - /health/ping_sentinel.sh 1 {{- end }} @@ -179,6 +199,8 @@ spec: volumeMounts: - name: health mountPath: /health + - name: tmp + mountPath: /tmp {{- if (include "valkey.createConfigmap" .) }} - name: config mountPath: /etc/valkey @@ -260,6 +282,8 @@ spec: configMap: name: {{ printf "%s-health" (include "valkey.fullname" .) }} defaultMode: 0755 + - name: tmp + emptyDir: {} {{- if (include "valkey.createConfigmap" .) }} - name: config configMap: diff --git a/values.yaml b/values.yaml index 7d76ae7..bd44e09 100644 --- a/values.yaml +++ b/values.yaml @@ -12,10 +12,11 @@ global: clusterDomain: cluster.local # Valkey image configuration +# Using Chainguard images for zero CVE security image: - registry: docker.io - repository: valkey/valkey - tag: "9.0.0" + registry: cgr.dev + repository: chainguard/valkey + tag: "latest" pullPolicy: IfNotPresent # Common configuration @@ -48,10 +49,11 @@ serviceAccount: name: "" # Pod Security Context +# Chainguard images run as user 65532 podSecurityContext: - fsGroup: 999 - runAsUser: 999 - runAsGroup: 999 + fsGroup: 65532 + runAsUser: 65532 + runAsGroup: 65532 # Security Context securityContext: @@ -61,7 +63,7 @@ securityContext: - ALL readOnlyRootFilesystem: true runAsNonRoot: true - runAsUser: 999 + runAsUser: 65532 # Common annotations and labels commonAnnotations: {} @@ -129,9 +131,9 @@ sentinel: parallelSyncs: 1 image: - registry: docker.io - repository: valkey/valkey - tag: "9.0.0" + registry: cgr.dev + repository: chainguard/valkey + tag: "latest" pullPolicy: IfNotPresent serviceAccount: @@ -142,9 +144,9 @@ sentinel: podSecurityContext: enabled: true - fsGroup: 999 - runAsUser: 999 - runAsGroup: 999 + fsGroup: 65532 + runAsUser: 65532 + runAsGroup: 65532 containerSecurityContext: enabled: true @@ -154,7 +156,7 @@ sentinel: - ALL readOnlyRootFilesystem: true runAsNonRoot: true - runAsUser: 999 + runAsUser: 65532 resources: limits: @@ -212,6 +214,11 @@ sentinel: initContainers: [] sidecars: [] + configuration: |- + # Valkey Sentinel configuration + port 26379 + dir /tmp + # Master configuration for sentinel mode master: replicaCount: 1 @@ -224,9 +231,9 @@ master: podSecurityContext: enabled: true - fsGroup: 999 - runAsUser: 999 - runAsGroup: 999 + fsGroup: 65532 + runAsUser: 65532 + runAsGroup: 65532 containerSecurityContext: enabled: true @@ -236,7 +243,7 @@ master: - ALL readOnlyRootFilesystem: true runAsNonRoot: true - runAsUser: 999 + runAsUser: 65532 resources: limits: @@ -337,9 +344,9 @@ replica: podSecurityContext: enabled: true - fsGroup: 999 - runAsUser: 999 - runAsGroup: 999 + fsGroup: 65532 + runAsUser: 65532 + runAsGroup: 65532 containerSecurityContext: enabled: true @@ -349,7 +356,7 @@ replica: - ALL readOnlyRootFilesystem: true runAsNonRoot: true - runAsUser: 999 + runAsUser: 65532 resources: limits: @@ -448,7 +455,7 @@ metrics: - ALL readOnlyRootFilesystem: true runAsNonRoot: true - runAsUser: 999 + runAsUser: 65532 resources: limits: @@ -522,13 +529,12 @@ metrics: rules: [] # Pre-upgrade hook configuration -# Uses Alpine with kubectl binary from official Kubernetes releases -# This avoids paid/deprecated Bitnami images +# Uses Chainguard kubectl image (zero CVE, distroless) preUpgradeHook: image: - registry: docker.io - repository: alpine/k8s - tag: "1.31.13" + registry: cgr.dev + repository: chainguard/kubectl + tag: "latest" pullPolicy: IfNotPresent resources: @@ -542,9 +548,9 @@ preUpgradeHook: volumePermissions: enabled: false image: - registry: docker.io - repository: alpine - tag: "3.22.2" + registry: cgr.dev + repository: chainguard/wolfi-base + tag: "latest" pullPolicy: IfNotPresent containerSecurityContext: