Deploy a Multicluster Ingress on Google Kubernetes Engine

In the previous part of this tutorial for Federated Kubernetes, we have configured a geographically distributed Kubernetes cluster through federation. Now, we will deploy an application in the federated cluster, and expose it via a global ingress endpoint.
While the federated control plane orchestrates the deployments across clusters, we need to configure an ingress that can route the traffic to the nearest cluster based on user’s location. In case one of the clusters suffers from an outage, the ingress must be intelligent enough to route the request to another cluster that’s healthy.
On the Google Kubernetes Engine (GKE), the global ingress is configured as an HTTP load balancer that talks to the backend NodePort on each cluster.
The Google Cloud Platform (GCP) load balancing provides global load balancing for HTTP(S) requests. Customers can configure URL rules that route some requests to one set of instances and route other to other instances. Requests are always routed to the instance group that is closest to the user, provided that group has enough capacity and is appropriate for the request. If the closest group does not have enough capacity, the request is sent to the closest group that does have the capacity.
Google took advantage of the features exclusively available in GCP load balancer. Even though it is not natively integrated with gcloud SDK — the official command line interface for GCP — Google’s engineers published kubemci, the tool that can do global, multi-cluster load balancing.
Once you have kubemci downloaded to your Mac or Linux box, you are ready to deploy and expose the application.
Since kubemci needs application credentials to access GCP resources, we will run the below command.
1 |
$ gcloud auth application-default login |
Application Default Credentials (ADC) provide a method to get credentials used in calling Google APIs. The gcloud auth application-default command group allows you to manage active credentials on your machine that are used for local application development.
We also need to pass each cluster configuration to kubemci. For this, we will create a new configuration file with the credentials. This will act as the custom kubeconfig file exclusively used by the tool.
1 2 3 4 5 |
$ KUBECONFIG=$HOME/mcikubeconfig gcloud container clusters get-credentials asia --zone asia-southeast1-a --project janakiramm-sandbox $ KUBECONFIG=$HOME/mcikubeconfig gcloud container clusters get-credentials europe --zone europe-west2-a --project janakiramm-sandbox $ KUBECONFIG=$HOME/mcikubeconfig gcloud container clusters get-credentials america --zone us-central1-a --project janakiramm-sandbox |
Don’t forget to replace the project id with your GCP project id.
We will also create a static IP address for our global ingress.
1 |
$ gcloud compute addresses create g-ingress --global |
The basic configuration is done, and we are ready to deploy and expose the workload.
Google’s engineers have built a nice application that prints the details of the zone where it is being served. We will deploy this sample application in our federated cluster.
Create a file called zone-printer.yaml with the following markup:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
apiVersion: extensions/v1beta1 kind: Deployment metadata: name: zoneprinter labels: app: zoneprinter spec: replicas: 6 selector: matchLabels: app: zoneprinter template: metadata: labels: app: zoneprinter spec: containers: - name: frontend image: gcr.io/google-samples/zone-printer:0.1 ports: - containerPort: 80 --- apiVersion: v1 kind: Service metadata: name: zoneprinter labels: app: zoneprinter spec: type: NodePort selector: app: zoneprinter ports: - name: http port: 80 nodePort: 30061 |
This creates a deployment with six replicas and also exposes that through a NodePort service.
Let’s go ahead and submit this to the federated control plane.
1 |
$ kubectl --context=global-context create -f zone-printer.yaml |
This simple command kicks off an orchestration that pushes the deployment into each registered cluster. Since we asked for six replicas, each cluster runs two pods.
You can verify it by checking the control plane followed by each cluster.
1 |
$ kubectl --context=global-context get deploy |
The global federated control plane reports 6 pods – 2 pods in each cluster.
Let’s switch the context to each of the clusters.
1 |
$ kubectl --context=asia-context get deploy |
1 |
$ kubectl --context=europe-context get deploy |
1 |
$ kubectl --context=america-context get deploy |
It’s the same case with the service. The below screenshot shows that each cluster has a NodePort assigned to the zoneprinter service.
Now, it’s time to create the ingress object. First, we will define the ingress, and then submit it via the kubemci tool. Note that kubemci is independent of the federated cluster concept. It can be used with multiple standalone clusters that are not federated. I am demonstrating how these two can be combined for exposing federated workloads.
1 2 3 4 5 6 7 8 9 10 11 |
apiVersion: extensions/v1beta1 kind: Ingress metadata: name: zoneprinter annotations: kubernetes.io/ingress.class: gce-multi-cluster kubernetes.io/ingress.global-static-ip-name: g-ingress spec: backend: serviceName: zoneprinter servicePort: 80 |
The ingress definition has an annotation that associates the object with the static IP address we created earlier. The annotation, gce-multi-cluster is a hint to GKE to provision a global HTTP(S) load balancer.
Run the below command to create the ingress object.
1 2 3 4 |
$ kubemci create zone-ingress \ --ingress=zone-ingress.yaml \ --gcp-project=janakiramm-sandbox \ --kubeconfig=$HOME/mcikubeconfig |
This single step results in a series of configuration tasks involving the creation of load balancers, firewall rules, health checks, and proxies.
Keep checking the GCP Console for the health status. Once all the clusters are registered with the ingress, it should show all the clusters as healthy. Wait till you see 3/3 in the Healthy column of Backend services section. It typically takes a few minutes for the health check to pass.
It’s time for the final test. To verify the geo-routing feature, I am using Opera browser with VPN enabled. You can choose the location of the VPN to emulate the traffic originated from a different place.
Depending on your VPN location, you will end up seeing a different output in the browser. The flag and the location indicate the GKE zone serving the request.
Kubernetes is slowly but steadily becoming the preferred choice for running highly-available and distributed workloads. Features such as federated clusters and global ingress bring additional capabilities to the platform. Combined with globally-distributed, and strongly consistent database services such as Google Cloud Spanner, it is now possible to run applications that are deployed across the globe.