GCP ACE: Fleet Networking — Multi-cluster Services and the Multi-cluster Gateway
A regular Kubernetes Service (covered early in this series) only resolves within its own cluster. Once workloads are spread across multiple clusters in a fleet, you need two more pieces: a way for a Service in Cluster A to be reachable from Cluster B, and a way to put one external load balancer in front of all of them. That’s multi-cluster Services (MCS) and the multi-cluster Gateway.
Multi-cluster Services (MCS)
MCS exports a Service from the cluster that owns it, and makes it discoverable — automatically — in every other fleet cluster that shares the same namespace.
Enable it once, at the fleet level:
gcloud container fleet multi-cluster-services enable --project PROJECT_ID
MCS authenticates through the fleet, and Google strongly recommends registering the clusters with Workload Identity Federation for GKE enabled. Otherwise you have to register them with a Google service account and complete extra authentication steps.
Exporting a Service: apply a ServiceExport object in the cluster that actually runs the Service. Its name must be the name of the Service you’re exporting, and its namespace must match the Service’s namespace:
kind: ServiceExport
apiVersion: net.gke.io/v1
metadata:
namespace: NAMESPACE
name: SERVICE_EXPORT_NAME
kubectl apply -f export.yaml
You never create the matching object yourself. MCS automatically creates a ServiceImport in every other fleet cluster that has a namespace of the same name — this is namespace sameness, from the Fleets intro article, doing real work. For a ClusterSetIP Service, the ServiceImport’s status.ips field holds the cluster-set IP; MCS also creates a matching EndpointSlice, referenced by the ServiceImport’s net.gke.io/derived-service annotation, which is useful for checking whether endpoints have actually propagated yet.
One detail that trips people up: a Service is only imported into clusters that already have a namespace matching the exporting one. If Cluster B has never had a payments namespace, exporting a Service from payments in Cluster A does not create anything in Cluster B — you have to create that namespace there first.
Reaching an exported Service from anywhere in the fleet:
SERVICE_EXPORT_NAME.NAMESPACE.svc.clusterset.local
Note the domain: clusterset.local, not the regular cluster.local used for same-cluster DNS. For a ClusterSetIP Service, this resolves to the cluster-set IP; for a headless Service, it resolves directly to endpoint IP addresses (MCS only supports DNS “A” records here — no AAAA/IPv6).
Multi-cluster Gateway
MCS makes a Service reachable across clusters internally. The multi-cluster Gateway is the external-facing counterpart: one load balancer, backed by Pods spread across multiple clusters, using the Kubernetes Gateway API (Gateway and HTTPRoute objects). The Ingress article earlier in this series introduced the Gateway API as Ingress’s recommended successor; a multi-cluster Gateway is the same API, pointed at more than one cluster’s worth of backends.
Every participating cluster must be a fleet member — multi-cluster Gateway is built directly on fleet membership, same prerequisite as MCS.
The config cluster
One cluster in the fleet is designated the config cluster — the single place you deploy Gateway API resources (Gateway, HTTPRoute). The GKE Gateway controller watches only that cluster’s API server for these objects and provisions/maintains the actual Google Cloud load-balancing infrastructure from what it finds there. Google recommends a regional (highly available) cluster for this role, since it becomes a single point of configuration for routing across the whole fleet.
GatewayClass values for multi-cluster
| GatewayClass | What it provisions |
|---|---|
gke-l7-global-external-managed-mc | Global external Application Load Balancer |
gke-l7-regional-external-managed-mc | Regional external Application Load Balancer |
gke-l7-cross-regional-internal-managed-mc | Cross-region internal Application Load Balancer |
gke-l7-rilb-mc | Regional internal Application Load Balancer |
gke-l7-gxlb-mc | Global external Application Load Balancer built on the classic Application Load Balancer |
The -mc suffix is the tell — every multi-cluster GatewayClass carries it, distinguishing it from the single-cluster classes (gke-l7-global-external-managed, gke-l7-rilb, gke-l7-gxlb, and so on).
How it actually routes traffic
The multi-cluster Gateway uses MCS underneath to discover which Services (and therefore which Pods) exist in which clusters, then groups them into one fleet-wide backend. The load balancer then routes each request directly to the optimal Pod in the best cluster for that request — based on real-time health checks, any configured traffic-splitting rules, and each cluster’s available capacity. This is also what enables features like weighted traffic splitting (e.g., 90% of traffic to Cluster A, 10% to Cluster B, for a canary across clusters rather than within one), header-based routing, traffic mirroring, and health-based failover between entire clusters, not just between Pods in one.
Putting it together
A practical picture: you run the same app in three regional clusters (US, EU, APAC) for latency reasons. MCS makes each cluster’s checkout Service discoverable fleet-wide under checkout.payments.svc.clusterset.local — useful for internal service-to-service calls that should prefer the nearest region. The multi-cluster Gateway, configured once on your designated config cluster, gives you a single global external IP that automatically routes each external user’s request to whichever regional cluster is healthiest and has capacity — without the client ever needing to know there are three clusters at all.
Exam Takeaways
- MCS requires fleet enablement (
gcloud container fleet multi-cluster-services enable), aServiceExportin the owning cluster, and a matching namespace already present in any cluster that should import it. - You never create a
ServiceImportmanually — MCS creates it automatically wherever the namespace already exists. - Cross-cluster service DNS uses
SERVICE.NAMESPACE.svc.clusterset.local— distinct from the regularsvc.cluster.localsingle-cluster domain. - Multi-cluster Gateway resources (
Gateway,HTTPRoute) are deployed to exactly one designated config cluster, which the controller watches — not to every cluster individually. - Multi-cluster GatewayClasses all carry the
-mcsuffix; everything else about them maps to the regular Gateway API resource types. - The multi-cluster Gateway uses MCS internally to discover cross-cluster backends, then load-balances by health, traffic-splitting rules, and capacity — across entire clusters, not just within one.
- Both MCS and multi-cluster Gateway require fleet membership as a hard prerequisite — neither works on an unregistered cluster.