Skip to content

Redis-Cluster Deployment on Kubernetes

ConfigMap - Configuration

Add below content on configmap.yaml and apply on kubernetes using kubectl apply -f configmap.yaml

Text Only
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: redis-cluster-default
  labels:
    app.kubernetes.io/name: redis-cluster
    helm.sh/chart: redis-cluster-7.4.6
    app.kubernetes.io/instance: redis-cluster
    app.kubernetes.io/managed-by: Helm
data:
  redis-default.conf: |-
    bind 127.0.0.1
    protected-mode yes
    port 6379
    tcp-backlog 511
    timeout 0
    tcp-keepalive 300
    daemonize no
    supervised no
    pidfile /opt/bitnami/redis/tmp/redis_6379.pid
    loglevel notice
    logfile ""
    databases 16
    always-show-logo yes
    save 900 1
    save 300 10
    save 60 10000
    stop-writes-on-bgsave-error yes
    rdbcompression yes
    rdbchecksum yes
    dbfilename dump.rdb
    rdb-del-sync-files no
    dir /bitnami/redis/data
    replica-serve-stale-data yes
    replica-read-only yes
    repl-diskless-sync no
    repl-diskless-sync-delay 5
    repl-diskless-load disabled
    repl-disable-tcp-nodelay no
    replica-priority 100
    acllog-max-len 128
    lazyfree-lazy-eviction no
    lazyfree-lazy-expire no
    lazyfree-lazy-server-del no
    replica-lazy-flush no
    lazyfree-lazy-user-del no
    appendonly no
    appendfilename "appendonly.aof"
    appendfsync everysec
    no-appendfsync-on-rewrite no
    auto-aof-rewrite-percentage 100
    auto-aof-rewrite-min-size 64mb
    aof-load-truncated yes
    aof-use-rdb-preamble yes
    lua-time-limit 5000
    cluster-enabled yes
    cluster-config-file /bitnami/redis/data/nodes.conf
    slowlog-log-slower-than 10000
    slowlog-max-len 128
    latency-monitor-threshold 0
    notify-keyspace-events ""
    hash-max-ziplist-entries 512
    hash-max-ziplist-value 64
    list-max-ziplist-size -2
    list-compress-depth 0
    set-max-intset-entries 512
    zset-max-ziplist-entries 128
    zset-max-ziplist-value 64
    hll-sparse-max-bytes 3000
    stream-node-max-bytes 4096
    stream-node-max-entries 100
    activerehashing yes
    client-output-buffer-limit normal 0 0 0
    client-output-buffer-limit replica 256mb 64mb 60
    client-output-buffer-limit pubsub 32mb 8mb 60
    hz 10
    dynamic-hz yes
    aof-rewrite-incremental-fsync yes
    rdb-save-incremental-fsync yes
    jemalloc-bg-thread yes

ConfigMap - Scripts

Add below content on scripts-configmap.yaml and apply on kubernetes using kubectl apply -f scripts-configmap.yaml

Text Only
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: redis-cluster-scripts
  labels:
    app.kubernetes.io/name: redis-cluster
    helm.sh/chart: redis-cluster-7.4.6
    app.kubernetes.io/instance: redis-cluster
    app.kubernetes.io/managed-by: Helm
data:
  ping_readiness_local.sh: |-
    #!/bin/sh
    set -e

    REDIS_STATUS_FILE=/tmp/.redis_cluster_check
    if [ ! -z "$REDIS_PASSWORD" ]; then export REDISCLI_AUTH=$REDIS_PASSWORD; fi;
    response=$(
      timeout -s 3 $1 \
      redis-cli \
        -h localhost \
        -p $REDIS_PORT \
        ping
    )
    if [ "$?" -eq "124" ]; then
      echo "Timed out"
      exit 1
    fi
    if [ "$response" != "PONG" ]; then
      echo "$response"
      exit 1
    fi
    if [ ! -f "$REDIS_STATUS_FILE" ]; then
      response=$(
        timeout -s 3 $1 \
        redis-cli \
          -h localhost \
          -p $REDIS_PORT \
          CLUSTER INFO | grep cluster_state | tr -d '[:space:]'
      )
      if [ "$?" -eq "124" ]; then
        echo "Timed out"
        exit 1
      fi
      if [ "$response" != "cluster_state:ok" ]; then
        echo "$response"
        exit 1
      else
        touch "$REDIS_STATUS_FILE"
      fi
    fi
  ping_liveness_local.sh: |-
    #!/bin/sh
    set -e
    if [ ! -z "$REDIS_PASSWORD" ]; then export REDISCLI_AUTH=$REDIS_PASSWORD; fi;
    response=$(
      timeout -s 3 $1 \
      redis-cli \
        -h localhost \
        -p $REDIS_PORT \
        ping
    )
    if [ "$?" -eq "124" ]; then
      echo "Timed out"
      exit 1
    fi
    responseFirstWord=$(echo $response | head -n1 | awk '{print $1;}')
    if [ "$response" != "PONG" ] && [ "$responseFirstWord" != "LOADING" ] && [ "$responseFirstWord" != "MASTERDOWN" ]; then
      echo "$response"
      exit 1
    fi

Headless Service

Text Only
---
apiVersion: v1
kind: Service
metadata:
  name: redis-cluster-headless
  labels:
    app.kubernetes.io/name: redis-cluster
    helm.sh/chart: redis-cluster-7.4.6
    app.kubernetes.io/instance: redis-cluster
    app.kubernetes.io/managed-by: Helm
spec:
  type: ClusterIP
  clusterIP: None
  publishNotReadyAddresses: true
  ports:
    - name: tcp-redis
      port: 6379
      targetPort: tcp-redis
    - name: tcp-redis-bus
      port: 16379
      targetPort: tcp-redis-bus
  selector:
    app.kubernetes.io/name: redis-cluster
    app.kubernetes.io/instance: redis-cluster

Secret Store

Text Only
---
apiVersion: v1
kind: Secret
metadata:
  name: redis-cluster
  labels:
    app.kubernetes.io/name: redis-cluster
    helm.sh/chart: redis-cluster-7.4.6
    app.kubernetes.io/instance: redis-cluster
    app.kubernetes.io/managed-by: Helm
type: Opaque
data:
  redis-password: "Q3lpc3c1Q3Y0TQ=="

Redis Service

Text Only
---
apiVersion: v1
kind: Service
metadata:
  name: redis-cluster
  labels:
    app.kubernetes.io/name: redis-cluster
    helm.sh/chart: redis-cluster-7.4.6
    app.kubernetes.io/instance: redis-cluster
    app.kubernetes.io/managed-by: Helm
  annotations:
spec:
  type: ClusterIP
  ports:
    - name: tcp-redis
      port: 6379
      targetPort: tcp-redis
      protocol: TCP
      nodePort: null
  selector:
    app.kubernetes.io/name: redis-cluster
    app.kubernetes.io/instance: redis-cluster

StatefulSet Deployment

Text Only
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: redis-cluster
  labels:
    app.kubernetes.io/name: redis-cluster
    helm.sh/chart: redis-cluster-7.4.6
    app.kubernetes.io/instance: redis-cluster
    app.kubernetes.io/managed-by: Helm
spec:
  updateStrategy:
    rollingUpdate:
      partition: 0
    type: RollingUpdate
  selector:
    matchLabels:
      app.kubernetes.io/name: redis-cluster
      app.kubernetes.io/instance: redis-cluster
  replicas: 2
  serviceName: redis-cluster-headless
  podManagementPolicy: Parallel
  template:
    metadata:
      labels:
        app.kubernetes.io/name: redis-cluster
        helm.sh/chart: redis-cluster-7.4.6
        app.kubernetes.io/instance: redis-cluster
        app.kubernetes.io/managed-by: Helm
    spec:
      hostNetwork: false
      enableServiceLinks: false

      securityContext:
        fsGroup: 1001
        runAsUser: 1001
        sysctls: []
      serviceAccountName: default
      affinity:
        podAffinity:

        podAntiAffinity:
          preferredDuringSchedulingIgnoredDuringExecution:
            - podAffinityTerm:
                labelSelector:
                  matchLabels:
                    app.kubernetes.io/name: redis-cluster
                    app.kubernetes.io/instance: redis-cluster
                topologyKey: kubernetes.io/hostname
              weight: 1
        nodeAffinity:

      containers:
        - name: redis-cluster
          image: docker.io/bitnami/redis-cluster:6.2.6-debian-10-r178
          imagePullPolicy: "IfNotPresent"
          securityContext:
            runAsNonRoot: true
            runAsUser: 1001
          command: ['/bin/bash', '-c']
          args:
            - |
              # Backwards compatibility change
              if ! [[ -f /opt/bitnami/redis/etc/redis.conf ]]; then
                  echo COPYING FILE
                  cp  /opt/bitnami/redis/etc/redis-default.conf /opt/bitnami/redis/etc/redis.conf
              fi
              pod_index=($(echo "$POD_NAME" | tr "-" "\n"))
              pod_index="${pod_index[-1]}"
              if [[ "$pod_index" == "0" ]]; then
                export REDIS_CLUSTER_CREATOR="yes"
                export REDIS_CLUSTER_REPLICAS="1"
              fi
              /opt/bitnami/scripts/redis-cluster/entrypoint.sh /opt/bitnami/scripts/redis-cluster/run.sh
          env:
            - name: POD_NAME
              valueFrom:
                fieldRef:
                  fieldPath: metadata.name
            - name: REDIS_NODES
              value: "redis-cluster-0.redis-cluster-headless redis-cluster-1.redis-cluster-headless "
            - name: REDISCLI_AUTH
              valueFrom:
                secretKeyRef:
                  name: redis-cluster
                  key: redis-password
            - name: REDIS_PASSWORD
              valueFrom:
                secretKeyRef:
                  name: redis-cluster
                  key: redis-password
            - name: REDIS_AOF_ENABLED
              value: "yes"
            - name: REDIS_TLS_ENABLED
              value: "no"
            - name: REDIS_PORT
              value: "6379"
          ports:
            - name: tcp-redis
              containerPort: 6379
            - name: tcp-redis-bus
              containerPort: 16379
          livenessProbe:
            initialDelaySeconds: 5
            periodSeconds: 5
            # One second longer than command timeout should prevent generation of zombie processes.
            timeoutSeconds: 6
            successThreshold: 1
            failureThreshold: 5
            exec:
              command:
                - sh
                - -c
                - /scripts/ping_liveness_local.sh 5
          readinessProbe:
            initialDelaySeconds: 5
            periodSeconds: 5
            # One second longer than command timeout should prevent generation of zombie processes.
            timeoutSeconds: 2
            successThreshold: 1
            failureThreshold: 5
            exec:
              command:
                - sh
                - -c
                - /scripts/ping_readiness_local.sh 1
          resources:
            limits: {}
            requests: {}
          volumeMounts:
            - name: scripts
              mountPath: /scripts
            - name: redis-data
              mountPath: /bitnami/redis/data
              subPath:
            - name: default-config
              mountPath: /opt/bitnami/redis/etc/redis-default.conf
              subPath: redis-default.conf
            - name: redis-tmp-conf
              mountPath: /opt/bitnami/redis/etc/
      volumes:
        - name: scripts
          configMap:
            name: redis-cluster-scripts
            defaultMode: 0755
        - name: default-config
          configMap:
            name: redis-cluster-default
        - name: redis-tmp-conf
          emptyDir: {}
  volumeClaimTemplates:
    - metadata:
        name: redis-data
        labels:
          app.kubernetes.io/name: redis-cluster
          app.kubernetes.io/instance: redis-cluster
      spec:
        accessModes:
          - "ReadWriteOnce"
        resources:
          requests:
            storage: "8Gi"

Last update: June 23, 2022
Created: June 23, 2022