Files
helm-charts/ci/valkey/test-values.yaml
T
jklein 813c796a7b
Validate Helm Charts / Detect changed charts (pull_request) Successful in 3s
Validate Helm Charts / Resource quantities (pull_request) Successful in 8s
Validate Helm Charts / Build ${{ fromJSON(needs.detect-changed-charts.outputs.charts) }} (pull_request) Successful in 4s
Validate Helm Charts / Trivy config ${{ fromJSON(needs.detect-changed-charts.outputs.scan-charts) }} (pull_request) Successful in 11s
Validate Helm Charts / Install-test ${{ fromJSON(needs.detect-changed-charts.outputs.install-charts) }} (pull_request) Successful in 1m22s
Publish Helm Chart with patched Application Version / publish-helm-chart (push) Successful in 7s
Publish Valkey Helm Chart / Publish Valkey Helm Chart (push) Successful in 7s
feat(valkey): one Valkey instance per application (1.0.0+up9.1.2.alpine)
A new chart for a single Valkey instance per application, replacing the
shared cluster-redis whose separation rests on one ACL file in one
1Password field - a construction in which every change touches six
applications and which cost a month of Paperless standstill.

Shape: StatefulSet with one replica, ClusterIP Service, no cluster mode,
no Ingress and no value to add one.

The password arrives as a finished configuration line ("requirepass
<secret>") in the 1Password field auth-conf, is mounted as a file and
included by the main configuration - never in argv, never in the
environment. The include is rendered last, so nothing in extraConfig can
override it. Because a misspelled or empty field would leave an open
server that looks perfectly healthy, an init container greps the mounted
file for the line and refuses to start the pod without it; it never
prints the file.

maxmemory is derived from the computed memory limit (maxmemoryFactor,
default 0.75) and a configured value above that limit aborts the render:
otherwise the kubelet's OOM kill decides what the eviction policy was
configured to decide. Persistence and eviction are documented as pairs -
queue (PVC + noeviction, the default) and cache (emptyDir +
allkeys-lru) - and the combination "no persistence + noeviction" carries
a warning in values.yaml and in NOTES.txt.

Probes: valkey-cli ping as an exec probe, authenticated through
VALKEYCLI_AUTH read out of the mounted file, with "-e" and an assertion
on the answer PONG. Without -e valkey-cli exits 0 on an error reply
(valkey 9.1.2, src/valkey-cli.c: the config.set_errcode branch in
cliReadReply), which would make the probe unable to fail.

Hardening: uid 999 / gid 1000 - the image's own valkey user - with
fsGroup matching, runAsNonRoot, readOnlyRootFilesystem, all capabilities
dropped and seccompProfile RuntimeDefault in the pod context so the init
container is covered too. /data is the only writable path.

NetworkPolicy on by default (first chart in this repo with one), with a
switch and a list of additional namespaces; values.yaml names that it is
only a boundary where the CNI enforces policies.

Wiring: publish-valkey.yml, the chart-name choice list, ci/valkey
fixtures for the persistent variant, a plain docker-versioning Renovate
block, README chart row.
2026-09-27 11:24:55 +00:00

38 lines
1.6 KiB
YAML

# CI values for the valkey install-test. The PERSISTENT variant on purpose: it is
# the chart's default and the only risky path there is (a provisioned PVC, the
# pod's fsGroup against it, an append-only file created on a volume the container
# did not create). The machinery can run one variant per chart, so the
# non-persistent path is covered by a local render only - named as a known gap in
# the PR that introduced this chart.
secrets:
authSecretRef: op://ci/valkey
persistence:
enabled: true
appendonly: true
# k3d's dynamic provisioner. The chart's default, longhorn-encrypted-ns, does
# not exist on the runner, and a pre-bound hostPath PV would be worse than this
# one: the kubelet does not apply fsGroup to a hostPath volume at all, so the
# test would silently stop exercising the ownership path it is here for.
storageClass: local-path
size: 128Mi
valkey:
# Small, so the whole thing stays inside the runner's budget. It still
# exercises the derivation: 64Mi x limitFactor 3 = 192Mi limit, maxmemory =
# 0.75 x that = 144Mi - and the render aborts if a configured maxmemory ever
# ends up above the limit.
resources:
requests:
cpu: 50m
memory: 64Mi
ephemeral-storage: 32Mi
# Left ON, although nothing in the test connects from another namespace: the
# point here is that the object is accepted and does not keep the pod's own
# traffic (the exec probes are local to the pod and unaffected) from working.
# Whether the policy actually FILTERS is a property of the cluster's CNI and is
# not claimed by this test.
networkPolicy:
enabled: true