RKE2 Cheatsheet

RKE2 CheatsheetAlle Kapitel

RKE2 Cheatsheet im Volltext

Stand RKE2 1.37 · Edition 2026.11

Cheatsheet im Volltext

Derselbe Inhalt wie im PDF, zum Mitlesen, Durchsuchen und direkten Kopieren der YAML-Snippets. Stand: RKE2 v1.37 (Edition 2026.11).

Architektur

Ein Binary, zwei Rollen

rke2-server / rke2-agent: je eine systemd-Unit, ein statisch gelinktes Binary. Der Supervisor startet und überwacht die eigene containerd-Instanz, das kubelet und, auf Servern, die Control-Plane als statische Pods.

Kein Docker: eigenes containerd unter /run/k3s/containerd, Socket containerd.sock.

Server-Node

embedded etcd: Default-Datastore (Raft), Quorum über ungerade Server-Zahl.

Control-Plane als static Pods: apiserver, controller-manager, scheduler, etcd, cloud-controller, Manifeste in /var/lib/rancher/rke2/agent/pod-manifests, vom kubelet gestartet (nicht in-process wie k3s). kube-proxy läuft als static Pod auf allen Nodes.

Externer CCM (Hetzner, AWS, OpenStack …): cloud-provider-name: external plus disable-cloud-controller: true auf allen Servern. v1.36.0 bis v1.36.5, v1.37.0 und v1.37.1 starten sonst trotz external den eingebauten CCM.

CNI & Netzwerk

Default Canal (Calico-Policy + Flannel-VXLAN). Alternativen per cni:: Cilium, Calico, Flannel (ohne NetworkPolicy). Multus ist nur Meta-Plugin für Multi-NIC, immer an erster Stelle neben einem primären CNI: cni: [multus, canal].

Ingress per ingress-controller: (traefik | none), Traefik ist seit 1.36 Default für neue Cluster. Ab 1.37 bricht ein explizites ingress-controller: ingress-nginx allein den Start ab, nginx ist nur noch im Dual-Betrieb mit Traefik wählbar (Migration). Upgegradete Cluster ohne gesetzten Wert erkennen nginx am vorhandenen Chart und behalten es (Community-Image v1.14.5-hardened2; laut ADR-Entwurf ohne weitere Updates, Chart entfällt in 1.38). Vor dem 1.37-Upgrade trotzdem explizit [ingress-nginx, traefik] setzen, Traefik dabei auf Ausweich-Ports (Migrationsdoku, Phase 1). traefik allein entfernt nginx.

Dazu CoreDNS, metrics-server, snapshot-controller, ab 1.37 rke2-gateway-api-crd (Gateway API v1.6) und rke2-security-responder, alle als HelmChart-CRs.

export KUBECONFIG=/etc/rancher/rke2/rke2.yaml
export PATH=$PATH:/var/lib/rancher/rke2/bin
kubectl get nodes -o wide
systemctl status rke2-server

Installation

Server aufsetzen

Installer zieht Binary + systemd-Unit, startet aber nicht selbst: curl -sfL https://get.rke2.io | sh -, dann systemctl enable --now rke2-server.

Agent: INSTALL_RKE2_TYPE=agent vor dem Installer, dann rke2-agent aktivieren.

Wichtige Pfade

Config: /etc/rancher/rke2/config.yaml. kubeconfig: /etc/rancher/rke2/rke2.yaml. Binaries (kubectl, crictl, ctr): /var/lib/rancher/rke2/bin. Node-Token: /var/lib/rancher/rke2/server/node-token. Server-Token (ins Backup): /var/lib/rancher/rke2/server/token.

Host vorbereiten

firewalld aus. Mit NetworkManager die CNI-Interfaces (flannel*, cali* …) per /etc/NetworkManager/conf.d/rke2-canal.conf als unmanaged-devices eintragen, nm-cloud-setup aus.

# /etc/rancher/rke2/config.yaml (erster Server)
token: <shared-secret>
tls-san:
  - rke2.example.com      # LB / VIP-Hostname
  - 10.0.0.10
write-kubeconfig-mode: "0640"
cni: canal
ingress-controller: traefik  # oder none
node-taint:
  - "CriticalAddonsOnly=true:NoExecute"
disable:
  - rke2-security-responder

HA Control-Plane

Quorum & Registration

Ungerade Server-Zahl (3 oder 5) für etcd-Quorum. Feste Registration-Address (LB/VIP) vor allen Servern, muss in tls-san stehen, sonst x509-Fehler über den LB.

Der erste Server bootstrappt (kein server:-Feld), weitere joinen über server: + gleichen token.

Der LB leitet 9345 und 6443 (TCP) weiter. Kritische Werte (cluster-cidr, service-cidr, agent-token, disable-cloud-controller …) auf allen Servern gleich.

Ports

9345: RKE2 Supervisor/Registration (nicht 6443!), darauf zeigt server:. 6443: kube-apiserver. 2379/2380/2381: etcd client/peer/metrics (nur Server). 10250: kubelet (alle Nodes). 8472/UDP: VXLAN (Canal, Cilium), Canal-Health 9099.

# config.yaml (zweiter/dritter Server)
server: https://rke2.example.com:9345
token: <shared-secret>
tls-san:
  - rke2.example.com
# Taint greift nur beim Join, disable je Server:
node-taint:
  - "CriticalAddonsOnly=true:NoExecute"
disable:
  - rke2-security-responder

Bundled Components

Auto-Deploy aus manifests/

Alles in /var/lib/rancher/rke2/server/manifests/ wird vom Deploy-Controller angewandt (HelmChart-CRs: rke2-canal, rke2-coredns, rke2-traefik, rke2-metrics-server). Nicht direkt editieren, beim Restart überschrieben.

Anpassen & Abschalten

Customizing über HelmChartConfig-CR (gleicher Name/Namespace, valuesContent wird gemergt).

Abschalten über disable: in der config.yaml, gültig u.a. rke2-coredns, rke2-metrics-server, rke2-security-responder, rke2-gateway-api-crd. Ingress nicht per disable:, sondern ingress-controller: none.

Das Gateway-API-CRD-Chart bringt die VAP safe-upgrades.gateway.networking.k8s.io (Deny) mit. Sie lehnt Gateway-API-CRDs ohne bundle-version-Annotation oder älter als v1.6 ab, ebenso Experimental- über Standard-CRDs: ältere oder Experimental-Manifeste aus Istio- oder Cilium-Anleitungen scheitern. experimental: {enabled: true} per HelmChartConfig ergänzt nur die x-k8s.io-CRDs (XBackend, XBackendTrafficPolicy, XMesh).

apiVersion: helm.cattle.io/v1
kind: HelmChartConfig
metadata:
  name: rke2-traefik
  namespace: kube-system
spec:
  valuesContent: |-
    ports:
      web:
        forwardedHeaders:
          trustedIPs: ["10.0.0.0/8"]
      websecure:
        forwardedHeaders:
          trustedIPs: ["10.0.0.0/8"]
    accessLog: {enabled: true}  # bis 1.36: logs.access

Security & Hardening

CIS-Profil

profile: cis in der config.yaml aktiviert die CIS-Benchmark-Härtung: PSA restricted als Default (außer kube-system, compliance-operator-system, tigera-operator), strenge Datei-Rechte, NetworkPolicies nur in kube-system, kube-public, default. Für eigene Namespaces Policies selbst anlegen und darin den Ingress-Controller zulassen. Self-Assessment: CIS 2.0 für 1.35 bis 1.37, CIS 1.12 für 1.34.

Host-Prereqs: etcd-User (useradd -r -M -U -s /sbin/nologin etcd) und rke2-cis-sysctl.conf (/usr/share/rke2/ bei RPM, /usr/local/share/rke2/ bei Tarball) nach /etc/sysctl.d/60-rke2-cis.conf kopieren: RKE2 legt die Datei ab, aktiviert sie aber nicht. profile setzt protect-kernel-defaults: true: fehlen die Sysctls, beendet sich RKE2 beim Start mit Fehler. systemd-sysctl nur auf frischen Nodes neu starten (CNIs setzen eigene Sysctls).

Weitere Defaults

Secrets-Encryption at rest: standardmäßig an (AES-CBC, alternativ secrets-encryption-provider: secretbox), verwaltet via rke2 secrets-encrypt. SELinux: unterstützt (selinux: true + rke2-selinux Policy).

Security Responder (ab 1.37, Default an): CronJob rke2-security-responder in kube-system, alle 8h. Sendet Cluster-Metadaten (K8s-Version, kube-system-UID, OS/Kernel, CNI, Ingress, Node-Zahlen) an SUSE (security-responder.version.rke2.io, HTTPS), meldet CVEs der laufenden Version. Ohne Egress scheitert der Lauf folgenlos für den Cluster, nichts wird gepuffert. Reduzieren: mode: minimal per HelmChartConfig. Kein Datenabfluss: disable: [rke2-security-responder].

rke2 secrets-encrypt status
rke2 secrets-encrypt rotate-keys   # Key-Rotation
# HA: reencrypt_finished abwarten, dann Neustarts
kubectl get --raw='/readyz?verbose'

Zertifikate & Tokens

Node-Zertifikate gelten 365 Tage und werden nur beim Start erneuert, wenn sie unter 120 Tage Restlaufzeit haben (Event CertificateExpirationWarning). Ein Node ohne Neustart über ein Jahr läuft in abgelaufene Zertifikate. CAs gelten 10 Jahre, ohne Auto-Renew (rke2 certificate rotate-ca).

Agents per eigenem agent-token joinen lassen. Nach token rotate alle Nodes mit dem neuen Token neu starten.

rke2 certificate check --output table
systemctl stop rke2-server
rke2 certificate rotate
systemctl start rke2-server
rke2 token rotate --token <alt> --new-token <neu>

etcd Snapshot / Restore

Snapshots

Automatisch an by default: etcd-snapshot-schedule-cron (Default alle 12h), etcd-snapshot-retention (Default 5, je Server-Node). Ablage: /var/lib/rancher/rke2/server/db/snapshots.

Off-node nach S3 sichern, sonst ist der Snapshot mit dem Node verloren. etcd-s3-retention (Default 5) zählt clusterweit je Bucket/Ordner. Alle Snapshots im Cluster: kubectl get etcdsnapshotfile.

# config.yaml (alle Server): Snapshots nach S3
etcd-s3: true
etcd-s3-endpoint: s3.example.com
etcd-s3-bucket: rke2-snapshots
etcd-s3-access-key: <key>
etcd-s3-secret-key: <secret>
rke2 etcd-snapshot save --name pre-upgrade
rke2 etcd-snapshot ls
# Restore (auf EINEM Server, andere vorher stoppen):
systemctl stop rke2-server
rke2 server \
  --cluster-reset \
  --cluster-reset-restore-path=/var/lib/rancher/rke2/server/db/snapshots/pre-upgrade-<node>-<ts>
systemctl start rke2-server

Restore-Ablauf

Restore läuft auf einem Server, alle anderen Server werden gestoppt und ihr db/-Verzeichnis geleert; danach re-joinen sie den zurückgesetzten Cluster über server: + token.

Mit etcd-s3 in der Config nur den Dateinamen angeben, für lokale Snapshots --etcd-s3=false setzen. Ohne den ursprünglichen token kein Restore: server/token sichern, auf neuem Host mit --token=<Wert> starten.

Quorum verloren (2 von 3 Servern weg): --cluster-reset ohne Restore-Pfad auf dem verbliebenen Server setzt etcd auf dieses Mitglied zurück, ohne Snapshot. Übrige Server danach leeren und neu joinen.

Upgrades

Zwei Wege

system-upgrade-controller (SUSE-Pattern): deklarative Plan-CRs, node-selektiert, Server zuerst, dann Agents.

Manuell: INSTALL_RKE2_VERSION setzen, Installer erneut laufen lassen, rke2-server neustarten.

Channels: INSTALL_RKE2_CHANNEL (stable | latest | v1.37). Default stable ist ein manuell gesetzter Pin und hängt hinter latest zurück (bei Redaktionsschluss v1.36.5, nicht 1.37).

Keine Minor überspringen: Ein Plan mit channel: springt direkt auf den Channel-Stand, auch über mehrere Minors, der Controller prüft das nicht. Rollback auf die alte Minor geht nur per Restore eines Snapshots, der auf dieser Minor erstellt wurde.

Agents: zweiter Plan mit prepare: {image: rancher/rke2-upgrade, args: [prepare, server-plan]}. RPM-Installation per Paketmanager aktualisieren, Rancher-verwaltete Cluster über Rancher.

apiVersion: upgrade.cattle.io/v1
kind: Plan
metadata: {name: server-plan, namespace: system-upgrade}
spec:
  concurrency: 1
  nodeSelector:
    matchExpressions:
    - {key: node-role.kubernetes.io/control-plane, operator: Exists}
  tolerations:   # sonst nie auf getainteten Servern
  - {key: CriticalAddonsOnly, operator: Exists}
  serviceAccountName: system-upgrade
  cordon: true
  upgrade: {image: rancher/rke2-upgrade}
  version: v1.37.1+rke2r1

Air-Gap

Images & Binary

Images-Tarball (rke2-images.linux-amd64.tar.zst = Core + Canal) nach /var/lib/rancher/rke2/agent/images/ legen, RKE2 importiert ihn beim Start in containerd. Andere CNIs: rke2-images-core plus CNI-Bundle (rke2-images-cilium, -calico, -flannel), Multus zusätzlich -multus.

Binary + install.sh offline via INSTALL_RKE2_ARTIFACT_PATH.

Seit 1.36 enthält rke2-images-core Traefik statt nginx. Wer nginx weiter betreibt, spiegelt zusätzlich rke2-images-ingress-nginx.

touch agent/images/.cache.json: Re-Import nur noch bei geänderter Datei. Für Upgrades per Plan zusätzlich rancher/rke2-upgrade, rancher/system-upgrade-controller und rancher/kubectl spiegeln.

Private Registry

/etc/rancher/rke2/registries.yaml: Mirror-Endpunkte + Auth + TLS, auf jedem Node, wirksam nach Neustart, für System-Images und Workloads. Kein Rückfall auf den Upstream bei gespiegelten Registries (je Node): disable-default-registry-endpoint: true.

# /etc/rancher/rke2/registries.yaml
mirrors:
  docker.io:
    endpoint:
      - "https://registry.internal:5000"
configs:
  registry.internal:5000:
    auth: {username: robot, password: <token>}
    tls: {ca_file: /etc/ssl/registry-ca.pem}

Diagnose

Werkzeuge

journalctl -u rke2-server -f (bzw. rke2-agent). crictl unter /var/lib/rancher/rke2/bin, Container/Images direkt am Node (containerd, nicht Docker). Static-Pod-Logs: crictl logs oder /var/log/pods.

kubelet und containerd loggen nicht ins Journal: agent/logs/kubelet.log, agent/containerd/containerd.log unter /var/lib/rancher/rke2/.

export CRI_CONFIG_FILE=/var/lib/rancher/rke2/agent/etc/crictl.yaml
/var/lib/rancher/rke2/bin/crictl ps
/var/lib/rancher/rke2/bin/crictl logs <container-id>
journalctl -u rke2-server --no-pager | tail -50

Reset & Removal

rke2-killall.sh: stoppt alle rke2-Prozesse + Container, lässt Daten liegen. rke2-uninstall.sh: vollständige Entfernung (Binaries, Daten, Unit).

Gleichnamigen Node neu aufsetzen: erst kubectl delete node, sonst scheitert der Join am alten Node-Passwort.

Anti-Patterns

Was du nicht tun solltest

Gerade Server-Zahl (2/4): 4 Server verkraften wie 3 nur einen Ausfall, bieten aber mehr Ausfallpunkte. Bei einer 2/2-Partition hat keine Seite Quorum. Immer 3 oder 5.

Snapshots nur on-node: Node-Verlust = etcd-Verlust. S3 konfigurieren.

Docker erwarten: RKE2 hat ein eigenes containerd; kein Docker-Socket, kein docker ps. Nutze crictl.

tls-san vergessen: API-Zertifikat kennt den LB/VIP-Namen nicht, x509-Fehler, sobald kubectl über den LB geht.

Server als Worker ohne Taint in Prod: Workloads konkurrieren mit etcd/Control-Plane, CriticalAddonsOnly-Taint setzen.

Alle Nodes getaintet: Ingress, metrics-server bleiben Pending.

manifests/ direkt editieren: beim Restart überschrieben, HelmChartConfig statt Datei-Patch.

Projekt und Quellen

Upstream

SUSE entwickelt RKE2 im Rancher-Projekt auf GitHub, Lizenz Apache 2.0.

Code: github.com/rancher/rke2 · Releases · Advisories. Doku: docs.rke2.io · Release Notes: docs.rke2.io/release-notes/v1.37.X. Release- und EOL-Daten: rke2-cheatsheet.de/lifecycle.