These instructions will demonstrate how to configure API Portal to use Redis for high availability session storage. The instructions were created with TAP in mind, but should also work for any cluster with the Cluster Essentials for VMware Tanzu installed. These instructions will:

  • Install a Redis Kubernetes operator
  • Deploy an instance of a Redis cluster and database
  • Create a service binding compliant secret using a SecretTemplate
  • Copy the secret to the api-portal namespace using SecretExport and SecretImport
  • Configure API Portal to use the secret to turn on session storage with Redis.

Note: To use Redis for session storage you will need to have API Portal configured to use SSO. For more details see [Configure Single Sign-On](configuring-k8s-sso.html#configure-sso-k8s))

Installing Redis

Installing the Redis operator is a relatively simple task as all the necessary resource definitions are contained in a single yaml file that is available at public URL. You will use the Redis Enterprise Cluster operator in this guide. To install the Redis operator, run the following commands:

kubectl create ns service-instances

kubectl apply -f https://raw.githubusercontent.com/RedisLabs/redis-enterprise-k8s-docs/v6.2.10-45/bundle.yaml -n service-instances

Validate the operator is installed with the following command:

kubectl get pods -l name=redis-enterprise-operator -n service-instances

You should see an output similar to the following:

NAME                                         READY   STATUS    RESTARTS   AGE
redis-enterprise-operator-74849d8c69-pnqvq   2/2     Running   0          39s

Now that the operator is deployed, you can create a Redis cluster and database. To deploy the cluster and database copy the instructions to a file named ha-setup.yml, run the command below. The configuration referenced in the following command, using some Carvel tools, creates a kubernetes service binding compliant secret and moves that secret to the api-portal namespace so your api-portal deployment can access it. It also deploys a SecretTemplate resource to convert the subsequent Redis configuration into a service binding compliant secret.

Note: These instructions assume you have API Portal installed in the namespace `api-portal`. If you are using a different namespace then substitute that value in where `api-portal` is mentioned.

( 
cat <<'EOF' 
#@ load("@ytt:data", "data")

---
apiVersion: "app.redislabs.com/v1"
kind: RedisEnterpriseCluster
metadata:
 name: #@ data.values.instance_name + "-cluster"
 namespace: #@ data.values.service_namespace
spec:
  nodes: 1
  redisEnterpriseNodeResources:
    limits:
      cpu: "2000m"
      memory: 4Gi
    requests:
      cpu: "100m"
      memory: 1Gi
  persistentSpec:
   enabled: true
   volumeSize: 10Gi
---
apiVersion: app.redislabs.com/v1alpha1
kind: RedisEnterpriseDatabase
metadata:
  name: #@ data.values.instance_name + "-db"
  namespace: #@ data.values.service_namespace
spec:
  memorySize: 1GB
---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: redis-enterprise-cluster-secret-template-reader
  namespace: #@ data.values.service_namespace
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: redis-enterprise-cluster-secret-template-reader
  namespace: #@ data.values.service_namespace
rules:
- apiGroups:
  - ""
  resources:
  - secrets
  - services
  verbs:
  - get
  - list
  - watch
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: redis-enterprise-cluster-secret-template-reader
  namespace: #@ data.values.service_namespace
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: redis-enterprise-cluster-secret-template-reader
subjects:
- kind: ServiceAccount
  name: redis-enterprise-cluster-secret-template-reader
---
apiVersion: secretgen.carvel.dev/v1alpha1
kind: SecretTemplate
metadata:
 name: #@ data.values.instance_name + "-redis-secret"
 namespace: #@ data.values.service_namespace
spec:
 serviceAccountName: redis-enterprise-cluster-secret-template-reader
 inputResources:
 - name: redis-service
   ref:
    apiVersion: v1
    kind: Service
    name: #@ data.values.instance_name  + "-db"
 - name: creds
   ref:
     apiVersion: v1
     kind: Secret
     name: #@ "redb-" + data.values.instance_name + "-db"
 template:
  metadata:
   labels:
     app.kubernetes.io/component: redis
     app.kubernetes.io/instance: #@ data.values.instance_name
     services.apps.tanzu.vmware.com/class: redis-enterprise-cluster
  stringData:
    host: "$(.redis-service.metadata.name).$(.redis-service.metadata.namespace)"
    provider: redis_enterprise
    type: redis
  data:
    password: $(.creds.data.password)
    port: $(.creds.data.port)
---
apiVersion: secretgen.carvel.dev/v1alpha1
kind: SecretExport
metadata:
  name: #@ data.values.instance_name + "-redis-secret"
  namespace: #@ data.values.service_namespace
spec:
  toNamespace: api-portal
---
apiVersion: secretgen.carvel.dev/v1alpha1
kind: SecretImport
metadata:
  name: #@ data.values.instance_name + "-redis-secret"
  namespace: api-portal
spec:
  fromNamespace: #@ data.values.service_namespace
EOF
) | ytt -v service_namespace=service-instances -v instance_name=redis-test -f- | kubectl apply -f-

This will create a cluster and database named redis-test. Once the cluster is ready, its configuration is written to a secret and service resource.

First validate that the cluster has been created and is operational by running the following command:

kubectl get sts redis-test-cluster -n service-instances

You should see an output similar to the following:

NAME             	 READY   AGE
redis-test-cluster   1/1 	 108s

Next, validate that the database is operational by running the following command:

kubectl get redisenterprisedatabase redis-test-db -n service-instances

You should see an output similar to the following:

NAME            VERSION   PORT	 CLUSTER               SHARDS   STATUS   SPEC STATUS   AGE
redis-test-db   6.0.13    10745  redis-test-cluster    1        active   Valid         5m55s

Next, validate the SecretTemplate was able to reconcile the Redis configuration into a service binding compliant secret by running the following command:

kubectl get secrettemplate redis-test-redis-secret -n service-instances

You should see an output similar to the following:

NAME                  	  DESCRIPTION       	AGE
redis-test-redis-secret   Reconcile succeeded   8m57s

Validate that the service binding compliant secret exists by running the following command:

kubectl get secret redis-test-redis-secret -n service-instances

Validate that the SecretExport was created by running the following command:

kubectl get secretexport.secretgen.carvel.dev/redis-test-redis-secret -n service-instances

You should see an output similar below. This might take a couple of minutes to reconcile.

NAME                      DESCRIPTION           AGE
redis-test-redis-secret   Reconcile succeeded   8m46s

Validate that the SecretImport was created in the api-portal namespace by running the following command:

kubectl get secretimport.secretgen.carvel.dev/redis-test-redis-secret -n api-portal

You should see an output similar to the following:

NAME                      DESCRIPTION           AGE
redis-test-redis-secret   Reconcile succeeded   12m

Finally make sure the service binding compliant secret was copied over to the api-portal namespace by running the following command:

kubectl get secret redis-test-redis-secret -n api-portal

You should see an output similar to the following:

NAME                  	  DESCRIPTION       	AGE
redis-test-redis-secret   Reconcile succeeded   8m57s

If you inspect the secret further, you will see it incorporates all the necessary fields to describe the binding as well as provides necessary connectivity and authentication information

kubectl describe secret redis-test-redis-secret -n api-portal

You should see an output similar to the following:

Name:         redis-test-redis-secret
Namespace:    api-portal
Labels:       <none>
Annotations:  <none>

Type:  Opaque

Data
====
host:      31 bytes
password:  8 bytes
port:      5 bytes
provider:  16 bytes
type:      5 bytes

Update your API Portal installation to use the new Redis Secret

Note: The following instructions are TAP specific.

Update the api_portal section of your tap values to include the sso.session.redisCredentialSecret. Below is an example

api_portal:
  sso:
    enabled: true
    secretName: sso-credentials
    session:
      redisCredentialSecret: redis-test-redis-secret

Once you have updated your values file you can refresh your tap installation. First you will need to find the version of TAP you are using. If you are unsure you can locate the version by running the following command:

tanzu package installed list -n tap-install

and look for a the line with the name of tap

NAME                                PACKAGE-NAME                                         PACKAGE-VERSION   STATUS
tap                                 tap.tanzu.vmware.com                                 1.5.1     Reconcile succeeded

Now you can update your installation by running the command below and replacing <TAP_VERSION> with the appropriate version and <VALUES.yaml> with your updated values file.

tanzu package install tap -p tap.tanzu.vmware.com -v <TAP_VERSION> --values-file <VALUES.yaml> -n tap-install

It might take a couple of minutes for the changes to propagate through. You can check the status of api portal by running the following command:

tanzu package installed get api-portal -n tap-install

Now your API Portal installation should be configured to use redis to store your sessions! If you want to double check you can look for a cookie by the name of API-PORTAL-SESSION, If you are not using redis you would only see SESSION

check-circle-line exclamation-circle-line close-line
Scroll to top icon