[Operational] poc-kcm-kcp
Installs the kcp side of the ADR-0001 cluster API into the workspace that owns
the exports (by convention root:controllers:cluster):
- five
APIResourceSchemas across three API groups, shipped verbatim fromschemas/; - the
cluster-tenantandcluster-catalogAPIExports; - per-export controller RBAC (
apiexportendpointslicesdiscovery andapiexports/content), scoped byresourceNamesto these two exports.
Install
helm upgrade --install cluster-kcp deploy/charts/poc-kcm-kcp \
--kube-context <context-pointing-at-root:controllers:cluster>
Then bind the exports (see examples/bindings.yaml at the repository root):
tenant workspaces bind cluster-tenant; the catalog workspace binds
cluster-catalog. kcp publishes a shard's URL in an endpoint slice only once
at least one APIBinding for the export exists on that shard, so a fresh
install shows empty slices until the first binding.
The catalog-workspace release
Catalog reads go over the front proxy, which no permission claim covers, so the controllers need RBAC inside the catalog workspace. That is a second release of this same chart, against that workspace, with the export-workspace objects switched off so it does not plant a second copy of the exports where nothing binds them:
helm upgrade --install cluster-catalog-rbac deploy/charts/poc-kcm-kcp \
--kube-context <context-pointing-at-root:providers> \
--set apis.create=false \
--set rbac.create=false \
--set catalogWorkspace.create=true \
--values catalog-subjects.yaml
catalog-subjects.yaml carries catalogWorkspace.readers. Every subject that
reads the catalog goes in it, cluster-scheduler included — the release renders one binding per
list, so a release that omits it drops the scheduler's own grant.
Verify with /readyz, not with a reconcile. Each controller reads the
catalog through a cache on the manager, so its readiness gate only flips once
that cache has synced. A wrong or missing subject leaves the pod permanently
not-ready with a Forbidden in its logs, while a correct one goes ready even
against an empty catalog:
kubectl -n edge-connect-system port-forward deploy/cluster-scheduler 8081:8081 &
curl -fsS localhost:8081/readyz && echo " ready"
That distinguishes a wrong subject string from a working one immediately. Left to first reconcile it looks like an unseeded catalog instead, which is what a fresh install is told to expect.
Values
| Key | Default | Notes |
|---|---|---|
exports.tenant.name | cluster-tenant | Must match the controller's --endpointslice |
exports.catalog.name | cluster-catalog | |
exports.*.subjects | the cluster-scheduler projected identity | kind: User with the full management identity — a kind: ServiceAccount subject never matches inside a kcp workspace |
apis.create | true | Render the export-workspace objects (schemas, both exports, identity Secrets, endpoint slices). Switch off for the catalog-workspace release |
catalogWorkspace.create | false | Render the catalog-workspace RBAC instead of the export-workspace manifests; install as a second release against the catalog workspace |
catalogWorkspace.readers | the scheduler's kind: User subject | Subjects granted get/list/watch on kubernetesclusterofferings and virtualmachinetypes. Whoever installs the catalog release owns every subject, not only their own: the release renders one binding from this list, so omitting cluster-scheduler drops the scheduler's grant |
exports.tenant.claims | one secrets claim | A provider controller writes the cluster's kubeconfig back as a Secret; a kcp claim cannot be scoped to a name, so verbs are enumerated and deletecollection is absent (ADR-0003) |
exports.catalog.claims | [] | The catalog reconciler reads only the kinds that export serves, and the export carries Provider; it stays claim-free |
exports.*.identity.enabled | false | Pins the export's identityHash to sha256hex(key), stable across export recreation |
endpointSlices.create | false | On kcp 0.32 an APIExport already materialises a slice of the same name; creating one here collides with it |
rbac.create | true | |
schema*.namePrefix | content hashes | Generated. Written by make schemas; never edit by hand |
Schema pins are generated
APIResourceSchema objects are immutable in kcp, so each schema's
metadata.name is <namePrefix>.<resource>.<group> where namePrefix is a
content hash of the CRD. make schemas regenerates the schemas, rewrites the
schema*.namePrefix values here, and copies the documents into schemas/ —
so the pins and the documents move together.
Note that schemaTenantCluster and schemaProviderCluster carry the same
resource name (kubernetesclusters) in different groups. That is why the
pinning in hack/generate-schemas.sh matches on group and resource: keying
on resource alone would rewrite the wrong block. hack/charts_test.go fails
the build if either the pins or the shipped documents fall behind config/kcp.