How to Set Up Cross-Cluster Communication in Kubernetes

Updated: January 30, 2024 By: Guest Contributor Post a comment

Introduction

In today’s modern application architectures, the need to scale and become more resilient often leads developers and system administrators to Kubernetes, a powerful orchestration tool. As your microservices spread over multiple clusters, it becomes essential to set up cross-cluster communication effectively. In this tutorial, we will walk through how to establish cross-cluster communication in Kubernetes.

Understanding the Basics

Before diving into cross-cluster communication, it is crucial to understand the components involved:

  • Kubernetes Cluster: A set of nodes that run containerized applications managed by Kubernetes.
  • Cluster API Server: The control plane’s API server acts as the front end for the Kubernetes control plane.
  • Service: An abstract way to expose an application running on a set of Pods as a network service.
  • Ingress: An API object that manages external access to the services in a cluster, typically HTTP.
  • Network Policies: Specifications of how groups of pods can communicate with each other and other network endpoints.

To enable communication between clusters, the API servers of both clusters must be discoverable and reachable from each other.

Prerequisites

  • Multiple Kubernetes clusters set up and running.
  • kubectl configured to communicate with each cluster.
  • Ability to create or modify DNS and firewall configurations.
  • Basic understanding of Kubernetes objects such as services, ingress, and network policies.

Step-by-Step Cross-Cluster Communication

Step 1: Access Configuration

Make sure you have access to both clusters by using the respective kubeconfig files. Check your current context to ensure you’re operating in the correct cluster:

kubectl config current-context

Output:

your-first-cluster-context

This output indicates that you are working with ‘your-first-cluster-context’. Switch between contexts using:

kubectl config use-context your-second-cluster-context

Step 2: Set Up the API Server Connectivity

Ensure the API Server of each cluster is reachable from the other cluster. Implementing a secure network connection typically involves establishing a VPN or using a technology like Submariner.

Example:

# Install Submariner on Cluster A
subctl join --kubeconfig /path/to/kubeconfig/a broker-info.subm --clusterid cluster-a

Repeat the process for the second cluster:

# Install Submariner on Cluster B
subctl join --kubeconfig /path/to/kubeconfig/b broker-info.subm --clusterid cluster-b

Check the connectivity using:

subctl show connections

Output:

GATEWAY                 CLUSTER                 REMOTE IP       CABLE DRIVER        SUBNETS                                STATUS
cluster-a-gw            cluster-b               192.168.1.2     libreswan           10.2.0.0/16, 10.3.0.0/16              connected
cluster-b-gw            cluster-a               192.168.1.1     libreswan           10.1.0.0/16, 10.0.0.0/16              connected

Step 3: Export and Import Services

After establishing the network connection, you need to make the services from one cluster available to the other using a ServiceExport resource. Let’s assume you have a Service named ‘my-service’ in ‘namespace-a’ of ‘cluster-a’ that you want to access from ‘cluster-b’.

# On cluster-a
kubectl -n namespace-a create serviceexport my-service

Once the ServiceExport is created, the service can be consumed in ‘cluster-b’ as follows:

# On cluster-b
kubectl -n namespace-a create serviceimport my-service

Now, ‘my-service’ can be accessed using the same service DNS name from ‘cluster-b’, just as you would within ‘cluster-a’.

Note: Some implementations may not require serviceimport to be manually created as it can be auto-populated based on the serviceexport from the exporting cluster.

Step 4: DNS and Firewall Configuration

Ensure the DNS is configured so that the service names can be resolved across clusters. You may need to set up a CoreDNS or similar DNS operator. Also, configure firewalls or network policies to allow traffic between the services exported and imported.

Assuming CoreDNS is set up and network policies need to be configured:

# Example of a network policy to allow traffic for 'namespace-a' (adjust as per your network setup)
kubectl apply -f - <<EOF
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-namespace-a-cross-cluster
  namespace: namespace-a
spec:
  podSelector: {}
  ingress:
    - from:
      - namespaceSelector:
          matchLabels:
            name: namespace-a
EOF

Step 5: Test the Cross-Cluster Service Communication

Deploy a test Pod in ‘cluster-b’ and try to access ‘my-service’ from ‘cluster-a’.

kubectl run test-pod --rm -it --image=busybox -- /bin/sh

From the interactive shell of ‘test-pod’, try to query ‘my-service’:

# Replace 'my-service' and 'namespace-a' with your service's name and namespace
nslookup my-service.namespace-a.svc.clusterset.local

If DNS resolves and your network policies are correctly configured, you will see the IP address of ‘my-service’ from ‘cluster-a’.

Conclusion

The ability to communicate between Kubernetes clusters is imperative for modern cloud-native architectures. By following the steps in this tutorial, you can achieve seamless service discovery and communication across your Kubernetes clusters, allowing for scalable and robust systems that can handle inter-cluster dependencies.