@@ -99,7 +99,8 @@ tags, and then generate with `hack/update-toc.sh`.
99
99
- [ DNS] ( #dns )
100
100
- [ No PTR records necessary for multicluster DNS] ( #no-ptr-records-necessary-for-multicluster-dns )
101
101
- [ Not allowing cluster-specific targeting via DNS] ( #not-allowing-cluster-specific-targeting-via-dns )
102
- - [ EndpointSlice] ( #endpointslice )
102
+ - [ Tracking Endpoints] ( #tracking-endpoints )
103
+ - [ Using <code >EndpointSlice</code > objects to track endpoints] ( #using--objects-to-track-endpoints )
103
104
- [ Endpoint TTL] ( #endpoint-ttl )
104
105
- [ Constraints and Conflict Resolution] ( #constraints-and-conflict-resolution )
105
106
- [ Global Properties] ( #global-properties )
@@ -546,20 +547,6 @@ resolution](#constraints-and-conflict-resolution)). If all `ServiceExport`
546
547
instances are deleted, each `ServiceImport` will also be deleted from all
547
548
clusters.
548
549
549
- Since a given `ServiceImport` may be backed by multiple `EndpointSlices`, a
550
- given `EndpointSlice` will reference its `ServiceImport` using the label
551
- ` multicluster.kubernetes.io/service-name` similarly to how an `EndpointSlice` is
552
- associated with its `Service` in a single cluster.
553
-
554
- Each imported `EndpointSlice` will also have a
555
- ` multicluster.kubernetes.io/source-cluster` label with the cluster id, a
556
- clusterset-scoped unique identifier for the cluster. The `EndpointSlice`s
557
- imported for a service are not guaranteed to exactly match the originally
558
- exported `EndpointSlice`s, but each slice is guaranteed to map only to a single
559
- source cluster.
560
-
561
- The mcs-controller is responsible for managing imported `EndpointSlice`s.
562
-
563
550
` ` ` golang
564
551
// ServiceImport describes a service imported from clusters in a clusterset.
565
552
type ServiceImport struct {
@@ -641,6 +628,7 @@ type ClusterStatus struct {
641
628
Cluster string `json:"cluster"`
642
629
}
643
630
```
631
+
644
632
``` yaml
645
633
apiVersion : multicluster.k8s.io/v1alpha1
646
634
kind : ServiceImport
@@ -659,52 +647,28 @@ spec:
659
647
status :
660
648
clusters :
661
649
- cluster : us-west2-a-my-cluster
662
- ---
663
- apiVersion : discovery.k8s.io/v1beta1
664
- kind : EndpointSlice
665
- metadata :
666
- name : imported-my-svc-cluster-b-1
667
- namespace : my-ns
668
- labels :
669
- multicluster.kubernetes.io/source-cluster : us-west2-a-my-cluster
670
- multicluster.kubernetes.io/service-name : my-svc
671
- ownerReferences :
672
- - apiVersion : multicluster.k8s.io/v1alpha1
673
- controller : false
674
- kind : ServiceImport
675
- name : my-svc
676
- addressType : IPv4
677
- ports :
678
- - name : http
679
- protocol : TCP
680
- port : 80
681
- endpoints :
682
- - addresses :
683
- - " 10.1.2.3"
684
- conditions :
685
- ready : true
686
- topology :
687
- topology.kubernetes.io/zone : us-west2-a
688
650
` ` `
689
651
690
652
The ` ServiceImport.Spec.IP` (VIP) can be used to access this service from within
691
653
this cluster.
692
654
655
+
693
656
# ## ClusterSet Service Behavior Expectations
694
657
695
658
# ### Service Types
696
659
697
660
- `ClusterIP` : This is the straightforward case most of the proposal assumes.
698
- Each `EndpointSlice` associated with the exported service is combined with
699
- slices from other clusters to make up the clusterset service. They will be
700
- imported to the cluster behind the clusterset IP, with a `ServiceImport` of
701
- type `ClusterSetIP`. [Details](#EndpointSlice)
661
+ Each endpoint from a producing cluster associated with the exported service is
662
+ aggregated with endpoints from other clusters to make up the clusterset
663
+ service. They will be imported to the cluster behind the clusterset IP, with a
664
+ ` ServiceImport` of type `ClusterSetIP`. The details on how the clusterset IP
665
+ is allocated or how the combined slices are maintained may vary by
666
+ implementation; see also [Tracking Endpoints](#TrackingEndpoints).
702
667
- `ClusterIP : none` (Headless): Headless services are supported and will be
703
- imported with a `ServiceImport` and `EndpointSlices` like any other
704
- ` ClusterIP` service, but do not configure a VIP and must be consumed via
705
- [DNS](#DNS). Their `ServiceImport`s will be of type `Headless`. A
706
- multi-cluster service's headlessness is derived from it's constituent exported
707
- services according to the [conflict resolution
668
+ imported with a `ServiceImport` like any other `ClusterIP` service, but do not
669
+ configure a VIP and must be consumed via [DNS](#DNS). Their `ServiceImport`s
670
+ will be of type `Headless`. A multi-cluster service's headlessness is derived
671
+ from it's constituent exported services according to the [conflict resolution
708
672
policy](#constraints-and-conflict-resolution).
709
673
710
674
_Exporting a non-headless service to an otherwise headless service can
@@ -713,7 +677,7 @@ this cluster.
713
677
deployment error. Conditions and events on the `ServiceExport` will be used to
714
678
communicate conflicts to the user._
715
679
- `NodePort` and `LoadBalancer` : These create `ClusterIP` services that would
716
- sync as expected. For example If you export a `NodePort` service, the
680
+ sync as expected. For example if you export a `NodePort` service, the
717
681
resulting cross-cluster service will still be a clusterset IP type. The local
718
682
service will not be affected. Node ports can still be used to access the
719
683
cluster-local service in the source cluster, and only the clusterset IP will
@@ -891,8 +855,25 @@ additional label gives additional context, which is implementation-dependent and
891
855
may be used for instance to uniquely identify the cluster registry with which a
892
856
cluster is registered.
893
857
858
+ ### Tracking Endpoints
859
+
860
+ The specific mechanism by which the `mcs-controller` maintains references to the
861
+ individual backends for an aggregated service is an implementation detail not
862
+ fully prescribed by this specification. Implementations may depend on a higher
863
+ level (possibly vendor-specific) API, offload to a load balancer or xDS server
864
+ (like Envoy), or use Kubernetes networking APIs. If the implementation depends
865
+ on Kubernetes networking APIs, specifically `EndpointSlice` objects, they must
866
+ conform to the specification in the following section.
867
+
868
+ #### Using `EndpointSlice` objects to track endpoints
894
869
895
- #### EndpointSlice
870
+ _Optional to create, but specification defined if present._
871
+
872
+ If an implementation does create `discovery.k8s.io/v1 EndpointSlice`s, they must
873
+ conform to the following structure. This structure was originally required as
874
+ part of this specification in alpha, and are the structure on which other
875
+ SIG-endorsed reference implementations and tooling, like the [CoreDNS
876
+ multicluster plugin](https://github.com/coredns/multicluster/), depend.
896
877
897
878
When a `ServiceExport` is created, this will cause `EndpointSlice` objects for
898
879
the underlying `Service` to be created in each importing cluster within the
@@ -904,6 +885,68 @@ controller, so that the endpoint slice controller doesn’t delete them.
904
885
`EndpointSlices` will have an owner reference to their associated
905
886
`ServiceImport`.
906
887
888
+ Since a given `ServiceImport` may be backed by multiple `EndpointSlices`, a
889
+ given `EndpointSlice` will reference its `ServiceImport` using the label
890
+ `multicluster.kubernetes.io/service-name` similarly to how an `EndpointSlice` is
891
+ associated with its `Service` in a single cluster.
892
+
893
+ Each imported `EndpointSlice` will also have a
894
+ `multicluster.kubernetes.io/source-cluster` label with the cluster id, a
895
+ clusterset-scoped unique identifier for the cluster. The `EndpointSlice`s
896
+ imported for a service are not guaranteed to exactly match the originally
897
+ exported `EndpointSlice`s, but each slice is guaranteed to map only to a single
898
+ source cluster.
899
+
900
+ If the implementation is using `EndpointSlice`s in this way, the mcs-controller
901
+ is responsible for managing the imported `EndpointSlice`s and making sure they
902
+ are conformant with this section.
903
+
904
+ ```yaml
905
+ apiVersion: multicluster.k8s.io/v1alpha1
906
+ kind: ServiceImport
907
+ metadata:
908
+ name: my-svc
909
+ namespace: my-ns
910
+ spec:
911
+ ips:
912
+ - 42.42.42.42
913
+ type: "ClusterSetIP"
914
+ ports:
915
+ - name: http
916
+ protocol: TCP
917
+ port: 80
918
+ sessionAffinity: None
919
+ status:
920
+ clusters:
921
+ - cluster: us-west2-a-my-cluster
922
+ ---
923
+ apiVersion: discovery.k8s.io/v1beta1
924
+ kind: EndpointSlice
925
+ metadata:
926
+ name: imported-my-svc-cluster-b-1
927
+ namespace: my-ns
928
+ labels:
929
+ multicluster.kubernetes.io/source-cluster: us-west2-a-my-cluster
930
+ multicluster.kubernetes.io/service-name: my-svc
931
+ ownerReferences:
932
+ - apiVersion: multicluster.k8s.io/v1alpha1
933
+ controller: false
934
+ kind: ServiceImport
935
+ name: my-svc
936
+ addressType: IPv4
937
+ ports:
938
+ - name: http
939
+ protocol: TCP
940
+ port: 80
941
+ endpoints:
942
+ - addresses:
943
+ - "10.1.2.3"
944
+ conditions:
945
+ ready: true
946
+ topology:
947
+ topology.kubernetes.io/zone: us-west2-a
948
+ ```
949
+
907
950
```
908
951
<<[UNRESOLVED]>>
909
952
We have not yet sorted out scalability impact here. We hope the upper bound for
0 commit comments