Software Development

Service to Service Call Pattern – Multi-Cluster Ingress

Multi-Cluster Ingress is a neat feature of Anthos and GKE (Google Kubernetes Engine), whereby a user accessing an application that is hosted on multiple GKE clusters, in different zones is directed to the right cluster that is nearest to the user!

So for eg. consider two GKE clusters, one in us-west1, based out of Oregon, USA and another in europe-north1, based out of Finland. An application is installed to these two clusters. Now, a user accessing the application from US will be lead to the GKE cluster in us-west1 and a user coming in from Europe will be lead to the GKE cluster in europe-north1. Multi-cluster Ingress enables this easily!

Enabling Multi-Cluster Ingress

Alright, so how does this work. 

Let me once again assume that I have two clusters available in my GCP project, one in us-west1-a zone and another in europe-north1-a, and an app called “Caller” deployed to these two clusters. For a cluster, the way to get traffic into the cluster from a user outside of it is typically done using an “Ingress”

This works great for a single cluster, however not so for a bunch of clusters. A different kind of an Ingress resource is required that spans GKE clusters and this is where a Multi-Cluster ingress comes in – an ingress that spans clusters.

Multi-Cluster Ingress is a Custom resource provided by GKE and looks something like this:

apiVersion: networking.gke.io/v1
kind: MultiClusterIngress
metadata:
  name: sample-caller-ingress
  namespace: istio-apps
spec:
  template:
    spec:
      backend:
        serviceName: sample-caller-mcs
        servicePort: 8080

It is defined in one of the clusters, designated as a “config” cluster. 

See how there is a a reference to “sample-caller-mcs” above, that is pointing to a “MultiClusterService” resource, which is again a custom resource that will work only in the context of a GKE project. A definition for such a resource, looks almost like a Service and here is the one for “sample-caller-mcs”

apiVersion: networking.gke.io/v1
kind: MultiClusterService
metadata:
  name: sample-caller-mcs
  namespace: istio-apps
spec:
  template:
    spec:
      selector:
        app: sample-caller
        version: v1
      ports:
        - name: web
          protocol: TCP
          port: 8080
          targetPort: 8080

Now that there is a MultiClusterIngress defined pointing to a MultiClusterService, what all happens under the covers:

1. A load balancer is created which uses an ip advertised using anycast – better details are here. These anycast ip’s help get the request through to the cluster closest to the user.

2. A Network Endpoint Group(NEG) is created for every cluster that matches the definition of MultiClusterService. These NEG’s are used as the backend of the loadbalancer.

Sample Application

I have a sample set of applications and deployment manifests available here that demonstrates Multi-Cluster Ingress. There are instructions to go with it here. This brings up an environment which looks like this:

Now to simulate a request coming in from us-west1-a is easy for me since I am in US, another approach is to simply spin up an instance in us-west1-a and use that to make a request the following way:

gcloud compute instances create us-west1-a-instance \
 --zone=us-west1-a --machine-type=e2-micro  \
 --create-disk=image=projects/debian-cloud/global/images/debian-10-buster-v20211209,mode=rw

gcloud compute ssh us-west1-a-instance --zone=us-west1-a

## From the instance..
curl 'http://ANYCAST_IP/caller/messages' \
  -H 'Content-Type: application/json' \
  -H 'Accept: */*' \
  --data-raw '{"payload":"dummy payload","delay":"100","responseCode":200}'

And the “caller” invoked should be the one in us-west1-a, similarly if the request is made from an instance in europe-north1-a:

gcloud compute instances create europe-north1-a-instance \
 --zone=europe-north1-a --machine-type=e2-micro  \
 --create-disk=image=projects/debian-cloud/global/images/debian-10-buster-v20211209,mode=rw

gcloud compute ssh europe-north1-a-instance --zone=europe-north1-a


curl 'http://ANYCAST_OP/caller/messages' \
  -H 'Content-Type: application/json' \
  -H 'Accept: */*' \
  --data-raw '{"payload":"dummy payload","delay":"100","responseCode":200}'

The “caller” invoked will be the one in europe-north1-a!!

Conclusion

This really boggles my mind, being able to spin up two clusters on two different continents, and having a request from the user directed to the one closest to them, in a fairly simple way. There is a lot going on under the covers, however this is abstracted out using the resource types of MultiClusterIngress and MultiClusterService. 

Published on Java Code Geeks with permission by Biju Kunjummen, partner at our JCG program. See the original article here: Service to Service Call Pattern – Multi-Cluster Ingress

Opinions expressed by Java Code Geeks contributors are their own.

Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Inline Feedbacks
View all comments
Back to top button