{"id":51418837,"url":"https://github.com/appthrust/kany8s","last_synced_at":"2026-07-04T22:30:47.945Z","repository":{"id":352996437,"uuid":"1141632643","full_name":"appthrust/kany8s","owner":"appthrust","description":null,"archived":false,"fork":false,"pushed_at":"2026-06-15T12:37:05.000Z","size":1260,"stargazers_count":0,"open_issues_count":1,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-15T13:15:47.656Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/appthrust.png","metadata":{"files":{"readme":"docs/README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"docs/AGENTS.md","dco":null,"cla":null}},"created_at":"2026-01-25T06:09:53.000Z","updated_at":"2026-06-15T12:36:17.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/appthrust/kany8s","commit_stats":null,"previous_names":["appthrust/kany8s"],"tags_count":11,"template":false,"template_full_name":null,"purl":"pkg:github/appthrust/kany8s","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/appthrust%2Fkany8s","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/appthrust%2Fkany8s/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/appthrust%2Fkany8s/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/appthrust%2Fkany8s/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/appthrust","download_url":"https://codeload.github.com/appthrust/kany8s/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/appthrust%2Fkany8s/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35138074,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-07-04T02:00:05.987Z","response_time":113,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"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":[],"created_at":"2026-07-04T22:30:47.167Z","updated_at":"2026-07-04T22:30:47.938Z","avatar_url":"https://github.com/appthrust.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Kany8s\n\n\u003e Any k8s, powered by kro.\n\n**Kany8s** is a (work-in-progress) Cluster API provider suite — `Kany8sCluster` (Infrastructure) + `Kany8sControlPlane` (ControlPlane) — that uses **kro** (ResourceGraphDefinition / RGD) as a \"concretization engine\" to create managed Kubernetes control planes (and their prerequisites) on *any* cloud/provider.\n\nThe goal is simple: **if you can express it as a kro RGD, Kany8s can drive it via Cluster API**.\n\n- Name: `Kany8s` = \"k(ro)\" + \"any\" + \"k8s\" (and it’s pronounceable)\n- Repo status: design-first / prototype\n\n## Concept\n\nKany8s separates responsibilities clearly:\n\n- **Cluster API-facing CRDs**\n  - `Kany8sCluster`: Infrastructure provider (referenced by `Cluster.spec.infrastructureRef`)\n  - `Kany8sControlPlane`: ControlPlane provider (sets endpoint/initialized/conditions per the CAPI contract)\n- **kro RGD (provider-specific)**: materializes real resources (EKS/ACK today, AKS/GKE tomorrow)\n  - Hides provider-specific status shapes\n  - Exposes a small, normalized status contract that Kany8s consumes\n\nThis keeps the controller provider-agnostic: **no “if EKS then … else if GKE then …” branches**.\n\n## Architecture (High Level)\n\n1. You create a Cluster API `Cluster` that references `Kany8sCluster` + `Kany8sControlPlane`.\n2. `Kany8sControlPlane` references a kro `ResourceGraphDefinition` via `spec.resourceGraphDefinitionRef`.\n3. Kany8s resolves the RGD’s generated GVK and creates exactly one **kro instance** (1:1).\n4. Kany8s watches **only** the kro instance `status`.\n5. When the kro instance reports ready + endpoint, Kany8s writes `Kany8sControlPlane.spec.controlPlaneEndpoint` and sets `status.initialization.controlPlaneInitialized` (Cluster controller then mirrors the endpoint into `Cluster.spec.controlPlaneEndpoint` per the CAPI contract).\n\n## Extensibility (Provider Packs / Plugins)\n\nKany8s keeps the core controllers **provider-agnostic** and pushes provider-specific behavior to the edges.\n\n- **Provider packs (docs + RGDs)**\n  - Provider-specific realization lives in kro `ResourceGraphDefinition` (RGD) YAMLs.\n  - Convention: `docs/\u003cprovider\u003e/` contains runnable procedures, sample manifests, and design notes.\n\n- **Plugins (optional controllers)**\n  - Some providers need extra “glue” beyond what fits naturally into the RGD status contract (e.g. short-lived auth, kubeconfig management, probes).\n  - For those cases, Kany8s supports **opt-in plugins**: separate binaries/controllers that run alongside the core controller-manager.\n  - Plugins should be:\n    - **Explicitly enabled** (annotation/label-driven), never on by default.\n    - **Scoped and non-invasive** (own only the resources they manage; avoid overwriting user-owned objects).\n\nRepository conventions (current / intended):\n\n- Docs: `docs/\u003cprovider\u003e/plugin/`\n- Code: `internal/plugin/\u003cprovider\u003e/` and `internal/controller/plugin/\u003cprovider\u003e/`\n- Manifests: `config/\u003cprovider\u003e-plugin/`\n- Image/build: `Dockerfile.\u003cprovider\u003e-plugin` + `make *-\u003cprovider\u003e-plugin` targets\n\nExample: AWS EKS needs a short-lived IAM token in kubeconfig; see `docs/eks/plugin/README.md` (kubeconfig rotator plugin).\n\n### Installing EKS plugins via Helm\n\n`clusterctl init --infrastructure kany8s --control-plane kany8s` (and\ncluster-api-operator's `InfrastructureProvider` / `ControlPlaneProvider`\nresources) install only the provider managers. The EKS-specific plugins live\noutside the CAPI provider contract and ship as standalone Helm charts:\n\n| Chart | OCI reference | What it does |\n|---|---|---|\n| `eks-kubeconfig-rotator` | `oci://ghcr.io/appthrust/charts/eks-kubeconfig-rotator` | Rotates short-lived EKS tokens in the CAPI kubeconfig Secret. |\n| `eks-karpenter-bootstrapper` | `oci://ghcr.io/appthrust/charts/eks-karpenter-bootstrapper` | Provisions IAM Role / OIDC provider / SecurityGroup / Fargate profile and installs Karpenter via Flux. |\n\n```bash\n# replace \u003ctag\u003e with a released version, e.g. v0.1.1\nhelm install rotator oci://ghcr.io/appthrust/charts/eks-kubeconfig-rotator \\\n  --version \u003ctag\u003e \\\n  --namespace kany8s-eks-system --create-namespace \\\n  --set \"serviceAccount.annotations.eks\\.amazonaws\\.com/role-arn=arn:aws:iam::123456789012:role/eks-rotator\"\n\nhelm install bootstrapper oci://ghcr.io/appthrust/charts/eks-karpenter-bootstrapper \\\n  --version \u003ctag\u003e \\\n  --namespace kany8s-eks-system \\\n  --set \"serviceAccount.annotations.eks\\.amazonaws\\.com/role-arn=arn:aws:iam::123456789012:role/eks-karpenter-bootstrapper\"\n```\n\nBoth charts follow the ACK controller credential convention: set\n`aws.credentials.secretName=\u003csecret\u003e` to mount a shared-credentials-file\nSecret (same format ACK consumes), or leave it empty to let the AWS SDK\ndefault chain resolve credentials from the ServiceAccount (IRSA / EKS Pod\nIdentity) or EC2 instance metadata. The image reference is a Bitnami-style\n`image.{registry,repository,tag,digest}` split with a `global.imageRegistry`\noverride for mirrored / air-gapped environments. See the per-chart READMEs\nat `charts/eks-kubeconfig-rotator/README.md` and\n`charts/eks-karpenter-bootstrapper/README.md` for full value reference and\noverride recipes.\n\nThe `config/eks-plugin/` and `config/eks-karpenter-bootstrapper/` kustomize\noverlays remain for local development and ACK co-location; the Helm charts\nare the recommended install path for new deployments.\n\nA Cluster API `Cluster` will look like this:\n\n```yaml\napiVersion: cluster.x-k8s.io/v1beta2\nkind: Cluster\nmetadata:\n  name: demo-cluster\nspec:\n  infrastructureRef:\n    apiGroup: infrastructure.cluster.x-k8s.io\n    kind: Kany8sCluster\n    name: demo-cluster\n  controlPlaneRef:\n    apiGroup: controlplane.cluster.x-k8s.io\n    kind: Kany8sControlPlane\n    name: demo-cluster\n```\n\n## ClusterTopology / ClusterClass (Planned)\n\nKany8s is designed to be consumed via Cluster API **ClusterTopology** (**ClusterClass**).\n\n- `Kany8sControlPlaneTemplate` selects the provider implementation via `resourceGraphDefinitionRef` and carries default `kroSpec`.\n- `Kany8sClusterTemplate` provides the InfrastructureRef required by Cluster API (minimal first; may later materialize shared prerequisites).\n- `Cluster.spec.topology.version` is the single source of truth for `Kany8sControlPlane.spec.version` (and is injected into the kro instance `spec.version`).\n\nA typical topology setup will look like:\n\n```yaml\napiVersion: cluster.x-k8s.io/v1beta2\nkind: ClusterClass\nmetadata:\n  name: kany8s-eks\nspec:\n  infrastructure:\n    ref:\n      apiVersion: infrastructure.cluster.x-k8s.io/v1alpha1\n      kind: Kany8sClusterTemplate\n      name: kany8s-aws\n  controlPlane:\n    ref:\n      apiVersion: controlplane.cluster.x-k8s.io/v1alpha1\n      kind: Kany8sControlPlaneTemplate\n      name: kany8s-eks\n  # variables + patches map into `.spec.kroSpec` (details TBD)\n```\n\n```yaml\napiVersion: cluster.x-k8s.io/v1beta2\nkind: Cluster\nmetadata:\n  name: demo-cluster\nspec:\n  topology:\n    class: kany8s-eks\n    version: \"1.34\"\n    variables:\n      - name: region\n        value: ap-northeast-1\n      - name: vpc.subnetIDs\n        value: [\"subnet-xxxx\", \"subnet-yyyy\"]\n      - name: vpc.securityGroupIDs\n        value: [\"sg-zzzz\"]\n```\n\n## Contract: kro instance status (Normalized)\n\nKany8s expects the referenced RGD instance to expose these fields:\n\n- `status.ready: boolean`\n  - Meaning: \"ControlPlane ready\" (at minimum, the API endpoint is known)\n- `status.endpoint: string`\n  - Format: `https://host[:port]` or `host[:port]`\n  - If port is omitted, Kany8s treats it as `443`\n- (optional) `status.reason: string`\n- (optional) `status.message: string`\n\nNote: kro adds reserved fields like `status.conditions` and `status.state` automatically, so Kany8s uses the dedicated names above (`ready/endpoint/reason/message`).\n\n## Example (Planned API)\n\n### Kany8s ControlPlane\n\n```yaml\napiVersion: controlplane.cluster.x-k8s.io/v1alpha1\nkind: Kany8sControlPlane\nmetadata:\n  name: demo-cluster\n  namespace: default\nspec:\n  version: \"1.34\"\n  # `controlPlaneEndpoint` is set by Kany8s (CAPI contract)\n  # controlPlaneEndpoint:\n  #   host: example.eks.amazonaws.com\n  #   port: 443\n  resourceGraphDefinitionRef:\n    name: eks-control-plane\n  kroSpec:\n    region: ap-northeast-1\n    vpc:\n      subnetIDs:\n        - subnet-xxxx\n        - subnet-yyyy\n      securityGroupIDs:\n        - sg-zzzz\n```\n\n### Generated kro instance (GVK is resolved from the RGD)\n\n```yaml\napiVersion: kro.run/v1alpha1\nkind: EKSControlPlane\nmetadata:\n  name: demo-cluster\n  namespace: default\nspec:\n  version: \"1.34\" # injected/overwritten by Kany8s\n  region: ap-northeast-1\n  vpc:\n    subnetIDs:\n      - subnet-xxxx\n      - subnet-yyyy\n    securityGroupIDs:\n      - sg-zzzz\n```\n\n### Normalizing status in the RGD (example idea)\n\n```yaml\nschema:\n  status:\n    ready: ${cluster.status.status == \"ACTIVE\" \u0026\u0026 cluster.status.endpoint != \"\"}\n    endpoint: ${cluster.status.endpoint}\n```\n\n## Scope (MVP)\n\n- MVP focuses on **ControlPlane provider** responsibilities (`Kany8sControlPlane`: endpoint/initialized/conditions)\n- Implements `spec.controlPlaneEndpoint` + `status.initialization.controlPlaneInitialized` per the CAPI contract\n- `Kany8sCluster` (Infrastructure provider) is planned/TBD\n- Keeps provider-specific logic inside RGD(s)\n- Does **not** adopt CAPT’s Terraform-style \"Template → Apply\" pattern as a core concept\n- Does **not** write Terraform-like outputs to Secrets for endpoint/initialized (for now)\n- Kubeconfig secret management (`\u003ccluster\u003e-kubeconfig`) is required by the CAPI contract (planned)\n\n## Demo (kind + kro)\n\nThis is a local smoke test that exercises the full flow:\n\n`install (kro + Kany8s)` -\u003e `apply RGD` -\u003e `apply Cluster / Kany8sControlPlane`.\n\nPrereqs:\n\n- `kind`, `kubectl`, and `docker`\n- `clusterctl` (only if you want to apply the Cluster API `Cluster` object)\n\n1. Create a kind management cluster:\n\n   - `kind create cluster --name kany8s --wait 60s`\n\n2. Install kro (v0.7.1 tested):\n\n   - `kubectl create namespace kro-system`\n   - `kubectl apply -f https://github.com/kubernetes-sigs/kro/releases/download/v0.7.1/kro-core-install-manifests.yaml`\n   - `kubectl rollout status -n kro-system deploy/kro`\n\n   Note: kro v0.7.1 may require relaxed RBAC for its dynamic controller to watch generated CRDs.\n   See `docs/reference/kro-v0.7.1-kind-notes.md` for details and the exact manifest.\n\n3. Install Kany8s CRDs:\n\n   - `make install`\n\n4. Run the controller locally (in another terminal):\n\n   - `make run`\n\n5. Apply the demo RGD (normalized `ready`/`endpoint` status contract):\n\n   - `kubectl apply -f examples/kro/ready-endpoint/rgd.yaml`\n\n6. Apply the sample Cluster + Kany8sControlPlane (requires Cluster API installed):\n\n   - `kubectl apply -f examples/capi/cluster.yaml`\n\n   If you don't have Cluster API installed yet, apply only the `Kany8sControlPlane` object from that file.\n\n7. Observe:\n\n   - `kubectl get kany8scontrolplanes -n default -o wide`\n   - `kubectl get democontrolplanes.kro.run -n default -o wide`\n\n## Acceptance runners\n\nFor reproducible end-to-end checks (fresh kind clusters + artifacts), see `test/acceptance_test/README.md`.\n\n- kro demo flow (managed control plane reflection): `make test-acceptance-kro-reflection`\n- kro demo flow (managed infra reflection): `make test-acceptance-kro-infra-reflection`\n- kro demo flow (managed infra cluster identity): `make test-acceptance-kro-infra-cluster-identity`\n- kro demo flow with 2 RGDs (multi-instance-kind): `make test-acceptance-kro-reflection-multi-rgd`\n- self-managed (CAPD + kubeadm): `make test-acceptance-capd-kubeadm`\n\nLegacy aliases are still supported:\n\n- `make test-acceptance` -\u003e `make test-acceptance-kro-reflection`\n- `make test-acceptance-multi-rgd` -\u003e `make test-acceptance-kro-reflection-multi-rgd`\n- `make test-acceptance-self-managed` -\u003e `make test-acceptance-capd-kubeadm`\n\n## Development\n\n### Prerequisites\n\n- Go (toolchain is pinned in `go.mod`)\n- `make`\n- Optional: `docker` (for `make docker-build`)\n- Optional: `kubectl` + access to a Kubernetes cluster (for `make run`)\n- Optional: `kind` (for `make test-e2e`)\n\nThe Makefile auto-downloads build/test tooling into `./bin/` (kustomize, controller-gen, setup-envtest, golangci-lint).\n\n### Quickstart\n\n- `make test`: run unit tests (includes `make generate` + `make manifests`)\n- `make lint`: run `golangci-lint`\n- `make run`: run the controller locally against your current kubeconfig context\n\nFor code generation only:\n\n- `make generate`\n- `make manifests`\n\n## Documents\n\n- `docs/PRD.md`: product requirements (Why/What/How)\n- `docs/adr/README.md`: design decisions (ADR)\n- `docs/reference/rgd-contract.md`: normalized status contract for RGD instances\n- `docs/reference/rgd-guidelines.md`: RGD authoring guidance (kro pitfalls)\n- `docs/guides/e2e-and-acceptance-test.md`: test layers and acceptance runners\n- `docs/runbooks/`: operational runbooks\n- `docs/eks/README.md`: AWS EKS smoke test (ACK + kro) and BYO network flow\n- `docs/eks/plugin/README.md`: provider-specific plugin notes (EKS kubeconfig rotator)\n- `docs/archive/`: historical notes/drafts\n\n## Roadmap (Sketch)\n\n- Implement `Kany8sControlPlane` CRD + controller\n- Implement `Kany8sCluster` CRD + controller (optional/minimal first)\n- Provide a working AWS/EKS RGD (`eks-control-plane`) as a reference\n- Add clusterctl/helm packaging\n- Add ClusterTopology/ClusterClass examples (templates + patches)\n- Extend RGD catalog for other providers (AKS/GKE/etc.)\n\n## License\n\nTBD\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fappthrust%2Fkany8s","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fappthrust%2Fkany8s","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fappthrust%2Fkany8s/lists"}