Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Requirements Checklist

Every port, health check and ordering rule a KubeadmControlPlane (KCP) or RKE2ControlPlane (RCP) cluster needs from a CAPTF cluster or machine module, grouped by topic. Details and citations are in kubeadm.md and rke2.md; the shared creation sequence and LB-membership patterns are in README.md. n/a means the row does not apply to that provider or module role.

“Verified by” is one of:

  • lint: tfcapi-lint can check it today.
  • e2e: only an end-to-end run with a real control-plane provider catches a violation.
  • operator: checked by whoever reviews or writes the module; no automated check exists.
  • none: not checked anywhere today.

Some lint-worthy rules have no check today; those are called out in kubeadm.md’s open questions and rke2.md’s open questions. The project has no end-to-end suite today, so no e2e row below has been verified against a real control plane.

Endpoint and load balancer

RequirementKubeadmControlPlaneRKE2ControlPlaneCluster moduleMachine moduleVerified by
Endpoint valid before any MachineKCP creates no Machine until Cluster.spec.controlPlaneEndpoint.IsValid() (host and port both set)RCP returns before creating any Machine, including the first, while !IsValid()MUST output a valid control_plane_endpoint no later than the apply that makes the cluster provisioned, unless the user sets onen/ae2e
LB frontend → CP backend portendpoint.port → CP :bindPort (default 6443); one frontendendpoint.port → CP :6443 (apiServerPort ignored); one of two frontendsMUST create a frontend on endpoint.port and a backend on api_server_port ?? 6443, kept equal to the module’s bindPort/RKE2’s fixed 6443n/aoperator
Second LB listener on 9345not applicable:9345 → CP :9345, same host as the endpoint; required for control-plane-endpoint (default) and address registration methodsMUST create this second listener for RKE2 clustersMUST register the instance in the 9345 target set alongside 6443operator
Hairpin reachabilityThe endpoint MUST be reachable from the first CP node itself — admin.conf/super-admin.conf/kubelet.conf all point at the endpoint, not the node’s local addressSame MUST applies to every RKE2 join. The init node itself has no server: configured and so needs no LB/9345 reachability at init time (rke2.md’s lifecycle constraints) — this does not weaken the MUST for every later joinMUST make the LB/VIP allow a backend to reach its own frontendn/anone
Endpoint stabilityOnce emitted, control_plane_endpoint MUST be stable for the life of the object — CAPI never updates Cluster.spec.controlPlaneEndpoint after the first valid copySame rule; RCP also builds tls-san and the kubeconfig Secret from the first copyMUST NOT replace the LB behind an already-emitted endpoint (new DNS name or IP); consider lifecycle { prevent_destroy = true } on that resourcen/anone

Health checks and backend membership

RequirementKubeadmControlPlaneRKE2ControlPlaneCluster moduleMachine moduleVerified by
Health check — API portTCP, or HTTPS /readyz//healthz without certificate verification; MUST go green with a single backend during initTCP, or HTTPS /healthz only if anonymous auth is enabledMUST configure a check matching one of thesen/aoperator
Health check — RKE2 supervisor (9345)not applicableTLS GET /v1-rke2/readyz expecting 403 (unauthenticated), or plain TCPMUST configure this check for RKE2 clustersn/aoperator
Backend membership timingInstance MUST be in the LB backend before kubeadm init/kubeadm join finishes on it, or controlPlaneInitialized never latchesInstance MUST be added before its Machine becomes Ready; the LB MUST tolerate a backend whose supervisor is not yet upn/a (registration is the machine module’s job)MUST register/deregister the instance in its own Terraform state, in the same apply as instance creatione2e
SG / firewall — control planeBackend port (bindPort) from LB, nodes and management; TCP 2379-2380 and 10250 between CP nodes; 10250 from CP to workersCP↔CP TCP 2379-2381; all→CP TCP 6443 and 9345; all↔all TCP 10250 and the NodePort range (default 30000-32767); CNI ports for the chosen CNI (default canal: 8472/udp, 9099/tcp); egress to get.rke2.io/GitHub releases unless air-gappedMUST create these security groups/firewall rulesMUST attach the instance to themoperator

Node identity and addresses

RequirementKubeadmControlPlaneRKE2ControlPlaneCluster moduleMachine moduleVerified by
provider_id == Node providerIDMUST match exactly — the Machine controller links Node to Machine only on an exact match; KCP gates join preflight, etcd matching and remediation on the resulting nodeRefMUST match exactly; a mismatch on the first CP Machine blocks every later join (no Ready CP Machine ⇒ availableServerIPs stays empty)n/aMUST emit the same value the Node’s kubelet/CCM will register (CCM sets it, or kubeletExtraArgs/agentConfig.kubelet.extraArgs: [provider-id=...])e2e
addresses types and orderNot read by KCP or CABPK at allRequired address types by registrationMethod: control-plane-endpoint/address — none; internal-first — InternalIP and/or ExternalIP; internal-only-ips — InternalIP; external-only-ips — ExternalIP. Order is fixed by the controller (InternalIP, InternalDNS, ExternalIP, ExternalDNS, Hostname), not the modulen/aMUST emit the required type(s) for the cluster’s registrationMethod; MUST NOT rely on emission ordernone
kubernetes_version suffixArrives as plain vX.Y.ZArrives as vX.Y.Z+rke2rN, copied verbatim from RKE2ControlPlane.spec.versionn/aUnder RKE2, MUST strip +rke2rN before using the value for an image lookup or a semver comparisonnone

Bootstrap payload

RequirementKubeadmControlPlaneRKE2ControlPlaneCluster moduleMachine moduleVerified by
bootstrap_format always setAlways written by CABPK (cloud-config default, ignition behind the alpha feature gate)Always written by CAPRKE2 (cloud-config default, ignition fully supported)n/aMUST accept both cloud-config and ignitione2e
bootstrap_data is base64, including the gzip casePayload is always UTF-8 text (cloud-config/ignition), base64-encoded by the CAPTF controller like every other bootstrap providerWith gzipUserData: true, the decoded payload is raw (non-UTF-8) gzip bytes — still base64-encoded by the CAPTF controller, same as any other payloadn/aMUST pass bootstrap_data to a base64-taking argument, or base64decode() it only when the content is known to be UTF-8 (never for a gzipped payload)none
CP bootstrap payload size and secrecyInit/join payload embeds cluster CA, etcd CA, service-account and front-proxy key material, uncompressedInit payload embeds four CA key pairs, uncompressed unless gzipUserData: truen/aMUST gzip the payload or stage it in a secret store with a small stub, and MUST keep key material out of readable instance metadatanone

Templates, timing and compatibility

RequirementKubeadmControlPlaneRKE2ControlPlaneCluster moduleMachine moduleVerified by
failure_domains[].control_plane defaultOnly entries with controlPlane == true are visible to KCP; nil counts as falseSame rule for RCPSHOULD leave the field at its default truen/anone
Control-plane bring-up timingN replicas ≈ N × (apply + boot + join); joins strictly serialized on the previous Machine’s nodeRefSame shape; a join additionally requires ≥1 already-Ready CP Machine (Node with matching providerID)n/an/a (informs MHC timeout sizing)none
Control-plane template defaultsTemplates SHOULD set remediation.maxRetry (e.g. 3) and a non-zero retryPeriodSeconds (defaults are unlimited retries, immediate retry); the control-plane MachineHealthCheck’s InfrastructureReady=False timeout MUST exceed apply time plus one drift interval (no fixed number specified here)RCP has its own remediationStrategy{maxRetry, retryPeriod, minHealthyPeriod}; no CAPTF-recommended value is givenn/an/aoperator
Control-plane provider / CAPI compatibilityBuilt for and tested against CAPI v1.14.2 (this provider’s target)CAPRKE2 v0.25.2 is tested by its own e2e suite only against CAPI core v1.12.11 and v1.13.5; CAPTF runs v1.14.2. Run a compatibility smoke test before relying on RKE2ControlPlane in productionn/an/anone

See also

  • README.md — the shared creation sequence and the LB-membership patterns.
  • kubeadm.md and rke2.md — the full guidance and citations behind each row above.
  • The module contract — the normative cluster and machine roles both guides build on.