Seamlessly encrypt traffic from any apps in your Service Mesh to Memorystore (Redis)

Mathieu Benoit
Google Cloud - Community
5 min readSep 8, 2022

Updated on December 16th, 2022 with the deployment of Online Boutique via its Helm chart.

The Online Boutique sample apps architecture with Memorystore (Redis)

Anthos Service Mesh (ASM), a managed Istio implementation, can improve your security posture for your Kubernetes clusters and your apps. Istio aims to bring as much value to users out of the box without any configuration at all. ASM, on top of that, simplifies all the management of both the control plane and the data plane and the integration with monitoring and logging. Without any compromise, your apps in your Mesh will benefit from advanced features like traffic encryption, logging, tracing, etc. without updating the code of your apps.

In this tutorial, we will see how easy and seamless it is to encrypt traffic from the Online Boutique sample apps to Memorystore (Redis) by leveraging Istio/ASM. For this, we will set up a TLS origination on the cartservice app, thanks to Istio configuration.

TLS origination occurs when an Istio proxy (sidecar or egress gateway) is configured to accept unencrypted internal HTTP connections, encrypt the requests, and then forward them to HTTPS servers that are secured using simple or mutual TLS. This is the opposite of TLS termination where an ingress proxy accepts incoming TLS connections, decrypts the TLS, and passes unencrypted requests on to internal mesh services.

Objectives

  • Create a Google Kubernetes Engine (GKE) cluster
  • Deploy the Online Boutique sample apps with an in-cluster redis database
  • Provision a Memorystore (Redis) instance allowing only in-transit encryption
  • Connect the cartservice app to the Memorystore (Redis) instance
  • Enable the managed Anthos Service Mesh (ASM) on this cluster
  • Configure the TLS origination from the cartservice app to the Memorystore (Redis) instance
  • Verify that the cartservice app is successfully communicating over TLS with the Memorystore (Redis) instance

Set up your environment

This assumes that you have a Google Cloud Project already created, that’s where we will provision all the resources needed for this tutorial.

Initialize the common variables used throughout this tutorial:

PROJECT_ID=FIXME-WITH-YOUR-EXISTING_PROJECT-ID
REGION=us-east4
ZONE=us-east4-a
PROJECT_NUMBER=$(gcloud projects describe ${PROJECT_ID} --format='get(projectNumber)')

To avoid repeating the --project in the commands throughout this tutorial, let's set the current project:

gcloud config set project ${PROJECT_ID}

Enable the required APIs

gcloud services enable \
redis.googleapis.com \
mesh.googleapis.com

Create a GKE cluster

CLUSTER=redis-tls-tutorial
gcloud container clusters create ${CLUSTER} \
--zone ${ZONE} \
--machine-type=e2-standard-4 \
--num-nodes 4 \
--workload-pool ${PROJECT_ID}.svc.id.goog \
--labels mesh_id=proj-${PROJECT_NUMBER} \
--network default

Deploy the Online Boutique sample apps

Deploy the Online Boutique sample apps using by default an in-cluster Redis database:

NAMESPACE=onlineboutique
helm upgrade onlineboutique oci://us-docker.pkg.dev/online-boutique-ci/charts/onlineboutique \
--install \
--create-namespace \
-n ${NAMESPACE}

After all the apps are successfully deployed, you could navigate to the Online Boutique website by clicking on the link below:

echo -n "http://" && kubectl get svc frontend-external -n ${NAMESPACE} -o json | jq -r '.status.loadBalancer.ingress[0].ip'

Provision a Memorystore (Redis) instance allowing only in-transit encryption

REDIS_NAME=redis-tls-tutorial
gcloud redis instances create ${REDIS_NAME} \
--size 1 \
--region ${REGION} \
--zone ${ZONE} \
--redis-version redis_6_x \
--network default \
--transit-encryption-mode SERVER_AUTHENTICATION

Notes:

  • You can connect to a Memorystore (Redis) instance from GKE clusters that are in the same region and use the same network as your instance.
  • You cannot connect to a Memorystore (Redis) instance from a GKE cluster without VPC-native/IP aliasing enabled.
  • In-transit encryption is only available at creation time of your Memorystore (Redis) instance. The Certificate Authority is valid for 10 years, rotation every 5 years.

Wait for the Memorystore (Redis) instance to be succesfully provisioned and get the connection information of the Memorystore (Redis) instance just provisioned, we will need these information in a following section:

REDIS_IP=$(gcloud redis instances describe ${REDIS_NAME} \
--region ${REGION} \
--format 'get(host)')
REDIS_PORT=$(gcloud redis instances describe ${REDIS_NAME} \
--region ${REGION} \
--format 'get(port)')

Connect the Online Boutique sample apps to the Memorystore (Redis) instance

Update the Online Boutique deployment via its Helm chart:

helm upgrade onlineboutique oci://us-docker.pkg.dev/online-boutique-ci/charts/onlineboutique \
--install \
--create-namespace \
-n ${NAMESPACE} \
--set cartDatabase.inClusterRedis.create=false \
--set cartDatabase.connectionString=${REDIS_IP}:${REDIS_PORT}

This deployment will:

  • Update the cartservice's environment variables to point to the Memorystore (Redis) instance;
  • Remove the default in-cluster redis database, not needed anymore.

Navigate to the Online Boutique website by clicking on the link below:

echo -n "http://" && kubectl get svc frontend-external -n ${NAMESPACE} -o json | jq -r '.status.loadBalancer.ingress[0].ip'

You should have a HTTP Status: 500 Internal Server Error page at this point. This is expected since we haven't yet set up the TLS communication between cartservice and the Memorystore (Redis) instance. With the next sections, we will leverage ASM and Istio in order to accomplish this part and fix the issue!

Install the managed ASM on this cluster

Register your cluster to a Fleet:

gcloud container fleet memberships register ${CLUSTER} \
--gke-cluster ${ZONE}/${CLUSTER} \
--enable-workload-identity

Enable ASM in your Fleet:

gcloud container fleet mesh enable

Enable the ASM automatic control plane management to let Google apply the recommended configuration of ASM:

gcloud container fleet mesh update \
--management automatic \
--memberships ${CLUSTER}

Wait for the managed ASM to be successfully enabled for your GKE cluster (controlePlaneManagement and dataPlaneManagement with state: ACTIVE):

gcloud container fleet mesh describe

Configure the TLS origination from the Mesh to the Memorystore (Redis) instance

Get the Certificate Authority of the Memorystore (Redis) instance:

REDIS_CERT=$(gcloud redis instances describe ${REDIS_NAME} \
--region ${REGION} \
--format 'get(serverCaCerts[0].cert)')

Update the Online Boutique deployment via its Helm chart:

helm upgrade onlineboutique oci://us-docker.pkg.dev/online-boutique-ci/charts/onlineboutique \
--install \
--create-namespace \
-n ${NAMESPACE} \
--set cartDatabase.inClusterRedis.create=false \
--set cartDatabase.connectionString=${REDIS_IP}:${REDIS_PORT} \
--set cartDatabase.externalRedisTlsOrigination.enable=true \
--set cartDatabase.externalRedisTlsOrigination.certificate="${REDIS_CERT}" \
--set cartDatabase.externalRedisTlsOrigination.endpointAddress=${REDIS_IP} \
--set cartDatabase.externalRedisTlsOrigination.endpointPort=${REDIS_PORT}

This deployment will:

  • Annotate the cartservice deployment to mount the redis-cert secret via its istio-proxy sidecar;
  • Deploy a ServiceEntry to register the Memorystore (Redis) instance in the Mesh as an external endpoint with its private IP address and port;
  • Deploy a DestinationRule to configure the outgoing connections to this Memorystore (Redis) instance with TLS in SIMPLE mode (not MUTUAL) with its associated Certificate Authority.

Label the the Online Boutique Namespace to inject the Istio/ASM sidecar proxies in its apps:

kubectl label namespace ${NAMESPACE} istio-injection=enabled

Restart the cartservice app in order to inject the Istio/ASM sidecar proxies and configs we just deployed previously:

kubectl rollout restart deployment cartservice \
-n ${NAMESPACE}

As a side note, since Online Boutique v0.38.0, the cartservice app got a fix allowing to make this TLS origination working properly.

Navigate to the Online Boutique website by clicking on the link below:

echo -n "http://" && kubectl get svc frontend-external -n ${NAMESPACE} -o json | jq -r '.status.loadBalancer.ingress[0].ip'

That’s it! You should now see the Online Boutique website working successfully again, now connected to the Memorystore (Redis) instance over TLS only. Congrats!

Cleaning up

To avoid incurring charges to your Google Cloud account, you can delete the resources used in this tutorial.

Unregister the GKE cluster from the Fleet:

gcloud container fleet memberships unregister ${CLUSTER} \
--project=${PROJECT_ID} \
--gke-cluster=${ZONE}/${CLUSTER}

Delete the GKE cluster:

gcloud container clusters delete ${CLUSTER} \
--zone ${ZONE}

Delete the Memorystore (Redis) instance:

gcloud redis instances delete ${REDIS_NAME}

What’s next

Originally posted at mathieu-benoit.github.io.

--

--

Mathieu Benoit
Google Cloud - Community

Customer Success Engineer at Humanitec | CNCF Ambassador | GDE Cloud