Cross-Cluster Service Discovery in Kubernetes
A complete, plain-English guide to helping services in one Kubernetes cluster find, trust and reliably call services in another — covering naming, networking, identity, failover and the real-world trade-offs of every major approach.
Imagine a company with offices in several cities. Inside each office, finding a colleague is easy: there is a directory on the wall, everyone knows the building, and the reception desk connects you in seconds. Now imagine you need to call someone in the office in another country. The local directory has no entry for them, the phone system does not know the route, you are not sure the person on the other end is really who they claim to be, and you are not sure which office to call if one of them is closed for a holiday.
Kubernetes clusters are exactly like those offices. Inside one cluster, services find each other effortlessly through built-in naming and routing. The moment a service needs a partner that lives in a different cluster, almost everything that made life easy stops working. In this guide you will learn why that happens, what the building blocks of a solution look like, how the major approaches work and differ, and how to choose and operate one without turning your platform into a tangle of fragile special cases.
1Why One Cluster Is Often Not Enough
Teams rarely plan to run many clusters. They end up there because good reasons keep appearing.
The pull toward many clusters
A single Kubernetes cluster can be very large, yet most organisations eventually run several. The reasons are practical rather than fashionable. A failure in one cluster, such as a bad upgrade or a broken network plugin, can affect every workload inside it. Splitting workloads across clusters limits how far such a failure can spread, which engineers call reducing the blast radius.
Other reasons are about geography and rules. Users in different continents want answers from nearby servers. Laws about where data may be stored can require separate clusters in separate countries. Different teams or customers may need strong separation. And sometimes there is no choice at all: a company that acquires another business inherits a second set of clusters, perhaps on a different cloud.
Failure isolation
A broken upgrade, runaway workload or misconfiguration stays inside one cluster instead of taking everything down.
Low latency for users
Running clusters in several regions places services physically close to the people who use them.
Data residency and compliance
Rules about where data lives often demand a dedicated cluster in a particular country or environment.
Scale and team boundaries
Very large estates are easier to manage as several clusters, each owned by a team or business unit.
High availability and disaster recovery
A second cluster in another region can keep serving when an entire region has trouble.
Hybrid, multi-cloud and migration
Moving from one platform to another, or mixing on-premises and cloud, naturally creates more than one cluster.
Think of a shopping chain that opens branches in several towns instead of building one enormous store. If a pipe bursts in one branch, the others keep trading. Customers visit the closest branch. Local rules are easy to follow. But the chain now needs a way for branches to share stock information, which is the problem cross-cluster service discovery solves.
The price of splitting
Splitting into clusters buys isolation and flexibility, and it also creates a new problem. Services that used to sit side by side are now in different clusters, often in different networks, sometimes in different countries. They still need to call each other, and the call should feel as simple and safe as it did before the split.
“Kubernetes can already do multi-cluster.” Kubernetes manages each cluster very well but, on its own, treats clusters as separate worlds. Names, addresses and routing built into one cluster do not automatically extend to another. Extra pieces are needed, and this guide explains which ones.
Scenario: the checkout that needed a remote partner
A retailer runs a cluster in Europe and another in North America. The European checkout service needs to call a stock service that lives only in the American cluster. Without cross-cluster discovery, engineers hard-code an address, which breaks every time the remote service moves, and nobody is sure whether the connection is even encrypted.
2How Service Discovery Works Inside One Cluster
To see what breaks across clusters, first see how smoothly it works inside one.
Pods come and go, so addresses cannot be trusted
Pods are temporary. They are created, destroyed and rescheduled all the time, and each new pod receives a new address. If one service called another by pod address, it would break every few minutes. Kubernetes solves this with an object called a Service, which gives a group of pods one stable name and one stable virtual address, no matter how often the pods behind it change.
Think of a restaurant’s main phone number. The kitchen staff change shifts constantly, yet customers always dial the same number and someone answers. A Kubernetes Service is that main number for a group of pods.
The four pieces that make it work
The Service object
Declares a name, a selector for matching pods and a stable virtual address, often called the cluster IP.
EndpointSlices
Keep a constantly updated list of the real pod addresses that currently back each Service, including whether each one is ready.
Cluster DNS
A name server, usually CoreDNS, that turns names like a service name plus namespace into the Service’s virtual address.
Node-level routing
Each node, through a component such as kube-proxy or an eBPF data path, spreads traffic sent to the virtual address across the real pods.
sequenceDiagram
participant C as Client pod
participant D as Cluster DNS
participant N as Node routing
participant P as Backend pod
C->>D: Look up orders.shop.svc.cluster.local
D-->>C: Stable service address
C->>N: Send request to service address
N->>P: Forward to a ready backend pod
P-->>C: Response
The sequence shows the full journey. The client asks DNS for a name, receives a stable address, and sends traffic to it. The node quietly swaps the stable address for a real, healthy pod. The client never needs to know which pod answered or even how many pods exist.
The naming convention
A Service is reachable by a predictable name made of the service name, its namespace and the cluster’s domain, which is by default a fixed suffix shared by all clusters. A short name works inside the same namespace, and the longer form works from anywhere inside the cluster. Notice the important detail: the default suffix is identical in every cluster. That is convenient for portability and, as you will see, a source of confusion when clusters meet.
| Name form | Works from | Resolves to |
|---|---|---|
| Service name only | Pods in the same namespace | The Service in that namespace |
| Service name plus namespace | Any pod in the cluster | The Service in the named namespace |
| Fully qualified name with the cluster suffix | Any pod in the cluster | The same Service, with no search-path guessing |
| Headless service name | Any pod in the cluster | The individual pod addresses instead of one virtual address |
The virtual address, the DNS records, the endpoint lists and the node routing all live inside one cluster. None of them is visible or reachable from outside it. Keep this sentence in mind, because it explains almost every cross-cluster difficulty.
3What Breaks at the Cluster Boundary
Four separate things fail when a call crosses clusters. Each needs its own answer.
Problem one: naming
The DNS server in cluster A knows only about the Services in cluster A. Ask it for a service that lives in cluster B and the answer is “no such name.” Even worse, if both clusters happen to have a Service with the same name in the same namespace, the name in each cluster points only to its own copy, so a client cannot say “I want the one in the other cluster.”
Problem two: connectivity
Even if a client somehow knew the other cluster’s virtual address, that address is not routable from outside. The virtual address exists only as a rule on the nodes of its own cluster. And the real pod addresses are often private, may be hidden behind separate networks, and may even overlap with the first cluster’s addresses, making the destination ambiguous.
Problem three: identity and trust
Inside a cluster, teams often rely on network policies and a service mesh to know who is calling whom. Across clusters, the caller and callee do not share the same certificate authority, the same account system or the same policy engine. A caller needs to be sure the remote service is genuine, and the remote service needs to be sure the caller is allowed.
Problem four: traffic policy
Inside one cluster, spreading traffic across pods is straightforward. Across clusters, new questions arise. Should calls prefer the local cluster and use the remote one only if the local one fails? What if the remote cluster is far away and slow? How quickly should traffic move when a cluster becomes unhealthy, and how can we avoid overwhelming the survivors?
| Problem | Symptom | Answer needed |
|---|---|---|
| Naming | The remote service name does not resolve | A way to publish and look up names across clusters |
| Connectivity | The name resolves but connections time out | A network path, such as routing, tunnels or gateways |
| Identity | Connections are refused or cannot be trusted | Shared trust and authentication between clusters |
| Traffic policy | Slow calls, no failover, or overloaded clusters | Locality, failover and weighting rules |
Calling a colleague in another country requires four things: you need their number, the phone network must connect the two countries, you need to be sure it is really them, and you need a plan for who to call if they are away. Missing any one of the four makes the call fail, even if the other three are perfect.
A common mistake is to make the name resolve and consider the job done. Then the first real call times out, or goes through unencrypted, or lands on a far-away cluster at the worst moment. A good solution addresses all four problems together.
Example: the half-solved integration
A team forwards DNS lookups for a remote domain to the other cluster’s DNS server. Names resolve, but the answers are virtual addresses that mean nothing outside that cluster, so every call hangs. The naming problem was solved while the connectivity problem was ignored.
4The Building Blocks of Any Solution
Every approach in this guide is a different combination of the same few layers.
flowchart TD
A["Application calls a service name"] --> B["Discovery: turn the name into healthy remote endpoints"]
B --> C["Traffic policy: choose local, remote or weighted targets"]
C --> D["Identity: authenticate both sides and encrypt"]
D --> E["Connectivity: carry packets across the network boundary"]
E --> F["Remote service responds"]
G["Observability: metrics, traces and logs across clusters"] -.-> B
G -.-> E
Reading from the top, the application simply uses a service name. Discovery finds the real destinations, policy chooses which to use, identity makes the connection trustworthy, and connectivity moves the bytes. Observability watches all of it. Different products bundle these layers differently, but none can skip a layer.
Discovery
Knowing which services exist in which clusters and which of their endpoints are healthy right now.
Connectivity
A working network path between clusters: direct routing, encrypted tunnels or gateways at the edge of each cluster.
Identity and security
Certificates, trust anchors and policies so that each side can verify the other and encrypt the traffic.
Traffic management
Rules for preferring nearby endpoints, failing over, shifting weights and handling overload.
Observability
Metrics, logs and traces that carry cluster labels, so problems can be located in the right place.
Operations and governance
Processes for adding clusters, rotating credentials, upgrading and deciding who may export which service.
Think of international shipping. Discovery is the catalogue showing which warehouse holds the item. Connectivity is the shipping route. Identity is customs checking the paperwork. Traffic management is choosing between the nearest warehouse and a distant one. Observability is the tracking number. A parcel needs all of them to arrive.
Two big design questions you will answer early
Flat model: clusters share one address space
- Pods can reach each other directly, with no translation
- Lower latency and simpler packet paths
- Works naturally with per-pod identity and headless services
- Needs careful, non-overlapping address planning in advance
Gateway model: clusters are reached through edge gateways
- Works even when address ranges overlap or networks are separate
- Only the gateways must be reachable, which shrinks the exposed surface
- Adds a hop and a component that must be scaled and protected
- Hides individual pods, which limits some stateful patterns
The choice between a flat model and a gateway model shapes everything else. Make it early, based on your address plan, your security rules and the network between your clusters, and then choose discovery and mesh tools that fit it.
5Network Foundations: Address Plans, Latency and Cost
Most cross-cluster pain starts with decisions made on the first day a cluster is created.
Plan the address ranges before you need them
Every cluster uses address ranges for its pods and for its Service virtual addresses. Many installers choose the same default ranges, so two clusters built from the same template often have identical ranges. If you ever want direct routing between them, overlapping ranges make it impossible to say which cluster a given address belongs to. Fixing this later usually means rebuilding a cluster, which is painful and risky.
Reserve one large block for all clusters
Allocate a planned address block for the whole organisation, and carve unique slices for each cluster’s pods and Services.
Keep ranges away from other networks
Avoid ranges used by on-premises networks, partner networks and virtual private networks that clusters may need to reach.
Leave room to grow
Choose slices larger than today’s needs, since clusters grow and new clusters will appear.
Record it in a registry
Keep a single, shared list of who owns which range, and make cluster creation check it automatically.
Think of two towns that both number their houses starting from one on every street. Inside each town the numbers work. The moment a postal service tries to deliver between them, “12 Oak Street” could be in either town. Giving every town its own range of numbers from the start avoids the confusion.
If ranges already overlap
Sometimes you inherit overlapping clusters. There are still workable options. A gateway model avoids exposing pod addresses at all, so overlap does not matter. Some tools offer address translation, which gives each cluster a second, unique set of virtual addresses used only for cross-cluster traffic. Both approaches cost some complexity and hide the real addresses, so they are better treated as bridges than as the ideal design.
Three physical facts that policy cannot change
Distance means delay
A call within one data centre takes a fraction of a millisecond. A call between regions can take tens or even hundreds of milliseconds, and a chain of such calls adds up quickly.
Data transfer costs money
Cloud providers usually charge for traffic between zones and regions, and more for traffic leaving a provider. Chatty cross-cluster calls can create surprising bills.
Tunnels shrink packets
Encrypted tunnels add header bytes, reducing the largest packet that fits. If the size setting is not adjusted, large packets can silently disappear, causing strange stalls.
Links can break
The network between clusters is less reliable than the one inside a data centre. Every cross-cluster design must assume it will occasionally fail.
| Connectivity option | How it works | Good when | Watch out for |
|---|---|---|---|
| Private network peering | Cloud networks are linked so that pod and node addresses route directly | Clusters share a provider and have unique ranges | Limits on peering scale and transitive routing |
| Encrypted tunnels between clusters | Gateways or nodes build secure tunnels across any network | Clusters sit on different networks or providers | Packet size limits and gateway capacity |
| Dedicated private links | Leased or provider-managed circuits between sites | Hybrid setups with heavy, steady traffic | Cost and lead time to set up |
| Public gateways with strong authentication | Services are exposed through load balancers with mutual authentication | No private path exists or is wanted | Larger attack surface and internet-level latency |
A request that makes five sequential calls, each crossing a region boundary with eighty milliseconds of delay, spends most of half a second just travelling. Keep tightly coupled services in the same cluster, and use cross-cluster calls for loosely coupled, less frequent interactions.
6Approach One: Stitching DNS and Aliases by Hand
The simplest approach uses only what Kubernetes already has. It works for small cases and teaches useful lessons.
Forwarding DNS to the other cluster
The built-in cluster DNS can be told to send questions for a chosen domain to a different DNS server. If cluster A forwards a special domain, such as one named after cluster B, to the DNS server of cluster B, then a pod in A can look up names that only B knows. This is often called a stub domain or conditional forwarding, and it needs no extra software beyond a small change to the DNS configuration.
There is a catch. The DNS server in the other cluster must be reachable from this cluster, which usually means exposing it through an internal load balancer. And the answers it gives are the other cluster’s virtual addresses, which are only useful if the network can actually route to them. In a flat network where Service ranges are unique and routed, this can work. In most setups it does not, because virtual addresses are deliberately cluster-local.
Think of an office switchboard that says “for anything starting with the Paris prefix, ask the Paris switchboard.” You can now look up Parisian extensions, but you still need a phone line to Paris to actually call them. Forwarding DNS gives you the directory, not the line.
Headless services and direct pod addresses
A headless Service, which has no virtual address, returns the real pod addresses from DNS. If those pod addresses are routable between clusters, a forwarded lookup returns something callable. This is why flat networks with unique pod ranges pair so naturally with this style. The cost is that the client sees every pod, must handle changes itself and loses the load spreading that the virtual address normally provides.
The ExternalName alias
Kubernetes also offers a Service type called ExternalName. It does not proxy anything. It simply tells DNS to answer with an alias pointing at another name. A team can create a local Service called “stock” that aliases a name published by another cluster, for example the address of a load balancer in front of the remote service. Applications keep using the short local name, and the alias can be repointed centrally. This is a tidy way to hide the remote location behind a stable local name.
| Technique | What it solves | What it leaves unsolved |
|---|---|---|
| DNS forwarding to the other cluster | Names from the other cluster resolve | Routing to virtual addresses, identity, failover |
| Headless services across routed networks | Direct pod-to-pod calls with unique pod addresses | Load spreading, health-aware failover, identity |
| ExternalName alias to a remote load balancer | A stable local name for a remote endpoint | Health checks beyond the load balancer, per-pod identity |
Advantages
- Nothing new to install; uses standard Kubernetes parts
- Easy to understand and to explain to a new team
- Fine for a handful of services between two clusters
- Good stepping stone while a bigger solution is chosen
Disadvantages
- Manual configuration that drifts and is hard to audit
- No built-in health-aware failover between clusters
- No shared identity, so security must be added separately
- Becomes unmanageable beyond a few clusters or services
Every new cluster multiplies the forwarding rules, aliases and exceptions. If you find yourself maintaining a spreadsheet of which cluster forwards which domain, it is time for a more systematic approach.
7Approach Two: Public or Private Gateways with Global DNS
Treat each cluster as a separate site that publishes services through normal front doors.
A very common design avoids special cluster-to-cluster plumbing. Each cluster exposes the services it wants to share through an ingress controller or a gateway behind a load balancer, with an ordinary, stable domain name. Other clusters, and outside users, call that name as they would call any web service. A global DNS service, often with health checks and location awareness, can return the address of the nearest healthy cluster.
flowchart TD
A["Client in any region"] --> B["Global DNS with health checks"]
B -->|"Nearest healthy"| C["Regional load balancer in Cluster A"]
B -->|"Failover"| D["Regional load balancer in Cluster B"]
C --> E["Ingress or gateway in Cluster A"]
D --> F["Ingress or gateway in Cluster B"]
E --> G["Service pods in Cluster A"]
F --> H["Service pods in Cluster B"]
The diagram shows the pattern. Global DNS decides which cluster front door a caller receives, based on location and health. Each cluster handles traffic internally with its normal Service routing. Neither cluster needs to know about the other’s pods, which keeps the design simple and robust.
Think of a national customer helpline. You dial one number, and the phone system connects you to the nearest open call centre. If one centre closes, calls flow to another. The callers never learn which building answered, and the call centres do not need direct lines to each other.
Tools that automate the publishing
ExternalDNS
A controller that watches Services, Ingresses and Gateways and creates matching records in a DNS provider automatically, so names stay in step with the cluster.
Provider traffic steering
Cloud and DNS providers offer routing by latency, geography, weight or failover, driven by health checks on the regional endpoints.
Gateway API
The newer Kubernetes routing standard describes gateways and routes in a portable way, and some platforms extend it across clusters.
Internal load balancers
Private load balancers expose services only inside your network, giving the simplicity of this model without public exposure.
What to watch for
| Issue | Why it happens | Mitigation |
|---|---|---|
| Slow failover | DNS answers are cached for the record’s time to live, and some clients cache longer | Use short but sane time-to-live values and clients that re-resolve names |
| Extra hop and cost | Traffic passes through load balancers and may cross provider boundaries | Use internal load balancers and keep traffic within a provider where possible |
| Limited identity | Callers are identified by the front door, not by the original service | Add mutual authentication and signed tokens at the gateway |
| Coarse health | The health check covers the gateway, not every backend behind it | Make checks reflect real dependencies and use deeper checks for critical paths |
If services call each other occasionally and tolerate some delay, gateways with global DNS are easy to run and easy to secure. They struggle only when you need very fast failover, per-pod addressing, or fine-grained service-to-service identity.
8The Multi-Cluster Services API: ServiceExport and ServiceImport
A community standard for the naming and discovery part of the problem, so that every tool can speak the same language.
Why a standard was needed
For years, every multi-cluster product invented its own way to say “this service should be visible elsewhere.” That made tools hard to swap and knowledge hard to reuse. The Kubernetes special interest group for multi-cluster work designed an API to describe it in a common way. It is known as the Multi-Cluster Services API, and it builds on two small objects.
ServiceExport
Created by a service owner in the cluster where the service lives. It means “please make the Service with this same name and namespace available to the other clusters.”
ServiceImport
Created automatically by the implementation in every cluster of the group. It represents the shared service locally, carrying its ports, type and a virtual address for the whole group.
Clusterset
The group of clusters that agree to share services under one set of rules, usually owned by one organisation or team.
Namespace sameness
Within a clusterset, a namespace with the same name in different clusters is treated as the same namespace, so a service name plus namespace identifies one logical service everywhere.
flowchart LR
A["Owner creates ServiceExport in Cluster A"] --> B["Controller notices the export"]
B --> C["ServiceImport appears in Cluster A and Cluster B"]
C --> D["Endpoint information for A is shared with B"]
D --> E["Local DNS answers the clusterset name in each cluster"]
E --> F["Clients in any cluster call one name"]
The flow starts with an owner’s simple declaration and ends with a working name in every cluster. In between, the implementation spreads the endpoint information, creates the import objects and teaches local DNS the new names. The owner never deals with addresses or routes directly.
Think of a company intranet directory. A department head says, “list our helpdesk in the company directory.” Within minutes every office sees one entry called “helpdesk,” no matter which city’s team actually answers the phone. Export is the request, import is the entry that appears in every office, and the clusterset is the company.
The new names
The standard defines a separate DNS domain for shared services, distinct from the local cluster domain. A service exported from the namespace “shop” with the name “orders” becomes reachable at a name made of the service, the namespace and a clusterset suffix. Using a different suffix is deliberate: it lets a client choose between “the local one” and “any one in the group.” Local names keep working exactly as before and are not disturbed.
| Name you use | What it means | Where it is answered |
|---|---|---|
| Service in the local cluster domain | The copy in this cluster only | Local cluster DNS, unchanged |
| Service in the clusterset domain | Any healthy copy in the group of clusters | Local cluster DNS, taught by the implementation |
| Per-pod name for a headless service in the clusterset domain | One specific pod in one specific cluster | Local cluster DNS, for stateful use cases |
A Service is never shared just because it exists. The owner must create a ServiceExport, which makes sharing a deliberate, auditable choice. This is a helpful safety property: sensitive services stay private until someone explicitly publishes them.
9The Multi-Cluster Services API in Practice
The API defines what to say. It does not, by itself, move packets or verify identities.
What it does and does not cover
| Concern | Covered by the API? | Who provides it |
|---|---|---|
| Declaring that a service should be shared | Yes, through ServiceExport | The service owner |
| Representing shared services locally | Yes, through ServiceImport | The implementation |
| Names for shared services | Yes, through the clusterset domain | The implementation, with local DNS |
| Network path between clusters | No | Your network, a tunnel product or a gateway |
| Identity and encryption | No | A service mesh or the network layer |
| Locality, weights and failover policy | Largely no | A mesh, a load balancer or the implementation’s own extensions |
Real implementations
Several projects implement the API or align with it. Managed Kubernetes services from major cloud providers have offered their own versions, and open-source networking projects have added support so that exports and imports work across any cluster they connect. Because the standard is still maturing and its object versions are early-stage, details such as supported features, installation steps and compatibility differ between products and releases. Always read the documentation for the exact versions you plan to run.
Managed cloud implementations
The cloud provider operates the controllers and the network path inside its platform. Easy to adopt, but tied to that provider’s clusters.
Network-layer projects
Tools that connect cluster networks, such as tunnel or mesh projects, add discovery on top so connectivity and naming come together.
Multi-cluster management platforms
Fleet and placement tools can distribute exports and imports as part of managing many clusters from one control point.
Service mesh integrations
Some meshes consume the standard objects or offer equivalent behaviour, combining discovery with identity and traffic policy.
Rules worth knowing
Same name and namespace means one service
If two clusters both export a Service named the same in the same namespace, they are merged into one logical service whose endpoints come from both.
Conflicts need a tie-breaker
If the two copies disagree on things such as ports or type, the standard defines a rule, such as preferring the older export, and reports the conflict in status conditions.
Healthy endpoints only
Only ready endpoints are shared, so a cluster with no healthy pods stops contributing without anyone changing a setting.
Withdrawing is just deleting the export
Removing the ServiceExport takes the service out of the shared pool, which is a convenient, reversible way to drain a cluster.
Namespace sameness only works if teams agree that a namespace and service name mean the same thing everywhere. If one cluster’s “payments” service differs in behaviour from another’s, merging them silently can send customers to the wrong version. Govern names across the clusterset.
Example: draining a cluster for maintenance
A team needs to upgrade one cluster. They delete the ServiceExport for their services there. Within moments, the shared name stops returning that cluster’s pods, and traffic flows to the other clusters. After the upgrade, they recreate the export and the cluster rejoins the pool.
10Approach Three: Connecting the Network Layer Itself
Some projects make several clusters behave as one network, and add service discovery on top.
Cluster mesh at the network plugin level
Some networking plugins can connect the data paths of several clusters directly. A well-known example in this family is Cilium’s Cluster Mesh. Each cluster runs a small service that publishes its state, and the nodes in every cluster read it, so each node learns about the pods and Services of the others. Pods can then reach pods in other clusters directly, provided the address ranges are unique and the nodes can talk to each other.
On top of this, services can be marked as global. A global service gathers the healthy endpoints from every connected cluster behind one name, and an affinity setting tells it whether to prefer local endpoints, prefer remote ones or treat them all equally. Network policies can also refer to the cluster of origin, which lets you write rules such as “only allow this service to be called from the production clusters.”
Think of two neighbouring housing estates that take down the fence between them and share one street map. Residents can walk directly between houses, and the estate rules apply to both. It is friendly and fast, but it works only if the two estates agreed in advance not to reuse the same house numbers.
Tunnel-based connectors
Other projects, such as Submariner, take a different path. They place gateway nodes in each cluster that build encrypted tunnels between clusters, and a route agent steers cross-cluster traffic into the tunnels. A discovery component implements the Multi-Cluster Services API on top, so exports become names that work everywhere. For clusters whose ranges overlap, an optional feature gives each cluster a second set of non-overlapping addresses used only for cross-cluster traffic.
| Aspect | Network plugin mesh | Tunnel-based connector |
|---|---|---|
| Where it lives | Inside the cluster network plugin on every node | Gateway nodes plus route agents added to existing clusters |
| Works with any existing network plugin | No, requires that plugin | Mostly yes, designed to sit alongside others |
| Overlapping address ranges | Not supported for direct routing | Possible with address translation features |
| Traffic path | Direct node-to-node or pod-to-pod | Through gateway nodes and tunnels |
| Network policy across clusters | Can be expressed in the plugin’s own policies | Usually relies on policies in each cluster plus mesh or firewall rules |
| Best fit | Clusters you build together with the same plugin | Existing, heterogeneous clusters you need to connect |
Strengths
- Names, routing and some policy come from one coherent system
- Direct data paths can be fast and efficient
- Good fit for per-pod communication and stateful systems
- Operationally consistent when you control all clusters
Trade-offs
- Ties you to a specific networking plugin or add-on
- Requires careful address planning and inter-cluster reachability
- Adds a control component that must be run and upgraded across clusters
- Policy and identity features differ widely between products
These projects move quickly. Limits such as the maximum number of connected clusters, support for particular cloud networks and the maturity of discovery features change between releases. Verify claims against current documentation before you design around them.
11Approach Four: Service Meshes That Span Clusters
A mesh brings discovery, identity, encryption and traffic rules together, and can extend all of them across clusters.
A service mesh places a small proxy beside every workload, or on every node, to handle calls between services. Because the proxy already knows how to find endpoints, encrypt traffic and apply rules, it is a natural place to solve cross-cluster problems. The main meshes each take a slightly different approach, but the shared idea is the same: make a remote service look like one more destination for the local proxy.
How a mesh learns about remote endpoints
Shared view of every cluster
In one style used by Istio, each cluster’s control plane is given read-only access to the other clusters’ Kubernetes APIs, so it can see all Services and endpoints and program its proxies with them.
Gateways at the cluster edge
When clusters sit on separate networks, special east-west gateways accept traffic from other clusters and forward it to local pods, so pod addresses never need to be routable.
Mirrored services
Linkerd’s multi-cluster feature copies exported services into other clusters as local Services, usually named with the source cluster’s name, and routes calls to them through a gateway or directly.
Mesh gateways and peering
Consul uses mesh gateways and cluster peering to connect separate datacentres or clusters, each keeping its own registry while sharing chosen services.
flowchart LR
subgraph A["Cluster A on Network 1"]
A1["Client pod with proxy"] --> A2["East-west gateway A"]
end
subgraph B["Cluster B on Network 2"]
B2["East-west gateway B"] --> B1["Server pod with proxy"]
end
A2 -->|"Encrypted, mutually authenticated traffic"| B2
C["Shared root of trust"] -.-> A1
C -.-> B1
In the picture, the client’s proxy sends a call to the local gateway, which tunnels it to the remote gateway, which hands it to the server’s proxy. Both ends present certificates issued under one shared root of trust, so each can verify the other. Pod addresses are never exposed across the network boundary.
Think of two embassies in different countries. Visitors do not walk through each other’s streets. They go through the embassy gate, show credentials issued by a recognised authority, and are escorted to the right office inside. Gateways are the embassy gates, and the shared root of trust is the recognised authority.
Comparing the common meshes
| Aspect | Istio | Linkerd | Consul |
|---|---|---|---|
| Cross-cluster discovery | Control planes read remote cluster endpoints, or share through gateways | Exported services are mirrored into other clusters | Each datacentre or cluster has a registry; services are shared by peering or federation |
| Different networks | East-west gateways forward traffic | A gateway, with newer options for direct pod-to-pod traffic on flat networks | Mesh gateways forward traffic |
| Trust model | Shared root with per-cluster intermediate authorities recommended | Shared trust anchor between clusters | Trust domains with federation or peering |
| Traffic policy | Rich locality, failover and weighting controls | Simpler routing with traffic split support | Service resolvers and failover policies |
| Feel | Very flexible, with more to learn | Lean and simple to operate | Strong for mixed Kubernetes and virtual machine estates |
Two Istio shapes you will hear about
Multi-primary
- Every cluster runs its own control plane
- One cluster’s control plane failing does not stop the others
- Each control plane needs access to every cluster’s API
- Preferred for high availability across regions
Primary-remote
- One cluster hosts the control plane for others
- Fewer control planes to run and upgrade
- The primary becomes a dependency for remote clusters
- Suitable for small or edge clusters that should stay light
Giving a control plane access to another cluster’s API means storing credentials for it. If those leak, an attacker can read information about the whole remote cluster. Use narrowly scoped, read-only access, rotate it regularly, and protect where it is stored.
Adding a mesh just for multi-cluster discovery brings sidecars or node proxies, certificates and a new control plane to run. It pays off when you also want identity, encryption and traffic control. If you only need names, a lighter approach may suffice.
12Identity and Trust Across Clusters
Finding a service is useless if you cannot be sure it is the real one, or if it cannot be sure you are allowed in.
Why addresses are poor identity
Inside one data centre, teams sometimes decide who may call a service by looking at the caller’s network address. Across clusters this breaks down. Addresses change, pass through gateways, get translated and may overlap. A rule that says “allow this address range” becomes both fragile and weak. The modern answer is to give every workload a cryptographic identity, usually a short-lived certificate, and to write rules in terms of identities instead of addresses.
Think of a building that lets people in because they come from a certain street. Anyone walking down that street gets in, and people from other streets are refused even if they work there. A staff badge that proves who you are works anywhere. Certificates are the badges, and addresses are the street names.
The pieces of cross-cluster trust
Shared root of trust
All clusters accept certificates that chain back to the same trusted root, so any workload can verify any other.
Per-cluster intermediate authorities
Each cluster issues certificates from its own intermediate authority, so a compromise stays inside one cluster and the root can be kept offline.
Workload identities
Each service gets a name, often following the SPIFFE standard, that encodes its trust domain, namespace and service account.
Mutual TLS
Both sides present certificates and verify each other, and the connection is encrypted end to end.
Authorization policy by identity
Rules such as “only the checkout service account may call the payment service,” enforced wherever the call lands.
Rotation and revocation
Short certificate lifetimes and automated renewal limit the damage of a stolen key.
One trust domain or federated domains
| Model | How it works | Best for |
|---|---|---|
| Single trust domain with a shared root | All clusters trust one root and use the same identity namespace | Clusters owned by one organisation and one platform team |
| Federated trust domains | Each cluster or business unit keeps its own domain and exchanges trust bundles with the others | Separate organisations, acquisitions and strong autonomy needs |
| Gateway-terminated trust | Identity is verified at the gateway, and an internal token continues the journey | Edges between very different environments |
Create the root and keep it safe
Generate the root authority, ideally offline or in a hardware-backed vault, and limit who can use it.
Issue an intermediate for each cluster
Each cluster receives its own signing certificate, so cluster-level compromise does not expose the root.
Automate workload certificates
Let the mesh or identity system issue and renew short-lived certificates without human steps.
Write policy in terms of identity
Express allowed callers as service accounts and namespaces, not addresses, and test the rules across clusters.
Plan rotation of the intermediates
Intermediate certificates expire too. Schedule their renewal well ahead and test the process in a staging environment.
If identities and policies are based on namespace and service account names, then a namespace with the same name in a less trusted cluster might be treated as equal to the trusted one. Make sure every cluster in the group meets the same security bar, or keep untrusted clusters outside the shared trust domain.
13Traffic Management: Locality, Failover and Weights
Once a service has endpoints in several clusters, someone must decide which ones to use and when to switch.
Prefer the near, keep the far in reserve
The most common policy is locality-aware routing. A call goes to an endpoint in the same cluster, or the same zone, when one is healthy. Only if none are available does it spill over to a more distant cluster. This keeps latency low, avoids data transfer charges and limits the blast radius of a remote problem. Meshes and network plugins offer settings to prefer local endpoints, define failover orders and cap how much traffic may leave the local area.
flowchart TD
A["Client calls the shared service name"] --> B{"Healthy endpoints in the local cluster?"}
B -->|"Yes"| C["Use local endpoints"]
B -->|"No"| D{"Healthy endpoints in the next preferred cluster?"}
D -->|"Yes"| E["Fail over to that cluster"]
D -->|"No"| F["Try the next cluster in the list or return a clear error"]
E --> G["Watch capacity and recover to local when healthy"]
The flow shows the ordering: local first, then the nearest remote cluster, then the next. Real systems also account for partial health, for example sending a share of traffic remote when the local cluster is stressed, and they return to local endpoints gradually once recovery is confirmed.
Think of choosing a supermarket. You go to the closest one every day. If it is closed, you drive to the next closest. You would not drive across the country for a loaf of bread while a store is open at the end of your street. Locality-aware routing is the same common sense for traffic.
The traffic tools you will use
Locality preference
Send traffic to the closest healthy endpoints, using zone and cluster labels to measure closeness.
Failover priorities
Define the order in which other clusters take over, so traffic does not scatter randomly during an outage.
Weighted distribution
Send fixed shares to different clusters, useful for gradual migrations and for balancing uneven capacity.
Outlier detection
Automatically stop sending traffic to endpoints that keep failing, and test them again after a cooling-off time.
Timeouts, retries and circuit breakers
Limit how long and how often a call tries, to prevent small remote problems from turning into storms.
Overload protection
Reject or queue excess requests so that a surviving cluster does not collapse when it inherits traffic.
If two clusters each run at eighty percent of capacity, one failing sends it all to the other, which then needs one hundred and sixty percent. Failover only works if the surviving clusters have headroom, or the ability to scale up quickly. Plan capacity for the failure case, not just the normal case.
Example: the thundering herd
A cluster in one region loses its ingress. All its traffic floods into the neighbouring cluster within seconds. The neighbour was sized for its own users only, becomes overloaded and starts failing, and both regions are now down. Headroom, overload protection and gradual traffic shifting would have prevented the cascade.
14Stateful and Headless Services Across Clusters
Services that care which exact pod they talk to need more than a single shared name.
When one name is not enough
A web service can be called by any copy, so one shared name is perfect. Databases, message brokers and clustered caches are different. Their members must find each other individually: a replica must connect to its primary, a broker must contact a specific peer. In one cluster, a StatefulSet with a headless Service gives each pod a stable, individual DNS name. Across clusters, the same idea needs names that also say which cluster a pod belongs to.
The Multi-Cluster Services standard covers this by defining per-pod names for exported headless services, which include the cluster identity. This allows members in different clusters to address each other directly, as long as the network path allows pod-to-pod traffic. Flat networks and network plugin meshes suit this well. Gateway-only designs usually do not, because individual pods are hidden.
Think of a hospital team. For general enquiries you call the main desk and anyone helps. For your own surgery you need to reach your own surgeon by name. Headless services give each member a personal name, and the cluster identity says which hospital they work in.
Stretching a database across clusters: think twice
It is tempting to form one database cluster whose members live in different Kubernetes clusters. Systems that need agreement among a majority of members, called quorum, suffer when members are far apart, because every write waits for the slowest required member. A network split can also leave one side unable to proceed. Many teams find it safer to run an independent database in each cluster and replicate changes between them, accepting slightly stale reads in return for resilience and simplicity.
| Pattern | How it works | Strength | Risk |
|---|---|---|---|
| Stretched cluster across clusters | One logical database with members in several clusters | Strong consistency and automatic failover | High write latency and sensitivity to network splits |
| Primary with remote replicas | Writes go to one cluster; others hold read copies | Fast local reads, simple model | Failover may need a manual or scripted promotion |
| Active-active with conflict handling | Several clusters accept writes and reconcile | Local writes everywhere | Complex conflict resolution and careful data design |
| Independent per-cluster data | Each cluster owns its own customers or regions | Maximum isolation and clarity | Cross-cluster queries are harder |
Service discovery can tell members how to find each other, but it cannot make a data system tolerate distance. Decide the data replication strategy on its own merits, then use discovery to implement it.
Example: a message broker with regional hubs
A company runs one broker cluster per region instead of one stretched cluster. A bridge component forwards selected topics between regions. Each region keeps working during a link failure, and when the link returns, the bridge catches up. Discovery handles the bridge’s connections, and the data design handles consistency.
15Security Hardening for a Multi-Cluster Estate
Connecting clusters connects their weaknesses too. Each link should be as strong as the clusters it joins.
Before clusters are connected, a break-in to one is contained. After they are connected, an attacker who gains a foothold in one may try to move into the others through the very paths you built. Security design must treat the connection itself as a sensitive asset, and apply the same principles you use inside a cluster: least privilege, strong identity, encryption and careful monitoring.
| Risk | How it appears | Control |
|---|---|---|
| Stolen remote credentials | Access tokens for another cluster’s API leak from a secret or a backup | Read-only, narrowly scoped access, short lifetimes, rotation and secret protection |
| Unencrypted cross-cluster traffic | Traffic crosses networks or the internet in clear text | Mutual TLS at the workload layer, and encrypted tunnels at the network layer |
| Over-broad exports | Sensitive services become visible to clusters that should not see them | Review and approval for every export, and policy that limits which namespaces may export |
| Weak cluster in a trusted group | A less secure cluster becomes a stepping stone | Common baseline controls, and separate trust domains for lower-assurance clusters |
| Gateway abuse | An exposed gateway is attacked or overloaded | Mutual authentication, rate limits, restricted source networks and monitoring |
| Policy gaps | Network policy exists in one cluster but not the other | Identity-based authorization applied consistently, and policy as code across clusters |
Encrypt at two layers
Use workload-level mutual TLS for identity, and network-level encryption between clusters as a second layer of defence.
Govern exports
Allow only approved teams and namespaces to publish services, and record who exported what and when.
Limit blast radius
Group clusters by sensitivity. Production, staging and high-compliance clusters should not share one flat trust domain.
Audit continuously
Log cross-cluster calls, policy denials and changes to exports, and alert on unusual patterns such as sudden new callers.
Think of two secure buildings joined by a new corridor. Each building was safe on its own, but the corridor creates a path between them. The corridor needs its own locks, cameras and guards, or a thief in one building can simply walk into the other.
Standard Kubernetes network policies apply inside one cluster. A policy in cluster A cannot protect a service in cluster B. Each cluster must enforce its own rules, ideally using identity-based authorization that behaves the same everywhere.
Example: a staging cluster joins the wrong group
A team connects a lightly secured staging cluster to the production group so developers can test cross-cluster calls. Because identities depend on namespace and account names, a test workload in staging can impersonate a production caller. The team moves staging into a separate trust domain with limited, explicit access.
16Choosing an Approach
There is no single best way to discover services across clusters. There is only the best fit for your size, skills and risk.
By now you have seen five families of solutions: manual DNS stitching, gateways with global DNS, the Multi-Cluster Services API, network-layer meshes and full service meshes. They overlap, and many real estates combine two of them. Choosing well means asking a short list of honest questions about your situation rather than picking whatever is fashionable.
Six questions that decide most cases
How many clusters and services are involved?
Two clusters sharing three services rarely justify a mesh. Twenty clusters sharing hundreds of services almost certainly need something systematic.
Can the clusters reach each other’s pods directly?
If networks are routable and address ranges are unique, a flat model is open to you. If not, you need gateways or a translation layer.
Do you need encryption and identity between services?
If regulation or internal policy demands mutual authentication for every call, a mesh or an equivalent identity layer moves from optional to required.
Do you need smart traffic rules?
Weighted splits, locality failover and retries are mesh strengths. Plain name resolution is far cheaper to run.
Does your platform already include a component?
A cloud provider’s managed multi-cluster feature, or a network plugin you already run, may deliver most of what you need with almost no new moving parts.
How much operational skill does the team have?
A powerful tool that nobody on the team understands will fail during the first real incident. Match ambition to skill, then grow both.
flowchart TD
S["Start: services in one cluster must call services in another"] --> Q1{"Only a few services and clusters?"}
Q1 -->|"Yes"| P1["Start with DNS stitching or a gateway with global DNS"]
Q1 -->|"No"| Q2{"Need mutual TLS and rich traffic rules?"}
Q2 -->|"Yes"| P2["Use a service mesh that spans clusters"]
Q2 -->|"No"| Q3{"Pod networks routable with unique ranges?"}
Q3 -->|"Yes"| P3["Use a network-layer mesh or the Multi-Cluster Services API"]
Q3 -->|"No"| P4["Use gateways or a tunnel-based network connector"]
The tree is intentionally blunt. It begins with the cheapest possible answer and moves to heavier tools only when a real requirement forces the move. Each step up adds capability and also adds things that can break, so you should climb only as high as the need.
Choosing an approach is like choosing how to get across a river. A few people can use a small boat. A daily commuter flow needs a bridge. A huge freight network needs a tunnel and a rail line. Building the freight tunnel for three hikers would be absurd, and sending freight trucks onto a rowing boat would be dangerous.
| Approach | Best when | Main strength | Main cost |
|---|---|---|---|
| DNS stitching and aliases | Very few services, small teams | Almost no new software | Manual upkeep and weak failover |
| Gateways with global DNS | Public or partner-facing services, separate networks | Well understood and easy to explain | DNS caching delays and edge cost |
| Multi-Cluster Services API | Standard, portable naming across clusters | One simple model with clear names | Needs an implementation and has limited traffic features |
| Network-layer mesh | Many services needing direct pod reachability | Fast, simple data path | Needs careful address planning |
| Service mesh | Strong identity and rich traffic control | Most complete feature set | Highest operational burden |
A common healthy mix is a network connector for pod reachability and shared naming, plus a mesh only for the services that truly need identity and traffic policy. You do not have to pick one tool for everything.
Example: a growing online retailer
A retailer starts with two clusters in one region and uses plain gateways and DNS for a single checkout service. When it adds a third region and a payment service that must be encrypted end to end, it adopts a mesh for those sensitive services only. The simple pieces stay simple, and the complexity is spent only where the risk justifies it.
17Designing for Failure Across Clusters
The whole point of a second cluster is to survive problems. Cross-cluster discovery must not become a new way to fail.
Connecting clusters creates a new class of failures. A link can drop while both clusters stay healthy. A control plane can be unreachable while traffic still flows. A name can point to a cluster that has quietly lost its backends. Good design assumes each of these will happen and decides in advance how the system should behave.
The failures to plan for
Link outage
The network between clusters breaks. Each cluster is healthy but cannot see the other, and cross-cluster calls time out.
Cluster outage
An entire cluster goes down. Traffic must move to the survivors, and they must have room to take it.
Stale endpoint data
A cluster keeps advertising backends that no longer exist, so callers are sent to dead addresses until the data expires.
Control-plane partition
The system that syncs service information loses contact with a cluster. Existing traffic often continues, but updates stop.
Partial degradation
A cluster is slow or half broken rather than fully down. This is the hardest case, because nothing clearly says “fail over now”.
Cascading overload
Failover pushes extra traffic to a healthy cluster that cannot cope, and it fails too, which pushes traffic to the next one.
Imagine three bridges over a river. If one closes, drivers move to the other two. That works only if those bridges have spare lanes. If every bridge is already full at rush hour, closing one does not move the traffic, it simply creates a jam on all of them.
Keep the data path independent of the control plane
The most important design rule is that live traffic should keep flowing even when the system that distributes service information is unavailable. Well-designed tools cache the last known endpoints at each cluster, so a control-plane outage stops updates but does not stop calls. When you evaluate a tool, ask what happens to existing traffic if its central brain disappears for an hour. The right answer is that traffic continues using the last known good data.
Fail fast, then fail over
Failover only helps if failure is noticed quickly. Short connection timeouts, active health checks and outlier detection let a caller abandon a bad cluster within seconds. Long timeouts do the opposite: every request waits a long time before giving up, threads pile up, and the caller itself becomes unhealthy. Tune timeouts to the real speed of the dependency, and keep retries bounded so they cannot multiply load.
flowchart LR
C["Caller in cluster A"] --> H{"Health check passes?"}
H -->|"Yes"| L["Local backends in cluster A"]
H -->|"No"| R["Retry with a budget"]
R --> F["Remote backends in cluster B"]
F --> W{"Cluster B has spare capacity?"}
W -->|"Yes"| OK["Request served"]
W -->|"No"| SH["Shed load and return a clear error"]
The diagram highlights the two safeguards that are most often forgotten. A retry budget prevents a flood of repeated attempts, and a load-shedding exit means a cluster that is full says no quickly instead of collapsing. Without these, failover can turn a small outage into a large one.
Plan capacity for the failure case
If you run three clusters and want to survive the loss of one, each cluster must be able to carry half again its normal share. That is real, paid-for headroom. Teams that skip this step find out during an incident that their failover plan only exists on paper. Write the target down, for example “any single cluster can be lost at peak”, and test it by actually draining a cluster during a calm period.
When a cluster recovers, every caller may switch back at the same instant, overwhelming the freshly restarted backends. Return traffic gradually, using weights that increase step by step, and let caches warm up before the cluster takes a full load.
Automatic failover
- Reacts in seconds, faster than any human
- Works at night and during holidays
- Reduces the duration of many outages
- Behaves the same way every time
Risks of automatic failover
- Can move traffic during a false alarm
- Can overload the surviving clusters
- Hides small problems until they become big
- Needs regular testing, or it silently rots
Example: a game studio loses a region
A studio runs match-making services in three regions. When one region fails, traffic shifts to the other two, which were sized for exactly this case. Players notice a small rise in delay but no outage. Because the studio rehearses this every quarter, the on-call engineers simply watch the dashboards instead of scrambling.
18Observability Across Clusters
You cannot fix what you cannot see. When a request crosses a cluster boundary, you need to see both sides of it.
Inside one cluster, an engineer can usually find a problem by looking at one set of logs and one dashboard. Once calls cross clusters, the evidence is scattered. The caller’s logs say the call failed, the remote cluster’s logs say nothing arrived, and the network in between belongs to neither. Observability across clusters means stitching these views into one story.
The three signals, extended across the boundary
Metrics
Numbers over time, such as request rate, error rate and latency. Label them with the source and destination cluster so you can tell local traffic from remote.
Logs
Detailed event records. Include the cluster name in every entry, and ship logs to a shared place so one search can span all clusters.
Traces
The path of one request through many services. Pass a common trace identifier across the boundary so the story continues in the next cluster.
Tracking a parcel that moves between two courier companies is hard if each company only knows its own part. A shared tracking number lets you follow it from start to finish. A trace identifier does the same for a request that crosses clusters.
Questions your dashboards should answer
How much traffic is leaving each cluster?
A sudden rise in remote calls often means local backends are unhealthy or a locality setting changed.
How slow are remote calls compared with local ones?
The gap shows the real price of crossing the boundary and helps you set sensible timeouts.
Is the clusterset in sync?
Track whether each cluster has recent, complete endpoint information. Lag here causes callers to reach dead or missing backends.
Are gateways and tunnels healthy?
Watch connection counts, handshake failures, throughput and certificate expiry on the components that carry cross-cluster traffic.
Who is calling whom?
A service dependency map across clusters reveals surprise dependencies before they cause an outage.
Where to keep the data
There are two common designs. In the first, every cluster runs its own monitoring stack, and a global layer queries them all on demand. This is simple to start and keeps data local, but a query across many clusters can be slow, and if a cluster is unreachable its data is too. In the second, every cluster sends its data to a central store. Queries are fast and data survives a cluster loss, but you pay for transfer and storage, and the central store becomes critical infrastructure. Many teams use a hybrid: short-term data stays local while summaries and alerts flow to a central place.
| Design | Strength | Weakness |
|---|---|---|
| Local stacks with a global query layer | Low transfer cost, data stays near its source | Slow wide queries, lost view when a cluster is unreachable |
| Central store for everything | One fast view, data survives cluster loss | Higher cost, and a new critical dependency |
| Hybrid of local detail and central summaries | Balances cost and visibility | More moving parts to design and maintain |
Alert when users feel pain, such as high error rates on a shared service, and use cluster-level data to find the cause. An alert for every link flap will train people to ignore alerts.
Example: the invisible slowdown
A team notices occasional slow checkouts. Their metrics, labelled by source and destination cluster, show that a small share of calls are going to a remote cluster because one local backend is restarting repeatedly. Without cluster labels the slowdown looked random. With them, the cause was visible in minutes.
19A Troubleshooting Playbook
When a cross-cluster call fails, work from the bottom of the stack to the top. Most problems are simple once you look in the right order.
Cross-cluster failures feel mysterious because many layers are involved. The calm way through is to test each layer in turn, always asking one question: does this layer work on its own? Start with the network, then names, then identity, then policy, then the application. Skipping ahead wastes time, because a failure low in the stack makes everything above it look broken.
flowchart TD
A["Cross-cluster call fails"] --> B{"Does the name resolve?"}
B -->|"No"| B1["Check export or import objects, DNS forwarding and sync status"]
B -->|"Yes"| C{"Can you reach the address?"}
C -->|"No"| C1["Check routes, tunnels, gateways, firewalls and address overlap"]
C -->|"Yes"| D{"Does the secure handshake succeed?"}
D -->|"No"| D1["Check certificates, trust roots, clock drift and identities"]
D -->|"Yes"| E{"Is the request allowed by policy?"}
E -->|"No"| E1["Check authorization rules in the destination cluster"]
E -->|"Yes"| F["Check the application, timeouts and backend health"]
Each box in the diagram is a separate question with a separate set of tools. Notice that the first two questions are about plumbing, while identity and policy come later. In practice, more than half of all cross-cluster incidents are caused by one of the first two: a name that does not resolve, or an address that cannot be reached.
Symptoms and likely causes
| Symptom | Likely cause | First check |
|---|---|---|
| Name not found | Service not exported, export in conflict, or DNS forwarding missing | Status of the export and import objects, and the DNS configuration |
| Name resolves but calls time out | No route, blocked firewall, tunnel down or overlapping addresses | Gateway and tunnel health, and security rules between networks |
| Connection resets during handshake | Certificate expired, wrong trust root or clock drift | Certificate dates and the trust configuration in both clusters |
| Calls denied with a permission error | Authorization policy does not allow the remote identity | Policy in the destination cluster and the identity of the caller |
| Only some calls fail | One bad endpoint, or one cluster partially unhealthy | Per-endpoint error rates and outlier detection events |
| Traffic goes to the wrong cluster | Locality or priority settings incorrect, or missing labels | Region and zone labels on nodes, and routing configuration |
| Changes take a long time to appear | DNS caching or slow synchronization | Record lifetime and the age of the last sync |
Troubleshooting a failed phone call goes in the same order. First, did you dial a real number? Then, is the line connected? Then, did the other person pick up? Then, did they agree to talk to you? Asking these in order stops you from arguing about the conversation when the line was never connected.
A calm routine for incidents
Define the failing path exactly
Write down the source cluster and service, the destination name and the exact error. Vague reports lead to wandering investigations.
Test from inside the source cluster
Run name and connection tests from a pod in the calling cluster, because that is where the real call starts and where its view of the world applies.
Compare with a working path
If another service works across the same boundary, compare the two. The difference between a working and a broken path usually points straight at the fault.
Check what changed recently
Look at recent upgrades, certificate rotations, firewall edits and new exports. Most incidents follow a change.
Fix, verify and record
After the repair, confirm from the same pod that the path works, and add what you learned to the runbook so the next person is faster.
Secure handshakes depend on certificate dates. If a node’s clock is wrong by even a few minutes, valid certificates can look expired or not yet valid. Always check time synchronization when handshakes fail without an obvious reason.
Example: the missing namespace
A team exports a service from one cluster, but callers in the other cluster cannot resolve it. After an hour of inspecting the network, someone notices that the importing cluster has no namespace with the same name. Because sameness depends on matching namespaces, the service had nowhere to appear. Creating the namespace fixed it immediately, and the checklist now includes this check first.
20Operating the Clusterset Day to Day
Building a multi-cluster system is a project. Keeping it healthy for years is a routine.
Once the connection works, the real work becomes ordinary operations: upgrades, certificate rotation, onboarding new clusters, retiring old ones and keeping versions compatible. These tasks are not exciting, but they are where most long-term outages originate. A little discipline here prevents most surprises.
Upgrades without breaking the link
Kubernetes, the mesh or connector, the network plugin and the custom resource definitions all evolve at different speeds. When clusters in one group run different versions, subtle incompatibilities appear. Most projects document which version differences are supported, and the safe pattern is to upgrade one cluster at a time, starting with a low-risk one, and to pause between steps to confirm cross-cluster traffic is healthy before moving on.
Read the compatibility notes
Check which versions of the connector or mesh work with which Kubernetes versions, and which skew between clusters is allowed.
Upgrade the least critical cluster first
A staging or low-traffic cluster acts as a canary and reveals problems before they reach important traffic.
Drain traffic if needed
For risky changes, shift traffic away from the cluster being upgraded, using the same failover tools you rely on in real incidents.
Verify cross-cluster paths
Run a fixed set of test calls, covering naming, connection, identity and policy, before declaring the step done.
Proceed one cluster at a time
Repeat the cycle. Never upgrade every cluster at once, because a bad change would then take down the whole estate together.
Upgrading a chain of connected bridges is like repairing them one lane at a time. Traffic continues over the others while a section is fixed. Closing all bridges on the same weekend might be faster on paper, but it guarantees the whole city is cut off if anything goes wrong.
Onboarding a new cluster
Adding a cluster should be a repeatable, mostly automated procedure, not a heroic effort. The steps usually include allocating non-overlapping address ranges, installing the connector or mesh components, issuing an identity certificate chained to the shared root, registering the cluster with the others, applying baseline security policy, and running the standard test suite. If any of these steps depends on one person’s memory, the process will eventually fail.
Retiring a cluster
Leaving is as important as joining. Before a cluster is removed, stop exporting its services, drain its traffic, remove its credentials from the other clusters, revoke or let expire its certificates and delete its records from DNS. Forgotten remote access credentials for a deleted cluster are a classic security leftover.
Certificates and credentials on a schedule
Everything that expires should be tracked. Root certificates often live for years, intermediate certificates for months and workload certificates for hours or days. Put each expiry on a calendar and, better, on an automated alert that fires weeks ahead. A root certificate that expires unnoticed will break every cross-cluster call at once, at a time nobody chose.
| Item | Typical lifetime | Rotation approach |
|---|---|---|
| Shared root certificate | Years | Planned overlap with old and new roots trusted together, then retire the old one |
| Per-cluster intermediate certificate | Months | Automated renewal with alerts well before expiry |
| Workload certificate | Hours to days | Automatic and invisible when the system is healthy |
| Remote cluster access credential | Short and scoped | Regular rotation, plus immediate revocation when a cluster leaves |
| Gateway and tunnel keys | Months | Rotate with a rolling restart, one gateway at a time |
Run a rehearsal for onboarding, retirement and root rotation in a test environment at least once. The first time you do these should never be during a real emergency.
Example: the quiet root expiry
A company’s shared root certificate was created five years earlier by an engineer who has since left. Nobody tracked its expiry. On the day it expired, every cross-cluster call failed at once. Afterwards the team built an inventory of every certificate, automated alerts sixty days ahead and scheduled yearly rotation drills.
21Migration Patterns: Moving Services Between Clusters
Cross-cluster discovery is not only for resilience. It is also the safest way to move a service from one cluster to another.
Teams move services between clusters for many reasons: replacing an old cluster, adopting a new Kubernetes version, changing cloud providers or splitting a crowded cluster. Without cross-cluster discovery, a move is a risky cut-over. With it, a move becomes a gradual shift in which both copies serve traffic at the same time and the old one is retired only after the new one proves itself.
The gradual migration pattern
sequenceDiagram
participant U as Callers
participant O as Old cluster
participant N as New cluster
U->>O: All traffic goes to the old cluster
Note over N: Deploy the same service and export it
U->>O: 90 percent of traffic
U->>N: 10 percent of traffic
Note over U,N: Watch errors and latency
U->>O: 50 percent of traffic
U->>N: 50 percent of traffic
U->>N: 100 percent of traffic
Note over O: Stop exporting, drain and retire
The sequence shows why a shared name matters. Callers keep using one service name throughout, and only the weights behind that name change. If the new cluster misbehaves at any step, the weights move back, and users barely notice. There is no day on which everything has to work perfectly at once.
Moving a shop to a new street is easier if you keep both shops open for a few weeks. Regular customers find the new shop gradually, you check that the new till and shelves work, and you close the old shop only when nobody is walking to it any more.
Migration steps in order
Prepare the new cluster
Install the connector or mesh, join the group, and confirm that identity, policy and monitoring work the same way as in the old cluster.
Deploy and export the service
Run the service in the new cluster with the same name and namespace, and export it so the shared name now has endpoints in both places.
Handle the data first
If the service owns data, plan replication or a data move before shifting traffic. Stateless services move easily, stateful ones need a careful sequence.
Shift traffic in small steps
Increase the share sent to the new cluster in stages, pausing at each stage to compare error rates and latency against the old one.
Keep a rollback path
Leave the old copy running and ready for a while after the move, so you can switch back quickly if a late problem appears.
Retire the old copy
Stop exporting it, drain remaining connections, remove it, and clean up names, credentials and monitoring that referred to it.
Whole-cluster replacement
Some teams go further and treat clusters as disposable. Instead of upgrading a cluster in place, they build a fresh cluster at the new version, move services across using the gradual pattern and delete the old one. This blue and green approach for whole clusters reduces upgrade risk, because the old cluster stays untouched until the new one has been proven. It does require that applications are fully described as code and that data lives somewhere that can move, but teams that reach this point find upgrades far calmer.
Some callers use old addresses, hard-coded names or cached DNS records and will keep sending traffic to the old cluster. Watch the old cluster’s traffic until it truly reaches zero, and investigate every remaining caller before you delete anything.
Example: a provider move without downtime
A media company wants to move its recommendation service to a different cloud provider. It joins a new cluster to the group, exports the same service and shifts traffic from five percent to one hundred percent over two weeks. When a memory problem appears at thirty percent, weights return to the old cluster within minutes. The fix is deployed, the shift resumes and the old cluster is retired without a single customer-visible outage.
22Cost and Performance Considerations
Every call that crosses a cluster boundary costs time and often money. Good design makes the cheap path the normal path.
Calling a service in the same cluster is fast and usually free. Calling a service in another region adds tens or hundreds of milliseconds, and most cloud providers charge for data that leaves a region or a zone. When discovery makes remote services as easy to call as local ones, it also makes expensive calls easy to make by accident. Cost and performance work is mostly about keeping traffic close to home unless there is a reason to travel.
Where the time and money go
Network distance
Light travels at a fixed speed. A round trip between continents takes a noticeable fraction of a second, whatever tool you use.
Data transfer charges
Traffic between zones, regions or providers is billed per amount of data. Chatty services can generate surprising bills.
Encryption and proxies
Mutual TLS and sidecar proxies add a small processing delay to each call and use extra memory and processor time on every node.
Gateway capacity
Gateways concentrate cross-cluster traffic. They must be sized and replicated, and they add a hop to every call that passes through.
Control-plane traffic
Syncing endpoint information between clusters uses bandwidth, and the volume grows with the number of services and how often they change.
Think of delivery fees. Ordering from the shop next door is quick and free. Ordering from a warehouse in another country is slow and costs shipping. If a website makes both feel the same at checkout, you will end up paying shipping on things you could have bought down the road.
The chain-of-calls trap
A single user request often triggers a chain of calls between services. If each call in a chain of five stays local, the total delay is small. If each one goes to a different region, five round trips add up to a long wait. Worse, the chance that something in the chain fails grows with every remote link. Keep chains local, and let only a few well-chosen calls cross the boundary.
flowchart LR
U["User request"] --> A["Frontend in cluster A"]
A -->|"local, fast"| B["Cart service in cluster A"]
B -->|"local, fast"| C["Pricing service in cluster A"]
B -->|"remote, slow"| D["Inventory service in cluster B"]
D -->|"local to B"| E["Inventory database in cluster B"]
The diagram shows a healthy pattern. Almost everything stays inside cluster A. A single call reaches into cluster B for data that lives there, and from that point onward the work stays local to B. One boundary crossing is easy to measure, budget for and monitor. Five would be hard to defend.
Practical ways to control cost and delay
Prefer local endpoints by default
Turn on locality-aware routing so remote clusters are used only when local ones are unavailable or overloaded.
Place data near the code that uses it
Move or replicate data so the busiest calls stay local, rather than reaching across regions for every read.
Cache and batch
Cache results that change rarely, and combine many small remote calls into fewer larger ones to cut round trips.
Measure the bill by service
Break out transfer costs by source and destination, so a team that creates heavy remote traffic can see and fix it.
Right-size the proxies
Give sidecars and gateways realistic resource requests, and review them regularly, so they neither starve nor waste capacity.
Decide how many cross-cluster calls a typical request is allowed to make, for example one or two. Review designs against that budget, and add alerts that fire when the share of remote traffic rises unexpectedly.
Example: the surprise transfer bill
A team exports a reporting service and a busy dashboard in another region begins to call it every few seconds for large result sets. At the end of the month, transfer charges are far above forecast. The fix is to cache results near the dashboard and to refresh them on a schedule instead of on every page view.
23Design Patterns and Anti-Patterns
Teams keep making the same handful of mistakes. Learning them in advance is cheaper than discovering them during an outage.
Patterns that work
Local first, remote on failure
Serve from the nearest healthy cluster, and let other clusters act as a safety net rather than as regular partners.
Share by explicit export
Services are visible to other clusters only when a team deliberately exports them, which keeps the shared surface small and reviewed.
Same names everywhere
Use consistent namespaces and service names in every cluster, so one logical name works in all of them.
Independent failure domains
Each cluster can run without the others. The shared layer adds help during failures but is never required for normal life.
Automation for joining and leaving
Clusters enter and leave the group through one tested procedure, driven by code and not by memory.
Healthy neighbouring towns each have their own hospital, fire station and water supply, and they agree to help each other in emergencies. Unhealthy ones share a single water tower, so one leak leaves everyone thirsty. Good patterns keep each town independent and make help optional but easy.
Anti-patterns to avoid
Problem
Every service in every cluster is exported to every other cluster, because exporting everything was easier than deciding what to share.
Why It’s Harmful
The shared surface becomes huge and nobody knows who depends on what. A change in one cluster can break a hidden consumer elsewhere, and a compromise in one cluster can reach almost anything.
Correct Approach
Export only services with a clear cross-cluster purpose. Require a review for each export, record the owner and keep an up-to-date list of consumers.
Problem
A stateful database is stretched across clusters in distant regions so that it is “automatically highly available”.
Why It’s Harmful
Writes must wait for acknowledgement from far-away nodes, so every transaction slows down. A network split can also leave the cluster without a majority, and the data service stops accepting writes exactly when it was needed most.
Correct Approach
Run a database per cluster and replicate between them with a method designed for distance, accepting a clear and documented trade-off between consistency and availability.
Problem
Clusters are joined with overlapping address ranges and a pile of translation rules added later to make things work.
Why It’s Harmful
Translation hides the real source of traffic, breaks tools that rely on addresses and makes debugging painful. Every new cluster adds more special cases.
Correct Approach
Plan unique address ranges for every cluster from the start, keep a central register of allocations and use translation only for clusters you cannot change.
Problem
Failover is configured but never tested, and the surviving clusters are sized only for normal traffic.
Why It’s Harmful
When a cluster fails, the survivors are overloaded and fail too. The team discovers that the resilience plan was a hope and not a capability.
Correct Approach
Reserve headroom for the loss of one cluster, rehearse failover on a schedule and measure how long recovery really takes.
Problem
Production and test clusters share one trust domain and one flat set of permissions, for the convenience of developers.
Why It’s Harmful
A weakly protected test cluster becomes a path into production. Identities from the test side look valid on the production side.
Correct Approach
Separate trust domains by sensitivity, connect them only through narrow, audited paths and apply identity-based authorization everywhere.
Example: two anti-patterns meet
A company exports everything and has never tested failover. When one cluster fails, traffic floods to another that was never sized for it, and a service nobody knew was shared collapses first. Fixing either problem alone would have helped. Fixing both turned a bad night into a manageable event.
24Best Practices and Common Mistakes
A short, practical summary of what the whole guide has been building towards.
Do these
- Plan unique address ranges for every cluster before the first one is built
- Keep names and namespaces consistent across clusters
- Export services deliberately, with review and ownership
- Use mutual authentication and identity-based authorization
- Prefer local endpoints, and keep failover capacity in reserve
- Automate joining, leaving and certificate rotation
Avoid these
- Adding a mesh or connector before there is a real need
- Exporting every service to every cluster by default
- Letting long DNS caching decide your failover time
- Stretching databases across distant regions
- Sharing one trust domain between production and test
- Leaving failover untested and certificates untracked
A launch checklist before going live
| Area | Question to answer before launch |
|---|---|
| Naming | Does one stable name reach the service from every cluster, and is it documented? |
| Network | Are address ranges unique, routes verified and firewalls opened only where needed? |
| Identity | Do all clusters trust the same root, and are certificates automatic and monitored? |
| Policy | Is access limited to named callers, and is the same policy applied in every cluster? |
| Traffic | Is local-first routing on, with an ordered failover list and sensible timeouts? |
| Capacity | Can the remaining clusters carry peak load if one is lost? |
| Observability | Can you see traffic by source and destination cluster, and follow one request across both? |
| Operations | Is there a tested runbook for upgrades, onboarding, retirement and root rotation? |
A pilot runs through a checklist before every flight, however many times the plane has flown. The checklist is not a sign of doubt about the pilot. It is how experienced people make sure small, boring details never become large, dramatic problems.
The mistakes seen most often
Treating discovery as the whole job
A name that resolves does not mean the path is reachable, trusted or allowed. All four layers must work together.
Skipping address planning
Overlapping ranges are cheap to prevent and costly to repair once real workloads depend on them.
Forgetting about time
Expiring certificates, cached records and clock drift cause failures that appear at awkward moments.
Underestimating the learning curve
Teams adopt a powerful tool without building the skill to run it, and then struggle during the first incident.
Multi-cluster standards and tools are still maturing, and details change between releases. Before committing, read the current documentation for the exact versions you plan to run, and test the behaviours your design depends on.
Example: the checklist that paid for itself
A platform team asks every service owner to complete the launch checklist before a service is exported. Over a year, the checklist catches a missing authorization rule, an untested failover path and an unplanned address overlap. Each would have caused an incident. Together they justified the extra hour per launch many times over.
25Real-World Scenarios
The ideas in this guide show up in many industries. These typical scenarios show how teams combine them.
The following scenarios are illustrative composites. They are typical of the patterns organisations report, and are not accounts of any specific company. Each one shows how the requirements of the business, not the fashion of the moment, drive the choice of approach.
Scenario one: a global online store
The store runs clusters in three regions so shoppers connect to a nearby site. Product browsing is served locally in each region, while a shared inventory service is exported from the region that owns the data. Locality-first routing keeps most calls local, and weighted failover moves traffic if a region fails. The team chose a mesh because payment services need mutual authentication and detailed traffic control.
Scenario two: a bank with data residency rules
A bank must keep customer data inside specific countries. Each country has its own cluster and database, and only a small set of reviewed services is exported between them, such as fraud scoring. Separate trust domains and strict identity-based policy limit what can cross a border. Failover never moves regulated data outside its country, even if that means a reduced service during an outage.
Scenario three: a software provider with many tenants
A provider gives large customers their own clusters for isolation, and runs shared platform services in a central cluster. Customer clusters import a small set of central services, such as billing and identity, through the standard naming model. The simple, standard approach keeps the effort per customer low, and new customer clusters are onboarded by automation in a few minutes.
Scenario four: a media company moving clouds
The company wants to leave one cloud provider for another without downtime. It joins new clusters to the existing group and shifts services across gradually using weights, as described in the migration chapter. At each step a rollback is one weight change away. When traffic to the old clusters reaches zero, they are retired.
Scenario five: a manufacturer with factories and a cloud
Small clusters run at each factory so production lines keep working when the internet link fails. A cloud cluster hosts analytics and planning. Factory clusters export a few local data services and import central planning services. Because the factory links are slow and unreliable, the design keeps all essential calls local and treats the cloud as an optional helper.
These scenarios are like different kinds of road networks: a motorway ring around a capital, a set of border crossings between countries, a ferry between islands. Every one is a transport system, yet each is shaped by geography and rules. Cross-cluster discovery is the same, shaped by data rules, distance and risk.
| Scenario | Main driver | Typical approach |
|---|---|---|
| Global store | Latency and resilience | Service mesh with locality-first routing |
| Bank | Data residency and security | Separate trust domains with strict policy and few exports |
| Software provider | Simplicity at large scale | Standard naming model with automated onboarding |
| Media company | Safe migration | Shared names with weighted traffic shifts |
| Manufacturer | Unreliable links | Local-first design with optional central services |
26Frequently Asked Questions
Short answers to the questions beginners ask most often.
It is the set of techniques that let a workload in one Kubernetes cluster find and call a service that runs in another cluster, using a stable name instead of a hard-coded address.
Normal service names and addresses exist only inside one cluster. Another cluster has its own separate records, its own address ranges and its own DNS, so the name simply does not exist there unless something shares it.
No. A mesh is one option and is most useful when you also need strong identity and rich traffic rules. Simpler approaches, such as DNS stitching, gateways or a standard multi-cluster naming layer, are enough for many cases.
It is a Kubernetes community standard that lets a team export a service from one cluster and import it into others, giving it a shared name in a common domain. It defines the objects and naming rules, while separate implementations do the actual work.
It is still an early-stage standard, and maturity varies by implementation. Several managed and open source tools support it. Check the status and documentation of the specific implementation and version you plan to use, and test it before relying on it.
For flat, direct connections, yes, and planning them early is strongly advised. If you cannot avoid overlap, gateway-based designs or translation features can work around it, but they add complexity and make debugging harder.
In a flat model, pods in different clusters can reach each other directly. In a gateway model, traffic between clusters passes through a small number of edge gateways, which is easier to set up across separate networks and exposes fewer addresses.
Callers prefer local endpoints. When health checks show that local backends are unavailable, traffic moves to the next cluster in a defined order. Good designs also limit retries, shed load when needed and return to local endpoints gradually after recovery.
Resolvers and applications cache DNS answers for the length of the record’s lifetime, and some keep them longer. Until the cache expires, clients may keep sending traffic to an address that is no longer healthy. Shorter lifetimes help but increase DNS load.
Clusters in a group usually trust a shared root certificate, and each workload receives a short-lived certificate that proves who it is. Calls use mutual TLS, so both sides verify each other, and authorization rules then decide what each identity may do.
You can, but it is rarely wise across long distances. Writes slow down, and a network split can stop the database from reaching a majority. Most teams run one database per cluster and replicate between them, accepting clear trade-offs.
A headless service gives each pod its own record instead of one shared address. Across clusters, it lets callers reach specific pods, which matters for stateful systems, but it needs direct pod-to-pod reachability or an equivalent mechanism.
Use mutual TLS, give remote access credentials narrow permissions and short lives, review every export, separate trust domains by sensitivity and apply the same identity-based policy in every cluster. Also encrypt at the network layer as a second defence.
Work from the bottom up. Check that the name resolves, then that the address is reachable, then that the secure handshake works, then that policy allows the call, and finally the application itself. Start inside the calling cluster.
As few as meet your needs for isolation, latency, data rules and resilience. Every extra cluster adds operating effort. Start with the minimum, and add clusters when a clear requirement justifies the added connection work.
Yes, and it is one of the safest uses. Export the service from both clusters, shift weights gradually towards the new one, keep a rollback path and retire the old copy only when its traffic has dropped to zero.
27Summary and Key Takeaways
Kubernetes is excellent at running workloads inside one cluster, and its naming, addressing and routing stop at the cluster edge. Cross-cluster service discovery extends those ideas outward so that a service in one cluster can be found and called from another, using a stable name. Doing this well means solving four connected problems: naming, connectivity, identity and traffic policy.
Solutions range from simple DNS stitching and gateways, through the standard Multi-Cluster Services model and network-layer connectors, to full service meshes with mutual authentication and rich traffic control. No option is best for everyone. The right choice follows your size, your networks, your security needs and your team’s skills, and it should grow only as real requirements demand.
Whatever you choose, the lasting success factors are ordinary and practical: unique address plans, consistent names, deliberate exports, strong identity, local-first routing with real spare capacity, clear observability and rehearsed operations. Treat the connection between clusters as something to be designed, secured, measured and maintained, and your second cluster will make your system stronger instead of merely more complicated.
Key Takeaways
- Clusters are separate worlds by default — names, addresses and routes inside one cluster do not automatically exist in another, so discovery must be added on purpose.
- Four problems must all be solved — naming, connectivity, identity and traffic policy. A name that resolves is only the beginning.
- Start simple and climb only when needed — DNS and gateways suit small estates, the Multi-Cluster Services model gives portable naming, and a mesh adds identity and traffic control at higher cost.
- Plan addresses and trust early — unique ranges and a shared root of trust are cheap at the start and very costly to repair later.
- Keep traffic local and failover real — prefer nearby endpoints, reserve capacity for the loss of a cluster, bound retries and test failover regularly.
- Secure the connection itself — use mutual TLS, narrow credentials, reviewed exports and separate trust domains for different sensitivity levels.
- Operate it like a product — automate joining and leaving, track every certificate, observe both sides of each call and keep a calm troubleshooting routine.