Cloud Native 16 min read

Deploying Istio Multi-Cluster Service Mesh with Multi-Control-Plane Topology

This guide explains how to set up Istio across multiple Kubernetes clusters using a multi‑control‑plane topology, covering CA secret creation, control‑plane installation, DNS configuration, sample application deployment, ServiceEntry and DestinationRule creation, and cross‑cluster traffic routing verification.

Alibaba Cloud Native
Alibaba Cloud Native
Alibaba Cloud Native
Deploying Istio Multi-Cluster Service Mesh with Multi-Control-Plane Topology

Overview

Istio can manage services across multiple Kubernetes clusters without a shared network by using a shared root CA, ServiceEntry resources, and a multi‑control‑plane topology (one Istio control plane per cluster). Traffic between clusters is secured with mutual TLS and appears as a single logical mesh.

Deploy an Istio control plane in each cluster

Create the istio-system namespace and a secret with the sample CA certificates.

Install Istio CRDs and wait for the API server to accept them.

Generate and apply the Istio control‑plane manifest using the values-istio-multicluster-gateways.yaml values file.

kubectl create namespace istio-system
kubectl create secret generic cacerts -n istio-system \
  --from-file=samples/certs/ca-cert.pem \
  --from-file=samples/certs/ca-key.pem \
  --from-file=samples/certs/root-cert.pem \
  --from-file=samples/certs/cert-chain.pem

for i in install/kubernetes/helm/istio-init/files/crd*.yaml; do
  kubectl apply -f $i
done

helm template install/kubernetes/helm/istio \
  --name istio --namespace istio-system \
  -f install/kubernetes/helm/istio/values-istio-multicluster-gateways.yaml > istio.yaml
kubectl apply -f istio.yaml

Run these steps on every cluster; the Helm command only needs to be executed once to produce the manifest.

Configure DNS for cross‑cluster service names

Remote services are addressed with the <name>.<namespace>.global suffix. Istio provides a CoreDNS server that resolves the .global domain.

For clusters using kube-dns, apply a ConfigMap that forwards .global queries to the Istio CoreDNS service:

apiVersion: v1
kind: ConfigMap
metadata:
  name: kube-dns
  namespace: kube-system
data:
  stubDomains: |
    {"global": ["$(kubectl get svc -n istio-system istiocoredns -o jsonpath={.spec.clusterIP})"]}

For clusters that already run CoreDNS, update the Corefile to add a .global server:

apiVersion: v1
kind: ConfigMap
metadata:
  name: coredns
  namespace: kube-system
data:
  Corefile: |
    .:53 {
        errors
        health
        kubernetes cluster.local in-addr.arpa ip6.arpa {
            pods insecure
            upstream
            fallthrough in-addr.arpa ip6.arpa
        }
        prometheus :9153
        proxy . /etc/resolv.conf
        cache 30
        reload
        loadbalance
    }
    global:53 {
        errors
        cache 30
        proxy . $(kubectl get svc -n istio-system istiocoredns -o jsonpath={.spec.clusterIP})
    }

Deploy sample applications

In cluster 1 deploy the sleep demo app:

kubectl create namespace app1
kubectl label namespace app1 istio-injection=enabled
kubectl apply -n app1 -f samples/sleep/sleep.yaml
export SLEEP_POD=$(kubectl get -n app1 pod -l app=sleep -o jsonpath={.items..metadata.name})

In cluster 2 deploy the httpbin demo app:

kubectl create namespace app2
kubectl label namespace app2 istio-injection=enabled
kubectl apply -n app2 -f samples/httpbin/httpbin.yaml

Obtain the ingress‑gateway address of cluster 2:

export CLUSTER2_GW_ADDR=$(kubectl get svc --selector=app=istio-ingressgateway -n istio-system -o jsonpath="{.items[0].status.loadBalancer.ingress[0].ip}")

Create a ServiceEntry for the remote service

In cluster 1, expose httpbin.app2.global via a ServiceEntry that points to the ingress gateway of cluster 2:

apiVersion: networking.istio.io/v1alpha3
kind: ServiceEntry
metadata:
  name: httpbin-app2
spec:
  hosts:
  - httpbin.app2.global
  location: MESH_INTERNAL
  ports:
  - name: http1
    number: 8000
    protocol: http
  resolution: DNS
  addresses:
  - 127.255.0.2
  endpoints:
  - address: ${CLUSTER2_GW_ADDR}
    ports:
      http1: 15443

Verify connectivity from the sleep pod:

kubectl exec $SLEEP_POD -n app1 -c sleep -- curl httpbin.app2.global:8000/headers

Cross‑cluster version routing example

Deploy three versions of a helloworld service: v1 in cluster 1, v2 and v3 in cluster 2.

# Cluster 1 – v1
kubectl create namespace hello
kubectl label namespace hello istio-injection=enabled
kubectl apply -n hello -f samples/helloworld/service.yaml
kubectl apply -n hello -f samples/helloworld/helloworld.yaml -l version=v1

# Cluster 2 – v2 and v3
kubectl create namespace hello
kubectl label namespace hello istio-injection=enabled
kubectl apply -n hello -f samples/helloworld/service.yaml
kubectl apply -n hello -f samples/helloworld/helloworld.yaml -l version=v2
kubectl apply -n hello -f samples/helloworld/helloworld.yaml -l version=v3

Create a ServiceEntry and a DestinationRule in cluster 1 that reference the remote .global host:

apiVersion: networking.istio.io/v1alpha3
kind: ServiceEntry
metadata:
  name: helloworld
spec:
  hosts:
  - helloworld.hello.global
  location: MESH_INTERNAL
  ports:
  - name: http1
    number: 5000
    protocol: http
  resolution: DNS
  addresses:
  - 127.255.0.8
  endpoints:
  - address: ${CLUSTER2_GW_ADDR}
    ports:
      http1: 15443
---
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: helloworld-global
spec:
  host: helloworld.hello.global
  trafficPolicy:
    tls:
      mode: ISTIO_MUTUAL
  subsets:
  - name: v2
    labels:
      version: v2
  - name: v3
    labels:
      version: v3

Create local DestinationRules for each cluster’s subsets:

# Cluster 1 – v1
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: helloworld
spec:
  host: helloworld.hello.svc.cluster.local
  trafficPolicy:
    tls:
      mode: ISTIO_MUTUAL
  subsets:
  - name: v1
    labels:
      version: v1
---
# Cluster 2 – v2 & v3
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: helloworld
spec:
  host: helloworld.hello.svc.cluster.local
  trafficPolicy:
    tls:
      mode: ISTIO_MUTUAL
  subsets:
  - name: v2
    labels:
      version: v2
  - name: v3
    labels:
      version: v3

Define a VirtualService that routes 70 % of traffic from user jason to v2, 30 % to v3, and all other traffic to the local v1 version:

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: helloworld
spec:
  hosts:
  - helloworld.hello.svc.cluster.local
  - helloworld.hello.global
  http:
  - match:
    - headers:
        end-user:
          exact: jason
    route:
    - destination:
        host: helloworld.hello.global
        subset: v2
      weight: 70
    - destination:
        host: helloworld.hello.global
        subset: v3
      weight: 30
  - route:
    - destination:
        host: helloworld.hello.svc.cluster.local
        subset: v1

Repeated calls from the jason user show the expected 70/30 split, confirming that traffic routing works identically in a multi‑control‑plane mesh as in a single‑cluster deployment.

Conclusion

The multi‑control‑plane topology is the simplest way to build a multi‑cluster Istio mesh because it imposes no special network requirements. All Istio routing resources—ServiceEntry, DestinationRule, VirtualService—operate the same way across clusters, enabling seamless traffic management in multi‑region environments.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

Cloud NativeKubernetestraffic routingMulti-ClusterIstio
Alibaba Cloud Native
Written by

Alibaba Cloud Native

We publish cloud-native tech news, curate in-depth content, host regular events and live streams, and share Alibaba product and user case studies. Join us to explore and share the cloud-native insights you need.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.