kadet-hub logokadet-hub

Redis on Kubernetes without Bitnami: Valkey with Kapitan

Valkey, in place of Bitnami's redis chart (standalone architecture): one StatefulSet with append-only persistence and a password. Valkey is the BSD-3-Clause fork of Redis 7.2 and speaks the same protocol. The password is a Kapitan ref, generated on the first compile into refs/valkey/password; compile again with --reveal, or apply through Tesoro, to get the value into the Secret. The base64 backend keeps the recipe self-contained and encrypts nothing: in a real project use gpg or a KMS backend. No operator needed.

Inventory class

inventory/classes/recipes/valkey.yml, as on the main branch of kadet-hub/examples. A target includes it next to the pins below.

# Valkey, in place of Bitnami's redis chart (standalone architecture): one
# StatefulSet with append-only persistence and a password. Valkey is the
# BSD-3-Clause fork of Redis 7.2 and speaks the same protocol. The password
# is a Kapitan ref, generated on the first compile into refs/valkey/password;
# compile again with --reveal, or apply through Tesoro, to get the value into
# the Secret. The base64 backend keeps the recipe self-contained and encrypts
# nothing: in a real project use gpg or a KMS backend. No operator needed.
classes:
  - recipes.lib.kubernetes

parameters:
  generators:
    kubernetes:
      namespaces:
        valkey: {}
  components:
    valkey:
      namespace: valkey
      type: statefulset
      image: docker.io/valkey/valkey:9.1.2
      security_profile: restricted
      workload_security_context:
        runAsUser: 999
        runAsGroup: 999
        fsGroup: 999
      args: [valkey-server, --requirepass, $(VALKEY_PASSWORD), --appendonly, "yes", --dir, /data]
      env:
        VALKEY_PASSWORD:
          secretKeyRef:
            key: password
      secrets:
        auth:
          string_data:
            password:
              value: ?{base64:valkey/password||random:str:32}
      ports:
        valkey:
          container_port: 6379
          service_port: 6379
      healthcheck:
        readiness:
          type: tcp
          port: valkey
        liveness:
          type: tcp
          port: valkey
      resources:
        requests: {cpu: 100m, memory: 128Mi}
        limits: {memory: 512Mi}
      volume_mounts:
        data:
          mount_path: /data
      volume_claims:
        data:
          spec:
            accessModes: [ReadWriteOnce]
            resources:
              requests:
                storage: 8Gi
      service:
        type: ClusterIP

Compile classes

The class includes one per generator; each compiles its generator once, so a target can combine several recipes.

inventory/classes/recipes/lib/kubernetes.yml

# Compiles the kubernetes generator; recipes include this class, so a target that
# combines several recipes compiles it once.
parameters:
  kapitan:
    compile:
      - {input_type: kadet, output_type: yml, input_paths: [lib/kubernetes], output_path: kubernetes/}

Generator pins

The entries of inventory/classes/generators.yml for these generators, pinned by version and digest.

parameters:
  kapitan:
    dependencies:
    - output_path: lib/kubernetes
      source: ghcr.io/kadet-hub/kubernetes:1.2.0@sha256:52017626e77dd5bf7293ce465ff0c3dc7a61dae1ae8353a56a53ffebe1bfb67c
      type: oci

How it is checked

The examples CI verifies the signed index and the attestation of every pinned generator, compiles the target, validates the output against the generators' schemas, deploys it to a new kind cluster with the operators above and fails unless the StatefulSet is ready and valkey-cli ping answers PONG. The Chainsaw test holds the assertions.

All recipes · Bitnami chart alternatives