A helmetica reagent for Redis, wrapping redis-ha as its prima materia.
Creating one provisions a single instance Redis. It will create backups, networkpolicies and credentials and provide them to the user.
The backup policy, the network seal and the maintenance window come from azoth,
the framework's library chart, through the single include in templates/azoth.yaml. The
credentials arcanum stays here, in templates/credentials.yaml, because its mapping varies
with the replica count. The auth secret, the backup script, the rituals and the values in
values.yaml are this chart's own too.
apiVersion: v0.redis.helmetica-bundles.io/bundle
kind: Redis
metadata:
name: cache
namespace: my-app
spec:
approval:
strategy: Automatic
version: 0.0.1
values:
service:
plan: standard-2
replicas: 3
storage: 20GiThe service is provisioned in its own instance namespace.
$ kubectl -n my-app get redis cache -o jsonpath='{.status.instanceNamespace}'
helx-redis-...| Value | Default | What it does |
|---|---|---|
service.plan |
standard-1 |
Cpu and memory of the redis container. See Plans. |
service.replicas |
1 |
1 or 3. Three brings replication and Sentinel. See Topology. |
service.storage |
10Gi |
The data volume, per replica. Unrelated to the plan: a dataset that fits in memory still needs room on disk for the append only file and the snapshots beside it. |
service.config |
{} |
Extra redis.conf entries. Values are strings, so a number needs quoting. maxmemory and min-replicas-to-write are computed and win over anything set here. |
backup.enabled |
true |
Whether the service is backed up at all. |
backup.mode |
Schedule |
Schedule drives k8up over the volumes. BucketOnly provisions the bucket and stops there. |
backup.schedule.backup |
nightly | Cron expression. Empty gets a time between 22:00 and 06:00, hashed from the instance so it stays put and no two instances collide. |
backup.schedule.prune |
controller default | Cron expression. Weekly by default. |
backup.schedule.check |
controller default | Cron expression. Weekly by default. |
backup.bucketClassName |
controller default | The COSI bucket class. |
backup.bucketAccessClassName |
controller default | The COSI bucket access class. |
backup.retention.* |
controller default | How many backups survive a prune. |
network.allowedNamespaces |
[] |
Namespaces allowed in on top of the claim's own, which is always allowed. |
network.allowAllNamespaces |
false |
Open it to the whole cluster. |
network.expose |
false |
Make Redis reachable from outside the cluster. The proxy with three replicas, otherwise the headless service. The address goes into the REDIS_EXTERNAL_* credentials. Sentinel is not exposed, see Topology. |
maintenance.window |
operator default | The MaintenanceWindow this instance starts in. |
maintenance.suspend |
false |
Keep the schedule but do not run maintenance. |
credentials.targetSecret |
<claim>-credentials |
Where the connection details are written. |
Everything else about the subchart is the reagent's decision and is not in the API. See
values.yaml for what is fixed and why.
The number in the plan is gibibytes of memory, and cpu follows it at 250 millicores per
gibibyte. Requests are set equal to the limits, so the pod is Guaranteed. maxmemory is
three quarters of the limit, leaving the rest for the copy Redis makes while it writes a
snapshot.
| Plan | Cpu | Memory | maxmemory |
|---|---|---|---|
standard-1 |
250m | 1Gi | 768mb |
standard-2 |
500m | 2Gi | 1536mb |
standard-4 |
1000m | 4Gi | 3072mb |
standard-8 |
2000m | 8Gi | 6144mb |
Credentials are automatically provided in the same namespace as the claim.
envFrom:
- secretRef:
name: cache-credentials| Key | Notes |
|---|---|
REDIS_HOST |
Fully qualified. The proxy with three replicas, otherwise the headless service. |
REDIS_PORT |
6379 |
REDIS_USERNAME |
default. Redis 6 and later map the password onto the built-in ACL user. |
REDIS_PASSWORD |
Authentication password. |
REDIS_URL |
redis://default:<password>@<host>:6379. No TLS yet, so the scheme is redis and not rediss. |
REDIS_EXTERNAL_HOST |
With network.expose only. The address from outside the cluster. |
REDIS_EXTERNAL_PORT |
With network.expose only. Picked by the platform from its port range. |
REDIS_EXTERNAL_URL |
With network.expose only. redis://default:<password>@<external host>:<external port> |
REDIS_SENTINEL_HOST |
Three replicas only. The headless service, so a client sees every sentinel rather than one of them. |
REDIS_SENTINEL_PORT |
Three replicas only. 26379 |
REDIS_MASTER_GROUP_NAME |
Three replicas only. mymaster |
One replica is a single Redis that serves reads and writes. Can be scaled to 3.
Three replicas is one master and two replicas.
The proxy comes with it. The redis service is headless, so its DNS record answers with
every pod, and a client that dials REDIS_URL without the proxy would land on a read-only
replica two writes in three and get READONLY. REDIS_HOST therefore points at the proxy,
which always forwards to the current master. A Sentinel-aware client can ignore it and use
the REDIS_SENTINEL_* credentials instead.
Limitation: Sentinel is not exposed. With network.expose, a client outside the
cluster only reaches the proxy, through the REDIS_EXTERNAL_* credentials.
This chart contains a backup script for Redis. The backup is automatically enabled by default. Backups are done via K8up and you can get existing backups via:
$ kubectl -n <instance-namespace> get snapshots.k8up.iorestart rolls the statefulset, one pod at a time, so Sentinel always has a master to
point at.
$ just test # helm lint and the offline unit tests, no cluster needed
$ just touchstone # end to end against a running athanorjust test needs azoth to be reachable for helm dependency build. What azoth renders is
tested in azoth; the unit tests here cover this chart's own templates and the wiring.
The cel: expressions in values.yaml are chrysopoeia's to evaluate, not helm's, so the
offline tests render against test/unit/computed-values.yaml, generated from
pkg/celvalues in chrysopoeia. Regenerate it there if the expressions change. The
touchstone is what proves the expressions themselves.
To develop against a local azoth checkout, just link ../azoth, and just unlink when
done. push and release refuse to run while it is linked.