# Chart defaults. Real configuration lives in # helm-overrides/gke-toolshed-prd-usc1/redis/custom-values.yaml. fullnameOverride: redis image: # Pulled from Docker Hub, like every other infra component here (gitea, # vault, harbor, postgresql). The base-images mirror in Harbor exists to # remove Docker Hub from the *application build* path — it is not in play # for platform components. repository: redis tag: "7-alpine" pullPolicy: IfNotPresent # Name of the Secret holding the admin password. Created by External # Secrets from Vault, not by this chart — a chart that generates its own # password regenerates it on every render, which would rewrite the ACL file # and lock every already-provisioned app out of its own data. existingSecret: redis-credentials secretKeys: password: password service: port: 6379 persistence: enabled: true # local-path-provisioner, this cluster's default StorageClass. Small: this # holds the ACL file and (if enabled) an RDB snapshot, not a dataset of # any size — maxmemory below is the real ceiling on what Redis will hold. # The volume is not resizable in place with this provisioner, so it is # sized up front. storageClass: local-path size: 1Gi config: # ACL FILE, NOT requirepass. This distinction is load-bearing and easy to # "simplify" into a security hole, so it is written down here rather than # left to be rediscovered: # # toolshed provisions per-app users with ACL SETUSER, and persists them # with ACL SAVE (internal/dbprovision.EnsureRedisUser) — without that # save, every provisioned user is lost on the next restart and every app # using Redis fails to authenticate with credentials that still look # valid. ACL SAVE requires an aclfile; that is why one is configured. # # But ACL SAVE also writes the *default* user's state to that file. With # `requirepass` set and the default user defined only by it, the saved # entry comes back as `user default on nopass ~* &* +@all` — and after # the next restart the ACL file wins, leaving Redis accepting # UNAUTHENTICATED connections with full access. Verified directly, not # inferred: with requirepass the restarted server answered an # unauthenticated PING with PONG and served a key. # # Defining the default user in the ACL file instead (seeded by the init # container, see the StatefulSet) keeps its password across every # subsequent ACL SAVE — the same restart then correctly answers # `NOAUTH Authentication required.` # # If you ever add `requirepass` here, you reintroduce that hole. maxmemory: 48mb # allkeys-lru, because this backs a connection kind literally called # "cache" and eviction under pressure is that contract. An app using # Redis as its only copy of something wants noeviction instead — at # which case writes start failing when full rather than data silently # disappearing. Neither is safe for every use; this one matches the name. maxmemoryPolicy: allkeys-lru # Snapshotting off. What must survive a restart is the ACL file, which is # written by ACL SAVE independently of RDB/AOF. Cached values are by # definition reconstructible, and on a node at its memory ceiling a # background save's copy-on-write spike is a real risk for no benefit. save: "" # Tuned for a node with 8GB total that is already near its ceiling. The # request is what the scheduler reserves; the limit is sized above # maxmemory so Redis hits its own eviction policy rather than being # OOM-killed by the kernel, which loses the whole instance instead of the # coldest keys. resources: requests: cpu: 25m memory: 32Mi limits: memory: 96Mi