GAP Documentation
GitHub Toggle Dark/Light/Auto mode Toggle Dark/Light/Auto mode Toggle Dark/Light/Auto mode Back to homepage

In-cluster Redis

Please consider using Cloud Memorystore because even the standard plan on Memorystore gives high availability out of the box. Running a single redis instance in the cluster will have downtime when the instance restarts. This restart can happen any time on the cluster. Also this example of the in-cluster redis does not provide persistence, the data will be wiped on restart, it is only suitable for caching.

If you really don’t care about HA and continuity of the data the following document will show you how to create a custom redis for your application.

To do this, you will have to do the following:

  • create a Redis custom resource in gap/gap_redis.yaml
  • configure your client to connect to redis via the kubernetes service name of the redis instance <my-application-name>-redis.<namespace>

Create Redis custom resource

This example contains

  • a k8s ServiceAccount that is used by redis
  • an AuthorizationPolicy to allow your application to call it through the service mesh (adapt this to specific ServiceAccounts that you are using if not default)
  • an example ConfigMap to contain the redis config, that is mounted on the pod
  • a k8s service resource to provide an endpoint for clients
  • a k8s statefulset to run the redis container

Create a yaml file under your gap folder with the following content (do not forget to replace <my-application-name> with your app name)

# gap/gap_redis.yaml
# An example ServiceAccount to be used by the redis pods
apiVersion: v1
automountServiceAccountToken: false
kind: ServiceAccount
metadata:
  labels:
    applicationName: <my-application-name>-redis
    app.kubernetes.io/instance: redis
  name: <my-application-name>-redis
---
# An example AuthorizationPolicy to allow speicific applications (through their ServiceAccounts) to access the redis (do not forget to replace `<namespace>` with the one where the service account resides as well).
# Every GAP application has a default service account generated based on the `name` key from the gap.yaml. If you are not using that or overriding the service account for specific deployments here you need to specify that.
apiVersion: security.istio.io/v1
kind: AuthorizationPolicy
metadata:
  labels:
    applicationName: <my-application-name>-redis
    app.kubernetes.io/instance: redis
  name: <my-application-name>-redis
spec:
  action: ALLOW
  rules:
  - from:
    - source:
        principals:
        # This should match your namespace and the ServiceAccount of the caller (default is the `name` field in the gap.yaml)
        - cluster.local/ns/<namespace>/sa/<my-application-name>
  selector:
    matchLabels:
      applicationName: <my-application-name>-redis
---
# An example ConfigMap containing the redis.conf file contents that is mounted on the pod.
apiVersion: v1
kind: ConfigMap
metadata:
  labels:
    applicationName: <my-application-name>-redis
    app.kubernetes.io/instance: redis
  name: <my-application-name>-redis
data:
  redis.conf: |
    maxmemory 100mb
    maxmemory-policy allkeys-lru
---
# An example service to allow other pods in the cluster to call the redis via a consistent host
apiVersion: v1
kind: Service
metadata:
  labels:
    applicationName: <my-application-name>-redis
    app.kubernetes.io/instance: redis
  name: <my-application-name>-redis
spec:
  ports:
    - name: redis
      protocol: TCP
      port: 6379
      targetPort: 6379
  selector:
    applicationName: <my-application-name>-redis
---
# An example StatefulSet to run the redis pod.
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: <my-application-name>-redis
  labels:
    applicationName: <my-application-name>-redis
    app.kubernetes.io/instance: redis
    mesh: enabled
spec:
  selector:
    matchLabels:
      applicationName: <my-application-name>-redis
  serviceName: <my-application-name>-redis
  replicas: 1
  template:
    metadata:
      labels:
        applicationName: <my-application-name>-redis
        app.kubernetes.io/instance: redis
        # this enables service mesh on the pods
        istio.io/rev: default
        redis: "true"
    spec:
      # This should match the ServiceAccount name we defined at the top of the file.
      serviceAccountName: <my-application-name>-redis
      containers:
        - name: redis
          image: redis:7
          args:
            - "/redis/redis.conf"
            - --appendonly
            - "yes"
            - --port
            - "6379"
          ports:
            - containerPort: 6379
              name: web
          resources:
            requests:
              memory: 200Mi
              cpu: 200m
            limits:
              memory: 300Mi
              cpu: 500m
          volumeMounts:
            - mountPath: /redis
              name: redisconf
      securityContext:
        runAsUser: 999
      volumes:
        - name: redisconf
          configMap:
            # This should match the name of the ConfigMap defined above.
            name: <my-application-name>-redis
            items:
              - key: redis.conf
                path: redis.conf

Interacting with the in-cluster Redis

You can exec onto the redis pod and run redis-cli

kubectl exec -n <namespace> -it <my-application-name>-redis-0 -- redis-cli

or port forward to the pod and connect locally

kubectl port-forward  -n <namespace> <my-application-name>-redis-0 6379

In the cluster the process should call through the k8s service defined above

redis-cli -h <my-application-name>.<namespace> -p 6379