├── .github ├── ISSUE_TEMPLATE │ ├── config.yml │ ├── something-else.md │ ├── bug_report.md │ └── feature_request.md ├── release.yml ├── workflows │ ├── linkcheck.yml │ ├── pr-cli.yml │ ├── pr-e2e-test.yml │ ├── codeql.yml │ ├── pr-check.yml │ └── release.yml └── dependabot.yml ├── pkg ├── controlplane │ ├── authz │ │ └── connectivitypdp │ │ │ ├── test_data │ │ │ ├── not_a_yaml │ │ │ ├── simple_privileged.yaml │ │ │ ├── privileged_and_regular.yaml │ │ │ ├── all_layers.yaml │ │ │ └── mixed_policies_and_other_resources.yaml │ │ │ └── accesspolicy.go │ ├── api │ │ ├── heartbeat.go │ │ ├── const.go │ │ └── xds.go │ └── xds │ │ ├── server.go │ │ └── controllers.go ├── dataplane │ └── api │ │ └── const.go ├── versioninfo │ ├── variables.go │ └── version.go ├── apis │ └── clusterlink.net │ │ └── v1alpha1 │ │ ├── groupversion_info.go │ │ ├── accesspolicy_test.go │ │ ├── export.go │ │ └── peer.go └── util │ ├── controller │ └── manager.go │ ├── grpc │ └── server.go │ └── tcp │ └── listener.go ├── website ├── content │ └── en │ │ ├── search.md │ │ ├── docs │ │ ├── main │ │ │ ├── tutorials │ │ │ │ ├── _index.md │ │ │ │ └── bookinfo │ │ │ │ │ └── bookinfo.png │ │ │ ├── concepts │ │ │ │ ├── _index.md │ │ │ │ └── fabric.md │ │ │ ├── tasks │ │ │ │ ├── _index.md │ │ │ │ ├── relay │ │ │ │ │ └── nginx-relay.png │ │ │ │ └── private-networks │ │ │ │ │ └── frp-system.png │ │ │ ├── _index.md │ │ │ └── getting-started │ │ │ │ └── _index.md │ │ ├── v0.1 │ │ │ ├── tutorials │ │ │ │ └── _index.md │ │ │ ├── concepts │ │ │ │ └── _index.md │ │ │ ├── _index.md │ │ │ └── getting-started │ │ │ │ └── _index.md │ │ ├── v0.2 │ │ │ ├── tutorials │ │ │ │ ├── _index.md │ │ │ │ └── bookinfo │ │ │ │ │ └── bookinfo.png │ │ │ ├── concepts │ │ │ │ └── _index.md │ │ │ ├── tasks │ │ │ │ └── _index.md │ │ │ ├── _index.md │ │ │ └── getting-started │ │ │ │ └── _index.md │ │ ├── v0.3 │ │ │ ├── tutorials │ │ │ │ ├── _index.md │ │ │ │ └── bookinfo │ │ │ │ │ └── bookinfo.png │ │ │ ├── concepts │ │ │ │ ├── _index.md │ │ │ │ └── fabric.md │ │ │ ├── tasks │ │ │ │ ├── _index.md │ │ │ │ └── relay │ │ │ │ │ └── nginx-relay.png │ │ │ ├── _index.md │ │ │ └── getting-started │ │ │ │ └── _index.md │ │ ├── v0.4 │ │ │ ├── tutorials │ │ │ │ ├── _index.md │ │ │ │ └── bookinfo │ │ │ │ │ └── bookinfo.png │ │ │ ├── concepts │ │ │ │ ├── _index.md │ │ │ │ └── fabric.md │ │ │ ├── tasks │ │ │ │ ├── _index.md │ │ │ │ ├── relay │ │ │ │ │ └── nginx-relay.png │ │ │ │ └── private-networks │ │ │ │ │ └── frp-system.png │ │ │ ├── _index.md │ │ │ └── getting-started │ │ │ │ └── _index.md │ │ └── _index.md │ │ ├── featured-background.png │ │ └── blog │ │ ├── hello-world │ │ └── sunflower.jpg │ │ ├── clusterlink-intro │ │ └── field.jpg │ │ └── _index.md ├── .gitignore ├── assets │ ├── icons │ │ └── logo.png │ └── scss │ │ └── _variables_project.scss ├── static │ ├── icons │ │ ├── icon1.png │ │ ├── icon2.png │ │ ├── icon3.png │ │ ├── icon4.png │ │ ├── icon5.png │ │ └── icon6.png │ ├── clusterlink_logo.png │ ├── favicons │ │ ├── favicon.ico │ │ ├── favicon.png │ │ ├── favicon-32x32.png │ │ └── apple-touch-icon-180x180.png │ ├── clusterlink_figure.png │ ├── logo-white-yellow.png │ ├── backgrounds │ │ ├── section2.jpg │ │ └── section4.jpg │ ├── logo-darkblue-yellow.png │ ├── logo-lightblue-yellow.png │ └── files │ │ ├── peer_crd_sample.yaml │ │ └── tutorials │ │ ├── allow-all-policy.md │ │ ├── cli-installation.md │ │ ├── envsubst.md │ │ ├── nginx │ │ └── nginx-output.md │ │ └── deploy-clusterlink.md ├── i18n │ └── en.toml ├── package.json ├── layouts │ ├── index.redirects │ ├── shortcodes │ │ ├── abbr.html │ │ ├── anchor.html │ │ ├── clusterlink │ │ │ ├── feature.html │ │ │ ├── intro.html │ │ │ ├── main.html │ │ │ └── card.html │ │ └── expand.html │ └── partials │ │ └── favicons.html ├── go.mod ├── netlify.toml ├── Makefile └── go.sum ├── docs ├── ClusteLink.pdf ├── mbg-proto.png ├── policy-arch.png ├── openspeedtest.png ├── figures │ ├── BookInfo_demo.png │ └── clusterlink.png └── Policy.md ├── demos ├── frp │ ├── testdata │ │ └── manifests │ │ │ ├── frp-ns.yaml │ │ │ ├── server │ │ │ ├── frps-configmap.yaml │ │ │ └── frps.yaml │ │ │ └── client │ │ │ ├── frpc.yaml │ │ │ ├── peer1 │ │ │ ├── frpc-configmap.yaml │ │ │ └── peer.yaml │ │ │ ├── peer2 │ │ │ ├── frpc-configmap.yaml │ │ │ └── peer.yaml │ │ │ └── peer3 │ │ │ ├── frpc-configmap.yaml │ │ │ └── peer.yaml │ └── kind │ │ └── test.py ├── nginx │ └── testdata │ │ ├── clusterlink │ │ ├── export-nginx.yaml │ │ ├── peer-client.yaml │ │ ├── peer-relay.yaml │ │ ├── peer-server.yaml │ │ ├── allow-policy.yaml │ │ ├── import-nginx.yaml │ │ └── import-nginx-relay.yaml │ │ ├── nginx-job.yaml │ │ ├── nginx-relay-job.yaml │ │ └── nginx-server.yaml ├── bookinfo │ ├── manifests │ │ ├── clusterlink │ │ │ ├── export-reviews.yaml │ │ │ ├── peer-client.yaml │ │ │ ├── peer-server1.yaml │ │ │ ├── peer-server2.yaml │ │ │ ├── allow-policy.yaml │ │ │ ├── import-reviews.yaml │ │ │ ├── import-reviews-lb-random.yaml │ │ │ ├── import-reviews-lb-static.yaml │ │ │ └── deny-server1-policy.yaml │ │ ├── review │ │ │ ├── rating.yaml │ │ │ ├── review-v2.yaml │ │ │ └── review-v3.yaml │ │ └── product │ │ │ ├── details.yaml │ │ │ ├── product.yaml │ │ │ └── product2.yaml │ ├── kind │ │ ├── gw_failover.py │ │ ├── apply_lb.py │ │ └── README.md │ └── cloud │ │ ├── gw_failover.py │ │ └── apply_lb.py ├── iperf3 │ ├── testdata │ │ └── manifests │ │ │ ├── clusterlink │ │ │ ├── export-iperf3.yaml │ │ │ ├── peer-client.yaml │ │ │ ├── peer-server.yaml │ │ │ ├── allow-policy.yaml │ │ │ └── import-iperf3.yaml │ │ │ ├── iperf3-server │ │ │ ├── kind-config.yaml │ │ │ ├── iperf3-svc.yaml │ │ │ └── iperf3.yaml │ │ │ └── iperf3-client │ │ │ ├── kind-config.yaml │ │ │ ├── iperf3-client.yaml │ │ │ └── iperf3-client2.yaml │ └── kind │ │ ├── test.py │ │ └── iperf3_client_start.py ├── utils │ ├── manifests │ │ └── kind │ │ │ ├── cl-svc.yaml │ │ │ ├── calico │ │ │ └── calico-config.yaml │ │ │ └── flannel │ │ │ ├── flannel-config.yaml │ │ │ └── create_cni_bridge.py │ ├── __init__.py │ └── common.py ├── speedtest │ └── testdata │ │ ├── policy │ │ ├── denyFromGw.yaml │ │ └── denyToSpeedtest.yaml │ │ └── manifests │ │ ├── firefox.yaml │ │ ├── firefox2.yaml │ │ └── speedtest.yaml └── qotd │ └── manifests │ ├── qotd_db.yaml │ ├── qotd_image.yaml │ ├── qotd_rating.yaml │ ├── qotd_pdf.yaml │ ├── qotd_engraving.yaml │ └── qotd_quote.yaml ├── design-proposals └── deployment.png ├── cmd ├── cl-operator │ └── Dockerfile ├── cl-dataplane │ ├── Dockerfile │ ├── cl-dataplane.go │ └── app │ │ └── envoy.go ├── cl-go-dataplane │ ├── Dockerfile │ └── cl-go-dataplane.go ├── cl-controlplane │ ├── Dockerfile │ └── cl-controlplane.go └── clusterlink │ ├── cmd │ ├── delete │ │ └── delete.go │ ├── deploy │ │ └── deploy.go │ ├── create │ │ └── create.go │ └── cmd.go │ └── cl-adm.go ├── CODE_OF_CONDUCT.md ├── netlify.toml ├── config ├── operator │ ├── rbac │ │ ├── service_account.yaml │ │ ├── role_binding.yaml │ │ ├── leader_election_role_binding.yaml │ │ ├── operator_viewer_role.yaml │ │ ├── operator_editor_role.yaml │ │ └── leader_election_role.yaml │ └── manager │ │ └── manager.yaml └── config.go ├── .gitignore ├── examples └── policies │ ├── allowAll.json │ ├── deny_from_gw1.json │ └── allowToReviews.json ├── CODEOWNERS ├── hack └── boilerplate.go.txt ├── .devcontainer ├── website │ ├── post-create.sh │ └── devcontainer.json └── dev │ ├── devcontainer.json │ └── post-create.sh ├── tests └── e2e │ └── k8s │ ├── k8s_test.go │ ├── services │ ├── httpecho │ │ └── server.go │ ├── iperf3 │ │ ├── server.go │ │ └── client.go │ └── errors.go │ ├── test_basic.go │ ├── util │ └── async.go │ ├── test_redundancy.go │ └── test_performance.go ├── Containerfile.dev └── .licenserc.yaml /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: false 2 | -------------------------------------------------------------------------------- /pkg/controlplane/authz/connectivitypdp/test_data/not_a_yaml: -------------------------------------------------------------------------------- 1 | just: for: testing: bad: path -------------------------------------------------------------------------------- /website/content/en/search.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Search Results 3 | layout: search 4 | --- -------------------------------------------------------------------------------- /docs/ClusteLink.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/clusterlink-net/clusterlink/HEAD/docs/ClusteLink.pdf -------------------------------------------------------------------------------- /docs/mbg-proto.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/clusterlink-net/clusterlink/HEAD/docs/mbg-proto.png -------------------------------------------------------------------------------- /docs/policy-arch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/clusterlink-net/clusterlink/HEAD/docs/policy-arch.png -------------------------------------------------------------------------------- /docs/openspeedtest.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/clusterlink-net/clusterlink/HEAD/docs/openspeedtest.png -------------------------------------------------------------------------------- /demos/frp/testdata/manifests/frp-ns.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Namespace 3 | metadata: 4 | name: frp 5 | -------------------------------------------------------------------------------- /docs/figures/BookInfo_demo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/clusterlink-net/clusterlink/HEAD/docs/figures/BookInfo_demo.png -------------------------------------------------------------------------------- /docs/figures/clusterlink.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/clusterlink-net/clusterlink/HEAD/docs/figures/clusterlink.png -------------------------------------------------------------------------------- /website/.gitignore: -------------------------------------------------------------------------------- 1 | # hugo files 2 | .hugo_build.lock 3 | public/ 4 | resources/ 5 | node_modules/ 6 | package-lock.json 7 | -------------------------------------------------------------------------------- /website/assets/icons/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/clusterlink-net/clusterlink/HEAD/website/assets/icons/logo.png -------------------------------------------------------------------------------- /website/static/icons/icon1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/clusterlink-net/clusterlink/HEAD/website/static/icons/icon1.png -------------------------------------------------------------------------------- /website/static/icons/icon2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/clusterlink-net/clusterlink/HEAD/website/static/icons/icon2.png -------------------------------------------------------------------------------- /website/static/icons/icon3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/clusterlink-net/clusterlink/HEAD/website/static/icons/icon3.png -------------------------------------------------------------------------------- /website/static/icons/icon4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/clusterlink-net/clusterlink/HEAD/website/static/icons/icon4.png -------------------------------------------------------------------------------- /website/static/icons/icon5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/clusterlink-net/clusterlink/HEAD/website/static/icons/icon5.png -------------------------------------------------------------------------------- /website/static/icons/icon6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/clusterlink-net/clusterlink/HEAD/website/static/icons/icon6.png -------------------------------------------------------------------------------- /design-proposals/deployment.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/clusterlink-net/clusterlink/HEAD/design-proposals/deployment.png -------------------------------------------------------------------------------- /website/static/clusterlink_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/clusterlink-net/clusterlink/HEAD/website/static/clusterlink_logo.png -------------------------------------------------------------------------------- /website/static/favicons/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/clusterlink-net/clusterlink/HEAD/website/static/favicons/favicon.ico -------------------------------------------------------------------------------- /website/static/favicons/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/clusterlink-net/clusterlink/HEAD/website/static/favicons/favicon.png -------------------------------------------------------------------------------- /website/i18n/en.toml: -------------------------------------------------------------------------------- 1 | # Set the search placeholder empty instead of the default "Search this site..." 2 | [ui_search] 3 | other = " " 4 | -------------------------------------------------------------------------------- /website/static/clusterlink_figure.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/clusterlink-net/clusterlink/HEAD/website/static/clusterlink_figure.png -------------------------------------------------------------------------------- /website/static/logo-white-yellow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/clusterlink-net/clusterlink/HEAD/website/static/logo-white-yellow.png -------------------------------------------------------------------------------- /website/content/en/docs/main/tutorials/_index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Tutorials 3 | description: Guided ClusterLink tutorials 4 | weight: 40 5 | --- -------------------------------------------------------------------------------- /website/content/en/docs/v0.1/tutorials/_index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Tutorials 3 | description: Guided ClusterLink tutorials 4 | weight: 40 5 | --- -------------------------------------------------------------------------------- /website/content/en/docs/v0.2/tutorials/_index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Tutorials 3 | description: Guided ClusterLink tutorials 4 | weight: 40 5 | --- -------------------------------------------------------------------------------- /website/content/en/docs/v0.3/tutorials/_index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Tutorials 3 | description: Guided ClusterLink tutorials 4 | weight: 40 5 | --- -------------------------------------------------------------------------------- /website/content/en/docs/v0.4/tutorials/_index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Tutorials 3 | description: Guided ClusterLink tutorials 4 | weight: 40 5 | --- -------------------------------------------------------------------------------- /website/static/backgrounds/section2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/clusterlink-net/clusterlink/HEAD/website/static/backgrounds/section2.jpg -------------------------------------------------------------------------------- /website/static/backgrounds/section4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/clusterlink-net/clusterlink/HEAD/website/static/backgrounds/section4.jpg -------------------------------------------------------------------------------- /website/static/logo-darkblue-yellow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/clusterlink-net/clusterlink/HEAD/website/static/logo-darkblue-yellow.png -------------------------------------------------------------------------------- /website/static/logo-lightblue-yellow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/clusterlink-net/clusterlink/HEAD/website/static/logo-lightblue-yellow.png -------------------------------------------------------------------------------- /website/content/en/docs/v0.1/concepts/_index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Core Concepts 3 | description: Core Concepts and Tasks 4 | weight: 30 5 | --- 6 | -------------------------------------------------------------------------------- /website/content/en/featured-background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/clusterlink-net/clusterlink/HEAD/website/content/en/featured-background.png -------------------------------------------------------------------------------- /website/static/favicons/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/clusterlink-net/clusterlink/HEAD/website/static/favicons/favicon-32x32.png -------------------------------------------------------------------------------- /website/content/en/blog/hello-world/sunflower.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/clusterlink-net/clusterlink/HEAD/website/content/en/blog/hello-world/sunflower.jpg -------------------------------------------------------------------------------- /website/content/en/docs/main/concepts/_index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Core Concepts 3 | description: Core Concepts of the ClusterLink system 4 | weight: 30 5 | --- 6 | -------------------------------------------------------------------------------- /website/content/en/docs/v0.2/concepts/_index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Core Concepts 3 | description: Core Concepts of the ClusterLink system. 4 | weight: 30 5 | --- 6 | -------------------------------------------------------------------------------- /website/content/en/docs/v0.3/concepts/_index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Core Concepts 3 | description: Core Concepts of the ClusterLink system 4 | weight: 30 5 | --- 6 | -------------------------------------------------------------------------------- /website/content/en/docs/v0.4/concepts/_index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Core Concepts 3 | description: Core Concepts of the ClusterLink system 4 | weight: 30 5 | --- 6 | -------------------------------------------------------------------------------- /website/content/en/blog/clusterlink-intro/field.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/clusterlink-net/clusterlink/HEAD/website/content/en/blog/clusterlink-intro/field.jpg -------------------------------------------------------------------------------- /website/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "devDependencies": { 3 | "autoprefixer": "^10.4.16", 4 | "postcss": "^8.4.31", 5 | "postcss-cli": "^10.1.0" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /website/static/favicons/apple-touch-icon-180x180.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/clusterlink-net/clusterlink/HEAD/website/static/favicons/apple-touch-icon-180x180.png -------------------------------------------------------------------------------- /website/content/en/blog/_index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: ClusterLink Blogs 3 | linkTitle: Blog 4 | menu: {main: {weight: 20, pre: "" }} 5 | --- 6 | -------------------------------------------------------------------------------- /website/content/en/docs/main/tasks/_index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Tasks 3 | description: How to do single specific targeted activities with ClusterLink 4 | weight: 35 5 | --- 6 | -------------------------------------------------------------------------------- /website/content/en/docs/v0.2/tasks/_index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Tasks 3 | description: How to do single specific targeted activities with ClusterLink. 4 | weight: 35 5 | --- 6 | -------------------------------------------------------------------------------- /website/content/en/docs/v0.3/tasks/_index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Tasks 3 | description: How to do single specific targeted activities with ClusterLink 4 | weight: 35 5 | --- 6 | -------------------------------------------------------------------------------- /website/content/en/docs/v0.4/tasks/_index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Tasks 3 | description: How to do single specific targeted activities with ClusterLink 4 | weight: 35 5 | --- 6 | -------------------------------------------------------------------------------- /website/content/en/docs/main/tasks/relay/nginx-relay.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/clusterlink-net/clusterlink/HEAD/website/content/en/docs/main/tasks/relay/nginx-relay.png -------------------------------------------------------------------------------- /website/content/en/docs/v0.3/tasks/relay/nginx-relay.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/clusterlink-net/clusterlink/HEAD/website/content/en/docs/v0.3/tasks/relay/nginx-relay.png -------------------------------------------------------------------------------- /website/content/en/docs/v0.4/tasks/relay/nginx-relay.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/clusterlink-net/clusterlink/HEAD/website/content/en/docs/v0.4/tasks/relay/nginx-relay.png -------------------------------------------------------------------------------- /website/content/en/docs/main/tutorials/bookinfo/bookinfo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/clusterlink-net/clusterlink/HEAD/website/content/en/docs/main/tutorials/bookinfo/bookinfo.png -------------------------------------------------------------------------------- /website/content/en/docs/v0.2/tutorials/bookinfo/bookinfo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/clusterlink-net/clusterlink/HEAD/website/content/en/docs/v0.2/tutorials/bookinfo/bookinfo.png -------------------------------------------------------------------------------- /website/content/en/docs/v0.3/tutorials/bookinfo/bookinfo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/clusterlink-net/clusterlink/HEAD/website/content/en/docs/v0.3/tutorials/bookinfo/bookinfo.png -------------------------------------------------------------------------------- /website/content/en/docs/v0.4/tutorials/bookinfo/bookinfo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/clusterlink-net/clusterlink/HEAD/website/content/en/docs/v0.4/tutorials/bookinfo/bookinfo.png -------------------------------------------------------------------------------- /demos/nginx/testdata/clusterlink/export-nginx.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: clusterlink.net/v1alpha1 2 | kind: Export 3 | metadata: 4 | name: nginx 5 | namespace: default 6 | spec: 7 | port: 80 8 | -------------------------------------------------------------------------------- /website/content/en/docs/main/tasks/private-networks/frp-system.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/clusterlink-net/clusterlink/HEAD/website/content/en/docs/main/tasks/private-networks/frp-system.png -------------------------------------------------------------------------------- /website/content/en/docs/v0.4/tasks/private-networks/frp-system.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/clusterlink-net/clusterlink/HEAD/website/content/en/docs/v0.4/tasks/private-networks/frp-system.png -------------------------------------------------------------------------------- /demos/bookinfo/manifests/clusterlink/export-reviews.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: clusterlink.net/v1alpha1 2 | kind: Export 3 | metadata: 4 | name: reviews 5 | namespace: default 6 | spec: 7 | port: 9080 8 | -------------------------------------------------------------------------------- /demos/frp/testdata/manifests/server/frps-configmap.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ConfigMap 3 | metadata: 4 | name: frps-config 5 | namespace: frp 6 | data: 7 | frps.toml: | 8 | bindPort = 4443 9 | -------------------------------------------------------------------------------- /demos/iperf3/testdata/manifests/clusterlink/export-iperf3.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: clusterlink.net/v1alpha1 2 | kind: Export 3 | metadata: 4 | name: iperf3-server 5 | namespace: default 6 | spec: 7 | port: 5000 8 | -------------------------------------------------------------------------------- /website/content/en/docs/_index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Documentation Versions 3 | linkTitle: Versions 4 | simple_list: true 5 | --- 6 | 7 | Welcome to the ClusterLink docs! The following doc versions are available: 8 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/something-else.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Something else 3 | about: Issues other than bug reports and enhancements (e.g., questions, documentation, 4 | etc.) 5 | title: '' 6 | labels: '' 7 | assignees: '' 8 | 9 | --- 10 | 11 | 12 | -------------------------------------------------------------------------------- /cmd/cl-operator/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM alpine:3.14 2 | 3 | 4 | 5 | FROM gcr.io/distroless/static:nonroot 6 | WORKDIR / 7 | ARG TARGETARCH 8 | COPY ./bin/$TARGETARCH/cl-operator cl-operator 9 | USER 65532:65532 10 | 11 | ENTRYPOINT ["/cl-operator"] 12 | -------------------------------------------------------------------------------- /demos/nginx/testdata/clusterlink/peer-client.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: clusterlink.net/v1alpha1 2 | kind: Peer 3 | metadata: 4 | name: client 5 | namespace: clusterlink-system 6 | spec: 7 | gateways: 8 | - host: "${CLIENT_IP}" 9 | port: 30443 10 | -------------------------------------------------------------------------------- /demos/nginx/testdata/clusterlink/peer-relay.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: clusterlink.net/v1alpha1 2 | kind: Peer 3 | metadata: 4 | name: relay 5 | namespace: clusterlink-system 6 | spec: 7 | gateways: 8 | - host: "${RELAY_IP}" 9 | port: 30443 10 | -------------------------------------------------------------------------------- /demos/nginx/testdata/clusterlink/peer-server.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: clusterlink.net/v1alpha1 2 | kind: Peer 3 | metadata: 4 | name: server 5 | namespace: clusterlink-system 6 | spec: 7 | gateways: 8 | - host: "${SERVER_IP}" 9 | port: 30443 10 | -------------------------------------------------------------------------------- /demos/bookinfo/manifests/clusterlink/peer-client.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: clusterlink.net/v1alpha1 2 | kind: Peer 3 | metadata: 4 | name: client 5 | namespace: clusterlink-system 6 | spec: 7 | gateways: 8 | - host: "${CLIENT_IP}" 9 | port: 30443 10 | -------------------------------------------------------------------------------- /demos/bookinfo/manifests/clusterlink/peer-server1.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: clusterlink.net/v1alpha1 2 | kind: Peer 3 | metadata: 4 | name: server1 5 | namespace: clusterlink-system 6 | spec: 7 | gateways: 8 | - host: "${SERVER1_IP}" 9 | port: 30443 10 | -------------------------------------------------------------------------------- /demos/bookinfo/manifests/clusterlink/peer-server2.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: clusterlink.net/v1alpha1 2 | kind: Peer 3 | metadata: 4 | name: server2 5 | namespace: clusterlink-system 6 | spec: 7 | gateways: 8 | - host: "${SERVER2_IP}" 9 | port: 30443 10 | -------------------------------------------------------------------------------- /demos/iperf3/testdata/manifests/clusterlink/peer-client.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: clusterlink.net/v1alpha1 2 | kind: Peer 3 | metadata: 4 | name: client 5 | namespace: clusterlink-system 6 | spec: 7 | gateways: 8 | - host: "${CLIENT_IP}" 9 | port: 30443 10 | -------------------------------------------------------------------------------- /demos/iperf3/testdata/manifests/clusterlink/peer-server.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: clusterlink.net/v1alpha1 2 | kind: Peer 3 | metadata: 4 | name: server 5 | namespace: clusterlink-system 6 | spec: 7 | gateways: 8 | - host: "${SERVER_IP}" 9 | port: 30443 10 | -------------------------------------------------------------------------------- /website/layouts/index.redirects: -------------------------------------------------------------------------------- 1 | {{- $latest := site.Params.latest_stable_version -}} 2 | /docs /docs/{{ $latest }} 301! 3 | /docs/latest /docs/{{ $latest }} 4 | /docs/latest/* /docs/{{ $latest }}/:splat 5 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Code of Conduct 2 | 3 | We follow the [CNCF Code of Conduct](https://github.com/cncf/foundation/blob/main/code-of-conduct.md). 4 | 5 | Please contact the [CNCF Code of Conduct Committee](mailto:conduct@cncf.io) 6 | in order to report violations of the Code of Conduct. 7 | -------------------------------------------------------------------------------- /demos/bookinfo/manifests/clusterlink/allow-policy.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: clusterlink.net/v1alpha1 2 | kind: AccessPolicy 3 | metadata: 4 | name: allow-policy 5 | namespace: default 6 | spec: 7 | action: allow 8 | from: 9 | - workloadSelector: {} 10 | to: 11 | - workloadSelector: {} 12 | -------------------------------------------------------------------------------- /demos/nginx/testdata/clusterlink/allow-policy.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: clusterlink.net/v1alpha1 2 | kind: AccessPolicy 3 | metadata: 4 | name: allow-policy 5 | namespace: default 6 | spec: 7 | action: allow 8 | from: 9 | - workloadSelector: {} 10 | to: 11 | - workloadSelector: {} 12 | -------------------------------------------------------------------------------- /website/content/en/docs/v0.1/_index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: v0.1 3 | cascade: 4 | version: v0.1 5 | versName: &name v0.1 6 | git_version_tag: v0.1.0 7 | exclude_search: false 8 | linkTitle: *name 9 | simple_list: true 10 | weight: -10 # Weight for doc version vX.Y should be -(100*X + Y)0 11 | --- 12 | -------------------------------------------------------------------------------- /website/content/en/docs/v0.2/_index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: v0.2 3 | cascade: 4 | version: v0.2 5 | versName: &name v0.2 6 | git_version_tag: v0.2.0 7 | exclude_search: false 8 | linkTitle: *name 9 | simple_list: true 10 | weight: -20 # Weight for doc version vX.Y should be -(100*X + Y)0 11 | --- 12 | -------------------------------------------------------------------------------- /website/static/files/peer_crd_sample.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: clusterlink.net/v1alpha1 2 | kind: Peer 3 | metadata: 4 | name: cluster17.us-east 5 | namespace: clusterlink-system 6 | spec: 7 | gateways: 8 | - host: "192.168.0.12" 9 | port: 443 10 | - host: "192.168.0.17" 11 | port: 443 12 | -------------------------------------------------------------------------------- /demos/iperf3/testdata/manifests/clusterlink/allow-policy.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: clusterlink.net/v1alpha1 2 | kind: AccessPolicy 3 | metadata: 4 | name: allow-policy 5 | namespace: default 6 | spec: 7 | action: allow 8 | from: 9 | - workloadSelector: {} 10 | to: 11 | - workloadSelector: {} 12 | -------------------------------------------------------------------------------- /demos/nginx/testdata/clusterlink/import-nginx.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: clusterlink.net/v1alpha1 2 | kind: Import 3 | metadata: 4 | name: nginx 5 | namespace: default 6 | spec: 7 | port: 80 8 | sources: 9 | - exportName: nginx 10 | exportNamespace: default 11 | peer: server 12 | -------------------------------------------------------------------------------- /demos/utils/manifests/kind/cl-svc.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: cl-svc 5 | spec: 6 | type: NodePort 7 | selector: 8 | app: cl-dataplane 9 | ports: 10 | - port: 443 11 | targetPort: 443 12 | nodePort: 30443 13 | protocol: TCP 14 | name: http 15 | -------------------------------------------------------------------------------- /demos/nginx/testdata/clusterlink/import-nginx-relay.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: clusterlink.net/v1alpha1 2 | kind: Import 3 | metadata: 4 | name: nginx-relay 5 | namespace: default 6 | spec: 7 | port: 80 8 | sources: 9 | - exportName: nginx 10 | exportNamespace: default 11 | peer: server 12 | -------------------------------------------------------------------------------- /netlify.toml: -------------------------------------------------------------------------------- 1 | # Netlify expects the configuration file in the repo's top level. 2 | # In our case, we use it only to redirect to the `website` directory which 3 | # holds the site and configuration. 4 | # See https://docs.netlify.com/configure-builds/file-based-configuration/ 5 | [build] 6 | base = "website/" 7 | publish = "public" 8 | -------------------------------------------------------------------------------- /demos/iperf3/testdata/manifests/clusterlink/import-iperf3.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: clusterlink.net/v1alpha1 2 | kind: Import 3 | metadata: 4 | name: iperf3-server 5 | namespace: default 6 | spec: 7 | port: 5000 8 | sources: 9 | - exportName: iperf3-server 10 | exportNamespace: default 11 | peer: server 12 | -------------------------------------------------------------------------------- /demos/nginx/testdata/nginx-job.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: batch/v1 2 | kind: Job 3 | metadata: 4 | name: curl-nginx-homepage 5 | spec: 6 | template: 7 | spec: 8 | containers: 9 | - name: curl 10 | image: curlimages/curl:latest 11 | command: ["curl", "http://nginx.default.svc.cluster.local"] 12 | restartPolicy: Never 13 | -------------------------------------------------------------------------------- /website/static/files/tutorials/allow-all-policy.md: -------------------------------------------------------------------------------- 1 | 2 | ```sh 3 | echo " 4 | apiVersion: clusterlink.net/v1alpha1 5 | kind: AccessPolicy 6 | metadata: 7 | name: allow-policy 8 | namespace: default 9 | spec: 10 | action: allow 11 | from: 12 | - workloadSelector: {} 13 | to: 14 | - workloadSelector: {} 15 | " | kubectl apply -f - 16 | ``` 17 | -------------------------------------------------------------------------------- /demos/nginx/testdata/nginx-relay-job.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: batch/v1 2 | kind: Job 3 | metadata: 4 | name: curl-nginx-relay-homepage 5 | spec: 6 | template: 7 | spec: 8 | containers: 9 | - name: curl 10 | image: curlimages/curl:latest 11 | command: ["curl", "http://nginx-relay.default.svc.cluster.local"] 12 | restartPolicy: Never 13 | -------------------------------------------------------------------------------- /website/static/files/tutorials/cli-installation.md: -------------------------------------------------------------------------------- 1 | 2 | 1. Install ClusterLink CLI on Linux or Mac using the installation script: 3 | 4 | ```sh 5 | curl -L https://github.com/clusterlink-net/clusterlink/releases/latest/download/clusterlink.sh | sh - 6 | ``` 7 | 8 | 2. Verify the installation: 9 | 10 | ```sh 11 | clusterlink --version 12 | ``` 13 | -------------------------------------------------------------------------------- /website/content/en/docs/v0.3/_index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: v0.3 3 | cascade: 4 | version: v0.3 5 | versName: &name v0.3 6 | git_version_tag: v0.3.0 7 | exclude_search: false 8 | linkTitle: *name 9 | simple_list: true 10 | weight: -30 # Weight for doc version vX.Y should be -(100*X + Y)0 11 | # For example: v0.2.x => -20 v3.6.7 => -3060. `main` is arbitrarily set to -9999 12 | --- 13 | -------------------------------------------------------------------------------- /website/content/en/docs/v0.4/_index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: v0.4 3 | cascade: 4 | version: v0.4 5 | versName: &name v0.4 6 | git_version_tag: v0.4.0 7 | exclude_search: false 8 | linkTitle: *name 9 | simple_list: true 10 | weight: -9999 # Weight for doc version vX.Y should be -(100*X + Y)0 11 | # For example: v0.2.x => -20 v3.6.7 => -3060. `main` is arbitrarily set to -9999 12 | --- 13 | -------------------------------------------------------------------------------- /website/layouts/shortcodes/abbr.html: -------------------------------------------------------------------------------- 1 | 7 | {{ .Get 0 | safeHTML }} 8 | -------------------------------------------------------------------------------- /website/content/en/docs/main/_index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: main (DRAFT) 3 | cascade: 4 | version: main 5 | versName: &name main (DRAFT) 6 | git_version_tag: main 7 | exclude_search: false 8 | linkTitle: *name 9 | simple_list: true 10 | weight: -9999 # Weight for doc version vX.Y should be -(100*X + Y)0 11 | # For example: v0.2.x => -20 v3.6.7 => -3060. `main` is arbitrarily set to -9999 12 | --- 13 | -------------------------------------------------------------------------------- /config/operator/rbac/service_account.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ServiceAccount 3 | metadata: 4 | labels: 5 | app.kubernetes.io/name: serviceaccount 6 | app.kubernetes.io/instance: controller-manager-sa 7 | app.kubernetes.io/component: rbac 8 | app.kubernetes.io/created-by: cl-operator 9 | app.kubernetes.io/part-of: cl-operator 10 | name: cl-operator-controller-manager 11 | namespace: clusterlink-operator 12 | -------------------------------------------------------------------------------- /demos/bookinfo/manifests/clusterlink/import-reviews.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: clusterlink.net/v1alpha1 2 | kind: Import 3 | metadata: 4 | name: reviews 5 | namespace: default 6 | spec: 7 | port: 9080 8 | sources: 9 | - exportName: reviews 10 | exportNamespace: default 11 | peer: server1 12 | - exportName: reviews 13 | exportNamespace: default 14 | peer: server2 15 | -------------------------------------------------------------------------------- /pkg/controlplane/authz/connectivitypdp/test_data/simple_privileged.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: clusterlink/v1alpha1 2 | kind: PrivilegedConnectivityPolicy 3 | metadata: 4 | name: allow-connecting-to-metering-service 5 | spec: 6 | action: allow 7 | from: 8 | - workloadSelector: {} 9 | to: 10 | - workloadSelector: 11 | matchLabels: 12 | workloadName: global-metering-service 13 | connectionAttrs: 14 | - protocol: TCP 15 | port: 5051 16 | -------------------------------------------------------------------------------- /website/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/clusterlink-net/clusterlink/website 2 | 3 | go 1.20 4 | 5 | require ( 6 | github.com/FortAwesome/Font-Awesome v0.0.0-20240402185447-c0f460dca7f7 // indirect 7 | github.com/google/docsy v0.10.0 // indirect 8 | github.com/google/docsy/dependencies v0.7.2 // indirect 9 | github.com/martignoni/hugo-notice v0.0.0-20240524142214-36e5ee342fef // indirect 10 | github.com/twbs/bootstrap v5.3.3+incompatible // indirect 11 | ) 12 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Binaries for programs and plugins 2 | *.exe 3 | *.exe~ 4 | *.dll 5 | *.so 6 | *.dylib 7 | *.pyc 8 | *.pyc 9 | .vscode/ 10 | # Test binary, built with `go test -c` 11 | *.test 12 | 13 | # Output of the go coverage tool, specifically when used with LiteIDE 14 | *.out 15 | 16 | # Dependency directories (remove the comment below to include it) 17 | # vendor/ 18 | 19 | # Binaries folder 20 | bin/ 21 | graphs/ 22 | 23 | # empty file targets 24 | dist/ 25 | -------------------------------------------------------------------------------- /demos/bookinfo/manifests/clusterlink/import-reviews-lb-random.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: clusterlink.net/v1alpha1 2 | kind: Import 3 | metadata: 4 | name: reviews 5 | namespace: default 6 | spec: 7 | port: 9080 8 | sources: 9 | - exportName: reviews 10 | exportNamespace: default 11 | peer: server1 12 | - exportName: reviews 13 | exportNamespace: default 14 | peer: server2 15 | lbScheme: random 16 | -------------------------------------------------------------------------------- /demos/bookinfo/manifests/clusterlink/import-reviews-lb-static.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: clusterlink.net/v1alpha1 2 | kind: Import 3 | metadata: 4 | name: reviews 5 | namespace: default 6 | spec: 7 | port: 9080 8 | sources: 9 | - exportName: reviews 10 | exportNamespace: default 11 | peer: server1 12 | - exportName: reviews 13 | exportNamespace: default 14 | peer: server2 15 | lbScheme: static 16 | -------------------------------------------------------------------------------- /website/netlify.toml: -------------------------------------------------------------------------------- 1 | [build] 2 | publish = "public" 3 | command = "hugo --minify --gc" 4 | 5 | [context.production.environment] 6 | HUGO_VERSION = "0.124.1" 7 | HUGO_ENV = "production" 8 | HUGO_ENABLEGITINFO = "true" 9 | 10 | [context.deploy-preview] 11 | command = "hugo --minify --buildFuture --buildDrafts --gc -b $DEPLOY_PRIME_URL" 12 | 13 | [context.deploy-preview.environment] 14 | HUGO_VERSION = "0.124.1" 15 | HUGO_ENV = "production" 16 | -------------------------------------------------------------------------------- /cmd/cl-dataplane/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM envoyproxy/envoy:v1.36.2 2 | 3 | # Populated during the build process, for example, with 'arm64' or 'amd64'. 4 | ARG TARGETARCH 5 | 6 | # Copy binary 7 | RUN mkdir -p /usr/local/bin 8 | COPY ./bin/$TARGETARCH/cl-dataplane /usr/local/bin/cl-dataplane 9 | 10 | # Create directory for private keys 11 | RUN mkdir -p /etc/ssl/private 12 | 13 | # Create directory for certificates 14 | RUN mkdir -p /etc/ssl/certs 15 | 16 | ENTRYPOINT ["/usr/local/bin/cl-dataplane"] 17 | -------------------------------------------------------------------------------- /cmd/cl-go-dataplane/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM alpine:3.22 2 | 3 | # Populated during the build process, for example, with 'arm64' or 'amd64'. 4 | ARG TARGETARCH 5 | 6 | # Copy binary 7 | RUN mkdir -p /usr/local/bin 8 | COPY ./bin/$TARGETARCH/cl-go-dataplane /usr/local/bin/cl-go-dataplane 9 | 10 | # Create directory for private keys 11 | RUN mkdir -p /etc/ssl/private 12 | 13 | # Create directory for certificates 14 | RUN mkdir -p /etc/ssl/certs 15 | 16 | ENTRYPOINT ["/usr/local/bin/cl-go-dataplane"] 17 | -------------------------------------------------------------------------------- /website/static/files/tutorials/envsubst.md: -------------------------------------------------------------------------------- 1 | 2 | Note that the provided YAML configuration files refer to environment variables 3 | (defined below) that should be set when running the tutorial. The values are 4 | replaced in the YAMLs using `envsubst` utility. 5 | 6 | {{% expand summary="Installing `envsubst` on macOS" %}} 7 | In case `envsubst` does not exist, you can install it with: 8 | 9 | ```sh 10 | brew install gettext 11 | brew link --force gettext 12 | ``` 13 | 14 | {{% /expand %}} 15 | -------------------------------------------------------------------------------- /.github/release.yml: -------------------------------------------------------------------------------- 1 | # .github/release.yml 2 | 3 | changelog: 4 | exclude: 5 | labels: 6 | - ignore-for-release 7 | - dependencies 8 | - documentation 9 | categories: 10 | - title: Breaking Changes 🛠 11 | labels: 12 | - breaking-change 13 | - title: New Features 🎉 14 | labels: 15 | - enhancement 16 | - title: Bug Fixes 🐞 17 | labels: 18 | - bugfix 19 | - title: Other Changes 20 | labels: 21 | - "*" 22 | -------------------------------------------------------------------------------- /demos/utils/manifests/kind/calico/calico-config.yaml: -------------------------------------------------------------------------------- 1 | ################################################################ 2 | #Name:config 3 | #Desc: Kind config for exposing port 30000 of kind 4 | # cluster 5 | ################################################################ 6 | # cluster-config.yml 7 | kind: Cluster 8 | apiVersion: kind.x-k8s.io/v1alpha4 9 | nodes: 10 | 11 | networking: 12 | disableDefaultCNI: true # disable kindnet 13 | podSubnet: 192.168.0.0/16 # set to Calico's default subnet -------------------------------------------------------------------------------- /demos/iperf3/testdata/manifests/iperf3-server/kind-config.yaml: -------------------------------------------------------------------------------- 1 | ################################################################ 2 | #Name:config 3 | #Desc: Kind config for exposing port 30000 of kind 4 | # cluster 5 | ################################################################ 6 | # cluster-config.yml 7 | kind: Cluster 8 | apiVersion: kind.x-k8s.io/v1alpha4 9 | nodes: 10 | - role: control-plane 11 | extraPortMappings: 12 | - containerPort: 30000 13 | hostPort: 21000 14 | protocol: TCP -------------------------------------------------------------------------------- /demos/speedtest/testdata/policy/denyFromGw.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: clusterlink.net/v1alpha1 2 | kind: AccessPolicy 3 | metadata: 4 | name: deny-from-gw 5 | namespace: default 6 | spec: 7 | action: deny 8 | from: [{ 9 | workloadSelector: { 10 | matchLabels: { 11 | peer.clusterlink.net/name: peer3 12 | } 13 | } 14 | } 15 | ] 16 | to: [{ 17 | workloadSelector: {} 18 | } 19 | ] 20 | 21 | -------------------------------------------------------------------------------- /website/layouts/shortcodes/anchor.html: -------------------------------------------------------------------------------- 1 | 6 | 7 | {{ if .IsNamedParams }} 8 | {{ $id := .Get `id` | lower | safeHTML }}{{ $anchor := anchorize $id }} 9 | 10 | {{ else }} 11 | {{ $id := .Get 0 | lower | safeHTML }}{{ $anchor := anchorize $id }} 12 | 13 | {{ end }} 14 | -------------------------------------------------------------------------------- /demos/bookinfo/manifests/clusterlink/deny-server1-policy.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: clusterlink.net/v1alpha1 2 | kind: PrivilegedAccessPolicy 3 | metadata: 4 | name: deny-from-server1 5 | spec: 6 | action: deny 7 | from: [{ 8 | workloadSelector: {} 9 | } 10 | ] 11 | to: 12 | [{ 13 | workloadSelector: { 14 | matchLabels: { 15 | peer.clusterlink.net/name: server1 16 | } 17 | } 18 | } 19 | ] 20 | 21 | -------------------------------------------------------------------------------- /examples/policies/allowAll.json: -------------------------------------------------------------------------------- 1 | { 2 | "kind": "AccessPolicy", 3 | "apiVersion": "clusterlink.net/v1alpha1", 4 | "metadata": { 5 | "name": "allow-all", 6 | "namespace": "default" 7 | }, 8 | "spec": { 9 | "action": "allow", 10 | "from": [ 11 | { 12 | "workloadSelector": {} 13 | } 14 | ], 15 | "to": [ 16 | { 17 | "workloadSelector": {} 18 | } 19 | ] 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /CODEOWNERS: -------------------------------------------------------------------------------- 1 | # These owners will be the default owners for everything in 2 | # the repo. Unless a later match takes precedence, 3 | # Order is important; the last matching pattern takes the most 4 | # precedence. 5 | * @elevran 6 | cmd/ @kfirtoledo 7 | demos/ @kfirtoledo 8 | pkg/ @elevran @kfirtoledo 9 | pkg/dataplane/go @praveingk 10 | pkg/controlplane/authz/ @zivnevo 11 | website/ @elevran @michalmalka 12 | 13 | -------------------------------------------------------------------------------- /website/layouts/shortcodes/clusterlink/feature.html: -------------------------------------------------------------------------------- 1 |
{{ .Inner }}
13 | {{ .Get "buttontext" }} 14 |{{ .Inner }}
5 |6 | Learn More 7 |
8 | 9 |
10 |
11 | If you see this page, the nginx web server is successfully installed and 20 | working. Further configuration is required.
21 | 22 |For online documentation and support please refer to
23 | nginx.org.
24 | Commercial support is available at
25 | nginx.com.
Thank you for using nginx.
28 | 29 | 30 | ``` 31 | 32 | {{% /expand %}} 33 | -------------------------------------------------------------------------------- /config/operator/rbac/leader_election_role.yaml: -------------------------------------------------------------------------------- 1 | # permissions to do leader election. 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: Role 4 | metadata: 5 | labels: 6 | app.kubernetes.io/name: role 7 | app.kubernetes.io/instance: leader-election-role 8 | app.kubernetes.io/component: rbac 9 | app.kubernetes.io/created-by: cl-operator 10 | app.kubernetes.io/part-of: cl-operator 11 | app.kubernetes.io/managed-by: kustomize 12 | name: cl-operator-leader-election-role 13 | namespace: clusterlink-operator 14 | rules: 15 | - apiGroups: 16 | - "" 17 | resources: 18 | - configmaps 19 | verbs: 20 | - get 21 | - list 22 | - watch 23 | - create 24 | - update 25 | - patch 26 | - delete 27 | - apiGroups: 28 | - coordination.k8s.io 29 | resources: 30 | - leases 31 | verbs: 32 | - get 33 | - list 34 | - watch 35 | - create 36 | - update 37 | - patch 38 | - delete 39 | - apiGroups: 40 | - "" 41 | resources: 42 | - events 43 | verbs: 44 | - create 45 | - patch 46 | -------------------------------------------------------------------------------- /demos/frp/testdata/manifests/client/peer1/peer.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: clusterlink.net/v1alpha1 2 | kind: Peer 3 | metadata: 4 | name: peer2 5 | namespace: clusterlink-system 6 | spec: 7 | gateways: 8 | - host: frp-peer2-clusterlink.frp.svc.cluster.local 9 | port: 6002 10 | 11 | --- 12 | apiVersion: v1 13 | kind: Service 14 | metadata: 15 | name: frp-peer2-clusterlink 16 | namespace: frp 17 | spec: 18 | type: ClusterIP 19 | selector: 20 | app: frpc 21 | ports: 22 | - port: 6002 23 | targetPort: 6002 24 | --- 25 | apiVersion: clusterlink.net/v1alpha1 26 | kind: Peer 27 | metadata: 28 | name: peer3 29 | namespace: clusterlink-system 30 | spec: 31 | gateways: 32 | - host: frp-peer3-clusterlink.frp.svc.cluster.local 33 | port: 6003 34 | 35 | --- 36 | apiVersion: v1 37 | kind: Service 38 | metadata: 39 | name: frp-peer3-clusterlink 40 | namespace: frp 41 | spec: 42 | type: ClusterIP 43 | selector: 44 | app: frpc 45 | ports: 46 | - port: 6003 47 | targetPort: 6003 48 | -------------------------------------------------------------------------------- /demos/frp/testdata/manifests/client/peer3/peer.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: clusterlink.net/v1alpha1 2 | kind: Peer 3 | metadata: 4 | name: peer1 5 | namespace: clusterlink-system 6 | spec: 7 | gateways: 8 | - host: frp-peer1-clusterlink.frp.svc.cluster.local 9 | port: 6001 10 | 11 | --- 12 | apiVersion: v1 13 | kind: Service 14 | metadata: 15 | name: frp-peer1-clusterlink 16 | namespace: frp 17 | spec: 18 | type: ClusterIP 19 | selector: 20 | app: frpc 21 | ports: 22 | - port: 6001 23 | targetPort: 6001 24 | --- 25 | apiVersion: clusterlink.net/v1alpha1 26 | kind: Peer 27 | metadata: 28 | name: peer2 29 | namespace: clusterlink-system 30 | spec: 31 | gateways: 32 | - host: frp-peer2-clusterlink.frp.svc.cluster.local 33 | port: 6002 34 | 35 | --- 36 | apiVersion: v1 37 | kind: Service 38 | metadata: 39 | name: frp-peer2-clusterlink 40 | namespace: frp 41 | spec: 42 | type: ClusterIP 43 | selector: 44 | app: frpc 45 | ports: 46 | - port: 6002 47 | targetPort: 6002 48 | -------------------------------------------------------------------------------- /tests/e2e/k8s/services/httpecho/server.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) The ClusterLink Authors. 2 | // Licensed under the Apache License, Version 2.0 (the "License"); 3 | // you may not use this file except in compliance with the License. 4 | // You may obtain a copy of the License at 5 | // 6 | // http://www.apache.org/licenses/LICENSE-2.0 7 | // 8 | // Unless required by applicable law or agreed to in writing, software 9 | // distributed under the License is distributed on an "AS IS" BASIS, 10 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | // See the License for the specific language governing permissions and 12 | // limitations under the License. 13 | 14 | package httpecho 15 | 16 | import "github.com/clusterlink-net/clusterlink/tests/e2e/k8s/util" 17 | 18 | func ServerPod(service util.Service, echoValue string) *util.PodAndService { 19 | return &util.PodAndService{ 20 | Service: service, 21 | Image: "hashicorp/http-echo", 22 | Args: []string{"-listen=:8080", "-text=" + echoValue}, 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for ClusterLink 4 | title: "[FEATURE]:" 5 | labels: enhancement 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. 12 | What are you trying to do and how would you want to do it differently? 13 | Is it something you currently you cannot do? Is this related to an issue/problem? 14 | 15 | **Describe the solution you'd like** 16 | A clear and concise description of what you want to happen. 17 | What is the motivation / use case for changing the behavior? 18 | 19 | **Describe alternatives you've considered** 20 | A clear and concise description of any alternative solutions or features you've considered. 21 | 22 | **Additional context** 23 | Add any other context or screenshots about the feature request here. 24 | 25 | If possible, please confirm: 26 | 27 | - [ ] **If the feature request is approved, I would be willing to submit a PR** 28 | -------------------------------------------------------------------------------- /pkg/dataplane/api/const.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) The ClusterLink Authors. 2 | // Licensed under the Apache License, Version 2.0 (the "License"); 3 | // you may not use this file except in compliance with the License. 4 | // You may obtain a copy of the License at 5 | // 6 | // http://www.apache.org/licenses/LICENSE-2.0 7 | // 8 | // Unless required by applicable law or agreed to in writing, software 9 | // distributed under the License is distributed on an "AS IS" BASIS, 10 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | // See the License for the specific language governing permissions and 12 | // limitations under the License. 13 | 14 | package api 15 | 16 | const ( 17 | // ListenPort is the dataplane external listening port. 18 | ListenPort = 4443 19 | // Name is the dataplane name. 20 | Name = "cl-dataplane" 21 | // Name of the go-dataplane image. 22 | GoDataplaneName = "cl-go-dataplane" 23 | // ReadinessListenPort is the port used to probe for dataplane readiness. 24 | ReadinessListenPort = 4445 25 | ) 26 | -------------------------------------------------------------------------------- /tests/e2e/k8s/services/iperf3/server.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) The ClusterLink Authors. 2 | // Licensed under the Apache License, Version 2.0 (the "License"); 3 | // you may not use this file except in compliance with the License. 4 | // You may obtain a copy of the License at 5 | // 6 | // http://www.apache.org/licenses/LICENSE-2.0 7 | // 8 | // Unless required by applicable law or agreed to in writing, software 9 | // distributed under the License is distributed on an "AS IS" BASIS, 10 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | // See the License for the specific language governing permissions and 12 | // limitations under the License. 13 | 14 | package iperf3 15 | 16 | import "github.com/clusterlink-net/clusterlink/tests/e2e/k8s/util" 17 | 18 | // ServerPod returns an iperf3 server pod. 19 | func ServerPod(service util.Service) *util.PodAndService { 20 | return &util.PodAndService{ 21 | Service: service, 22 | Image: "networkstatic/iperf3", 23 | Args: []string{"-s", "-p", "5201"}, 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /Containerfile.dev: -------------------------------------------------------------------------------- 1 | FROM docker.io/library/golang:1.22-bullseye 2 | 3 | # To allow installing kubectl 4 | RUN mkdir /etc/apt/keyrings &&\ 5 | apt-get install -y apt-transport-https ca-certificates curl &&\ 6 | curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.28/deb/Release.key | gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg &&\ 7 | echo 'deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.28/deb/ /' | tee /etc/apt/sources.list.d/kubernetes.list 8 | 9 | RUN apt-get update -qy && \ 10 | apt-get install --no-install-recommends -qy \ 11 | ca-certificates \ 12 | curl \ 13 | python3 \ 14 | make \ 15 | git \ 16 | docker.io \ 17 | kubectl \ 18 | && \ 19 | apt-get clean 20 | 21 | # 22 | # Install go build tools, and cache go modules. 23 | # 24 | COPY ./hack/install-devtools.sh /src/ 25 | COPY go.mod /src/ 26 | COPY go.sum /src/ 27 | RUN cd /src &&\ 28 | sh -x ./install-devtools.sh &&\ 29 | go mod download &&\ 30 | cd / &&\ 31 | rm -rf /src 32 | -------------------------------------------------------------------------------- /.github/workflows/pr-cli.yml: -------------------------------------------------------------------------------- 1 | name: PR check - CLI Installation test 2 | on: 3 | push: 4 | branches: [ main ] 5 | pull_request: 6 | branches: [ main ] 7 | 8 | jobs: 9 | cli-test: 10 | runs-on: ${{ matrix.os }} 11 | strategy: 12 | matrix: 13 | os: [ubuntu-latest] 14 | 15 | steps: 16 | - name: checkout 17 | uses: actions/checkout@v6 18 | with: 19 | fetch-tags: true 20 | - name: Set up Go 21 | uses: actions/setup-go@v6 22 | with: 23 | go-version-file: ./go.mod 24 | - name: Install kind 25 | uses: helm/kind-action@v1.13.0 26 | with: 27 | install_only: true 28 | - name: Run build 29 | run: make build 30 | - name: Build docker images 31 | run: make docker-build 32 | - name: Run installation test using CLI 33 | run: ./tests/cli/basic_test.sh 34 | - name: upload e2e k8s test logs 35 | uses: actions/upload-artifact@v5 36 | if: failure() 37 | with: 38 | name: tests-cli 39 | path: /tmp/clusterlink-cli 40 | -------------------------------------------------------------------------------- /.github/workflows/pr-e2e-test.yml: -------------------------------------------------------------------------------- 1 | name: PR check - e2e tests 2 | on: 3 | push: 4 | branches: [ main ] 5 | pull_request: 6 | branches: [ main ] 7 | 8 | jobs: 9 | e2e-connectivity-test: 10 | runs-on: ubuntu-latest 11 | 12 | steps: 13 | - name: checkout 14 | uses: actions/checkout@v6 15 | with: 16 | fetch-tags: true 17 | - name: Set up Go 18 | uses: actions/setup-go@v6 19 | with: 20 | go-version-file: ./go.mod 21 | - name: Install kind 22 | uses: helm/kind-action@v1.13.0 23 | with: 24 | install_only: true 25 | - name: Run build 26 | run: make build 27 | - name: Build docker images 28 | run: make docker-build 29 | - name: Run e2e k8s test on a kind cluster 30 | run: CICD=1 ${{ runner.debug == '1' && 'DEBUG=1' || '' }} make tests-e2e-k8s 31 | - name: upload e2e k8s test logs 32 | uses: actions/upload-artifact@v5 33 | if: failure() 34 | with: 35 | name: tests-e2e-k8s 36 | path: /tmp/clusterlink-k8s-tests 37 | -------------------------------------------------------------------------------- /demos/bookinfo/manifests/review/rating.yaml: -------------------------------------------------------------------------------- 1 | ################################################################################################## 2 | # Ratings service 3 | ################################################################################################## 4 | apiVersion: v1 5 | kind: Service 6 | metadata: 7 | name: ratings 8 | labels: 9 | app: ratings 10 | service: ratings 11 | spec: 12 | ports: 13 | - port: 9080 14 | name: http 15 | selector: 16 | app: ratings 17 | --- 18 | apiVersion: apps/v1 19 | kind: Deployment 20 | metadata: 21 | name: ratings-v1 22 | labels: 23 | app: ratings 24 | version: v1 25 | spec: 26 | replicas: 1 27 | selector: 28 | matchLabels: 29 | app: ratings 30 | template: 31 | metadata: 32 | labels: 33 | app: ratings 34 | version: v1 35 | spec: 36 | containers: 37 | - name: ratings 38 | image: docker.io/istio/examples-bookinfo-ratings-v1 39 | imagePullPolicy: IfNotPresent 40 | ports: 41 | - containerPort: 9080 42 | --- 43 | -------------------------------------------------------------------------------- /demos/bookinfo/manifests/review/review-v2.yaml: -------------------------------------------------------------------------------- 1 | ################################################################################################## 2 | # Reviews service 3 | ################################################################################################## 4 | apiVersion: v1 5 | kind: Service 6 | metadata: 7 | name: reviews 8 | labels: 9 | app: reviews 10 | service: reviews 11 | spec: 12 | ports: 13 | - port: 9080 14 | name: http 15 | selector: 16 | app: reviews 17 | --- 18 | apiVersion: apps/v1 19 | kind: Deployment 20 | metadata: 21 | name: reviews-v2 22 | labels: 23 | app: reviews-v2 24 | version: v2 25 | spec: 26 | replicas: 1 27 | selector: 28 | matchLabels: 29 | app: reviews 30 | template: 31 | metadata: 32 | labels: 33 | app: reviews 34 | version: v2 35 | spec: 36 | containers: 37 | - name: reviews-v2 38 | image: docker.io/istio/examples-bookinfo-reviews-v2 39 | imagePullPolicy: IfNotPresent 40 | ports: 41 | - containerPort: 9080 42 | --- 43 | -------------------------------------------------------------------------------- /demos/bookinfo/manifests/review/review-v3.yaml: -------------------------------------------------------------------------------- 1 | ################################################################################################## 2 | # Reviews service 3 | ################################################################################################## 4 | apiVersion: v1 5 | kind: Service 6 | metadata: 7 | name: reviews 8 | labels: 9 | app: reviews 10 | service: reviews 11 | spec: 12 | ports: 13 | - port: 9080 14 | name: http 15 | selector: 16 | app: reviews 17 | --- 18 | apiVersion: apps/v1 19 | kind: Deployment 20 | metadata: 21 | name: reviews-v3 22 | labels: 23 | app: reviews-v3 24 | version: v3 25 | spec: 26 | replicas: 1 27 | selector: 28 | matchLabels: 29 | app: reviews 30 | template: 31 | metadata: 32 | labels: 33 | app: reviews 34 | version: v3 35 | spec: 36 | containers: 37 | - name: reviews-v3 38 | image: docker.io/istio/examples-bookinfo-reviews-v3 39 | imagePullPolicy: IfNotPresent 40 | ports: 41 | - containerPort: 9080 42 | --- 43 | -------------------------------------------------------------------------------- /cmd/clusterlink/cmd/delete/delete.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) The ClusterLink Authors. 2 | // Licensed under the Apache License, Version 2.0 (the "License"); 3 | // you may not use this file except in compliance with the License. 4 | // You may obtain a copy of the License at 5 | // 6 | // http://www.apache.org/licenses/LICENSE-2.0 7 | // 8 | // Unless required by applicable law or agreed to in writing, software 9 | // distributed under the License is distributed on an "AS IS" BASIS, 10 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | // See the License for the specific language governing permissions and 12 | // limitations under the License. 13 | 14 | package deletion 15 | 16 | import ( 17 | "github.com/spf13/cobra" 18 | ) 19 | 20 | // NewCmdDelete returns a cobra.Command to run the delete command. 21 | func NewCmdDelete() *cobra.Command { 22 | cmds := &cobra.Command{ 23 | Use: "delete", 24 | Short: "Delete ClusterLink resources", 25 | Long: "Delete ClusterLink resources", 26 | } 27 | 28 | cmds.AddCommand(NewCmdDeletePeer()) 29 | 30 | return cmds 31 | } 32 | -------------------------------------------------------------------------------- /cmd/clusterlink/cmd/deploy/deploy.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) The ClusterLink Authors. 2 | // Licensed under the Apache License, Version 2.0 (the "License"); 3 | // you may not use this file except in compliance with the License. 4 | // You may obtain a copy of the License at 5 | // 6 | // http://www.apache.org/licenses/LICENSE-2.0 7 | // 8 | // Unless required by applicable law or agreed to in writing, software 9 | // distributed under the License is distributed on an "AS IS" BASIS, 10 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | // See the License for the specific language governing permissions and 12 | // limitations under the License. 13 | 14 | package deploy 15 | 16 | import ( 17 | "github.com/spf13/cobra" 18 | ) 19 | 20 | // NewCmdDeploy returns a cobra.Command to run the deploy command. 21 | func NewCmdDeploy() *cobra.Command { 22 | cmds := &cobra.Command{ 23 | Use: "deploy", 24 | Short: "Deploy ClusterLink resources", 25 | Long: "Deploy ClusterLink resources", 26 | } 27 | 28 | cmds.AddCommand(NewCmdDeployPeer()) 29 | 30 | return cmds 31 | } 32 | -------------------------------------------------------------------------------- /website/layouts/partials/favicons.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /demos/iperf3/testdata/manifests/iperf3-client/iperf3-client.yaml: -------------------------------------------------------------------------------- 1 | ################################################################ 2 | #Name: iperf3_client 3 | #Desc: YAML file for creating iperf3 client to send test traffic. 4 | ################################################################ 5 | apiVersion: apps/v1 6 | kind: DaemonSet 7 | metadata: 8 | name: iperf3-client 9 | labels: 10 | app: iperf3-client 11 | spec: 12 | selector: 13 | matchLabels: 14 | app: iperf3-client 15 | template: 16 | metadata: 17 | labels: 18 | app: iperf3-client 19 | spec: 20 | tolerations: 21 | - key: node-role.kubernetes.io/master 22 | operator: Exists 23 | effect: NoSchedule 24 | containers: 25 | - name: iperf3-client 26 | #image: networkstatic/iperf3 27 | image: taoyou/iperf3-alpine 28 | imagePullPolicy: IfNotPresent 29 | command: ['/bin/sh', '-c', 'sleep infinity'] 30 | # To benchmark manually: kubectl exec iperf3-client-jlfxq -- /bin/sh -c 'iperf3 -c iperf3-server' 31 | terminationGracePeriodSeconds: 0 32 | -------------------------------------------------------------------------------- /.devcontainer/dev/post-create.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Copyright (c) The ClusterLink Authors. 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | 16 | # Initialize Go tools 17 | go install github.com/golangci/golangci-lint/cmd/golangci-lint@v1.54.2 18 | go install golang.org/x/tools/cmd/goimports@latest 19 | go install github.com/mfridman/tparse@latest 20 | go install sigs.k8s.io/controller-tools/cmd/controller-gen@v0.14.0 21 | go install sigs.k8s.io/controller-runtime/tools/setup-envtest@latest 22 | go install mvdan.cc/gofumpt@v0.6.0 23 | go install github.com/raviqqe/muffet/v2@v2.9.3 24 | -------------------------------------------------------------------------------- /cmd/cl-dataplane/cl-dataplane.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) The ClusterLink Authors. 2 | // Licensed under the Apache License, Version 2.0 (the "License"); 3 | // you may not use this file except in compliance with the License. 4 | // You may obtain a copy of the License at 5 | // 6 | // http://www.apache.org/licenses/LICENSE-2.0 7 | // 8 | // Unless required by applicable law or agreed to in writing, software 9 | // distributed under the License is distributed on an "AS IS" BASIS, 10 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | // See the License for the specific language governing permissions and 12 | // limitations under the License. 13 | 14 | // The cl-dataplane binary runs an instance of a clink dataplane. 15 | package main 16 | 17 | import ( 18 | "os" 19 | 20 | "github.com/clusterlink-net/clusterlink/cmd/cl-dataplane/app" 21 | "github.com/clusterlink-net/clusterlink/pkg/versioninfo" 22 | ) 23 | 24 | func main() { 25 | command := app.NewCLDataplaneCommand() 26 | command.Version = versioninfo.Short() 27 | if err := command.Execute(); err != nil { 28 | os.Exit(1) 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /demos/iperf3/testdata/manifests/iperf3-client/iperf3-client2.yaml: -------------------------------------------------------------------------------- 1 | ################################################################ 2 | #Name: iperf3_client 3 | #Desc: YAML file for creating iperf3 client to send test traffic. 4 | ################################################################ 5 | apiVersion: apps/v1 6 | kind: DaemonSet 7 | metadata: 8 | name: iperf3-client2 9 | labels: 10 | app: iperf3-client2 11 | spec: 12 | selector: 13 | matchLabels: 14 | app: iperf3-client2 15 | template: 16 | metadata: 17 | labels: 18 | app: iperf3-client2 19 | spec: 20 | tolerations: 21 | - key: node-role.kubernetes.io/master 22 | operator: Exists 23 | effect: NoSchedule 24 | containers: 25 | - name: iperf3-client2 26 | #image: networkstatic/iperf3 27 | image: taoyou/iperf3-alpine 28 | imagePullPolicy: IfNotPresent 29 | command: ['/bin/sh', '-c', 'sleep infinity'] 30 | # To benchmark manually: kubectl exec iperf3-client2-jlfxq -- /bin/sh -c 'iperf3 -c iperf3-server' 31 | terminationGracePeriodSeconds: 0 32 | -------------------------------------------------------------------------------- /cmd/cl-go-dataplane/cl-go-dataplane.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) The ClusterLink Authors. 2 | // Licensed under the Apache License, Version 2.0 (the "License"); 3 | // you may not use this file except in compliance with the License. 4 | // You may obtain a copy of the License at 5 | // 6 | // http://www.apache.org/licenses/LICENSE-2.0 7 | // 8 | // Unless required by applicable law or agreed to in writing, software 9 | // distributed under the License is distributed on an "AS IS" BASIS, 10 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | // See the License for the specific language governing permissions and 12 | // limitations under the License. 13 | 14 | // The cl-dataplane binary runs an instance of a clink dataplane. 15 | package main 16 | 17 | import ( 18 | "os" 19 | 20 | "github.com/clusterlink-net/clusterlink/cmd/cl-go-dataplane/app" 21 | "github.com/clusterlink-net/clusterlink/pkg/versioninfo" 22 | ) 23 | 24 | func main() { 25 | command := app.NewCLGoDataplaneCommand() 26 | command.Version = versioninfo.Short() 27 | if err := command.Execute(); err != nil { 28 | os.Exit(1) 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /demos/bookinfo/manifests/product/details.yaml: -------------------------------------------------------------------------------- 1 | ################################################################################################## 2 | # Details service 3 | ################################################################################################## 4 | apiVersion: v1 5 | kind: Service 6 | metadata: 7 | name: details 8 | labels: 9 | app: details 10 | service: details 11 | spec: 12 | ports: 13 | - port: 9080 14 | name: http 15 | selector: 16 | app: details 17 | --- 18 | apiVersion: apps/v1 19 | kind: Deployment 20 | metadata: 21 | name: details-v1 22 | labels: 23 | app: details 24 | version: v1 25 | spec: 26 | replicas: 1 27 | selector: 28 | matchLabels: 29 | app: details 30 | template: 31 | metadata: 32 | annotations: 33 | sidecar.istio.io/inject: "true" 34 | labels: 35 | app: details 36 | version: v1 37 | spec: 38 | containers: 39 | - name: details 40 | image: docker.io/istio/examples-bookinfo-details-v1 41 | imagePullPolicy: IfNotPresent 42 | ports: 43 | - containerPort: 9080 44 | --- 45 | -------------------------------------------------------------------------------- /cmd/clusterlink/cmd/create/create.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) The ClusterLink Authors. 2 | // Licensed under the Apache License, Version 2.0 (the "License"); 3 | // you may not use this file except in compliance with the License. 4 | // You may obtain a copy of the License at 5 | // 6 | // http://www.apache.org/licenses/LICENSE-2.0 7 | // 8 | // Unless required by applicable law or agreed to in writing, software 9 | // distributed under the License is distributed on an "AS IS" BASIS, 10 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | // See the License for the specific language governing permissions and 12 | // limitations under the License. 13 | 14 | package create 15 | 16 | import ( 17 | "github.com/spf13/cobra" 18 | ) 19 | 20 | // NewCmdCreate returns a cobra.Command to run the create command. 21 | func NewCmdCreate() *cobra.Command { 22 | cmds := &cobra.Command{ 23 | Use: "create", 24 | Short: "Create ClusterLink resources", 25 | Long: "Create ClusterLink resources", 26 | } 27 | 28 | cmds.AddCommand(NewCmdCreateFabric()) 29 | cmds.AddCommand(NewCmdCreatePeerCert()) 30 | 31 | return cmds 32 | } 33 | -------------------------------------------------------------------------------- /.github/workflows/codeql.yml: -------------------------------------------------------------------------------- 1 | name: "CodeQL" 2 | 3 | on: 4 | push: 5 | branches: [ "main" ] 6 | pull_request: 7 | # The branches below must be a subset of the branches above 8 | branches: [ "main" ] 9 | schedule: 10 | - cron: '16 6 * * 3' 11 | 12 | permissions: 13 | contents: read 14 | 15 | jobs: 16 | analyze: 17 | name: Analyze 18 | runs-on: 'ubuntu-latest' 19 | timeout-minutes: 360 20 | permissions: 21 | actions: read 22 | contents: read 23 | security-events: write 24 | 25 | strategy: 26 | fail-fast: false 27 | matrix: 28 | language: [ 'go' ] 29 | 30 | steps: 31 | - name: Checkout repository 32 | uses: actions/checkout@v6 33 | with: 34 | fetch-tags: true 35 | - name: Initialize CodeQL 36 | uses: github/codeql-action/init@v4 37 | with: 38 | languages: ${{ matrix.language }} 39 | 40 | - name: Autobuild 41 | uses: github/codeql-action/autobuild@v4 42 | 43 | - name: Perform CodeQL Analysis 44 | uses: github/codeql-action/analyze@v4 45 | with: 46 | category: "/language:${{matrix.language}}" 47 | -------------------------------------------------------------------------------- /demos/qotd/manifests/qotd_db.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: qotd-db 5 | namespace: qotd-svc-iks 6 | labels: 7 | app: qotd 8 | tier: data 9 | spec: 10 | replicas: 1 11 | selector: 12 | matchLabels: 13 | app: qotd-db 14 | template: 15 | metadata: 16 | labels: 17 | app: qotd-db 18 | spec: 19 | containers: 20 | - name: qotd-db 21 | image: registry.gitlab.com/quote-of-the-day/qotd-db/v4.0.0:latest 22 | imagePullPolicy: Always 23 | ports: 24 | - name: mysql 25 | containerPort: 3306 26 | protocol: TCP 27 | env: 28 | - name: MYSQL_ROOT_PASSWORD 29 | value: "root" 30 | - name: MYSQL_DATABASE 31 | value: "qotd" 32 | --- 33 | apiVersion: v1 34 | kind: Service 35 | metadata: 36 | name: qotd-db 37 | namespace: qotd-svc-iks 38 | labels: 39 | app: qotd-db 40 | tier: data 41 | spec: 42 | type: ClusterIP 43 | ports: 44 | - name: mysql 45 | port: 3306 46 | targetPort: 3306 47 | protocol: TCP 48 | selector: 49 | app: qotd-db -------------------------------------------------------------------------------- /website/Makefile: -------------------------------------------------------------------------------- 1 | #------------------------------------------------------ 2 | # website targets 3 | #------------------------------------------------------ 4 | .PHONY: module_update build clean serve serve-dev checklinks checklinks-dev 5 | 6 | module_update: ; $(info updating hugo modules...) 7 | @hugo mod get -u ./... 8 | @hugo mod tidy 9 | 10 | build: ; $(info building site...) 11 | @hugo 12 | 13 | # delete hugo modules under clean? 14 | clean: ; $(info cleaning website output directory...) 15 | @rm -rf ./public 16 | 17 | serve: ; $(info running locally with env=production...) 18 | @hugo server --gc --cleanDestinationDir --disableFastRender 19 | 20 | serve-dev: ; $(info running locally env=dev \(drafts and future\)...) 21 | @hugo server --gc --cleanDestinationDir --disableFastRender --buildDrafts --buildFuture --enableGitInfo 22 | 23 | checklinks: ; $(info running link check on https://clusterlink.net...) 24 | @muffet -c 16 -b 65536 --rate-limit 16 https://clusterlink.net 25 | 26 | # run "make serve-dev" in one terminal and this command in another... 27 | checklinks-dev: ; $(info running link check on http://localhost:1313...) 28 | @muffet -c 16 -b 65536 --rate-limit 16 http://localhost:1313 29 | -------------------------------------------------------------------------------- /demos/bookinfo/manifests/product/product.yaml: -------------------------------------------------------------------------------- 1 | ################################################################################################## 2 | # Productpage services 3 | ################################################################################################## 4 | apiVersion: v1 5 | kind: Service 6 | metadata: 7 | name: productpage 8 | labels: 9 | app: productpage 10 | service: productpage 11 | spec: 12 | ports: 13 | - port: 9080 14 | #targetPort: 9080 15 | nodePort: 30001 16 | #protocol: TCP 17 | name: http 18 | selector: 19 | app: productpage 20 | #type: LoadBalancer 21 | type: NodePort 22 | --- 23 | apiVersion: apps/v1 24 | kind: Deployment 25 | metadata: 26 | name: productpage-v1 27 | labels: 28 | app: productpage 29 | version: v1 30 | spec: 31 | replicas: 1 32 | selector: 33 | matchLabels: 34 | app: productpage 35 | template: 36 | metadata: 37 | labels: 38 | app: productpage 39 | version: v1 40 | spec: 41 | containers: 42 | - name: productpage 43 | image: docker.io/istio/examples-bookinfo-productpage-v1 44 | imagePullPolicy: IfNotPresent 45 | ports: 46 | - containerPort: 9080 47 | -------------------------------------------------------------------------------- /demos/bookinfo/manifests/product/product2.yaml: -------------------------------------------------------------------------------- 1 | ################################################################################################## 2 | # Productpage services 3 | ################################################################################################## 4 | apiVersion: v1 5 | kind: Service 6 | metadata: 7 | name: productpage2 8 | labels: 9 | app: productpage2 10 | service: productpage2 11 | spec: 12 | ports: 13 | - port: 9080 14 | #targetPort: 9080 15 | nodePort: 30002 16 | #protocol: TCP 17 | name: http 18 | selector: 19 | app: productpage2 20 | #type: LoadBalancer 21 | type: NodePort 22 | --- 23 | apiVersion: apps/v1 24 | kind: Deployment 25 | metadata: 26 | name: productpage2-v1 27 | labels: 28 | app: productpage2 29 | version: v1 30 | spec: 31 | replicas: 1 32 | selector: 33 | matchLabels: 34 | app: productpage2 35 | template: 36 | metadata: 37 | labels: 38 | app: productpage2 39 | version: v1 40 | spec: 41 | containers: 42 | - name: productpage2 43 | image: docker.io/istio/examples-bookinfo-productpage-v1 44 | imagePullPolicy: IfNotPresent 45 | ports: 46 | - containerPort: 9080 47 | -------------------------------------------------------------------------------- /pkg/versioninfo/variables.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) The ClusterLink Authors. 2 | // Licensed under the Apache License, Version 2.0 (the "License"); 3 | // you may not use this file except in compliance with the License. 4 | // You may obtain a copy of the License at 5 | // 6 | // http://www.apache.org/licenses/LICENSE-2.0 7 | // 8 | // Unless required by applicable law or agreed to in writing, software 9 | // distributed under the License is distributed on an "AS IS" BASIS, 10 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | // See the License for the specific language governing permissions and 12 | // limitations under the License. 13 | 14 | // Package versioninfo uses Go's runtime/debug to set executable revision information. 15 | package versioninfo 16 | 17 | import ( 18 | "time" 19 | ) 20 | 21 | var ( 22 | // GitTag will hold the Git tag information. 23 | GitTag string 24 | // Version will be the version tag if the binary is built or "(devel)". 25 | Version = "unknown" 26 | // Revision is taken from the vcs.revision tag. 27 | Revision = "unknown" 28 | // LastCommit is taken from the vcs.time tag. 29 | LastCommit time.Time 30 | // DirtyBuild is taken from the vcs.modified tag. 31 | DirtyBuild = false 32 | ) 33 | -------------------------------------------------------------------------------- /website/layouts/shortcodes/clusterlink/card.html: -------------------------------------------------------------------------------- 1 | {{- $href := .Get "url" }} 2 | {{- $pattern := "@VERSION@"}} 3 | {{- with $href }} 4 | {{- if findRE $pattern . }} 5 | {{- $href = strings.Replace . $pattern site.Params.latest_stable_version -}} 6 | {{- end }} 7 | {{- end -}} 8 | 9 |20 | Learn More 21 |
22 |
6 |
7 | The ClusterLink's control plane and data plane have hookpoints to publish events to another component called event manager. A hookpoint is a point in code where *a new connection request has arrived* or *a service listing request arrives*. The event manager receives an event-type, and standard attributes which are associated with the event-type. The event manager then publishes the event to Policy Dispatcher which maintains a list of policy agents (ACL, LB, Limiter, Monitor, etc) which have subscribed to a policy with a certain priority in which they need to executed. For example, *a new connection request* event could be subscribed by ACL, LB and Monitor with a priority of 0, 1 and 2 which means ACL will be the first policy agent and Monitor the last. This also means that Policy Dispatcher maintains the states and handles the stitching of multiple policy agents for an event and handles the movement of shared states between the policy agents.
8 |
9 | Policy engine is kept separate to allow extensibility. We could consider dynamically loadable policy agents in javascript web assembly (WASM). However, initially we will start with a set of well known policy agents manually written in golang. The Operator should be able to send commands to the policy dispatcher to program it (add policy, remove policy, subscribe policy event, etc)
10 |
11 | ### Events + Attributes + Policy Agents Interested + Responses
12 |
13 | | Event |Attributes |Policy Agents |Response |
14 | |----------------|-------------------------------|-----------------------------|----------|
15 | |New connection|Src Service, Dst Service, Direction, *Optional Src Peer* |ACL, LB, Connection Limiter, Rate Limiter, Monitor | Allow/Deny, Target Peer, Optional Rate-limit |
16 | |Expose Service | Service ID | ACL | Target Peers|
17 | |Service List Request | Src Peer |ACL|Services|
18 |
19 | More such events should be added and their attributes clearly attributed, This is just a first step towards that.
20 |
--------------------------------------------------------------------------------
/demos/qotd/manifests/qotd_image.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: v1
2 | kind: Namespace
3 | metadata:
4 | name: qotd
5 | ---
6 | kind: Deployment
7 | apiVersion: apps/v1
8 | metadata:
9 | name: qotd-image
10 | namespace: qotd
11 | labels:
12 | app: qotd
13 | tier: api
14 | spec:
15 | replicas: 2
16 | selector:
17 | matchLabels:
18 | app: qotd-image
19 | template:
20 | metadata:
21 | labels:
22 | app: qotd-image
23 | spec:
24 | restartPolicy: Always
25 | containers:
26 | - name: qotd-image
27 | image: registry.gitlab.com/quote-of-the-day/qotd-image-service/v4.0.0:latest
28 | imagePullPolicy: Always
29 | ports:
30 | - name: http
31 | containerPort: 3003
32 | protocol: TCP
33 | env:
34 | - name: LOG_LEVEL
35 | value: "INFO"
36 | - name: ENABLE_INSTANA
37 | value: "false"
38 | - name: ANOMALY_GENERATOR_URL
39 | value: "qotd-usecase.qotd-load.svc.cluster.local:3012"
40 | livenessProbe:
41 | httpGet:
42 | path: /health
43 | port: 3003
44 | initialDelaySeconds: 60
45 | timeoutSeconds: 20
46 | periodSeconds: 60
47 | successThreshold: 1
48 | failureThreshold: 10
49 | readinessProbe:
50 | httpGet:
51 | path: /health
52 | port: 3003
53 | initialDelaySeconds: 5
54 | timeoutSeconds: 10
55 | periodSeconds: 10
56 | successThreshold: 1
57 | failureThreshold: 5
58 | resources:
59 | requests:
60 | cpu: "25m"
61 | memory: "200Mi"
62 | limits:
63 | cpu: "200m"
64 | memory: "800Mi"
65 | ---
66 | apiVersion: v1
67 | kind: Service
68 | metadata:
69 | name: qotd-image
70 | namespace: qotd
71 | labels:
72 | app: qotd
73 | tier: api
74 | spec:
75 | type: ClusterIP
76 | ports:
77 | - port: 3003
78 | targetPort: 3003
79 | protocol: TCP
80 | name: http
81 | selector:
82 | app: qotd-image
--------------------------------------------------------------------------------
/tests/e2e/k8s/test_performance.go:
--------------------------------------------------------------------------------
1 | // Copyright (c) The ClusterLink Authors.
2 | // Licensed under the Apache License, Version 2.0 (the "License");
3 | // you may not use this file except in compliance with the License.
4 | // You may obtain a copy of the License at
5 | //
6 | // http://www.apache.org/licenses/LICENSE-2.0
7 | //
8 | // Unless required by applicable law or agreed to in writing, software
9 | // distributed under the License is distributed on an "AS IS" BASIS,
10 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 | // See the License for the specific language governing permissions and
12 | // limitations under the License.
13 |
14 | package k8s
15 |
16 | import (
17 | "fmt"
18 |
19 | "github.com/stretchr/testify/require"
20 |
21 | "github.com/clusterlink-net/clusterlink/tests/e2e/k8s/services/iperf3"
22 | "github.com/clusterlink-net/clusterlink/tests/e2e/k8s/util"
23 | )
24 |
25 | func (s *TestSuite) TestPerformance() {
26 | // measure baseline performance
27 | baseBPS, err := iperf3.RunClient(s.clusters[0], &iperf3Service)
28 | require.Nil(s.T(), err)
29 | s.exportLogs()
30 |
31 | fmt.Printf("Baseline performance: %.2f Gbit/s\n", baseBPS/(1024*1024*1024))
32 |
33 | s.RunOnAllDataplaneTypes(func(cfg *util.PeerConfig) {
34 | // iperf is expected to generate many MBs of traffic
35 | cfg.ExpectLargeDataplaneTraffic = true
36 |
37 | cl, err := s.fabric.DeployClusterlinks(2, cfg)
38 | require.Nil(s.T(), err)
39 |
40 | require.Nil(s.T(), cl[0].CreateService(&iperf3Service))
41 | require.Nil(s.T(), cl[0].CreateExport(&iperf3Service))
42 | require.Nil(s.T(), cl[0].CreatePolicy(util.PolicyAllowAll))
43 | require.Nil(s.T(), cl[1].CreatePeer(cl[0]))
44 |
45 | importedService := &util.Service{
46 | Name: iperf3Service.Name,
47 | Namespace: cl[1].Namespace(),
48 | Port: 80,
49 | }
50 | require.Nil(s.T(), cl[1].CreateImport(importedService, cl[0], iperf3Service.Name))
51 |
52 | require.Nil(s.T(), cl[1].CreatePolicy(util.PolicyAllowAll))
53 |
54 | bps, err := iperf3.RunClient(cl[1].Cluster(), importedService)
55 | require.Nil(s.T(), err)
56 |
57 | fmt.Printf("Performance drop: %.2f\n", baseBPS/bps)
58 | })
59 | }
60 |
--------------------------------------------------------------------------------
/demos/qotd/manifests/qotd_rating.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: v1
2 | kind: Namespace
3 | metadata:
4 | name: qotd-svc-ocp
5 | ---
6 | kind: Deployment
7 | apiVersion: apps/v1
8 | metadata:
9 | name: qotd-rating
10 | namespace: qotd-svc-ocp
11 | labels:
12 | app: qotd
13 | tier: api
14 | spec:
15 | replicas: 1
16 | selector:
17 | matchLabels:
18 | app: qotd-rating
19 | template:
20 | metadata:
21 | labels:
22 | app: qotd-rating
23 | spec:
24 | restartPolicy: Always
25 | containers:
26 | - name: qotd-rating
27 | image: registry.gitlab.com/quote-of-the-day/qotd-ratings-service/v4.0.0:latest
28 | imagePullPolicy: Always
29 | ports:
30 | - name: http
31 | containerPort: 3004
32 | protocol: TCP
33 | env:
34 | - name: LOG_LEVEL
35 | value: "INFO"
36 | - name: ENABLE_INSTANA
37 | value: "false"
38 | - name: ANOMALY_GENERATOR_URL
39 | value: "qotd-usecase.qotd-load.svc.cluster.local:3012"
40 | livenessProbe:
41 | httpGet:
42 | path: /health
43 | port: 3004
44 | initialDelaySeconds: 60
45 | timeoutSeconds: 20
46 | periodSeconds: 60
47 | successThreshold: 1
48 | failureThreshold: 10
49 | readinessProbe:
50 | httpGet:
51 | path: /health
52 | port: 3004
53 | initialDelaySeconds: 5
54 | timeoutSeconds: 10
55 | periodSeconds: 10
56 | successThreshold: 1
57 | failureThreshold: 5
58 | resources:
59 | requests:
60 | cpu: "25m"
61 | memory: "200Mi"
62 | limits:
63 | cpu: "200m"
64 | memory: "800Mi"
65 | # nodeSelector:
66 | # ocpnode: qotd-svc-ocp
67 | ---
68 | apiVersion: v1
69 | kind: Service
70 | metadata:
71 | name: qotd-rating
72 | namespace: qotd-svc-ocp
73 | labels:
74 | app: qotd
75 | tier: api
76 | spec:
77 | type: ClusterIP
78 | ports:
79 | - port: 3004
80 | targetPort: 3004
81 | protocol: TCP
82 | name: http
83 | selector:
84 | app: qotd-rating
--------------------------------------------------------------------------------
/demos/utils/manifests/kind/flannel/create_cni_bridge.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) The ClusterLink Authors.
2 | # Licensed under the Apache License, Version 2.0 (the "License");
3 | # you may not use this file except in compliance with the License.
4 | # You may obtain a copy of the License at
5 | #
6 | # http://www.apache.org/licenses/LICENSE-2.0
7 | #
8 | # Unless required by applicable law or agreed to in writing, software
9 | # distributed under the License is distributed on an "AS IS" BASIS,
10 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 | # See the License for the specific language governing permissions and
12 | # limitations under the License.
13 |
14 | import os
15 | import shutil
16 |
17 | projDir = os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))))))
18 | pluginsFol=f'{projDir}/bin/plugins/'
19 |
20 | #Download plugins bridge for flannel
21 | def createCniBridge():
22 | if not os.path.exists(f"{pluginsFol}/bin/bridge"):
23 | print("Start building plugins for flannel")
24 | os.makedirs(pluginsFol, exist_ok=True)
25 | os.chdir(pluginsFol)
26 | os.system('git clone https://github.com/containernetworking/plugins.git')
27 | os.chdir(f'{pluginsFol}/plugins')
28 | os.system(f'./build_linux.sh')
29 | os.chdir(projDir)
30 | shutil.copytree(f'{projDir}/bin/plugins/plugins/bin', f'{projDir}/bin/plugins/bin')
31 | shutil.rmtree(f'{pluginsFol}/plugins')
32 | os.chdir(projDir)
33 | else:
34 | print(f"file {projDir}/bin/plugins/bridge exist")
35 |
36 | #Create kind config file with plugins for flannel
37 | def createKindCfgForflunnel():
38 | cfgFile=f'{pluginsFol}/flannel-config.yaml'
39 | if not os.path.exists(cfgFile):
40 | with open(f"{projDir}/demos/utils/manifests/kind/flannel/flannel-config.yaml", 'r') as file:
41 | lines = file.readlines()
42 |
43 | # replace the line you want to modify (line 3 in this example)
44 | lines[12] = f' - hostPath: {projDir}/bin/plugins/bin \n'
45 |
46 | with open(cfgFile, 'w') as file:
47 | file.writelines(lines)
48 |
49 | if __name__ == "__main__":
50 | createCniBridge()
51 | createKindCfgForflunnel()
--------------------------------------------------------------------------------
/.github/workflows/release.yml:
--------------------------------------------------------------------------------
1 | name: Release Images and Binaries
2 |
3 | on:
4 | push:
5 | tags:
6 | - 'v**'
7 |
8 | jobs:
9 | release:
10 | runs-on: ubuntu-latest
11 | permissions:
12 | contents: write
13 | packages: write
14 | steps:
15 | - name: checkout
16 | uses: actions/checkout@v6
17 | - name: Set up Go
18 | uses: actions/setup-go@v6
19 | with:
20 | go-version-file: ./go.mod
21 | - name: Login to GitHub Container Registry
22 | uses: docker/login-action@v3
23 | with:
24 | registry: ghcr.io
25 | username: ${{ github.actor }}
26 | password: ${{ secrets.GITHUB_TOKEN }}
27 | - name: Build binaries for amd64
28 | run: GOARCH=amd64 make build
29 | - name: Build binaries for arm64
30 | run: GOARCH=arm64 make build
31 | - name: Tag and push ClusterLink images with tag 'latest' and ${{ github.ref_name }}
32 | run: |
33 | docker buildx create --use --driver docker-container
34 | PLATFORMS=linux/amd64,linux/arm64 make push-image
35 | PLATFORMS=linux/amd64,linux/arm64 make push-image IMAGE_VERSION=${{ github.ref_name }}
36 | - name: Build and compress binaries
37 | run: |
38 | for pair in "linux:amd64" "linux:arm64" "darwin:amd64" "darwin:arm64"; do
39 | IFS=':' read -r os arch <<< "$pair"
40 | GOOS="$os" GOARCH="$arch" CGO_ENABLED=0 make cli-build BIN_DIR="$os"
41 | tar -czvf "clusterlink-$os-$arch.tar.gz" --transform "s/$os/clusterlink/" ./"$os"
42 | done
43 | - name: Upload binaries to release
44 | uses: svenstaro/upload-release-action@v2
45 | with:
46 | repo_token: ${{ secrets.GITHUB_TOKEN }}
47 | file: ./clusterlink*
48 | tag: ${{ github.ref }}
49 | overwrite: true
50 | file_glob: true
51 | - name: Update script installation version
52 | run: sed -i "s/VERSION=\"latest\"/VERSION=\"${{ github.ref_name }}\"/" hack/install_clusterlink.sh
53 | - name: Upload script installation
54 | uses: svenstaro/upload-release-action@v2
55 | with:
56 | repo_token: ${{ secrets.GITHUB_TOKEN }}
57 | file: ./hack/install_clusterlink.sh
58 | asset_name: clusterlink.sh
59 | tag: ${{ github.ref }}
60 | overwrite: true
61 |
--------------------------------------------------------------------------------
/demos/qotd/manifests/qotd_pdf.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: v1
2 | kind: Namespace
3 | metadata:
4 | name: qotd-svc-ocp
5 | ---
6 | kind: Deployment
7 | apiVersion: apps/v1
8 | metadata:
9 | name: qotd-pdf
10 | namespace: qotd-svc-ocp
11 | labels:
12 | app: qotd
13 | tier: api
14 | spec:
15 | replicas: 1
16 | selector:
17 | matchLabels:
18 | app: qotd-pdf
19 | template:
20 | metadata:
21 | labels:
22 | app: qotd-pdf
23 | spec:
24 | restartPolicy: Always
25 | containers:
26 | - name: qotd-pdf
27 | image: registry.gitlab.com/quote-of-the-day/qotd-pdf-service/v4.0.0:latest
28 | imagePullPolicy: Always
29 | ports:
30 | - name: http
31 | containerPort: 3005
32 | protocol: TCP
33 | env:
34 | - name: LOG_LEVEL
35 | value: "INFO"
36 | - name: ENABLE_INSTANA
37 | value: "false"
38 | - name: ANOMALY_GENERATOR_URL
39 | value: "qotd-usecase.qotd-load.svc.cluster.local:3012"
40 | - name: QUOTE_SVC
41 | value: "qotd-quote:3001"
42 | livenessProbe:
43 | httpGet:
44 | path: /health
45 | port: 3005
46 | initialDelaySeconds: 60
47 | timeoutSeconds: 20
48 | periodSeconds: 60
49 | successThreshold: 1
50 | failureThreshold: 10
51 | readinessProbe:
52 | httpGet:
53 | path: /health
54 | port: 3005
55 | initialDelaySeconds: 5
56 | timeoutSeconds: 10
57 | periodSeconds: 10
58 | successThreshold: 1
59 | failureThreshold: 5
60 | resources:
61 | requests:
62 | cpu: "25m"
63 | memory: "300Mi"
64 | limits:
65 | cpu: "200m"
66 | memory: "800Mi"
67 | # nodeSelector:
68 | # ocpnode: qotd-svc-ocp
69 | ---
70 | apiVersion: v1
71 | kind: Service
72 | metadata:
73 | name: qotd-pdf
74 | namespace: qotd-svc-ocp
75 | labels:
76 | app: qotd
77 | tier: api
78 | spec:
79 | type: ClusterIP
80 | ports:
81 | - port: 3005
82 | targetPort: 3005
83 | protocol: TCP
84 | name: http
85 | selector:
86 | app: qotd-pdf
--------------------------------------------------------------------------------
/demos/bookinfo/kind/README.md:
--------------------------------------------------------------------------------
1 |
2 | # BookInfo application Test
3 |
4 | **This BookInfo script and demo are for internal use only.**
5 |
6 | This demo set [Istio BookInfo application](https://istio.io/latest/docs/examples/bookinfo/) in different clusters.
7 | This demo shows different load-balancing policies like: random, round-robin or static destination.
8 | This test create three kind clusters:
9 |
10 | * Two Product-Page microservice (application frontend) and details microservice run on the first cluster.
11 | * The Reviews-V2 (display rating with black stars) and Rating microservices run on the second cluster.
12 | * The Reviews-V3 (display rating with black stars) and Rating microservices run on the third cluster.
13 | System illustration:
14 |
15 |
16 |
17 | ## Pre-requires installations
18 |
19 | To run a Kind test, check all pre-requires are installed (Go, docker, Kubectl, Kind):
20 |
21 | export PROJECT_FOLDER=`git rev-parse --show-toplevel`
22 | cd $PROJECT_FOLDER
23 | make prereqs
24 |
25 | ## BookInfo test
26 |
27 | Use a single script to build the kind clusters and BookInfo application.
28 |
29 | python3 ./test.py
30 |
31 | To run the BookInfo application use a Firefox web browser to connect the ProductPage microservice:
32 |
33 | export GW1IP=`kubectl get nodes -o jsonpath={.items[0].status.addresses[0].address}`
34 | firefox http://$GW1IP:30001/productpage
35 | firefox http://$GW1IP:30002/productpage
36 |
37 | Note: by default, a random policy is set.
38 |
39 | ### Apply round-robin load balancing policy.
40 |
41 | To apply round-robin load balancing policy to both ProductPage1 and ProductPage2:
42 |
43 | python3 ./apply_lb.py -t round-robin
44 |
45 | ### Apply static load balancing policy
46 |
47 | To apply static policy on ProductPage1 and ProductPage2 that directs them to the same Review service destination:
48 |
49 | python3 ./apply_lb.py -t same
50 |
51 | To apply a static policy on ProductPage1 and ProductPage2 that directs them to different Review service destinations:
52 |
53 | python3 ./apply_lb.py -t same
54 |
55 | ### Clean policy rules
56 |
57 | To clean all the policy rules:
58 |
59 | python3 ./apply_lb.py -t clean
60 |
61 | ### Cleanup
62 |
63 | Delete all Kind cluster.
64 |
65 | make clean-kind
66 |
--------------------------------------------------------------------------------
/demos/frp/kind/test.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 | # Copyright (c) The ClusterLink Authors.
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # http://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 |
15 | ################################################################
16 | # Name: FRP demo that connect 3 Kind clusters using FRP:
17 | # Desc: create 3 kind clusters :
18 | # 1) GW, iPerf3 client, FRP client, and FRP server
19 | # 2) GW, iPerf3 server, and FRP client
20 | # 3) GW, iPerf3 client, and FRP client
21 | ###############################################################
22 | import os
23 | import sys
24 | import time
25 | projDir = os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname( os.path.abspath(__file__)))))
26 | sys.path.insert(0,f'{projDir}')
27 |
28 | from demos.utils.common import printHeader
29 | from demos.utils.kind import Cluster
30 | from demos.iperf3.kind.iperf3_client_start import directTestIperf3,testIperf3Client
31 | from demos.frp.test import frpTest
32 |
33 | testOutputFolder = f"{projDir}/bin/tests/frp"
34 |
35 | ############################### MAIN ##########################
36 | if __name__ == "__main__":
37 | printHeader("\n\nStart Kind Test\n\n")
38 | printHeader("Start pre-setting")
39 |
40 | # cl parameters
41 | cl1= Cluster("peer1")
42 | cl2= Cluster("peer2")
43 | cl3= Cluster("peer3")
44 | srcSvc = "iperf3-client"
45 | destSvc = "iperf3-server"
46 | destPort = 5000
47 | iperf3DirectPort = "30001"
48 |
49 | # Setup
50 | frpTest(cl1, cl2, cl3, testOutputFolder)
51 | #Testing
52 | printHeader("\n\nStart Iperf3 testing")
53 | cl2.useCluster()
54 | cl2.setKindIp()
55 | directTestIperf3(cl1, srcSvc, cl2.ip, iperf3DirectPort)
56 | time.sleep(5)
57 | testIperf3Client(cl1, srcSvc, destSvc, destPort)
58 | testIperf3Client(cl3, srcSvc, destSvc, destPort)
59 |
60 |
61 |
62 |
--------------------------------------------------------------------------------
/demos/qotd/manifests/qotd_engraving.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: v1
2 | kind: Namespace
3 | metadata:
4 | name: qotd
5 | ---
6 | kind: Deployment
7 | apiVersion: apps/v1
8 | metadata:
9 | name: qotd-engraving
10 | namespace: qotd
11 | labels:
12 | app: qotd
13 | tier: api
14 | spec:
15 | replicas: 2
16 | selector:
17 | matchLabels:
18 | app: qotd-engraving
19 | template:
20 | metadata:
21 | labels:
22 | app: qotd-engraving
23 | spec:
24 | restartPolicy: Always
25 | containers:
26 | - name: qotd-engraving
27 | image: registry.gitlab.com/quote-of-the-day/qotd-engraving-service/v4.0.0:latest
28 | imagePullPolicy: Always
29 | ports:
30 | - name: http
31 | containerPort: 3006
32 | protocol: TCP
33 | env:
34 | - name: LOG_LEVEL
35 | value: "INFO"
36 | - name: ENABLE_INSTANA
37 | value: "false"
38 | - name: ANOMALY_GENERATOR_URL
39 | value: "qotd-usecase.qotd-load.svc.cluster.local:3012"
40 | - name: SUPPLY_CHAIN_URL
41 | value: ""
42 | - name: SUPPLY_CHAIN_SIMULATE
43 | value: "true"
44 | livenessProbe:
45 | httpGet:
46 | path: /health
47 | port: 3006
48 | initialDelaySeconds: 60
49 | timeoutSeconds: 20
50 | periodSeconds: 60
51 | successThreshold: 1
52 | failureThreshold: 10
53 | readinessProbe:
54 | httpGet:
55 | path: /health
56 | port: 3006
57 | initialDelaySeconds: 5
58 | timeoutSeconds: 10
59 | periodSeconds: 10
60 | successThreshold: 1
61 | failureThreshold: 5
62 | resources:
63 | requests:
64 | cpu: "25m"
65 | memory: "200Mi"
66 | limits:
67 | cpu: "200m"
68 | memory: "800Mi"
69 | ---
70 | apiVersion: v1
71 | kind: Service
72 | metadata:
73 | name: qotd-engraving
74 | namespace: qotd
75 | labels:
76 | app: qotd
77 | tier: api
78 | spec:
79 | type: ClusterIP
80 | ports:
81 | - port: 3006
82 | targetPort: 3006
83 | protocol: TCP
84 | name: http
85 | selector:
86 | app: qotd-engraving
--------------------------------------------------------------------------------
/pkg/controlplane/xds/controllers.go:
--------------------------------------------------------------------------------
1 | // Copyright (c) The ClusterLink Authors.
2 | // Licensed under the Apache License, Version 2.0 (the "License");
3 | // you may not use this file except in compliance with the License.
4 | // You may obtain a copy of the License at
5 | //
6 | // http://www.apache.org/licenses/LICENSE-2.0
7 | //
8 | // Unless required by applicable law or agreed to in writing, software
9 | // distributed under the License is distributed on an "AS IS" BASIS,
10 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 | // See the License for the specific language governing permissions and
12 | // limitations under the License.
13 |
14 | package xds
15 |
16 | import (
17 | "context"
18 |
19 | "k8s.io/apimachinery/pkg/types"
20 | ctrl "sigs.k8s.io/controller-runtime"
21 |
22 | "github.com/clusterlink-net/clusterlink/pkg/apis/clusterlink.net/v1alpha1"
23 | "github.com/clusterlink-net/clusterlink/pkg/util/controller"
24 | )
25 |
26 | // CreateControllers creates the various k8s controllers used to update the xDS manager.
27 | func CreateControllers(mgr *Manager, controllerManager ctrl.Manager) error {
28 | err := controller.AddToManager(controllerManager, &controller.Spec{
29 | Name: "xds.export",
30 | Object: &v1alpha1.Export{},
31 | AddHandler: func(ctx context.Context, object any) error {
32 | return mgr.AddExport(object.(*v1alpha1.Export))
33 | },
34 | DeleteHandler: func(ctx context.Context, name types.NamespacedName) error {
35 | return mgr.DeleteExport(name)
36 | },
37 | })
38 | if err != nil {
39 | return err
40 | }
41 |
42 | err = controller.AddToManager(controllerManager, &controller.Spec{
43 | Name: "xds.peer",
44 | Object: &v1alpha1.Peer{},
45 | AddHandler: func(ctx context.Context, object any) error {
46 | return mgr.AddPeer(object.(*v1alpha1.Peer))
47 | },
48 | DeleteHandler: func(ctx context.Context, name types.NamespacedName) error {
49 | return mgr.DeletePeer(name.Name)
50 | },
51 | })
52 | if err != nil {
53 | return err
54 | }
55 |
56 | return controller.AddToManager(controllerManager, &controller.Spec{
57 | Name: "xds.import",
58 | Object: &v1alpha1.Import{},
59 | AddHandler: func(ctx context.Context, object any) error {
60 | return mgr.AddImport(object.(*v1alpha1.Import))
61 | },
62 | DeleteHandler: func(ctx context.Context, name types.NamespacedName) error {
63 | return mgr.DeleteImport(name)
64 | },
65 | })
66 | }
67 |
--------------------------------------------------------------------------------
/website/static/files/tutorials/deploy-clusterlink.md:
--------------------------------------------------------------------------------
1 |
2 | 1. Create the fabric and peer certificates for the clusters:
3 |
4 | *Client cluster*:
5 |
6 | ```sh
7 | clusterlink create fabric
8 | clusterlink create peer-cert --name client
9 | ```
10 |
11 | *Server cluster*:
12 |
13 | ```sh
14 | clusterlink create peer-cert --name server
15 | ```
16 |
17 | All peer certificates (i.e., for the `client` and `server` clusters, in this tutorial) should be created from the same fabric CA files.
18 | In this tutorial, we assume the server has access to the Fabric certificate created in the `default_fabric` folder.
19 | In this tutorial, we assume the `server` cluster creation has access to the fabric certificate stored in the
20 | `default_fabric` folder. If it doesn't, the fabric certificate should be copied from the `client` to the `server`.
21 |
22 | For more details regarding fabric and peer see [core concepts][].
23 |
24 | 2. Deploy ClusterLink on each cluster:
25 |
26 | *Client cluster*:
27 |
28 | ```sh
29 | clusterlink deploy peer --name client --ingress=NodePort --ingress-port=30443
30 | ```
31 |
32 | *Server cluster*:
33 |
34 | ```sh
35 | clusterlink deploy peer --name server --ingress=NodePort --ingress-port=30443
36 | ```
37 |
38 | This tutorial uses **NodePort** to create an external access point for the kind clusters.
39 | By default `deploy peer` creates an ingress of type **LoadBalancer**,
40 | which is more suitable for Kubernetes clusters running in the cloud.
41 |
42 | 3. Verify that ClusterLink control and data plane components are running:
43 |
44 | It may take a few seconds for the deployments to be successfully created.
45 |
46 | *Client cluster*:
47 |
48 | ```sh
49 | kubectl rollout status deployment cl-controlplane -n clusterlink-system
50 | kubectl rollout status deployment cl-dataplane -n clusterlink-system
51 | ```
52 |
53 | *Server cluster*:
54 |
55 | ```sh
56 | kubectl rollout status deployment cl-controlplane -n clusterlink-system
57 | kubectl rollout status deployment cl-dataplane -n clusterlink-system
58 | ```
59 |
60 | {{% expand summary="Sample output" %}}
61 |
62 | deployment "cl-controlplane" successfully rolled out
63 | deployment "cl-dataplane" successfully rolled out
64 |
65 | {{% /expand %}}
66 |
67 | [core concepts]: {{< relref "../../concepts/_index.md" >}}
68 |
--------------------------------------------------------------------------------
/pkg/apis/clusterlink.net/v1alpha1/export.go:
--------------------------------------------------------------------------------
1 | // Copyright (c) The ClusterLink Authors.
2 | // Licensed under the Apache License, Version 2.0 (the "License");
3 | // you may not use this file except in compliance with the License.
4 | // You may obtain a copy of the License at
5 | //
6 | // http://www.apache.org/licenses/LICENSE-2.0
7 | //
8 | // Unless required by applicable law or agreed to in writing, software
9 | // distributed under the License is distributed on an "AS IS" BASIS,
10 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 | // See the License for the specific language governing permissions and
12 | // limitations under the License.
13 |
14 | package v1alpha1
15 |
16 | import (
17 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
18 | )
19 |
20 | // +kubebuilder:object:root=true
21 | // +kubebuilder:subresource:status
22 |
23 | // Export defines a service being exported by the local Peer for use by others.
24 | // Only explicitly exported services can be accessed remotely.
25 | type Export struct {
26 | metav1.TypeMeta `json:",inline"`
27 | metav1.ObjectMeta `json:"metadata,omitempty"`
28 |
29 | // Spec represents the attributes of the exported service.
30 | Spec ExportSpec `json:"spec,omitempty"`
31 | // Status represents the export status.
32 | Status ExportStatus `json:"status,omitempty"`
33 | }
34 |
35 | // ExportSpec contains all attributes of an exported service.
36 | type ExportSpec struct {
37 | // Host of the exported service.
38 | // If empty, export will point to a service with the same
39 | // name and namespace as the export object.
40 | Host string `json:"host,omitempty"`
41 | // Port of the exported service.
42 | Port uint16 `json:"port,omitempty"`
43 | }
44 |
45 | const (
46 | // ExportValid is a condition type for indicating whether the export is valid.
47 | ExportValid string = "ExportValid"
48 | )
49 |
50 | // ExportStatus represents the status of an exported service.
51 | type ExportStatus struct {
52 | // Conditions of the export.
53 | Conditions []metav1.Condition `json:"conditions,omitempty"`
54 | }
55 |
56 | // +kubebuilder:object:root=true
57 |
58 | // ExportList is a list of export objects.
59 | type ExportList struct {
60 | metav1.TypeMeta `json:",inline"`
61 | metav1.ListMeta `json:"metadata,omitempty"`
62 |
63 | // Items is the list of export objects.
64 | Items []Export `json:"items"`
65 | }
66 |
67 | func init() {
68 | SchemeBuilder.Register(&Export{}, &ExportList{})
69 | }
70 |
--------------------------------------------------------------------------------
/demos/qotd/manifests/qotd_quote.yaml:
--------------------------------------------------------------------------------
1 | apiVersion: v1
2 | kind: Namespace
3 | metadata:
4 | name: qotd-svc-iks
5 | ---
6 | apiVersion: apps/v1
7 | kind: Deployment
8 | metadata:
9 | name: qotd-quote
10 | namespace: qotd-svc-iks
11 | labels:
12 | app: qotd
13 | tier: api
14 | spec:
15 | replicas: 1
16 | selector:
17 | matchLabels:
18 | app: qotd-quote
19 | template:
20 | metadata:
21 | labels:
22 | app: qotd-quote
23 | spec:
24 | restartPolicy: Always
25 | containers:
26 | - name: qotd-quote
27 | image: registry.gitlab.com/quote-of-the-day/quote-service/v4.0.0:latest
28 | imagePullPolicy: Always
29 | ports:
30 | - name: http
31 | containerPort: 3001
32 | protocol: TCP
33 | env:
34 | - name: LOG_LEVEL
35 | value: "INFO"
36 | - name: ENABLE_INSTANA
37 | value: "false"
38 | - name: ANOMALY_GENERATOR_URL
39 | value: "qotd-usecase.qotd-load.svc.cluster.local:3012"
40 | - name: DB_HOST
41 | value: "qotd-db.qotd-svc-iks.svc.cluster.local"
42 | - name: DB_USER
43 | value: "root"
44 | - name: DB_PASS
45 | value: "root"
46 | - name: DB_NAME
47 | value: "qotd"
48 | livenessProbe:
49 | httpGet:
50 | path: /health
51 | port: 3001
52 | initialDelaySeconds: 60
53 | timeoutSeconds: 20
54 | periodSeconds: 60
55 | successThreshold: 1
56 | failureThreshold: 10
57 | readinessProbe:
58 | httpGet:
59 | path: /health
60 | port: 3001
61 | initialDelaySeconds: 5
62 | timeoutSeconds: 10
63 | periodSeconds: 10
64 | successThreshold: 1
65 | failureThreshold: 5
66 | resources:
67 | requests:
68 | cpu: "25m"
69 | memory: "200Mi"
70 | limits:
71 | cpu: "200m"
72 | memory: "800Mi"
73 | ---
74 | apiVersion: v1
75 | kind: Service
76 | metadata:
77 | name: qotd-quote
78 | namespace: qotd-svc-iks
79 | labels:
80 | app: qotd
81 | tier: api
82 | spec:
83 | type: ClusterIP
84 | ports:
85 | - port: 3001
86 | targetPort: 3001
87 | protocol: TCP
88 | name: http
89 | selector:
90 | app: qotd-quote
--------------------------------------------------------------------------------
/pkg/apis/clusterlink.net/v1alpha1/peer.go:
--------------------------------------------------------------------------------
1 | // Copyright (c) The ClusterLink Authors.
2 | // Licensed under the Apache License, Version 2.0 (the "License");
3 | // you may not use this file except in compliance with the License.
4 | // You may obtain a copy of the License at
5 | //
6 | // http://www.apache.org/licenses/LICENSE-2.0
7 | //
8 | // Unless required by applicable law or agreed to in writing, software
9 | // distributed under the License is distributed on an "AS IS" BASIS,
10 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 | // See the License for the specific language governing permissions and
12 | // limitations under the License.
13 |
14 | package v1alpha1
15 |
16 | import (
17 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
18 | )
19 |
20 | // +kubebuilder:object:root=true
21 | // +kubebuilder:subresource:status
22 |
23 | // Peer represents a location (or site) that can be used to import services from.
24 | type Peer struct {
25 | metav1.TypeMeta `json:",inline"`
26 | metav1.ObjectMeta `json:"metadata,omitempty"`
27 |
28 | // Spec represents the peer attributes.
29 | Spec PeerSpec `json:"spec"`
30 | // Status represents the peer status.
31 | Status PeerStatus `json:"status,omitempty"`
32 | }
33 |
34 | // Endpoint represents a network endpoint (i.e., host or IP and a port).
35 | type Endpoint struct {
36 | // Host or IP address of the endpoint.
37 | Host string `json:"host"`
38 | // Port of the endpoint.
39 | Port uint16 `json:"port"`
40 | }
41 |
42 | // PeerSpec contains all peer attributes.
43 | type PeerSpec struct {
44 | // Gateways serving the Peer.
45 | Gateways []Endpoint `json:"gateways"`
46 | }
47 |
48 | const (
49 | // PeerReachable is a condition type for indicating whether a peer is reachable (heartbeat responding).
50 | PeerReachable string = "PeerReachable"
51 | )
52 |
53 | // PeerStatus represents the status of a peer.
54 | type PeerStatus struct {
55 | // Conditions of the peer.
56 | Conditions []metav1.Condition `json:"conditions,omitempty"`
57 | // Labels holds peer labels, as reported by the remote peer
58 | Labels map[string]string `json:"labels,omitempty"`
59 | }
60 |
61 | // +kubebuilder:object:root=true
62 |
63 | // PeerList is a list of peer objects.
64 | type PeerList struct {
65 | metav1.TypeMeta `json:",inline"`
66 | metav1.ListMeta `json:"metadata,omitempty"`
67 |
68 | // Items is the list of peer objects.
69 | Items []Peer `json:"items"`
70 | }
71 |
72 | func init() {
73 | SchemeBuilder.Register(&Peer{}, &PeerList{})
74 | }
75 |
--------------------------------------------------------------------------------
/demos/bookinfo/cloud/apply_lb.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 | # Copyright (c) The ClusterLink Authors.
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # http://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 |
15 | import os
16 | import sys
17 | import argparse
18 |
19 | projDir = os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname( os.path.abspath(__file__)))))
20 | sys.path.insert(0,f'{projDir}')
21 | sys.path.insert(1,f'{projDir}/demos/utils/cloud/')
22 |
23 | from demos.bookinfo.test import applyPolicy
24 | from demos.utils.cloud import Cluster
25 |
26 | srcSvc1 = "productpage"
27 | srcSvc2 = "productpage2"
28 | destSvc = "reviews"
29 | clList = { "peer1gcp" : Cluster(name="peer1", zone = "us-west1-b" , platform = "gcp"), # Oregon
30 | "peer1ibm" : Cluster(name="peer1", zone = "sjc04" , platform = "ibm"), # San jose
31 | "peer2gcp" : Cluster(name="peer2", zone = "us-central1-b" , platform = "gcp"), # Iowa
32 | "peer2ibm" : Cluster(name="peer2", zone = "dal10" , platform = "ibm"), # Dallas
33 | "peer3gcp" : Cluster(name="peer3", zone = "us-east4-b" , platform = "gcp"), # Virginia
34 | "peer3ibm" : Cluster(name="peer3", zone = "wdc04" , platform = "ibm")} # Washington DC
35 |
36 | ############################### MAIN ##########################
37 | if __name__ == "__main__":
38 | parser = argparse.ArgumentParser(description='Description of your program')
39 | parser.add_argument('-p','--peer', help='Either peer1/peer2/peer3', required=False, default="peer1")
40 | parser.add_argument('-t','--type', help='Either round-robin/random/same/diff/clean/show', required=False, default="round-robin")
41 | parser.add_argument('-cloud','--cloud', help='Cloud setup using gcp/ibm', required=False, default="gcp")
42 |
43 | args = vars(parser.parse_args())
44 | print(f'Working directory {projDir}')
45 | os.chdir(projDir)
46 | cl = clList[args["peer"] + args["cloud"]]
47 | cl.set_kube_config()
48 | applyPolicy(cl, args["type"])
49 |
--------------------------------------------------------------------------------
/cmd/cl-dataplane/app/envoy.go:
--------------------------------------------------------------------------------
1 | // Copyright (c) The ClusterLink Authors.
2 | // Licensed under the Apache License, Version 2.0 (the "License");
3 | // you may not use this file except in compliance with the License.
4 | // You may obtain a copy of the License at
5 | //
6 | // http://www.apache.org/licenses/LICENSE-2.0
7 | //
8 | // Unless required by applicable law or agreed to in writing, software
9 | // distributed under the License is distributed on an "AS IS" BASIS,
10 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 | // See the License for the specific language governing permissions and
12 | // limitations under the License.
13 |
14 | package app
15 |
16 | import (
17 | "bytes"
18 | "fmt"
19 | "os"
20 | "os/exec"
21 | "text/template"
22 |
23 | cpapi "github.com/clusterlink-net/clusterlink/pkg/controlplane/api"
24 | "github.com/clusterlink-net/clusterlink/pkg/dataplane/api"
25 | )
26 |
27 | const (
28 | envoyPath = "/usr/local/bin/envoy"
29 |
30 | adminPort = 1500
31 | )
32 |
33 | func (o *Options) runEnvoy(dataplaneID string) error {
34 | envoyConfArgs := map[string]interface{}{
35 | "dataplaneID": dataplaneID,
36 |
37 | "adminPort": adminPort,
38 |
39 | "controlplaneHost": o.ControlplaneHost,
40 | "controlplanePort": cpapi.ListenPort,
41 |
42 | "dataplaneListenPort": api.ListenPort,
43 |
44 | "certificateFile": CertificateFile,
45 | "keyFile": KeyFile,
46 | "caFile": CAFile,
47 |
48 | "controlplaneCluster": cpapi.ControlplaneCluster,
49 | "egressRouterCluster": cpapi.EgressRouterCluster,
50 |
51 | "egressRouterListener": cpapi.EgressRouterListener,
52 | "ingressRouterListener": cpapi.IngressRouterListener,
53 |
54 | "certificateSecret": cpapi.CertificateSecret,
55 | "validationSecret": cpapi.ValidationSecret,
56 |
57 | "authorizationHeader": cpapi.AuthorizationHeader,
58 | "targetClusterHeader": cpapi.TargetClusterHeader,
59 | }
60 |
61 | var envoyConf bytes.Buffer
62 | t := template.Must(template.New("").Parse(envoyConfigurationTemplate))
63 | if err := t.Execute(&envoyConf, envoyConfArgs); err != nil {
64 | return fmt.Errorf("cannot create Envoy configuration off template: %w", err)
65 | }
66 |
67 | args := []string{
68 | "--log-level", o.LogLevel,
69 | "--config-yaml", envoyConf.String(),
70 | }
71 | if o.LogFile != "" {
72 | args = append(args, "--log-path", o.LogFile)
73 | }
74 |
75 | cmd := exec.Command(envoyPath, args...)
76 | cmd.Stdout = os.Stdout
77 | cmd.Stderr = os.Stderr
78 | return cmd.Run()
79 | }
80 |
--------------------------------------------------------------------------------
/website/content/en/docs/main/concepts/fabric.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Fabric
3 | description: Defining a ClusterLink fabric
4 | weight: 10
5 | ---
6 |
7 | The concept of a *Fabric* encapsulates a set of cooperating [peers][].
8 | All peers in a fabric can communicate and may share [services][]
9 | between them, with access governed by [policies][].
10 | The Fabric acts as a root of trust for peer-to-peer communications (i.e.,
11 | it functions as the certificate authority enabling mutual authentication between
12 | peers).
13 |
14 | Currently, the concept of a Fabric is just that - a concept. It is not represented
15 | or backed by any managed resource in a ClusterLink deployment. Once a Fabric is created,
16 | its only relevance is in providing a certificate for use by each peer's gateways.
17 | One could potentially consider a more elaborate implementation where a central
18 | management entity explicitly deals with Fabric life cycle, association of peers to
19 | a fabric, etc. The role of this central management component in ClusterLink is currently
20 | delegated to users who are responsible for coordinating the transfer of certificates
21 | between peers, out of band.
22 |
23 | ## Initializing a new fabric
24 |
25 | ### Prerequisites
26 |
27 | The following sections assume that you have access to the `clusterlink` CLI and one or more
28 | peers (i.e., clusters) where you'll deploy ClusterLink. The CLI can be downloaded
29 | from the ClusterLink [releases page on GitHub][].
30 |
31 | ### Create a new fabric CA
32 |
33 | To create a new fabric certificate authority (CA), execute the following CLI command:
34 |
35 | ```sh
36 | clusterlink create fabric --name