Multi-cluster Service Discovery

Users are able to export and import services between clusters with Multi-cluster Service APIs.

Note: To use this feature, the Kubernetes version of the member cluster must be v1.21 or later.

Prerequisites

Karmada has been installed

We can install Karmada by referring to Quick Start, or directly run hack/local-up-karmada.sh script which is also used to run our E2E cases.

Member Cluster Network

Ensure that at least two clusters have been added to Karmada, and the container networks between member clusters are connected.

  • If you use the hack/local-up-karmada.sh script to deploy Karmada, Karmada will have three member clusters, and the container networks of the member1 and member2 will be connected.
  • You can use Submariner or other related open source projects to connected networks between member clusters.

Note: In order to prevent routing conflicts, Pod and Service CIDRs of clusters need non-overlapping.

The ServiceExport and ServiceImport CRDs have been installed

We need to install ServiceExport and ServiceImport in the member clusters.

After ServiceExport and ServiceImport have been installed on the Karmada Control Plane, we can create ClusterPropagationPolicy to propagate those two CRDs to the member clusters.

  1. # propagate ServiceExport CRD
  2. apiVersion: policy.karmada.io/v1alpha1
  3. kind: ClusterPropagationPolicy
  4. metadata:
  5. name: serviceexport-policy
  6. spec:
  7. resourceSelectors:
  8. - apiVersion: apiextensions.k8s.io/v1
  9. kind: CustomResourceDefinition
  10. name: serviceexports.multicluster.x-k8s.io
  11. placement:
  12. clusterAffinity:
  13. clusterNames:
  14. - member1
  15. - member2
  16. ---
  17. # propagate ServiceImport CRD
  18. apiVersion: policy.karmada.io/v1alpha1
  19. kind: ClusterPropagationPolicy
  20. metadata:
  21. name: serviceimport-policy
  22. spec:
  23. resourceSelectors:
  24. - apiVersion: apiextensions.k8s.io/v1
  25. kind: CustomResourceDefinition
  26. name: serviceimports.multicluster.x-k8s.io
  27. placement:
  28. clusterAffinity:
  29. clusterNames:
  30. - member1
  31. - member2

Example

Step 1: Deploy service on the member1 cluster

We need to deploy service on the member1 cluster for discovery.

  1. apiVersion: apps/v1
  2. kind: Deployment
  3. metadata:
  4. name: serve
  5. spec:
  6. replicas: 1
  7. selector:
  8. matchLabels:
  9. app: serve
  10. template:
  11. metadata:
  12. labels:
  13. app: serve
  14. spec:
  15. containers:
  16. - name: serve
  17. image: jeremyot/serve:0a40de8
  18. args:
  19. - "--message='hello from cluster member1 (Node: {{env \"NODE_NAME\"}} Pod: {{env \"POD_NAME\"}} Address: {{addr}})'"
  20. env:
  21. - name: NODE_NAME
  22. valueFrom:
  23. fieldRef:
  24. fieldPath: spec.nodeName
  25. - name: POD_NAME
  26. valueFrom:
  27. fieldRef:
  28. fieldPath: metadata.name
  29. ---
  30. apiVersion: v1
  31. kind: Service
  32. metadata:
  33. name: serve
  34. spec:
  35. ports:
  36. - port: 80
  37. targetPort: 8080
  38. selector:
  39. app: serve
  40. ---
  41. apiVersion: policy.karmada.io/v1alpha1
  42. kind: PropagationPolicy
  43. metadata:
  44. name: mcs-workload
  45. spec:
  46. resourceSelectors:
  47. - apiVersion: apps/v1
  48. kind: Deployment
  49. name: serve
  50. - apiVersion: v1
  51. kind: Service
  52. name: serve
  53. placement:
  54. clusterAffinity:
  55. clusterNames:
  56. - member1

Step 2: Export service to the member2 cluster

  • Create a ServiceExport object on Karmada Control Plane, and then create a PropagationPolicy to propagate the ServiceExport object to the member1 cluster.

    1. apiVersion: multicluster.x-k8s.io/v1alpha1
    2. kind: ServiceExport
    3. metadata:
    4. name: serve
    5. ---
    6. apiVersion: policy.karmada.io/v1alpha1
    7. kind: PropagationPolicy
    8. metadata:
    9. name: serve-export-policy
    10. spec:
    11. resourceSelectors:
    12. - apiVersion: multicluster.x-k8s.io/v1alpha1
    13. kind: ServiceExport
    14. name: serve
    15. placement:
    16. clusterAffinity:
    17. clusterNames:
    18. - member1
  • Create a ServiceImport object on Karmada Control Plane, and then create a PropagationPolicy to propagate the ServiceImport object to the member2 cluster.

    1. apiVersion: multicluster.x-k8s.io/v1alpha1
    2. kind: ServiceImport
    3. metadata:
    4. name: serve
    5. spec:
    6. type: ClusterSetIP
    7. ports:
    8. - port: 80
    9. protocol: TCP
    10. ---
    11. apiVersion: policy.karmada.io/v1alpha1
    12. kind: PropagationPolicy
    13. metadata:
    14. name: serve-import-policy
    15. spec:
    16. resourceSelectors:
    17. - apiVersion: multicluster.x-k8s.io/v1alpha1
    18. kind: ServiceImport
    19. name: serve
    20. placement:
    21. clusterAffinity:
    22. clusterNames:
    23. - member2

Step 3: Access the service from member2 cluster

After the above steps, we can find the derived service which has the prefix derived- on the member2 cluster. Then, we can access the derived service to access the service on the member1 cluster.

  1. # get the services in cluster member2, and we can find the service with the name 'derived-serve'
  2. $ kubectl --kubeconfig ~/.kube/members.config --context member2 get svc
  3. NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
  4. derived-serve ClusterIP 10.13.205.2 <none> 80/TCP 81s
  5. kubernetes ClusterIP 10.13.0.1 <none> 443/TCP 15m

Start a pod request on the member2 cluster to access the ClusterIP of derived service:

  1. $ kubectl --kubeconfig ~/.kube/members.config --context member2 run -i --rm --restart=Never --image=jeremyot/request:0a40de8 request -- --duration={duration-time} --address={ClusterIP of derived service}

Eg, if we continue to access service for 3s, ClusterIP is 10.13.205.2:

  1. # access the service of derived-serve, and the pod in member1 cluster returns a response
  2. $ kubectl --kubeconfig ~/.kube/members.config --context member2 run -i --rm --restart=Never --image=jeremyot/request:0a40de8 request -- --duration=3s --address=10.13.205.2
  3. If you don't see a command prompt, try pressing enter.
  4. 2022/07/24 15:13:08 'hello from cluster member1 (Node: member1-control-plane Pod: serve-9b5b94f65-cp87p Address: 10.10.0.5)'
  5. 2022/07/24 15:13:09 'hello from cluster member1 (Node: member1-control-plane Pod: serve-9b5b94f65-cp87p Address: 10.10.0.5)'
  6. pod "request" deleted