{"id":17495823,"url":"https://github.com/feiskyer/mcs","last_synced_at":"2025-04-14T22:21:36.875Z","repository":{"id":57574988,"uuid":"347527715","full_name":"feiskyer/mcs","owner":"feiskyer","description":"Multi-Cluster Service Operator on Azure","archived":false,"fork":false,"pushed_at":"2021-07-05T05:42:25.000Z","size":129,"stargazers_count":3,"open_issues_count":0,"forks_count":2,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-03-28T10:21:22.474Z","etag":null,"topics":["kubernetes-operator","multi-cluster"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/feiskyer.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2021-03-14T02:37:33.000Z","updated_at":"2022-04-26T18:31:39.000Z","dependencies_parsed_at":"2022-09-18T06:34:21.252Z","dependency_job_id":null,"html_url":"https://github.com/feiskyer/mcs","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/feiskyer%2Fmcs","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/feiskyer%2Fmcs/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/feiskyer%2Fmcs/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/feiskyer%2Fmcs/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/feiskyer","download_url":"https://codeload.github.com/feiskyer/mcs/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248969074,"owners_count":21191187,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["kubernetes-operator","multi-cluster"],"created_at":"2024-10-19T14:33:29.507Z","updated_at":"2025-04-14T22:21:36.853Z","avatar_url":"https://github.com/feiskyer.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Multi-Cluster Service Operator on Azure\n\nAn operator for exposing services from multiple Kubernetes clusters by leveraging [Azure cross-region load balancer](https://docs.microsoft.com/en-us/azure/load-balancer/cross-region-overview).\n\n![](https://docs.microsoft.com/en-us/azure/load-balancer/media/cross-region-overview/cross-region-load-balancer.png)\n\n- **Status:** DRAFT\n- **Issues:** due to limitations of Global LoadBalancer, FloatingIP needs to be enabled on both Global LoadBalancer and regional LoadBalancer. And the the global VIP needs to be configured on each nodes to make FloatingIP work (this could be done by adding global VIP to each cluster's `service.status.loadBalancer.ingress[]`.\n\n## How to deploy MCS operator\n\nCreate Azure service principal and then create the the following `cloud-config` file:\n\n```json\n{\n  \"cloud\": \"AzurePublicCloud\",\n  \"tenantId\": \"\u003ctenantId\u003e\",\n  \"subscriptionId\": \"\u003csubscriptionId\u003e\",\n  \"aadClientId\": \"\u003caadClientId\u003e\",\n  \"aadClientSecret\": \"\u003caadClientSecret\u003e\",\n  \"globalLoadBalancerName\": \"\u003cglbName\u003e\",\n  \"globalVIPLocation\": \"\u003cregion\u003e\",\n  \"globalLoadBalancerResourceGroup\": \"\u003cresourceGroup\u003e\"\n}\n```\n\nThen create a secret based on this config file:\n\n```sh\nkubectl create secret generic azure-mcs-config --from-file=cloud-config\n```\n\nAfter that, deploy the MCS operator in MCS cluster (it could be any Kubernetes cluster):\n\n```sh\nkubectx mcs-cluster\nmake deploy\n```\n\n## Samples\n\n### Create KubeCluster\n\nAssume you have two Kubernetes clusters running on Azure, one is created via aks-engine and the other is created via AKS.\n\nSwitch kubeconfig to MCS cluster, and then create the following two KubeCluster:\n\n```sh\n# For cluster aks-engine\nkubectl create secret generic aks-engine --from-file=kubeconfig\ncat \u003c\u003cEOF | kubectl apply -f -\napiVersion: networking.aks.io/v1alpha1\nkind: KubeCluster\nmetadata:\n  name: aks-engine\n  namespace: default\nspec:\n  kubeConfigSecret: aks-engine\nEOF\n\n# For cluster aks-cluster\nkubectl create secret generic aks-cluster --from-file=kubeconfig\ncat \u003c\u003cEOF | kubectl apply -f -\napiVersion: networking.aks.io/v1alpha1\nkind: KubeCluster\nmetadata:\n  name: aks-cluster\n  namespace: default\nspec:\n  kubeConfigSecret: aks-cluster\nEOF\n```\n\n### Create GlobalService\n\nSwitch kubeconfig to MCS cluster and then create global service:\n\n```sh\nkubectx mcs-cluster\n\ncat \u003c\u003cEOF | kubectl apply -f -\napiVersion: networking.aks.io/v1alpha1\nkind: GlobalService\nmetadata:\n  name: nginx\n  namespace: default\nspec:\n  clusterSet:\n  - aks-engine\n  - aks-cluster\n  ports:\n  - name: http\n    port: 80\n    protocol: TCP\nEOF\n```\n\n### Deploy nginx service in both cluster\n\nMCS operator assumes the service names are same as globalservice in all clusters.\n\n```sh\nkubectx aks-engine\nkubectl create deployment nginx --image nginx --save-config\nkubectl expose deploy nginx --port=80 --type=LoadBalancer\nkubectl get service nginx\n\nkubectx aks-cluster\nkubectl create deployment nginx --image nginx --save-config\nkubectl expose deploy nginx --port=80 --type=LoadBalancer\nkubectl get service nginx\n```\n\n### Verify Global VIP\n\nSwitch kubeconfig back to MCS cluster and then verify the VIP for the global service:\n\n```sh\n$ kubectl get globalservice nginx -o yaml\napiVersion: networking.aks.io/v1alpha1\nkind: GlobalService\nmetadata:\n  name: nginx\n  namespace: default\n  resourceVersion: \"279410693\"\n  selfLink: /apis/networking.aks.io/v1alpha1/namespaces/default/globalservices/nginx\n  uid: edb771f9-328e-4785-b94d-b70e13b10ffe\nspec:\n  ports:\n  - name: http\n    port: 80\n    protocol: TCP\nstatus:\n  endpoints:\n  - cluster: default/aks-engine\n    ip: 52.184.9.136\n    resourceGroup: \"\u003crg1\u003e\"\n  - cluster: default/aks-cluster\n    ip: 20.198.185.119\n    resourceGroup: \"\u003crg2\u003e\"\n  vip: 23.98.101.30\n\n# verify the vip is available\n$ curl 23.98.101.30\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffeiskyer%2Fmcs","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffeiskyer%2Fmcs","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffeiskyer%2Fmcs/lists"}