This blog post was orginially publishes on DigitalOcean's docs by Abhimanyu Selvan
Multi-cluster Kubernetes refers to managing multiple Kubernetes clusters, which are groups of nodes working together to orchestrate and run containerized applications. These clusters can be distributed across different data centers, regions, or cloud providers to ensure high availability, fault tolerance, and better performance.
Multi-cluster Kubernetes offers several advantages in specific scenarios:
Service Mesh frameworks are dedicated infrastructure layers to simplify the management and configuration of micro-service-based applications in a distributed system. Service meshes introduce a sidecar container as a proxy to provide multiple features (i.e., secure connections with mutual TLS, circuit breaking, canary deployments).
Some of the most popular service mesh architectures like Istio and Linkerd have multi-cluster support to embrace multi-cluster microservices applications. The interconnection among different clusters uses a dedicated proxy to route traffic from the mesh of one cluster to another. Similarly, Istio and Linkerd can create an ad-hoc mutual TLS tunnel across clusters and provide primitives to expose services across the clusters, enabling cross-cluster communication and traffic-splitting features.
In this POC, we will use the Multi-cluster extension of Linkerd to set up secure cross-cluster communication between regions.
We need to install some CLI tools to set up the POC successfully.
Open a terminal and let’s go!
# Create DOKS Cluster in "sfo3(west)"
doctl kubernetes cluster create west --region sfo3 --count 3 --size s-8vcpu-16gb
# Update the kubeconfig for the newly created cluster
doctl kubernetes cluster kubeconfig save YOUR_CLUSTER_ID_HERE
# Rename the context to "west" for ease of demo
kubectl config rename-context do-sfo3-west west
# Create DOKS Cluster in "syd1(east)"
doctl kubernetes cluster create east --region syd1 --count 3 --size s-8vcpu-16gb
# Update the kubeconfig for the newly created cluster
doctl kubernetes cluster kubeconfig save YOUR_CLUSTER_ID_HERE
# Rename the cluster context to "east" for ease of demo
kubectl config rename-context do-syd1-east east
Linkerd requires a shared trust anchor between the installations in all clusters that communicate with each other. This encrypts the traffic between clusters and authorizes requests that reach the gateway so your cluster is not open to the public internet.
# Generate trust anchor "root certificate and key.”
step certificate create root.linkerd.cluster.local root.crt root.key \
--profile root-ca --no-password --insecure
# The trust anchor we’ve generated is a self-signed certificate
# which can be used to create new certificates (a certificate authority).
# Generate the "issuer credentials" using the trust anchor.
step certificate create identity.linkerd.cluster.local issuer.crt issuer.key \
--profile intermediate-ca --not-after 8760h --no-password --insecure \
--ca root.crt --ca-key root.key
Note: The commands in the following section will assume that you renamed the contexts to west and east.
# Install "Linkerd CRDs" on both clusters `east ` and `west.`
linkerd install --crds | tee \
>(kubectl --context=west apply -f -) \
>(kubectl --context=east apply -f -)
# Install "Linkerd with identity configuration" on both clusters
linkerd install \
--identity-trust-anchors-file root.crt \
--identity-issuer-certificate-file issuer.crt \
--identity-issuer-key-file issuer.key \
| tee \
>(kubectl --context=west apply -f -) \
>(kubectl --context=east apply -f -)
Two components implement Linkerd’s multi-cluster functionality:
linkerd-viz is a monitoring application based on Prometheus and Grafana, autoconfigured to collect metrics from linkerd.
# Install linkerd-viz extension on both the clusters
for ctx in west east; do
linkerd --context=${ctx} multicluster install | \
kubectl --context=${ctx} apply -f - || break
linkerd --context=${ctx} viz install | \
kubectl --context=${ctx} apply -f - || break
done
To link west to east, a credentials secret, Link resource, and service-mirror controller are created. The credentials secret includes a kubeconfig for accessing the east cluster’s Kubernetes API. The Link resource configures service mirroring with gateway settings and label selectors. The service-mirror controller utilizes the Link and secret to identify and copy matching services from the east cluster to the west cluster.
linkerd --context=east multicluster link --cluster-name east | \
kubectl --context=west apply -f -
In this case, we would like cluster west to mirror the services from cluster east so the service mirror component is installed only on the west cluster.
The service mirror is a Kubernetes Operator. Once installed, it mirrors a remote cluster’s services locally to provide service discovery and allow pods to refer to the remote services. It also manages configuring endpoints so that traffic goes to the correct IP address.
Services are not automatically mirrored in linked clusters. Only services with the mirror.linkerd.io/exported label will be mirrored by default.
# Label web-svc for service-mirroring
# For more details: https://linkerd.io/2020/02/25/multicluster-kubernetes-with-service-mirroring/
kubectl --context=east label svc -n emojivoto web-svc mirror.linkerd.io/exported=true
# Get endpoint IP of web-svc-east in the west cluster
kubectl --context=west -n emojivoto get endpoints web-svc-east \
-o 'custom-columns=ENDPOINT_IP:.subsets[*].addresses[*].ip'
# Get the IP of the linkerd-gateway service in the east cluster
kubectl --context=east -n linkerd-multicluster get svc linkerd-gateway \
-o "custom-columns=GATEWAY_IP:.status.loadBalancer.ingress[*].ip"
mTLS (mutual Transport Layer Security) is an extension of regular TLS (Transport Layer Security) that ensures the server and the client are authenticated. By default, TLS only authenticates the server, but mTLS establishes mutual authentication, making the authenticity of both parties symmetric.
By default, requests will be going across the public Internet. Linkerd extends its automatic mTLS across clusters to ensure that the communication going across the public internet is encrypted.
To verify mTLS:
linkerd --context=west -n emojivoto viz tap deploy/vote-bot | \
grep "$(kubectl --context=east -n linkerd-multicluster get svc linkerd-gateway \
-o "custom-columns=GATEWAY_IP:.status.loadBalancer.ingress[*].ip")"
Output(check tls=true):
req id=19:0 proxy=out src=10.244.1.114:44966 dst=134.209.136.167:4143 "tls=true" :method=GET :authority=web-svc.emojivoto.svc.cluster.local:80 :path=/api/list
rsp id=19:0 proxy=out src=10.244.1.114:44966 dst=134.209.136.167:4143 "tls=true" :status=200 latency=18381µs
Linkerd enables mutually-authenticated Transport Layer Security (mTLS) for all TCP traffic between meshed pods. There are exceptions where non-mTLS traffic may still exist, such as traffic to or from pods outside the mesh (e.g., Kubernetes health checks) or traffic on ports designated as skip ports, bypassing the Linkerd proxy.\
To demonstrate the traffic flow between the two clusters across two different regions, we need to make the following changes:
# Retrieve the clusterIP of `web-svc-east.`
kubectl --context=west -n emojivoto get svc web-svc-east -o=jsonpath='{.spec.clusterIP}' && echo
# Edit vote-bot deployment in the west cluster to point to web-svc-east
# Replace with the IP obtained from the previous command
kubectl set env deployment/vote-bot -n emojivoto WEB_HOST=:80 --context west
Now the deployment/vote-bot forwards the requests to svc/web-svc-east whose endpoints are configured to point to the EXTERNAL-IP of the linkerd-gateway on the east cluster.
We will now use the linkerd-viz dashboards to monitor the cross-cluster service communication.
# Open and inspect Linkerd dashboards for both clusters
linkerd viz dashboard --context west --port 50750 &
linkerd viz dashboard --context east --port 50760 &
The built-on linkerd dashboard below shows the live calls and route metrics between the deployment/vote-bot and svc/web-svc-east (mirrored) on the cluster east:
The built-on linkerd dashboard below shows the live calls and route metrics between the deployment/linkerd-gateway and svc/web-svc on the cluster west:
The following figure depicts the secure end-to-end flow between the services in cluster west to the services in cluster east:
As technology evolves, multi-cluster setups are increasingly crucial for handling modern application requirements. With the guidance provided in this tutorial, readers can navigate the complexities of multi-cluster environments and unlock the full potential of their Kubernetes deployments.