Skip to content

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.20 owned 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-apiserver https://127.0.0.1:6443 and the RKE2 supervisor on 127.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 endpoint https://10.72.0.20:6443 (kubeconfig clients). tls-san is 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.