{"id":25489823,"url":"https://github.com/ruzickap/k8s-multicluster-gitops","last_synced_at":"2026-05-05T17:31:31.635Z","repository":{"id":277956986,"uuid":"934033162","full_name":"ruzickap/k8s-multicluster-gitops","owner":"ruzickap","description":"Infrastructure as Code for provisioning multiple Kubernetes clusters, managed using GitOps with ArgoCD","archived":false,"fork":false,"pushed_at":"2026-05-03T05:54:55.000Z","size":305,"stargazers_count":0,"open_issues_count":2,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-05-03T07:26:24.274Z","etag":null,"topics":["aks","argocd","eks","gitops","infrastructure-as-code","k8s","k8s-gitops","kind","kubernetes","multi-cluster","terraform","vcluster"],"latest_commit_sha":null,"homepage":"","language":"Shell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ruzickap.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null}},"created_at":"2025-02-17T06:52:24.000Z","updated_at":"2026-05-03T05:54:58.000Z","dependencies_parsed_at":"2026-03-01T12:35:43.325Z","dependency_job_id":null,"html_url":"https://github.com/ruzickap/k8s-multicluster-gitops","commit_stats":null,"previous_names":["ruzickap/k8s-multicluster-gitops"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/ruzickap/k8s-multicluster-gitops","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ruzickap%2Fk8s-multicluster-gitops","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ruzickap%2Fk8s-multicluster-gitops/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ruzickap%2Fk8s-multicluster-gitops/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ruzickap%2Fk8s-multicluster-gitops/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ruzickap","download_url":"https://codeload.github.com/ruzickap/k8s-multicluster-gitops/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ruzickap%2Fk8s-multicluster-gitops/sbom","scorecard":{"id":893768,"data":{"date":"2025-08-24T11:48:17Z","repo":{"name":"github.com/ruzickap/k8s-multicluster-gitops","commit":"759087efe53834fe380ebcde6a5293eaf5f60941"},"scorecard":{"version":"v5.2.1","commit":"ab2f6e92482462fe66246d9e32f642855a691dc1"},"score":8.1,"checks":[{"name":"Code-Review","score":0,"reason":"Found 0/28 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/ab2f6e92482462fe66246d9e32f642855a691dc1/docs/checks.md#code-review"}},{"name":"Maintained","score":10,"reason":"29 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 10","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/ab2f6e92482462fe66246d9e32f642855a691dc1/docs/checks.md#maintained"}},{"name":"Security-Policy","score":10,"reason":"security policy file detected","details":["Info: security policy file detected: SECURITY.md:1","Info: Found linked content: SECURITY.md:1","Info: Found disclosure, vulnerability, and/or timelines in security policy: SECURITY.md:1","Info: Found text in security policy: SECURITY.md:1"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/ab2f6e92482462fe66246d9e32f642855a691dc1/docs/checks.md#security-policy"}},{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/ab2f6e92482462fe66246d9e32f642855a691dc1/docs/checks.md#dangerous-workflow"}},{"name":"Dependency-Update-Tool","score":10,"reason":"update tool detected","details":["Info: detected update tool: RenovateBot: .github/renovate.json5:1"],"documentation":{"short":"Determines if the project uses a dependency update tool.","url":"https://github.com/ossf/scorecard/blob/ab2f6e92482462fe66246d9e32f642855a691dc1/docs/checks.md#dependency-update-tool"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/ab2f6e92482462fe66246d9e32f642855a691dc1/docs/checks.md#binary-artifacts"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/ab2f6e92482462fe66246d9e32f642855a691dc1/docs/checks.md#packaging"}},{"name":"Token-Permissions","score":10,"reason":"GitHub workflow tokens follow principle of least privilege","details":["Info: jobLevel 'packages' permission set to 'read': .github/workflows/codeql-actions.yml:25","Warn: jobLevel 'contents' permission set to 'write': .github/workflows/release-please.yml:19","Info: topLevel permissions set to 'read-all': .github/workflows/codeql-actions.yml:17","Info: topLevel permissions set to 'read-all': .github/workflows/mega-linter.yml:13","Info: topLevel permissions set to 'read-all': .github/workflows/pr-slack-notification.yml:22","Info: topLevel permissions set to 'read-all': .github/workflows/release-please.yml:13","Info: topLevel permissions set to 'read-all': .github/workflows/renovate.yml:49","Info: topLevel permissions set to 'read-all': .github/workflows/run-tests.yml:13","Info: topLevel permissions set to 'read-all': .github/workflows/scorecards.yml:14","Info: topLevel 'pull-requests' permission set to 'read': .github/workflows/semantic-pull-request.yml:16"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/ab2f6e92482462fe66246d9e32f642855a691dc1/docs/checks.md#token-permissions"}},{"name":"Pinned-Dependencies","score":10,"reason":"all dependencies are pinned","details":["Info:  14 out of  14 GitHub-owned GitHubAction dependencies pinned","Info:  10 out of  10 third-party GitHubAction dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/ab2f6e92482462fe66246d9e32f642855a691dc1/docs/checks.md#pinned-dependencies"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/ab2f6e92482462fe66246d9e32f642855a691dc1/docs/checks.md#cii-best-practices"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/ab2f6e92482462fe66246d9e32f642855a691dc1/docs/checks.md#vulnerabilities"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/ab2f6e92482462fe66246d9e32f642855a691dc1/docs/checks.md#fuzzing"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/ab2f6e92482462fe66246d9e32f642855a691dc1/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":9,"reason":"branch protection is not maximal on development and all release branches","details":["Info: 'allow deletion' disabled on branch 'main'","Info: 'force pushes' disabled on branch 'main'","Warn: 'branch protection settings apply to administrators' is disabled on branch 'main'","Info: 'stale review dismissal' is required to merge on branch 'main'","Info: required approving review count is 2 on branch 'main'","Info: codeowner review is required on branch 'main'","Info: 'last push approval' is required to merge on branch 'main'","Info: 'up-to-date branches' is required to merge on branch 'main'","Info: status check found to merge onto on branch 'main'","Info: PRs are required in order to make changes on branch 'main'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/ab2f6e92482462fe66246d9e32f642855a691dc1/docs/checks.md#branch-protection"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: Apache License 2.0: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/ab2f6e92482462fe66246d9e32f642855a691dc1/docs/checks.md#license"}},{"name":"Contributors","score":3,"reason":"project has 1 contributing companies or organizations -- score normalized to 3","details":["Info: found contributions from: mckinsey \u0026 company"],"documentation":{"short":"Determines if the project has a set of contributors from multiple organizations (e.g., companies).","url":"https://github.com/ossf/scorecard/blob/ab2f6e92482462fe66246d9e32f642855a691dc1/docs/checks.md#contributors"}},{"name":"SAST","score":9,"reason":"SAST tool detected but not run on all commits","details":["Info: SAST configuration detected: CodeQL","Warn: 5 commits out of 7 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/ab2f6e92482462fe66246d9e32f642855a691dc1/docs/checks.md#sast"}},{"name":"CI-Tests","score":10,"reason":"7 out of 7 merged PRs checked by a CI test -- score normalized to 10","details":null,"documentation":{"short":"Determines if the project runs tests before pull requests are merged.","url":"https://github.com/ossf/scorecard/blob/ab2f6e92482462fe66246d9e32f642855a691dc1/docs/checks.md#ci-tests"}}]},"last_synced_at":"2025-08-24T12:53:24.973Z","repository_id":277956986,"created_at":"2025-08-24T12:53:24.974Z","updated_at":"2025-08-24T12:53:24.974Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32660159,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-05T11:29:49.557Z","status":"ssl_error","status_checked_at":"2026-05-05T11:29:48.587Z","response_time":54,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["aks","argocd","eks","gitops","infrastructure-as-code","k8s","k8s-gitops","kind","kubernetes","multi-cluster","terraform","vcluster"],"created_at":"2025-02-18T21:17:58.695Z","updated_at":"2026-05-05T17:31:31.628Z","avatar_url":"https://github.com/ruzickap.png","language":"Shell","funding_links":[],"categories":[],"sub_categories":[],"readme":"# k8s-multicluster-gitops\n\nInfrastructure as Code (IaC) for provisioning and managing multiple Kubernetes\nclusters across multiple cloud accounts, using GitOps principles with ArgoCD.\n\n## Requirements\n\nGuides on setting up Kubernetes clusters in the cloud are common, but few cover\nmanaging clusters across multiple providers and accounts, which is a key need\nfor large enterprises.\n\nThis project aims to provide a practical example:\n\n- ✅ Provisioning and managing Kubernetes clusters across multiple cloud\n  providers (AWS, Azure, GCP).\n- ✅ Deploying and maintaining Kubernetes clusters across multiple accounts and\n  regions.\n\n## Architecture\n\nYou will likely need to deploy multiple Kubernetes clusters across various cloud\nproviders and accounts.\n\nEach cloud provider has a designated \"management account\" where subdomains are hosted:\n\n- `aws.mylabs.dev` - AWS\n- `az.mylabs.dev` - Azure\n- `gcp.mylabs.dev` - Google Cloud Platform\n\n\u003e The second-level domain `mylabs.dev` is hosted externally (e.g., Cloudflare),\n\u003e and it's the user's responsibility to configure DNS delegation properly.\n\nAn IAM role (or its equivalent for each cloud provider) will be created in the\nmanagement account. This role will allow GitHub Actions/mise to manage resources\nin the management account and will also be used to access other accounts where\nKubernetes clusters are deployed.\n\n## Cloud Providers - Multi-Account Setup\n\nLet's assume you have two AWS accounts, two Azure accounts, and two GCP accounts,\nand you want to deploy two Kubernetes clusters (EKS, AKS, GKE) in each account:\n\n| Cloud Provider                                   | Account 01                                                   | Account 02                                                   |\n|--------------------------------------------------|--------------------------------------------------------------|--------------------------------------------------------------|\n| **AWS** (`aws.mylabs.dev`, `k8s.aws.mylabs.dev`) | `k01.k8s.aws.mylabs.dev` (US), `k02.k8s.aws.mylabs.dev` (EU) | `k03.k8s.aws.mylabs.dev` (US), `k04.k8s.aws.mylabs.dev` (EU) |\n| **Azure** (`az.mylabs.dev`, `k8s.az.mylabs.dev`) | `k01.k8s.az.mylabs.dev` (US), `k02.k8s.az.mylabs.dev` (EU)   | `k03.k8s.az.mylabs.dev` (US), `k04.k8s.az.mylabs.dev` (EU)   |\n| **GCP** (`gcp.mylabs.dev`, `k8s.gcp.mylabs.dev`) | `k01.k8s.gcp.mylabs.dev` (US), `k02.k8s.gcp.mylabs.dev` (EU) | `k03.k8s.gcp.mylabs.dev` (US), `k04.k8s.gcp.mylabs.dev` (EU) |\n\n### AWS\n\nYou should have access to all your AWS accounts via the AWS CLI (using\n`AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`, ...)\n\n#### Management account\n\nSelect one of your AWS accounts to serve as the management account.\n\n##### AWS CLI User\n\nCreate an `aws-cli` [IAM user](https://us-east-1.console.aws.amazon.com/iam/home?region=us-east-1#/users)\nin your management AWS account. Then, add the user's ARN to the [mise.toml](mise.toml)\nfile under the `env.AWS_USER_ARN` variable.\n\n```bash\nAWS_USER_NAME=\"aws-cli\"\nAWS_POLICY_ARN=\"arn:aws:iam::aws:policy/AdministratorAccess\"\n\n# Create IAM user\naws iam create-user --user-name \"${AWS_USER_NAME}\"\n\n# Attach a policy to the user\naws iam attach-user-policy --user-name \"${AWS_USER_NAME}\" --policy-arn \"${AWS_POLICY_ARN}\"\n\n# Create access keys for the user\naws iam create-access-key --user-name \"${AWS_USER_NAME}\"\n\n# Get the ARN of the user\nAWS_USER_ARN=$(aws iam list-users --query \"Users[? UserName==\\`${AWS_USER_NAME}\\`].Arn\" --output text)\nsed -i \"s@^AWS_USER_ARN.*@AWS_USER_ARN = \\\"${AWS_USER_ARN}\\\"@\" mise.local.toml\n```\n\nThe `aws-cli` user is created in the management AWS account. It will be used to\naccess all AWS accounts via the AWS CLI by assuming the appropriate IAM role.\n\n##### Route35 Hosted Zone + GitHub Action IAM Role\n\nThe following steps will create a Route 53 hosted zone for the subdomain\n`aws.mylabs.dev` and a GitHub Actions IAM role that can be assumed by the\nGitHub Actions workflow.\nThe GitHub Actions IAM role will be used to manage resources in the management\naccount and to access other accounts where Kubernetes clusters are deployed.\n\nCreate a Route 53 hosted zone for `aws.mylabs.dev`:\n\n\u003e Ensure that the necessary environment variables are set for the AWS CLI\n\u003e (e.g., `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`).\n\n```bash\nmise run create:aws-mgmt:cf-route53-gh-action-iam-role-oidc\n```\n\n\u003e For more details please inspect the [mise.toml](./mise.toml) file.\n\nNext, manually set up the DNS delegation between your second-level domain\n`mylabs.dev` and the `aws.mylabs.dev` hosted zone in Route 53.\n\nExample:\n\n![Cloudflare DNS records for mylabs.dev](images/cloudflare-mylabs-dev-dns-records.avif)\n\n#### Tenant Accounts\n\nCreate an IAM role in each tenant account that allows the management account to\nassume a role in that tenant account.\n\n\u003e Make sure to use AWS credentials (`AWS_ACCESS_KEY_ID`,\n\u003e `AWS_SECRET_ACCESS_KEY`) for the tenant account.\n\n```bash\nmise run create:aws-tenant:cf-iam-role\n```\n\n### Azure\n\n### GCP\n\n## K8s Clusters\n\nAll kubeconfig files will be stored in the `clusters/.kubeconfigs`\ndirectory.\n\n### Kind\n\nThe [kind clusters](https://kind.sigs.k8s.io/) are created using the `kind`\ntool, which is a tool for running Kubernetes clusters in Docker containers.\n\n```bash\nmise run create:kind:kind01-internal\nmise run delete:kind:kind01-internal\nmise run create:kind:kind02-internal\nmise run delete:kind:kind02-internal\nmise run create-kind-all\nmise run delete-kind-all\n```\n\n### K3d\n\nThe [k3d clusters](https://k3d.io/) are created using the `k3d` tool, which\nis a lightweight wrapper to run `k3s` in Docker containers.\n\n```bash\nmise run create:k3d:k3d01-internal\nmise run delete:k3d:k3d01-internal\nmise run create:k3d:k3d02-internal\nmise run delete:k3d:k3d02-internal\nmise run create-k3d-all\nmise run delete-k3d-all\n```\n\n\u003e You can also create all the clusters at once using the `create-all` and\n\u003e `delete-all` commands:\n\u003e\n\u003e ```bash\n\u003e mise run \"create-kind-all\" ::: \"create-k3d-all\"\n\u003e mise run \"delete-kind-all\" ::: \"delete-k3d-all\"\n\u003e ```\n\n## Architecture diagrams\n\n### DNS diagram\n\n```mermaid\nflowchart TB\n  subgraph \"Cloudflare\"\n    mylabs.dev@{ icon: \"logos:cloudflare-icon\", form: \"square\", label: \"mylabs.dev\", pos: \"b\", h: 60 }\n  end\n\n  subgraph \"AWS\"\n    subgraph \"AWS Management Account\"\n      aws.mylabs.dev@{ icon: \"logos:aws-route53\", form: \"circle\", label: \"aws.mylabs.dev\", pos: \"b\", h: 60 }\n      k8s.aws.mylabs.dev@{ icon: \"logos:aws-route53\", form: \"square\", label: \"k8s.aws.mylabs.dev\", pos: \"b\", h: 60 }\n    end\n    subgraph \"AWS Account 02\"\n      k03.k8s.aws.mylabs.dev@{ icon: \"logos:aws-route53\", form: \"square\", label: \"k03.k8s.aws.mylabs.dev\", pos: \"b\", h: 60 }\n      k04.k8s.aws.mylabs.dev@{ icon: \"logos:aws-route53\", form: \"square\", label: \"k04.k8s.aws.mylabs.dev\", pos: \"b\", h: 60 }\n    end\n    subgraph \"AWS Account 01\"\n      k01.k8s.aws.mylabs.dev@{ icon: \"logos:aws-route53\", form: \"square\", label: \"k01.k8s.aws.mylabs.dev\", pos: \"b\", h: 60 }\n      k02.k8s.aws.mylabs.dev@{ icon: \"logos:aws-route53\", form: \"square\", label: \"k02.k8s.aws.mylabs.dev\", pos: \"b\", h: 60 }\n    end\n  end\n\n  subgraph \"Azure\"\n    subgraph \"Azure Management Account\"\n      az.mylabs.dev@{ icon: \"logos:azure-icon\", form: \"circle\", label: \"az.mylabs.dev\", pos: \"b\", h: 60 }\n      k8s.az.mylabs.dev@{ icon: \"logos:azure-icon\", form: \"square\", label: \"k8s.az.mylabs.dev\", pos: \"b\", h: 60 }\n    end\n    subgraph \"Azure Account 02\"\n      k03.k8s.az.mylabs.dev@{ icon: \"logos:azure-icon\", form: \"square\", label: \"k03.k8s.az.mylabs.dev\", pos: \"b\", h: 60 }\n      k04.k8s.az.mylabs.dev@{ icon: \"logos:azure-icon\", form: \"square\", label: \"k04.k8s.az.mylabs.dev\", pos: \"b\", h: 60 }\n    end\n    subgraph \"Azure Account 01\"\n      k01.k8s.az.mylabs.dev@{ icon: \"logos:azure-icon\", form: \"square\", label: \"k01.k8s.az.mylabs.dev\", pos: \"b\", h: 60 }\n      k02.k8s.az.mylabs.dev@{ icon: \"logos:azure-icon\", form: \"square\", label: \"k02.k8s.az.mylabs.dev\", pos: \"b\", h: 60 }\n    end\n  end\n\n  subgraph \"GCP\"\n    subgraph \"GCP Management Account\"\n      gcp.mylabs.dev@{ icon: \"logos:google-cloud\", form: \"circle\", label: \"gcp.mylabs.dev\", pos: \"b\", h: 60 }\n      k8s.gcp.mylabs.dev@{ icon: \"logos:google-cloud\", form: \"square\", label: \"k8s.gcp.mylabs.dev\", pos: \"b\", h: 60 }\n    end\n    subgraph \"GCP Account 02\"\n      k03.k8s.gcp.mylabs.dev@{ icon: \"logos:google-cloud\", form: \"square\", label: \"k03.k8s.gcp.mylabs.dev\", pos: \"b\", h: 60 }\n      k04.k8s.gcp.mylabs.dev@{ icon: \"logos:google-cloud\", form: \"square\", label: \"k04.k8s.gcp.mylabs.dev\", pos: \"b\", h: 60 }\n    end\n    subgraph \"GCP Account 01\"\n      k01.k8s.gcp.mylabs.dev@{ icon: \"logos:google-cloud\", form: \"square\", label: \"k01.k8s.gcp.mylabs.dev\", pos: \"b\", h: 60 }\n      k02.k8s.gcp.mylabs.dev@{ icon: \"logos:google-cloud\", form: \"square\", label: \"k02.k8s.gcp.mylabs.dev\", pos: \"b\", h: 60 }\n    end\n  end\n\n  mylabs.dev --\u003e aws.mylabs.dev\n  aws.mylabs.dev --\u003e k8s.aws.mylabs.dev\n  k8s.aws.mylabs.dev --\u003e k01.k8s.aws.mylabs.dev\n  k8s.aws.mylabs.dev --\u003e k02.k8s.aws.mylabs.dev\n  k8s.aws.mylabs.dev --\u003e k03.k8s.aws.mylabs.dev\n  k8s.aws.mylabs.dev --\u003e k04.k8s.aws.mylabs.dev\n  mylabs.dev --\u003e az.mylabs.dev\n  az.mylabs.dev --\u003e k8s.az.mylabs.dev\n  k8s.az.mylabs.dev --\u003e k01.k8s.az.mylabs.dev\n  k8s.az.mylabs.dev --\u003e k02.k8s.az.mylabs.dev\n  k8s.az.mylabs.dev --\u003e k03.k8s.az.mylabs.dev\n  k8s.az.mylabs.dev --\u003e k04.k8s.az.mylabs.dev\n  mylabs.dev --\u003e gcp.mylabs.dev\n  gcp.mylabs.dev --\u003e k8s.gcp.mylabs.dev\n  k8s.gcp.mylabs.dev --\u003e k01.k8s.gcp.mylabs.dev\n  k8s.gcp.mylabs.dev --\u003e k02.k8s.gcp.mylabs.dev\n  k8s.gcp.mylabs.dev --\u003e k03.k8s.gcp.mylabs.dev\n  k8s.gcp.mylabs.dev --\u003e k04.k8s.gcp.mylabs.dev\n```\n\n### AWS diagram\n\nSuppose you have three AWS accounts and want to provision one EKS cluster in each.\nThe setup would look like this:\n\n- **AWS Management Account** - centralized account responsible for provisioning\n  and managing infrastructure, hosting two EKS clusters, and assuming IAM roles\n  in tenant accounts\n  - k01.k8s.aws.mylabs.dev\n  - k02.k8s.aws.mylabs.dev\n- **AWS Tenant Account 01** – tenant account hosting two EKS clusters. These\n  clusters are created using a local IAM role, which is assumed by the IAM role\n  from the management account\n  - k03.k8s.aws.mylabs.dev\n  - k04.k8s.aws.mylabs.dev\n- **AWS Tenant Account 02** – tenant account hosting two EKS clusters. These\n  clusters are created using a local IAM role, which is assumed by the IAM role\n  from the management account\n  - k05.k8s.aws.mylabs.dev\n  - k06.k8s.aws.mylabs.dev\n\n```mermaid\nflowchart TB\n\n  subgraph \"AWS\"\n    subgraph \"AWS Management Account\"\n      aws-cli@{ icon: \"logos:panda\", form: \"rounded\", label: \"aws-cli\", pos: \"b\", h: 60 }\n      aws-mgmt-iam-role@{ icon: \"logos:aws-iam\", form: \"square\", label: \"aws-mgmt-iam-role\", pos: \"b\", h: 60 }\n      aws-01-iam-role@{ icon: \"logos:aws-iam\", form: \"square\", label: \"aws-01-iam-role\", pos: \"b\", h: 60 }\n      k01.k8s.aws.mylabs.dev@{ icon: \"logos:aws-eks\", form: \"square\", label: \"k01.k8s.aws.mylabs.dev\", pos: \"b\", h: 60 }\n      k02.k8s.aws.mylabs.dev@{ icon: \"logos:aws-eks\", form: \"square\", label: \"k02.k8s.aws.mylabs.dev\", pos: \"b\", h: 60 }\n    end\n    subgraph \"AWS Account 01\"\n      aws-02-iam-role@{ icon: \"logos:aws-iam\", form: \"square\", label: \"aws-02-iam-role\", pos: \"b\", h: 60 }\n      k03.k8s.aws.mylabs.dev@{ icon: \"logos:aws-eks\", form: \"square\", label: \"k03.k8s.aws.mylabs.dev\", pos: \"b\", h: 60 }\n      k04.k8s.aws.mylabs.dev@{ icon: \"logos:aws-eks\", form: \"square\", label: \"k04.k8s.aws.mylabs.dev\", pos: \"b\", h: 60 }\n    end\n    subgraph \"AWS Account 02\"\n      aws-03-iam-role@{ icon: \"logos:aws-iam\", form: \"square\", label: \"aws-03-iam-role\", pos: \"b\", h: 60 }\n      k05.k8s.aws.mylabs.dev@{ icon: \"logos:aws-eks\", form: \"square\", label: \"k05.k8s.aws.mylabs.dev\", pos: \"b\", h: 60 }\n      k06.k8s.aws.mylabs.dev@{ icon: \"logos:aws-eks\", form: \"square\", label: \"k06.k8s.aws.mylabs.dev\", pos: \"b\", h: 60 }\n    end\n  end\n\n  aws-cli -- \"Assume Role (STS)\" --\u003e aws-mgmt-iam-role\n  aws-mgmt-iam-role -- \"Assume Role (STS)\" --\u003e aws-01-iam-role\n  aws-01-iam-role --\u003e k01.k8s.aws.mylabs.dev\n  aws-01-iam-role --\u003e k02.k8s.aws.mylabs.dev\n  aws-mgmt-iam-role -- \"Assume Role (STS)\" --\u003e aws-02-iam-role\n  aws-02-iam-role --\u003e k03.k8s.aws.mylabs.dev\n  aws-02-iam-role --\u003e k04.k8s.aws.mylabs.dev\n  aws-mgmt-iam-role -- \"Assume Role (STS)\" --\u003e aws-03-iam-role\n  aws-03-iam-role --\u003e k05.k8s.aws.mylabs.dev\n  aws-03-iam-role --\u003e k06.k8s.aws.mylabs.dev\n```\n\n## Tests\n\n```bash\ndocker run --rm -it --env GITHUB_TOKEN \\\n  -v \"$PWD:/mnt\" -v \"/var/run/docker.sock:/var/run/docker.sock\" \\\n  --workdir /mnt \\\n  bash bash -c 'set -euo pipefail \u0026\u0026 \\\n    apk add docker \u0026\u0026 \\\n    wget -q https://mise.run -O - | sh \u0026\u0026 \\\n    eval \"$(~/.local/bin/mise activate bash)\" \u0026\u0026 \\\n    mise run \"create-kind-all\" ::: \"create-k3d-all\" \u0026\u0026 \\\n    mise run \"delete-kind-all\" ::: \"delete-k3d-all\" \\\n  '\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fruzickap%2Fk8s-multicluster-gitops","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fruzickap%2Fk8s-multicluster-gitops","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fruzickap%2Fk8s-multicluster-gitops/lists"}