CRD reference

Field-level reference for the tenantplane custom resources.

All four resources live in the tenantplane.io/v1alpha1 API group. The authoritative definitions are the CRDs in config/crd; this page summarizes the fields.

TenantCluster

FieldTypeNotes
spec.modestringshared | dedicated | private. Only shared implemented.
spec.kubernetesVersionstringRequested minor version, e.g. v1.31 (patch optional and ignored). Only v1.28-v1.33 have a known k3s image; others are rejected at admission.
spec.isolationProfileRef.namestringReferenced IsolationProfile.
spec.syncPolicyRef.namestringReferenced SyncPolicy.
spec.controlPlane.replicasintControl-plane replicas, 1-5. Above 1 requires datastore.type: etcd; an odd number is recommended for quorum.
spec.controlPlane.datastore.typestringsqlite (single replica) or etcd (a dedicated etcd StatefulSet for this tenant). postgres is on the roadmap.
spec.controlPlane.storage.classNamestringStorageClass for the control-plane volume (e.g. gp3 on EKS, managed-csi on AKS, standard-rwo on GKE). Empty = cluster default.
spec.controlPlane.storage.sizestringControl-plane volume size (default 1Gi).
spec.controlPlane.expose.loadBalancerboolPublish the tenant API server via a LoadBalancer Service.
spec.controlPlane.expose.annotationsmapAnnotations for the LoadBalancer Service (cloud-specific behavior).
spec.controlPlane.extraTLSSANs[]stringExtra TLS SANs for the tenant API certificate (e.g. the LB address).
spec.networking.podCIDR / serviceCIDRstringOptional tenant CIDRs.
spec.networking.egressPolicystringEgress posture, e.g. deny-by-default.
spec.migration.allowModeChangeboolWhether mode migration is permitted.
spec.resources.cpu / memorystringControl-plane and quota sizing.
status.phasestringPending/Provisioning/Ready/Degraded.
status.endpointstringIn-cluster tenant API server address once Ready.
status.externalEndpointstringLoad-balancer address once expose.loadBalancer has provisioned.
status.conditions[]listReady, Synced, ModeSupported, IsolationEnforced, SyncSupported, AdmissionHardening, ControllerRBACScoped.

IsolationProfile

FieldTypeNotes
spec.levelstringbaseline | restricted | sandboxed.
spec.controls.podSecuritystringPSA level applied to the namespace.
spec.controls.defaultDenyNetworkPolicyboolCreate a default-deny NetworkPolicy.
spec.controls.requireResourceRequestsboolCreate ResourceQuota + LimitRange.
spec.controls.runtimeClassNamestringOptional runtime class for tenant pods.
spec.controls.blockHostPathVolumesboolPolicy intent (enforcement expanding).
spec.controls.blockPrivilegedContainersboolPolicy intent (enforcement expanding).
spec.controls.apiFairnessstringAPI fairness posture.

SyncPolicy

FieldTypeNotes
spec.conflictPolicystringmanual | tenant-wins | host-wins.
spec.driftDetection.enabledboolWhether drift detection is on.
spec.driftDetection.intervalstringDrift check cadence, e.g. 30s.
spec.explain.recordDecisionsboolRecord a decision per sync action.
spec.explain.retainintHow many decisions to retain.
spec.resources[].apiVersionstringe.g. v1.
spec.resources[].kindstringe.g. Pod, ConfigMap.
spec.resources[].directionstringtoHost | fromHost | bidirectional — all implemented.

SyncDecision

Namespaced, one per tenant — same name and namespace as its TenantCluster, and owned by it. Only created when the owning SyncPolicy sets explain.recordDecisions; see SyncPolicy.

FieldTypeNotes
status.entries[].timestring (date-time)When the decision was recorded.
status.entries[].actionstringCreate | Update | Delete | Skip.
status.entries[].kindstringResource kind.
status.entries[].tenantNamespace / tenantNamestringThe tenant-side object.
status.entries[].hostNamespace / hostNamestringThe host-side object.
status.entries[].reasonstringHuman-readable explanation.
status.lastConverged[hostName].tenantResourceVersionstringTenant object’s resourceVersion the last time this bidirectional pair agreed.
status.lastConverged[hostName].hostResourceVersionstringHost object’s resourceVersion at that same point.

status.entries is bounded to at most explain.retain entries, oldest evicted first. status.lastConverged has no such cap — it only grows with the number of distinct bidirectional objects, not with time — and backs conflictPolicy: manual’s one-sided-drift-vs-genuine-conflict detection (see sync engine).

Reverse-mapping metadata

Host objects created by the sync engine carry these labels and annotations:

KeyKindMeaning
app.kubernetes.io/managed-by=tenantplanelabelOwnership marker.
tenantplane.io/tenantlabelTenant name.
tenantplane.io/virtual-namespacelabelVirtual namespace (sanitized).
tenantplane.io/kindlabelResource kind.
tenantplane.io/virtual-namespaceannotationVerbatim virtual namespace.
tenantplane.io/virtual-nameannotationVerbatim virtual name.

Found a gap? Open an issue or PR.