-
Notifications
You must be signed in to change notification settings - Fork 15
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Feature Request: Provide an MCS Controller Implementation Using Sveltos’s Event Framework #435
Comments
Thank you @kahirokunn Let me summarise it to see if I got it.
Is that correct? |
Thank you @gianlucam76 The port (443/https in the example) is not a constant - it matches exactly with the port of the Kubernetes Service that has the same name as the ServiceExport. Everything else in your summary is accurate! Also, one important point to add: Even if you have three clusters in a clusterset and two of them create ServiceExports, there should only be one ServiceImport created. |
Thank you. This is achievable already with Sveltos. Next week (I am pretty tight this week), I will prepare the Sveltos configuration for this and share. I might need your help testing it though. |
Please allow me to re-read the KEP and share the revised version with you. MCS Controller Implementation Guide Using Sveltos - RevisedOverviewThis guide details how to automate the implementation of the Kubernetes Multi-Cluster Services (MCS) API using Sveltos's Event Framework. In this revised document, we introduce the concept of creating derived Services named “derived-$hashServiceExport,” where $hash is computed from the ServiceExport name. Refer to the following implementation for hashing: We also create one EndpointSlice for each source cluster associated with the ServiceExport, named “derived-$hash-$clusterId.” For clarity, the label “multicluster.kubernetes.io/service-name: ” is added to both the EndpointSlice and the derived Service. Additionally, we establish OwnerReferences from the ServiceImport to the Service, and from the Service to the EndpointSlice. Processing Patterns by Service Type1. ClusterIP / LoadBalancer / NodePort ServicesThese service types can be handled with the same processing pattern. Below is an example: Original Service in Source Cluster (ClusterID: cluster-a)apiVersion: v1
kind: Service
metadata:
name: web-service
namespace: default
spec:
type: ClusterIP # or LoadBalancer or NodePort
selector:
app: web
ports:
- name: http
port: 80
targetPort: 8080 ServiceExport (ClusterID: cluster-a)apiVersion: multicluster.k8s.io/v1alpha1
kind: ServiceExport
metadata:
name: web-service
namespace: default Generated ServiceImport (ClusterID: cluster-b)apiVersion: multicluster.k8s.io/v1alpha1
kind: ServiceImport
metadata:
name: web-service
namespace: default
annotations:
multicluster.kubernetes.io/derived-service: derived-$hashServiceExport
spec:
type: ClusterSetIP
ports:
- name: http
port: 80
protocol: TCP
ips:
- "10.96.0.1" # Cluster IP assigned to the derived Service
status:
clusters:
- cluster: cluster-a Generated Service (ClusterID: cluster-b)apiVersion: v1
kind: Service
metadata:
name: derived-$hashServiceExport
namespace: default
labels:
multicluster.kubernetes.io/service-name: web-service
multicluster.kubernetes.io/service-imported: "true"
app.kubernetes.io/managed-by: sveltos
ownerReferences:
- apiVersion: multicluster.k8s.io/v1alpha1
kind: ServiceImport
name: web-service
# other fields (uid, controller, blockOwnerDeletion) required by OwnerReference
spec:
type: ClusterIP
selector: # Selector is maintained based on namespace sameness
app: web
ports:
- name: http
port: 80
targetPort: 8080 Generated EndpointSlice (ClusterID: cluster-b)apiVersion: discovery.k8s.io/v1
kind: EndpointSlice
metadata:
name: derived-$hashServiceExport-clustera
namespace: default
labels:
kubernetes.io/service-name: web-service
multicluster.kubernetes.io/service-name: web-service
cluster.x-k8s.io/cluster-name: cluster-a
endpointslice.kubernetes.io/managed-by: sveltos
ownerReferences:
- apiVersion: multicluster.k8s.io/v1alpha1
kind: ServiceImport
name: web-service
# other fields (uid, controller, blockOwnerDeletion) required by OwnerReference
addressType: IPv4
ports:
- name: http
protocol: TCP
port: 80
endpoints:
- addresses:
- "10.0.1.1"
conditions:
ready: true
nodeName: node-a
- addresses:
- "10.0.1.2"
conditions:
ready: true
nodeName: node-b 2. Headless Services (clusterIP: None)Headless services require special handling, typically relying on DNS-based service discovery instead of a VIP (Virtual IP). Initially, one might assume an MCS controller only needs to create ServiceImport objects; however, since CoreDNS uses EndpointSlices as a record source (reference: https://github.com/coredns/multicluster/blob/49f47d950355f793d656aec8a6d198daf1d888b1/multicluster.go#L347-L381), the controller must also create EndpointSlices for each source cluster for correct DNS-based service discovery. Original Service in Source Cluster (ClusterId: cluster-a)apiVersion: v1
kind: Service
metadata:
name: stateful-service
namespace: default
spec:
clusterIP: None
selector:
app: stateful
ports:
- name: http
port: 80
targetPort: 8080 ServiceExport (ClusterId: cluster-a)apiVersion: multicluster.k8s.io/v1alpha1
kind: ServiceExport
metadata:
name: stateful-service
namespace: default Generated ServiceImport (ClusterID: cluster-b)apiVersion: multicluster.k8s.io/v1alpha1
kind: ServiceImport
metadata:
name: stateful-service
namespace: default
annotations:
multicluster.kubernetes.io/derived-service: derived-$hashServiceExport
spec:
type: Headless
ports:
- name: http
port: 80
protocol: TCP
status:
clusters:
- cluster: cluster-a Generated EndpointSlice for Headless Service (ClusterID: cluster-b)apiVersion: discovery.k8s.io/v1
kind: EndpointSlice
metadata:
name: derived-$hashServiceExport-clustera
namespace: default
labels:
kubernetes.io/service-name: stateful-service
multicluster.kubernetes.io/service-name: stateful-service
cluster.x-k8s.io/cluster-name: cluster-a
endpointslice.kubernetes.io/managed-by: sveltos
ownerReferences:
- apiVersion: multicluster.k8s.io/v1alpha1
kind: ServiceImport
name: web-service
# other fields (uid, controller, blockOwnerDeletion) required by OwnerReference
addressType: IPv4
ports:
- name: http
protocol: TCP
port: 80
endpoints:
- addresses:
- "10.0.2.1"
conditions:
ready: true
nodeName: node-c
- addresses:
- "10.0.2.2"
conditions:
ready: true
nodeName: node-d 3. ExternalName ServicesExternalName services cannot be exported. Original Service in Source Cluster (ClusterId: cluster-a)apiVersion: v1
kind: Service
metadata:
name: external-db
namespace: default
spec:
type: ExternalName
externalName: db.example.com ServiceExport (ClusterId: cluster-a)apiVersion: multicluster.k8s.io/v1alpha1
kind: ServiceExport
metadata:
name: external-db
namespace: default This ServiceExport will fail with the following status: apiVersion: multicluster.k8s.io/v1alpha1
kind: ServiceExport
metadata:
name: external-db
namespace: default
status:
conditions:
- type: InvalidService
status: "True"
reason: UnsupportedServiceType
message: "ExternalName services cannot be exported" Key Implementation Points
Architectural Considerations
|
Summary
We propose a feature (or guideline documentation) illustrating how to implement an MCS (Multi-Cluster Services) controller using Sveltos’s Event Framework. This controller detects the presence of a ServiceExport in a “source” cluster, then automates the creation and maintenance of:
derived-$hashServiceExport
that inherits key fields (e.g., ports, selectors) from the exported Service.derived-$hashServiceExport-$clusterId
, which reflects the actual Pod endpoints from that source.The solution adheres to KEP-1645, following the principle of namespace sameness. It manages ClusterIP, Headless, and LoadBalancer/NodePort services consistently, while explicitly disallowing ExternalName services.
Background
The Kubernetes MCS API standardizes how services can be exported from one cluster and discovered in others. By pairing this with Sveltos’s Event Framework, we can fully automate the “service export → derived service + endpointslice + serviceimport” pipeline. This removes the burden of manually provisioning these resources across multiple clusters.
Proposed Baseline Example
Below are minimal YAML snippets representing the core resources that will be generated or updated whenever a new ServiceExport is detected in a source cluster. The controller computes “$hashServiceExport” from the ServiceExport’s name (refer to the official MCS implementation for details).
Workflow
Benefits
By following the strategies outlined above and implementing them in Sveltos’s Event Framework, platform engineers can reliably export services from any source cluster and consume them with minimal configuration overhead. This significantly accelerates multi-cluster use cases—whether for high availability, traffic optimization, or cross-environment integrations—without inventing a proprietary approach.
The text was updated successfully, but these errors were encountered: