This page shows you how to enable and use multi-cluster Services (MCS). To learn more about how MCS works and its benefits, see Multi-cluster Services.
The Google Kubernetes Engine (GKE) MCS feature extends the reach of the Kubernetes Service beyond the cluster boundary and lets you discover and invoke Services across multiple GKE clusters. You can export a subset of existing Services or new Services.
When you export a Service with MCS, that Service is then available across all of the clusters in your fleet.
Google Cloud resources managed by MCS
MCS manages the following components of Google Cloud:
Cloud DNS: MCS configures Cloud DNS zones and records for each exported Service in your fleet clusters. This lets you connect to Services that are running in other clusters. These zones and records are created, read, updated, and deleted based on the Services that you choose to export across clusters.
Firewall rules: MCS configures firewall rules that let Pods communicate with each other across clusters within your fleet. Firewall rules are created, read, updated, and deleted based on the clusters that you add to your fleet. These rules are similar to the rules that GKE creates to enable communication between Pods within a GKE cluster.
Cloud Service Mesh: MCS uses Cloud Service Mesh as a control plane to keep track of endpoints and their health across clusters.
Requirements
MCS has the following requirements:
MCS only supports exporting services from VPC-native GKE clusters on Google Cloud. For more information, see Creating a VPC-native cluster. You cannot use non VPC-native GKE Standard clusters.
Connectivity between clusters depends on clusters running within the same VPC network, in peered or shared VPC networks. If clusters are in separate, non-connected networks, calls to external services will be blocked. We recommend that you enable MCS in projects where the clusters are in the same VPC network.
While a fleet might span multiple Google Cloud projects and VPC networks, a single multi-cluster service must be exported from a single project and a single VPC network.
MCS is not supported with network policies.
Clusters must have the
HttpLoadBalancing
add-on enabled. Ensure that theHttpLoadBalancing
add-on is enabled. TheHttpLoadBalancing
add-on is enabled by default and shouldn't be disabled.
Pricing
Multi-cluster Services is included as part of the GKE cluster management fee and has no extra cost for usage. You must enable the Traffic Director API, but MCS does not incur any Cloud Service Mesh endpoint charges. GKE Enterprise licensing is not required to use MCS.
Before you begin
Before you start, make sure you have performed the following tasks:
Install the Google Cloud SDK.
Enable the Google Kubernetes Engine API:
Connect your VPC networks with VPC Network Peering, Cloud Interconnect or Cloud VPN.
Enable the MCS, fleet (hub), Resource Manager, Cloud Service Mesh, and Cloud DNS APIs:
gcloud services enable \ multiclusterservicediscovery.googleapis.com \ gkehub.googleapis.com \ cloudresourcemanager.googleapis.com \ trafficdirector.googleapis.com \ dns.googleapis.com \ --project=PROJECT_ID
Replace
PROJECT_ID
with the project ID from the project where you plan to register your clusters to a fleet.
Enabling MCS in your project
MCS requires that participating GKE clusters be registered into the same fleet. Once the MCS feature is enabled for a fleet, any clusters can export Services between clusters in the fleet.
While MCS does require registration to a fleet, it does not require you to enable the GKE Enterprise platform.
GKE Enterprise
If the GKE Enterprise API is enabled in your fleet host project as a prerequisite for using other GKE Enterprise components, then any clusters registered to the project's fleet are charged according to GKE Enterprise pricing. This pricing model lets you use all GKE Enterprise features on registered clusters for a single per-vCPU charge. You can confirm if the GKE Enterprise API is enabled using the following command:
gcloud services list --project=PROJECT_ID | grep anthos.googleapis.com
If the output is similar to the following, the full GKE Enterprise platform is enabled and any clusters registered to the fleet will incur GKE Enterprise charges:
anthos.googleapis.com Anthos API
If this is not expected then contact your project administrator.
An empty output indicates that GKE Enterprise is not enabled.
Enabling MCS on your GKE cluster
Enable the MCS feature for your project's fleet:
gcloud container fleet multi-cluster-services enable \ --project PROJECT_ID
Replace
PROJECT_ID
with the project ID from the project where you plan to register your clusters to a fleet. This is your fleet host project.Register your GKE clusters to the fleet. We strongly recommend that you register your cluster with Workload Identity Federation for GKE enabled. If you do not enable Workload Identity Federation for GKE, you need to register the cluster with a Google Cloud service account for authentication, and complete the additional steps in Authenticating service accounts.
To register your cluster with Workload Identity Federation for GKE, run the following command:
gcloud container fleet memberships register MEMBERSHIP_NAME \ --gke-cluster CLUSTER_LOCATION/CLUSTER_NAME \ --enable-workload-identity \ --project PROJECT_ID
Replace the following:
MEMBERSHIP_NAME
: the membership name that you choose to uniquely represent the cluster in the fleet. Typically, a cluster's fleet membership name is the cluster's name, but you might need to specify a new name if another cluster with the original name already exists in the fleet.CLUSTER_LOCATION
: the zone or region where the cluster is located.CLUSTER_NAME
: the name of the cluster.
Grant the required Identity and Access Management (IAM) permissions for MCS Importer:
gcloud projects add-iam-policy-binding PROJECT_ID \ --member "serviceAccount:PROJECT_ID.svc.id.goog[gke-mcs/gke-mcs-importer]" \ --role "roles/compute.networkViewer"
Replace
PROJECT_ID
with the project ID from the fleet host project.Ensure that each cluster in the fleet has a namespace to share Services in. If needed, create a namespace by using the following command:
kubectl create ns NAMESPACE
Replace
NAMESPACE
with a name for the namespace.To verify that MCS is enabled, run the following command:
gcloud container fleet multi-cluster-services describe \ --project PROJECT_ID
The output is similar to the following:
createTime: '2021-08-10T13:05:23.512044937Z' membershipStates: projects/PROJECT_ID/locations/global/memberships/MCS_NAME: state: code: OK description: Firewall successfully updated updateTime: '2021-08-10T13:14:45.173444870Z' name: projects/PROJECT_NAME/locations/global/features/multiclusterservicediscovery resourceState: state: ACTIVE spec: {}
If the value of
state
is notACTIVE
, see the troubleshooting section.
Authenticating service accounts
If you registered your GKE clusters to a fleet using a service
account, you need to take additional steps to authenticate the service account.
MCS deploys a component called gke-mcs-importer
. This component receives
endpoint updates from Cloud Service Mesh, so as part of enabling MCS you need to grant
your service account permission to read information
from Cloud Service Mesh.
When you use a service account, you can use the Compute Engine default service account or your own node service account:
If you are using a Compute Engine default service account, enable the following scopes:
https://www.googleapis.com/auth/compute.readonly
https://www.googleapis.com/auth/cloud-platform
To learn more about enabling scopes, see Changing the service account and access scopes for an instance.
If you are using your own node service account, assign the
roles/compute.networkViewer
role to your service account.
Using MCS
The following sections show you how to use MCS. MCS uses the Kubernetes multi-cluster services API.
Registering a Service for export
To register a Service for export to other clusters within your fleet, complete the following steps:
Create a
ServiceExport
object namedexport.yaml
:# export.yaml kind: ServiceExport apiVersion: net.gke.io/v1 metadata: namespace: NAMESPACE name: SERVICE_EXPORT_NAME
Replace the following:
NAMESPACE
: the namespace of theServiceExport
object. This namespace must match the namespace of the Service that you are exporting.SERVICE_EXPORT_NAME
: the name of a Service in your cluster that you want to export to other clusters within your fleet.
Create the
ServiceExport
resource by running the following command:kubectl apply -f export.yaml
The initial export of your Service takes approximately five minutes to sync to clusters registered in your fleet. After a Service is exported, subsequent endpoint syncs happen immediately.
You can export the same Service from multiple clusters to create a single highly
available multi-cluster service endpoint with traffic distribution across
clusters. Before you export Services that have the same name and namespace,
ensure that you want them to be grouped in this manner. We recommend against
exporting services in the default
and kube-system
namespaces because of the
high probability of unintended name conflicts and the resulting unintended
grouping. If you are exporting more than five services with the same name and
namespace, traffic distribution on imported services might be limited to five
exported services.
Consuming cross-cluster Services
MCS only supports ClusterSetIP and headless Services. Only DNS "A" records are available.
After you create a ServiceExport
object, the following domain name resolves to
your exported Service from any Pod in any fleet cluster:
SERVICE_EXPORT_NAME.NAMESPACE.svc.clusterset.local
The output includes the following values:
SERVICE_EXPORT_NAME
andNAMESPACE
: the values you define in yourServiceExport
object.
For ClusterSetIP Services, the domain resolves to the ClusterSetIP
. You
can find this value by locating the ServiceImport
object in a cluster in the
namespace that the ServiceExport
object was created in. The ServiceImport
object is automatically created.
For example:
kind: ServiceImport
apiVersion: net.gke.io/v1
metadata:
namespace: EXPORTED-SERVICE-NAMESPACE
name: external-svc-SERVICE-EXPORT-TARGET
status:
ports:
- name: https
port: 443
protocol: TCP
targetPort: 443
ips: CLUSTER_SET_IP
MCS creates an Endpoints
object as part of importing a Service
into a
cluster. By investigating this object you can monitor the progress of a Service
import. To find the name of the Endpoints
object, look up the value of the
annotation net.gke.io/derived-service
on a ServiceImport
object
corresponding to your imported Service. For example:
kind: ServiceImport
apiVersion: net.gke.io/v1
annotations: net.gke.io/derived-service: DERIVED_SERVICE_NAME
metadata:
namespace: EXPORTED-SERVICE-NAMESPACE
name: external-svc-SERVICE-EXPORT-TARGET
Next, look up the Endpoints
object to check if MCS has already propagated the
endpoints to the importing cluster. The Endpoints
object is created in the
same namespace as the ServiceImport
object, under the name stored in the
net.gke.io/derived-service
annotation. For example:
kubectl get endpoints DERIVED_SERVICE_NAME -n NAMESPACE
Replace the following:
DERIVED_SERVICE_NAME
: the value of the annotationnet.gke.io/derived-service
on theServiceImport
object.NAMESPACE
: the namespace of theServiceExport
object.
You can find out more on the healthiness status of the endpoints using the Cloud Service Mesh dashboard in Google Cloud console.
For headless Services, the domain resolves to the list of IP addresses of the endpoints in the exporting clusters. Each backend Pod with a hostname is also independently addressable with a domain name of the following form:
HOSTNAME.MEMBERSHIP_NAME.LOCATION.SERVICE_EXPORT_NAME.NAMESPACE.svc.clusterset.local
The output includes the following values:
SERVICE_EXPORT_NAME
andNAMESPACE
: the values you define in yourServiceExport
object.MEMBERSHIP_NAME
: the unique identifier in the fleet for the cluster that the Pod is in.LOCATION
: the location of the membership. Memberships are eitherglobal
, or their location is one of the regions or zones that the Pod is in, such asus-central1
.HOSTNAME
: the hostname of the Pod.
You can also address a backend Pod with a hostname exported from a cluster registered with a global Membership, using a domain name of the following format:
HOSTNAME.MEMBERSHIP_NAME.SERVICE_EXPORT_NAME.NAMESPACE.svc.clusterset.local
Disabling MCS
To disable MCS, complete the following steps:
For each cluster in your fleet, delete each ServiceExport object that you created:
kubectl delete serviceexport SERVICE_EXPORT_NAME \ -n NAMESPACE
Replace the following:
SERVICE_EXPORT_NAME
: the name of your ServiceExport object.NAMESPACE
: the namespace of theServiceExport
object.
Verify that the
ServiceExport
disappears from the list in 30 minutes.Unregister your clusters from the fleet if they don't need to be registered for another purpose.
Disable the
multiclusterservicediscovery
feature:gcloud container fleet multi-cluster-services disable \ --project PROJECT_ID
Replace
PROJECT_ID
with the project ID from the project where you registered clusters.Disable the API for MCS:
gcloud services disable multiclusterservicediscovery.googleapis.com \ --project PROJECT_ID
Replace
PROJECT_ID
with the project ID from the project where you registered clusters.
Limitations
Number of clusters, Pods, and Service ports
The following limits are not enforced, and in some cases you can exceed these limits depending on the load in your clusters or project, and the rate of endpoint churn. You might experience performance issues when these limits are exceeded.
In Kubernetes, a Service is uniquely identified by its name and the namespace it belongs to. This name and the namespace pair is called a namespaced name.
Exporting clusters: A single Service, identified by a namespaced name, can be safely exported from up to 5 clusters simultaneously. Beyond that limit, it's possible that only a subset of endpoints can be imported to consuming clusters. You can export different Services from different subsets of clusters.
The number of Pods behind a single Service: It's safe if you keep below 250 Pods behind a single Service. This is the same limitation that single cluster Services have. With relatively static workloads and a small number of multi-cluster Services, it might be possible to significantly exceed this number into thousands of endpoints per Service. As with single cluster Services, all endpoints are watched by
kube-proxy
on every node. When going beyond this limit, especially when exporting from multiple clusters simultaneously, larger nodes might be required.The number of multi-cluster Services simultaneously exported: We recommend that you simultaneously export no more than 250 unique Service ports.
A unique Service port is identified by a namespaced name and a port number, that is a (name, namespace, port number) tuple. This means:
Services with the same namespaced name and port, exported from multiple clusters count as a single unique Service port.
Two Services with the same name and port, but different namespaces, for example (name, ns1, port-80) and (name, ns2, port-80) are two different Service ports, counting against two of the 250 unique Service port limit.
An exported Service exposing two ports 80 and 443 counts against two of the 250 unique Service port limit, regardless of the number of clusters in the fleet simultaneously exporting this Service.
Each multi-cluster Service counts toward your Backend Services quota, and each zone of each exporting cluster creates a network endpoint group (NEG). Increasing these quotas doesn't change the stated limit for the total count of unique Service ports.
Service types
MCS only supports ClusterSetIP and Headless Services. NodePort and LoadBalancer Services are not supported and might lead to an unexpected behaviour.
Using IPmasq Agent with MCS
MCS operates as expected when you use a default or other non masqueraded Pod IP range.
If you use a custom Pod IP range or a custom IPmasq agent ConfigMap, MCS traffic can be masqueraded. This prevents MCS from working because the firewall rules only allow traffic from Pod IPs.
To avoid this issue, you should either use the default Pod IP range or specify
all Pod IP ranges in the nonMasqueradeCIDRs
field of the
IPmasq agent ConfigMap.
If you use Autopilot or you must use a non-default Pod IP range and
cannot specify all Pod IP ranges in the ConfigMap, you should
use Egress NAT Policy to configure IP masquerade.
Reusing port numbers within an MCS Service
You can't reuse the same port number within one MCS Service even if the protocols are different.
This applies both within one Kubernetes Service and across all Kubernetes Services for one MCS Service.
MCS with clusters in multiple projects
You cannot export a service if that service is already being exported by other clusters in a different project in the fleet with the same name and namespace. You can access the service in other clusters in the fleet in other projects, but those clusters cannot export the same service in the same namespace.
Troubleshooting
The following sections provide you with troubleshooting tips for MCS.
Viewing the featureState
Viewing the feature state can help you confirm if MCS was configured successfully. You can view the MCS feature state by using the following command:
gcloud container fleet multi-cluster-services describe
The output is similar to the following:
createTime: '2021-08-10T13:05:23.512044937Z'
membershipStates:
projects/PROJECT_ID/locations/global/memberships/MCS_NAME:
state:
code: OK
description: Firewall successfully updated
updateTime: '2021-08-10T13:14:45.173444870Z'
name: projects/PROJECT_NAME/locations/global/features/multiclusterservicediscovery
resourceState:
state: ACTIVE
spec: {}
The most helpful fields for troubleshooting are code
and description
.
Codes in the featureState
A code indicates the member's general state in relation to MCS. You can find
these fields in the state.code
field. There are three possible
codes:
OK
: The membership was successfully added to MCS and is ready to use.WARNING
: MCS is in the process of reconciling membership setup. The description field can provide more information about what caused this code.FAILED
: This membership was not added to MCS. Other memberships in the fleet with anOK
code are not affected by thisFAILED
membership. The description field can provide more information about what caused this code.ERROR
: This membership is missing resources. Other memberships in the fleet with anOK
code are not affected by thisERROR
membership. The description field can provide more information about what caused this code.
Descriptions in the featureState
A description gives you further information about the membership's state in
MCS. You can find these descriptions in the state.description
field and you
can see the following descriptions:
Firewall successfully created
: This message indicates that the member's firewall rule was successfully created and or updated. The membership's code isOK
.Firewall creation pending
: This message indicates that the member's firewall rule is pending creation or update. The membership's code isWARNING
. This membership can experience issues updating and connecting to new multi-cluster Services and memberships added while the firewall rule is pending.GKE Cluster missing
: This message indicates that the registered GKE cluster is unavailable and or deleted. The membership's code isERROR
. This membership needs to be manually unregistered from the fleet after a GKE cluster is deleted.Project that member lives in is missing required permissions and/or has not enabled all required APIs - additional setup steps are required
: This message indicates there are internal StatusForbidden (403) errors, and the membership's code isFAILED
. This error occurs in the following scenarios:You have not enabled the necessary APIs in the member's project.
If the member cluster lives in a separate project than the fleet, see cross-project setup to ensure you have completed all necessary steps. If you have completed all steps, ensure that the following APIs are enabled in the registration project with the following commands:
gcloud services enable multiclusterservicediscovery.googleapis.com --project PROJECT_ID gcloud services enable dns.googleapis.com --project PROJECT_ID gcloud services enable trafficdirector.googleapis.com --project PROJECT_ID gcloud services enable cloudresourcemanager.googleapis.com --project PROJECT_ID
Replace
PROJECT_ID
with the project ID from the project where you registered clusters.The
mcsd
orgkehub
service account requires more permissions in the member's project.The
mcsd
andgkehub
service accounts should automatically have been created in the fleet host project with all the required permissions. To verify the service accounts exist, run the following commands:gcloud projects get-iam-policy PROJECT_ID | grep gcp-sa-mcsd gcloud projects get-iam-policy PROJECT_ID | grep gcp-sa-gkehub
Replace
PROJECT_ID
with the project ID from the fleet host project.
These commands should show you the full name of the
mcsd
andgkehub
service accounts.Multiple VPCs detected in the hub - VPC must be peered with other VPCs for successful connectivity
: This message occurs when clusters hosted in different VPCs are registered to the same fleet. Membership status isOK
. A cluster's VPC network is defined by its NetworkConfig's network. Multi-cluster Services require a flat network, and these VPCs must be actively peered for multi-cluster Services to properly connect to each other. To learn more, see Peer two networks.Member does not exist in the same project as hub - additional setup steps are required, errors may occur if not completed.
: This message reminds you that cross-project clusters require additional setup steps. Membership status isOK
. Cross-project memberships are defined as a member cluster that is not in the same project as the fleet. For more information, see cross-project setup.Non-GKE clusters are currently not supported
: This message reminds you that MCS only supports GKE clusters. Non-GKE clusters cannot be added to MCS. Membership status isFAILED
.
Known issues
MCS Services with multiple ports
There is a known issue with multi-cluster Services with multiple (TCP/UDP) ports on GKE Dataplane V2 where some endpoints are not programmed in the dataplane. This issue impacts GKE versions earlier than 1.26.3-gke.400.
As a workaround, when using GKE Dataplane V2, use multiple MCS with a single port instead of one MCS with multiple ports.
Port number reused within one MCS Service
You can't reuse the same port number within an MCS Service even if the protocols are different.
This applies both within one Kubernetes Service and across all Kubernetes Services for one MCS Service.
This behavior will be fixed in an upcoming release of MCS.
MCS with Shared VPC
With the current implementation of MCS, if you deploy more than one fleet in the same Shared VPC, metadata are shared between fleets. When a Service is created in one fleet, Service metadata is exported or imported in all other fleets that are part of the same Shared VPC and visible to the user.
This behavior will be fixed in an upcoming release of MCS.
Health check uses default port instead of containerPort
When you deploy a Service with a targetPort
field referencing a named port in
a Deployment, MCS configures the default port for the health check instead of
the specified containerPort
.
To avoid this issue, use numerical values in the Service field
ports.targetPort
and the Deployment field
readinessProbe.httpGet.port
instead of named values.
This behavior will be fixed in an upcoming release of MCS.
What's next
- Learn more about Services.
- Learn how to expose apps with Services.
- Implement a basic multi-cluster Services example.