{{- $maxmemory := include "valkey.maxmemoryBytes" (dict "resources" .Values.valkey.resources "maxmemory" .Values.valkey.maxmemory "maxmemoryFactor" .Values.valkey.maxmemoryFactor) -}} {{- $limitBytes := include "valkey.memoryLimitBytes" .Values.valkey.resources -}} apiVersion: v1 kind: ConfigMap metadata: name: "{{ .Release.Name }}-{{ .Chart.Name }}-configmap" data: # The server's whole configuration. It is mounted as a directory at # /etc/valkey and passed to the image as an argument, so the entrypoint starts # "valkey-server /etc/valkey/valkey.conf". # # The pod template carries checksum/config over this ConfigMap: without it a # changed configuration would restart nothing, and Valkey reads its # configuration exactly once, at start. valkey.conf: | # Rendered by the valkey Helm chart - do not edit in the cluster, the next # helm upgrade overwrites it. Every value below comes from values.yaml. port 6379 # The data directory. It is also the image's WORKDIR, so this is only made # explicit for whoever reads the file; it is a PVC when # persistence.enabled is true and an emptyDir otherwise. dir /data # maxmemory is derived from the container's memory limit # ({{ $limitBytes }} bytes = {{ include "valkey.humanBytes" $limitBytes }}), not configured independently of it: # {{ if kindIs "invalid" .Values.valkey.maxmemory }}maxmemoryFactor {{ .Values.valkey.maxmemoryFactor | default 0.75 }} x that limit{{ else }}valkey.maxmemory was set explicitly and checked against that limit{{ end }}. # The remainder of the limit is for what maxmemory does NOT cover: client # output buffers, the AOF buffer, and the copy-on-write pages of the fork() # that writes a snapshot or rewrites the AOF. maxmemory {{ $maxmemory }} maxmemory-policy {{ required "valkey.maxmemoryPolicy must be set (see values.yaml for the two sensible pairs)" .Values.valkey.maxmemoryPolicy }} {{- if .Values.persistence.enabled }} {{- if .Values.persistence.appendonly }} # Append-only file: every write is appended, so a crash loses at most the # last fsync interval instead of everything since the last snapshot. The # RDB save points stay at their defaults, as a second, cheaper copy. appendonly yes {{- else }} # persistence.appendonly is false: the dataset survives only as periodic RDB # snapshots (Valkey's default save points), so a crash loses every write # since the last one - and it does so silently, because the instance comes # back looking healthy, only shorter. appendonly no {{- end }} {{- else }} # persistence.enabled is false: /data is an emptyDir, so nothing written # there survives a pod restart anyway. Both persistence mechanisms are # switched off rather than left writing into ephemeral storage - "save """ # disables the RDB save points, which are on by default. appendonly no save "" {{- end }} {{- with .Values.valkey.extraConfig }} # valkey.extraConfig, verbatim. {{ tpl . $ | trim | nindent 4 }} {{- end }} # The password, as a complete configuration line out of the 1Password item # (field "auth-conf"), mounted as a file. Two things about this line are # deliberate: # # - it is an "include" rather than a "requirepass" written here, so the # password is never part of this ConfigMap, of the process list, or of # anything Helm renders; # - it is LAST. In a Valkey configuration the last occurrence of a # directive wins, so nothing in valkey.extraConfig above can switch the # password off, by accident or otherwise. # # An init container has already verified that this file carries a # "requirepass " line before the server ever starts. include /etc/valkey-auth/auth.conf # The probe command for all three probes. A script rather than an inline shell # one-liner, because the two things that make it a real check need to be # written down next to them. ping.sh: | #!/bin/sh # Authenticated liveness/readiness/startup check for Valkey. # # WHY "-e" AND grep, i.e. two assertions rather than one: a bare # "valkey-cli ping" probe CANNOT FAIL. Read off the source (valkey 9.1.2, # src/valkey-cli.c): cliReadReply turns an error reply into exit(1) in # exactly one branch, guarded by config.set_errcode, and "-e" is the only # thing that sets it ("-e Return exit error code when command execution # fails."). Without -e the command prints "NOAUTH Authentication required." # and exits 0 - green, forever, whatever the server does. # # Either half alone would catch that: "grep -qx PONG" asserts the ANSWER, so # it fails on an error reply even without -e. Both are here on purpose. The # grep is the assertion; "-e" makes the failure explicit and, because the # error then goes to stderr instead of stdout, puts the server's own message # ("NOAUTH...", "WRONGPASS...") into the probe's failure output where # kubectl describe shows it. # # WHY THE PASSWORD COMES THROUGH THE ENVIRONMENT: "valkey-cli -a " # puts the password in the process list, where every container in this pod # can read it. VALKEYCLI_AUTH is valkey-cli's own environment variable for # it (REDISCLI_AUTH is still honoured as the legacy spelling), and it is set # only for the duration of this one command. # # Nothing here prints the password: it only ever lives in a shell variable, # and valkey-cli's own error messages do not echo it. set -eu AUTH_FILE=/etc/valkey-auth/auth.conf # The same file the server was configured from, so probe and server can # never disagree about the password. sed's character class is written the # POSIX way (no \+): this runs in the image's BusyBox shell. pass="$(sed -n 's/^requirepass[[:space:]][[:space:]]*//p' "$AUTH_FILE" | head -n 1)" # Valkey's configuration parser allows the value to be quoted; strip one # surrounding pair of double quotes if present. case "$pass" in '"'*'"') pass="${pass#\"}"; pass="${pass%\"}" ;; esac VALKEYCLI_AUTH="$pass" valkey-cli -e -p 6379 ping | grep -qx PONG # The init container's check. It validates the mounted auth file and does NOT # assemble it - the password is a finished configuration line from the vault. check-auth.sh: | #!/bin/sh # Refuse to start unless the mounted auth file really carries a # "requirepass " line. # # The failure this prevents: the password arrives as a ready-made # configuration line from a 1Password field, and a misspelled key # ("requirepas"), a stray quote or an empty field would leave Valkey running # WITHOUT any password - no render error, no crash, a green pod, and an open # server (the official image compiles protected-mode off). Of all the ways # this chart can be misconfigured, that is the only one nothing else would # report. # # It never prints the file: an error message containing the password would # put it in the pod's event log and in every CI diagnostics dump. set -eu AUTH_FILE=/etc/valkey-auth/auth.conf if [ ! -r "$AUTH_FILE" ]; then echo "valkey: $AUTH_FILE is missing or unreadable." >&2 echo " The 1Password item behind secrets.authSecretRef must carry a field" >&2 echo " named 'auth-conf'. The 1Password operator turns each field of the" >&2 echo " item into one key of the Kubernetes Secret, so a differently named" >&2 echo " field produces no such file." >&2 exit 1 fi if ! grep -q '^requirepass[[:space:]][[:space:]]*[^[:space:]]' "$AUTH_FILE"; then echo "valkey: the mounted auth file carries no 'requirepass ' line." >&2 echo " Expected the field 'auth-conf' of the 1Password item to contain" >&2 echo " exactly one configuration line:" >&2 echo " requirepass " >&2 echo " Refusing to start: Valkey would come up without a password, report" >&2 echo " healthy, and accept connections from the whole pod network." >&2 echo " (The file's contents are deliberately not printed.)" >&2 exit 1 fi