RKE2 cluster — topology, control plane and node roles¶
Purpose¶
How the Kubernetes cluster layer is built on the Wetopi node LAN: node topology, the HA control plane and its stable API endpoint, and the node-role contract that the CNI, edge and GitOps planes all depend on.
Topology¶
3 control planes + 3 platform workers + 2 edge workers = 8 nodes, all
Ready (live-verified from wetopi-ops01, 2026-08-31). RKE2 v1.36.3+rke2r1
pinned on every node. All node identity and cluster-plane traffic rides the
node LAN (VLAN 4, 10.72.0.0/23); edge nodes additionally carry a WAN NIC
(see edge.md).
flowchart LR
subgraph LAN["Node LAN — VLAN 4, 10.72.0.0/23 (vmbr4)"]
direction TB
subgraph CP["Control plane (embedded etcd)"]
CP1["rke-cp01<br/>10.72.0.21 (bootstrap)"]
CP2["rke-cp02<br/>10.72.0.22"]
CP3["rke-cp03<br/>10.72.0.23"]
end
VIP["API VIP 10.72.0.20<br/>keepalived VRRP"]
subgraph PW["Platform workers<br/>wetopi.io/role=platform"]
P1["rke-platform01<br/>10.72.0.41"]
P2["rke-platform02<br/>10.72.0.42"]
P3["rke-platform03<br/>10.72.0.43"]
end
subgraph EW["Edge workers<br/>wetopi.io/role=edge (dual-NIC)"]
E1["rke-wan01<br/>LAN 10.72.0.51 / WAN 79.137.114.193"]
E2["rke-wan02<br/>LAN 10.72.0.52 / WAN 79.137.114.194"]
end
end
VIP --- CP1 & CP2 & CP3
CP1 -->|server :9345 / API :6443| P1 & P2 & P3 & E1 & E2
| Node | LAN IP | Role / label | Notes |
|---|---|---|---|
rke-cp01 |
10.72.0.21 |
control-plane (bootstrap) | node-role.kubernetes.io/control-plane:NoSchedule taint |
rke-cp02 |
10.72.0.22 |
control-plane | keepalived priority 100 |
rke-cp03 |
10.72.0.23 |
control-plane | keepalived priority 50 |
rke-platform01..03 |
10.72.0.41-43 |
wetopi.io/role=platform |
host internal platform services |
rke-wan01 |
10.72.0.51 |
wetopi.io/role=edge |
WAN 79.137.114.193 (eth0); node-ip bound to LAN |
rke-wan02 |
10.72.0.52 |
wetopi.io/role=edge |
WAN 79.137.114.194 (eth0) |
Node sizing and datastore placement (Proxmox nodes, vCPU/RAM/disk, local
vs vmssd) are physical-infra facts — see the legacy
bootstrap VMs record until the
infra section reorg lands.
Control plane and API endpoint (ADR-0004)¶
- Embedded etcd on the three control planes (no external etcd).
- API VIP
10.72.0.20owned by a keepalived VRRP group (VRID 51, unicast peers) on the CP nodes: cp01 priority 150 (MASTER), cp02 100, cp03 50. The health check probes the local kube-apiserverhttps://127.0.0.1:6443and the RKE2 supervisor on127.0.0.1:9345, so a failing CP drops the VIP to the next priority. - Client endpoints: server/registration URL
https://10.72.0.20:9345, API endpointhttps://10.72.0.20:6443(kubeconfig clients).tls-sanis IP-only: the VIP + the three CP IPs, no DNS SAN. - The VIP is reachable only on the node LAN — never on the Internet (ADR-0004).
- RKE2 at-rest encryption of Kubernetes secrets is ACTIVE by default (AES-CBC; verified enabled on all three CPs).
The decision record and failure-mode analysis: ADR-0004.
Deployment model¶
The cluster is built by Ansible from the infrastructure repo — Ansible owns node bootstrap only; everything inside the cluster is Argo CD's (see gitops.md):
Repo: infrastructure — bootstrap/IaC README · ops handbook: records/platform/rke2-ops-handbook.md
| Piece | Path in infrastructure | Role |
|---|---|---|
rke2-server role + rke2-cp.yml |
ansible/roles/rke2-server/, ansible/playbooks/rke2-cp.yml |
renders /etc/rancher/rke2/config.yaml on CPs (bootstrap/join split), tls-san, CIDRs, cni: none |
keepalived role |
ansible/roles/keepalived/ |
VRRP VIP 10.72.0.20 + local /readyz/9345 health check |
rke2-agent role + rke2-workers.yml |
ansible/roles/rke2-agent/, ansible/playbooks/rke2-workers.yml |
worker join (platform + edge), exact-label gates |
rke2-workers-validate.yml |
ansible/playbooks/ |
post-join validation (data-dir, labels, scheduling) |
| node token | ansible/files/rke2/node-token |
mode 0600, gitignored, never committed |
RKE2 configuration: cni: none (no Canal; Cilium is the CNI —
cilium-network.md), cluster-cidr: 10.64.0.0/14,
service-cidr: 10.68.0.0/16. Edge workers additionally carry
node-ip: 10.72.0.5x (LAN-bound node identity, ADR-0006 condition 4) and the
edge label/taint consumed by the edge Traefik placement.
Invariants¶
- CP taint
NoSchedule: control planes host no platform workloads. - Worker labels are exact:
wetopi.io/role=platform/wetopi.io/role=edge(asserted at join time; the CNI edge override and edge scheduling both key off them). - All cluster-plane traffic (etcd, kubelet, VXLAN, service CIDR) stays on the node LAN; the WAN interface of edge nodes carries only public 80/443 inbound (plus ordinary egress) — ADR-0006 condition 4.
- The API VIP is the only stable client endpoint; per-CP IPs are internal.
- No secrets in Git: join token and kubeconfigs exist only on hosts/ops01.
Verified state (2026-08-31, live from ops01)¶
8/8 nodes Ready; RKE2 v1.36.3+rke2r1 on all nodes; embedded etcd quorum on
the three CPs. Dated observation — re-read kubectl get nodes before
relying on it (DocOps §1: live state outranks this pill).
Dependencies¶
- Depends on: node LAN (VLAN 4), the keepalived VIP design (ADR-0004), the Cilium addon (no node is Ready without it — ADR-0005).
- Depends on this: Cilium network (node roles, LAN underlay), edge v1 (edge node NIC/label contract), GitOps plane (in-cluster ownership boundary).
Failure considerations¶
- Losing 1 CP: VIP fails over (etcd quorum survives 1 loss of 3); cluster stays up. Losing 2: etcd quorum lost — restore path per the RKE2 apply & restore runbook.
- Losing 1 edge worker: its A record keeps resolving until operator remediation — reduced-availability semantics documented in edge.md.
- Losing 1 platform worker: reschedulable; no VIP/endpoint impact.
Live inventory (verified 2026-09-06, BookStack mirror — T1.6)¶
- etcd embebido;
kube-proxyReplacement: false(kube-proxy convive); IPVS + VRRP + DSR en el edge. - API VIP 10.72.0.20 (keepalived), server URL :9345, API :6443;
tls-san= VIP + 3 CPs.