主题
第三部分 RKE2 从入门到精通
RKE2(Rancher Kubernetes Engine 2,又名 RKE Government)是 Rancher 推出的第二代 Kubernetes 发行版。它把"安全、合规、简单"刻进了基因:控制平面以静态 Pod 运行在 containerd 之上,默认开启 CIS 加固基线,提供 FIPS 140-2 认证的加密模块,一条安装命令即可拉起一个生产级集群。本部分将带你从 RKE2 的设计哲学出发,完整走过安装、HA 部署、配置调优、私有仓库接入、etcd 备份恢复、升级维护、安全加固与故障排查的全流程——这也是成为一名合格的 K8s 运维工程师的必经之路。
第 1 章 RKE2 简介
1.1 什么是 RKE2
RKE2 是 SUSE Rancher 公司开源的 Kubernetes 发行版,是 RKE1(Rancher Kubernetes Engine)的下一代产品。它完全兼容上游 Kubernetes API,同时做了以下关键改造:
| 特性 | 说明 |
|---|---|
| 控制平面形态 | kube-apiserver / kube-controller-manager / kube-scheduler / etcd 以静态 Pod 形式运行在 containerd 上,不再是 Docker 容器 |
| 容器运行时 | 内置并仅支持 containerd(RKE1 依赖 Docker) |
| 安全基线 | 内置 CIS Kubernetes Benchmark 加固 profile(cis profile) |
| FIPS | 提供通过 FIPS 140-2 认证的 Go 加密模块(BoringCrypto)构建版本 |
| 分发形态 | 单一二进制 rke2,安装后以 systemd 服务(rke2-server / rke2-agent)运行 |
| 版本号 | 形如 v1.35.6+rke2r1,前半部分是 Kubernetes 版本,后半部分是 RKE2 打包修订号 |
1.2 RKE2 与 RKE1、k3s、kubeadm 对比
| 对比维度 | RKE1 | RKE2 | k3s | kubeadm |
|---|---|---|---|---|
| 厂商 | Rancher | Rancher | Rancher | Kubernetes 社区 |
| 容器运行时 | Docker | containerd(内置) | containerd(内置) | 需自行安装(containerd/CRI-O) |
| 控制平面部署 | Docker 容器 | 静态 Pod | 单进程内嵌 | systemd 直跑二进制 + 静态 Pod(自托管可选) |
| 组件形态 | 多组件容器 | 单二进制 + 内置组件 | 单二进制(极简) | 多个独立二进制 |
| etcd | 容器化 | 嵌入式 etcd(静态 Pod) | 可选嵌入式 etcd / SQLite | 静态 Pod 或外部 etcd |
| CIS 加固 | 需手工 | 内置 cis profile | 部分支持 | 需手工 |
| FIPS 140-2 | 不支持 | 支持 | 不支持 | 不支持 |
| 默认 CNI | Canal/Calico/Flannel 可选 | Canal(可换 Calico/Cilium/Multus) | Flannel | 无(需自行安装) |
| 资源占用 | 中 | 中 | 极小(适合边缘/IoT) | 中 |
| 适用场景 | 存量集群 | 生产环境、政企合规 | 边缘、开发测试 | 学习、完全自定义 |
选型建议:
- 企业生产集群、有等保/CIS/FIPS 合规要求 → RKE2
- 边缘节点、资源受限、轻量测试 → k3s
- 深入理解 K8s 组件细节、做 CKA 备考 → kubeadm
- 已有 RKE1 集群 → 规划向 RKE2 迁移(RKE1 已进入维护期)
1.3 RKE2 设计哲学
安全第一(Secure by Default)
- 默认启用 SELinux 支持,提供
cisprofile 一键满足 CIS Benchmark 大部分检查项。 - 所有组件间通信使用双向 TLS,证书由 RKE2 自动生成与轮换。
- 控制平面静态 Pod 清单只读挂载,kubelet 直接管理,杜绝手工篡改。
- 默认启用 SELinux 支持,提供
一切皆静态 Pod
- 控制平面组件(etcd、kube-apiserver、kube-controller-manager、kube-scheduler、kube-proxy、cloud-controller-manager)的清单由 RKE2 渲染到
/var/lib/rancher/rke2/agent/pod-manifests/,由 kubelet 拉起。这意味着你可以用crictl ps直接看到控制平面容器。
- 控制平面组件(etcd、kube-apiserver、kube-controller-manager、kube-scheduler、kube-proxy、cloud-controller-manager)的清单由 RKE2 渲染到
声明式组件管理
- 内置 helm-controller,集群插件(CoreDNS、ingress-nginx、metrics-server 等)以
HelmChartCRD 形式声明在/var/lib/rancher/rke2/server/manifests/,可被用户自定义覆盖。
- 内置 helm-controller,集群插件(CoreDNS、ingress-nginx、metrics-server 等)以
离线友好
- 提供 tarball 离线安装包(含全部系统镜像),支持完全离线(air-gapped)部署,适合政企内网环境。
1.4 RKE2 架构
RKE2 集群有两种节点角色:
- server 节点:运行控制平面(etcd + apiserver + controller-manager + scheduler),同时也默认承担 worker 负载(可打污点禁止调度)。
- agent 节点:纯 worker 节点,只运行 kubelet + kube-proxy + CNI。
┌────────────────────────────────────────────┐
│ 固定注册地址 (VIP/LB) │
│ https://<vip>:9345 (注册引导) │
│ https://<vip>:6443 (kube-apiserver) │
└───────────────┬────────────────────────────┘
│
┌───────────────────────────────┼───────────────────────────────┐
│ │ │
┌───────▼────────┐ ┌────────▼───────┐ ┌────────▼───────┐
│ server-1 │ │ server-2 │ │ server-3 │
│ (首节点/引导) │◄──etcd────►│ control-plane │◄───etcd────►│ control-plane │
│ │ 2379/2380 │ + etcd │ 2379/2380 │ + etcd │
│ 静态 Pod: │ │ 静态 Pod: │ │ 静态 Pod: │
│ etcd │ │ etcd │ │ etcd │
│ kube-apiserver│ │ kube-apiserver│ │ kube-apiserver│
│ controller-mgr│ │ controller-mgr│ │ controller-mgr│
│ scheduler │ │ scheduler │ │ scheduler │
│ kube-proxy │ │ kube-proxy │ │ kube-proxy │
│ kubelet+containerd │ kubelet+containerd │ kubelet+containerd
└───────┬────────┘ └────────┬───────┘ └────────┬───────┘
│ CNI (Canal/Calico VXLAN 8472 / WireGuard 51820) │
┌───────▼────────┐ ┌────────▼───────┐
│ agent-1 │ │ agent-2 │
│ kubelet │ │ kubelet │
│ kube-proxy │ │ kube-proxy │
│ containerd │ │ containerd │
└────────────────┘ └────────────────┘server 节点上的静态 Pod 清单目录:
bash
ls /var/lib/rancher/rke2/agent/pod-manifests/
# cloud-controller-manager.yaml etcd.yaml kube-apiserver.yaml
# kube-controller-manager.yaml kube-proxy.yaml kube-scheduler.yaml集群级组件清单目录(helm-controller 托管):
bash
ls /var/lib/rancher/rke2/server/manifests/
# coredns.yaml rke2-canal.yaml rke2-ingress-nginx.yaml
# rke2-metrics-server.yaml ...注意事项:以上两个目录中的文件由 RKE2 自动渲染,不要手工修改。要自定义组件,应使用
HelmChartConfigCRD(见第 9 章)或disable配置项。
第 2 章 安装详解
2.1 安装方式总览
| 方式 | 适用场景 | 核心命令 |
|---|---|---|
| 在线脚本(官方源) | 可访问 GitHub | curl -sfL https://get.rke2.io | sh - |
| 在线脚本(国内镜像) | 国内网络 | INSTALL_RKE2_MIRROR=cn curl -sfL https://rancher-mirror.rancher.cn/rke2/install.sh | sh - |
| Tarball 离线安装 | 离线/内网环境 | 预下载 tar 包 + INSTALL_RKE2_ARTIFACT_PATH |
| RPM 安装 | RHEL/Rocky 9 | yum install rke2-server(较少用) |
2.2 安装脚本环境变量
| 环境变量 | 说明 | 示例 |
|---|---|---|
INSTALL_RKE2_VERSION | 指定版本 | v1.35.6+rke2r1 |
INSTALL_RKE2_CHANNEL | 指定通道(与 VERSION 二选一) | stable / latest / v1.35 |
INSTALL_RKE2_TYPE | 安装类型 | server(默认)/ agent |
INSTALL_RKE2_MIRROR | 镜像源 | cn(使用 rancher-mirror.rancher.cn) |
INSTALL_RKE2_ARTIFACT_PATH | 本地离线包路径 | /opt/rke2-artifacts |
INSTALL_RKE2_EXEC | 启动命令参数注入 | server / agent 及其参数 |
INSTALL_RKE2_SKIP_ENABLE | 只安装不 enable 服务 | true |
2.3 在线安装(官方源)
bash
# 安装 server(最新 stable 通道)
curl -sfL https://get.rke2.io | sh -
# 指定版本
curl -sfL https://get.rke2.io | INSTALL_RKE2_VERSION="v1.35.6+rke2r1" sh -
# 安装 agent
curl -sfL https://get.rke2.io | INSTALL_RKE2_TYPE="agent" sh -2.4 国内镜像源安装
国内环境推荐使用 Rancher 中国镜像站:
bash
# 方式一:INSTALL_RKE2_MIRROR=cn(脚本内部自动切换到 rancher-mirror.rancher.cn)
curl -sfL https://get.rke2.io | INSTALL_RKE2_MIRROR=cn sh -
# 方式二:直接从中国镜像站获取脚本
curl -sfL https://rancher-mirror.rancher.cn/rke2/install.sh | \
INSTALL_RKE2_MIRROR=cn \
INSTALL_RKE2_VERSION="v1.35.6+rke2r1" \
sh -系统镜像(容器镜像)仍会默认从 docker.io/rancher 拉取,离线或内网环境需要配合 system-default-registry(见第 5、6 章)。
2.5 Tarball 离线安装(生产内网推荐)
第一步:在能联网的机器下载制品
bash
mkdir -p /opt/rke2-artifacts && cd /opt/rke2-artifacts
# 安装脚本
curl -sfL https://get.rke2.io -o install.sh
# RKE2 二进制包
curl -sfLO https://github.com/rancher/rke2/releases/download/v1.35.6+rke2r1/rke2.linux-amd64.tar.gz
# 校验文件
curl -sfLO https://github.com/rancher/rke2/releases/download/v1.35.6+rke2r1/sha256sum-amd64.txt
# 系统镜像包(containerd 会从中预导入镜像,无需联网拉取)
curl -sfLO https://github.com/rancher/rke2/releases/download/v1.35.6+rke2r1/rke2-images.linux-amd64.tar.zst
# 若使用 calico CNI 还需:
curl -sfLO https://github.com/rancher/rke2/releases/download/v1.35.6+rke2r1/rke2-images-calico.linux-amd64.tar.zst第二步:拷贝到目标机器并安装
bash
cd /opt/rke2-artifacts
INSTALL_RKE2_ARTIFACT_PATH=/opt/rke2-artifacts \
INSTALL_RKE2_VERSION="v1.35.6+rke2r1" \
INSTALL_RKE2_TYPE=server \
sh install.sh
systemctl enable rke2-server --now镜像包也可以放到 /var/lib/rancher/rke2/agent/images/ 目录,RKE2 启动时会自动导入 containerd。
本仓库实战参考:
rke2/README.md记录了使用本地 Nginx 作为软件源(INSTALL_RKE2_ARTIFACT_PATH=/opt/rke2-artifacts)的完整离线安装流程;rke2/install-server.sh与rke2/install-agent.sh是可直接执行的自动化脚本。
2.6 systemd 单元
安装脚本会创建并注册 systemd 服务:
| 服务 | 节点角色 | 单元文件 |
|---|---|---|
rke2-server.service | server 节点 | /usr/lib/systemd/system/rke2-server.service |
rke2-agent.service | agent 节点 | /usr/lib/systemd/system/rke2-agent.service |
bash
systemctl enable rke2-server --now # 启动 server
systemctl status rke2-server # 查看状态
journalctl -u rke2-server -f # 跟踪日志
systemctl restart rke2-agent # 重启 agent注意事项:server 首次启动需要导入镜像、生成证书、引导 etcd,耗时可能长达 1~5 分钟,期间
systemctl status显示activating是正常现象。
2.7 二进制与目录结构
| 路径 | 说明 |
|---|---|
/usr/local/bin/rke2 | RKE2 主二进制(安装脚本通常软链到 /usr/bin/rke2) |
/usr/local/bin/{kubectl,crictl,ctr} | 包装命令软链 |
/etc/rancher/rke2/config.yaml | 主配置文件 |
/etc/rancher/rke2/registries.yaml | 私有镜像仓库配置 |
/etc/rancher/rke2/rke2.yaml | 管理员 kubeconfig |
/var/lib/rancher/rke2/bin/ | 内置 kubectl/crictl/ctr 等工具 |
/var/lib/rancher/rke2/data/ | 解压的组件二进制(按版本分目录) |
/var/lib/rancher/rke2/agent/pod-manifests/ | 控制平面静态 Pod 清单 |
/var/lib/rancher/rke2/agent/images/ | 离线镜像包放置目录 |
/var/lib/rancher/rke2/agent/containerd/ | containerd 数据目录 |
/var/lib/rancher/rke2/server/manifests/ | 集群组件 HelmChart 清单 |
/var/lib/rancher/rke2/server/token | server token |
/var/lib/rancher/rke2/server/node-token | 节点注册 token |
/var/lib/rancher/rke2/server/agent-token | agent 注册 token |
/var/lib/rancher/rke2/server/db/ | etcd 数据与快照 |
/var/lib/rancher/rke2/server/tls/ | 集群 CA 与组件证书 |
/var/log/pods/ | Pod 日志 |
/var/log/syslog 或 journald | 系统日志 |
kubeconfig 位置与使用:
bash
# server 节点上的管理员 kubeconfig
export KUBECONFIG=/etc/rancher/rke2/rke2.yaml
kubectl get nodes
# 或写入 root 的默认位置
mkdir -p ~/.kube
cp /etc/rancher/rke2/rke2.yaml ~/.kube/config
# 注意:rke2.yaml 中 server 地址默认是 https://127.0.0.1:6443,
# 拷贝到集群外使用时要改成 https://<server-ip 或 VIP>:6443(且该地址必须在 tls-san 中)rke2 包装命令:
bash
rke2 kubectl get nodes # 等价于内置 kubectl
rke2 crictl ps # 操作内置 containerd(自动带正确 endpoint)
rke2 crictl images
rke2 ctr -n k8s.io images ls # 底层 ctr
rke2 etcd-snapshot save --name snap1 # etcd 快照子命令
rke2 certificate rotate # 证书轮换
rke2 secrets-encrypt rotate # 加密密钥轮换最佳实践:把下面几行加入
/root/.bashrc,避免每次手敲长路径:bashexport KUBECONFIG=/etc/rancher/rke2/rke2.yaml export PATH=$PATH:/var/lib/rancher/rke2/bin export CRI_CONFIG_FILE=/var/lib/rancher/rke2/agent/etc/crictl.yaml
第 3 章 单节点与 HA 集群部署
3.1 节点规划示例
以本仓库 rke2/README.md 中的真实环境为例:
| 节点名 | IP 地址 | 角色 | 说明 |
|---|---|---|---|
| rocky9-vm-04 | 192.168.122.190 | control-plane,etcd | 第一个 server 节点 |
| rocky9-vm-05 | 192.168.122.96 | worker | agent 节点 |
| rocky9-vm-06 | 192.168.122.231 | worker | agent 节点 |
集群 CIDR:10.12.0.0/16;Service CIDR:10.13.0.0/16(生产环境建议避免使用默认的 10.42/10.43,以便与现有网络区分并方便排障)。
3.2 部署前准备(RHEL/Rocky 9)
bash
# 关闭或配置防火墙(生产建议放行端口而非直接关闭,端口列表见第 11 章)
systemctl disable firewalld --now
# 关闭 swap
swapoff -a
sed -i '/swap/d' /etc/fstab
# SELinux:RKE2 原生支持 SELinux,保持 enforcing 即可(需安装容器策略包)
dnf install -y container-selinux selinux-policy-base
# 若使用 cis profile 需安装:
dnf install -y rke2-selinux # 通常随 rke2 自动安装
# NetworkManager 配置(Calico/Canal 要求忽略 CNI 接口,防止 veth 被 NM 干扰)
cat > /etc/NetworkManager/conf.d/rke2-canal.conf <<EOF
[keyfile]
unmanaged-devices=interface-name:cali*;interface-name:flannel*
EOF
systemctl reload NetworkManager
# 时间同步(etcd 对时钟敏感)
dnf install -y chrony && systemctl enable chronyd --nowUbuntu 24.04 类似(apt install chrony、ufw disable 或放行端口)。
3.3 首台 server(引导节点)
编写 /etc/rancher/rke2/config.yaml(本仓库 rke2/server-config.yaml 的实战版本):
yaml
node-name: rocky9-vm-04
node-ip: 192.168.122.190
advertise-address: 192.168.122.190
tls-san:
- 192.168.122.190
- rocky9-vm-04
# 如果有 VIP/LB,必须加在这里!
# - 192.168.122.200
# - rke2-api.example.com
cluster-cidr: 10.12.0.0/16
service-cidr: 10.13.0.0/16
kube-proxy-arg:
- "proxy-mode=ipvs"
system-default-registry: 192.168.122.156:30000
etcd-snapshot-retention: 5
etcd-snapshot-schedule-cron: "0 */6 * * *"启动:
bash
systemctl enable rke2-server --now
# 等待 kubeconfig 生成
until [ -f /etc/rancher/rke2/rke2.yaml ]; do sleep 2; done
export KUBECONFIG=/etc/rancher/rke2/rke2.yaml
kubectl get nodes3.4 固定注册地址(Fixed Registration Address)
这是 HA 部署中最容易被忽视、却最关键的设计。 每个 agent 和后续加入的 server 都需要一个 server: https://<地址>:9345 来注册。如果直接写首节点 IP:
- 首节点宕机后,新节点无法加入;
- kubectl 通过首节点 6443 访问,首节点挂了控制面不可达(即使其余 server 正常)。
方案对比:
| 方案 | 优点 | 缺点 | 适用 |
|---|---|---|---|
| kube-vip | 无额外机器、ARP/BGP 宣告 VIP | 仅 L2/需交换机配合 | 裸金属/虚拟化同网段 |
| haproxy + keepalived | 经典稳定、可健康检查 | 需 2 台 LB 机器(可与 server 复用) | 通用生产 |
| 云 LB(SLB/NLB) | 免运维 | 云厂商绑定 | 公有云 |
| DNS 轮询 | 简单 | 无健康检查、切换慢 | 不推荐生产 |
haproxy + keepalived 配置示例(部署在两台 LB 上,VIP 192.168.122.200):
bash
# /etc/haproxy/haproxy.cfg
frontend rke2-frontend
bind *:9345
mode tcp
default_backend rke2-server-9345
frontend rke2-apiserver
bind *:6443
mode tcp
default_backend rke2-server-6443
backend rke2-server-9345
mode tcp
balance roundrobin
server s1 192.168.122.190:9345 check
server s2 192.168.122.191:9345 check
server s3 192.168.122.192:9345 check
backend rke2-server-6443
mode tcp
balance roundrobin
server s1 192.168.122.190:6443 check
server s2 192.168.122.191:6443 check
server s3 192.168.122.192:6443 checkbash
# /etc/keepalived/keepalived.conf(主节点;备节点 state BACKUP、priority 90)
vrrp_instance VI_RKE2 {
state MASTER
interface eth0
virtual_router_id 51
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass rke2vip1
}
virtual_ipaddress {
192.168.122.200/24
}
}kube-vip 方案(无需独立 LB 节点):在每个 server 节点上以静态 Pod 形式运行 kube-vip(ARP 模式),或由 RKE2 的 HelmChart 部署。社区常用做法:
yaml
# /var/lib/rancher/rke2/server/manifests/kube-vip.yaml(server 启动后自动部署)
apiVersion: helm.cattle.io/v1
kind: HelmChart
metadata:
name: kube-vip
namespace: kube-system
spec:
chart: kube-vip
repo: https://kube-vip.github.io/helm-charts
set:
config.address: "192.168.122.200"最佳实践:无论用哪种方案,首节点的
tls-san中必须包含 VIP 和 VIP 对应域名,否则 kubectl 走 VIP 时证书校验失败。事后补加 tls-san 需要重启所有 server 触发证书重新生成。
3.5 多 server 加入
后续 server 节点 /etc/rancher/rke2/config.yaml:
yaml
server: https://192.168.122.200:9345 # 固定注册地址(或首节点 IP)
token: <首节点 /var/lib/rancher/rke2/server/node-token 的内容>
node-name: rocky9-vm-07
node-ip: 192.168.122.191
tls-san:
- 192.168.122.200
cluster-cidr: 10.12.0.0/16 # 必须与首节点完全一致!
service-cidr: 10.13.0.0/16 # 必须与首节点完全一致!
kube-proxy-arg:
- "proxy-mode=ipvs"
system-default-registry: 192.168.122.156:30000bash
systemctl enable rke2-server --now注意事项(真实踩坑):新增 server 时
cluster-cidr、service-cidr、cni、disable列表等关键配置必须与既有 server 完全一致,否则rke2-server会反复重启并报critical configuration value mismatch between servers。详见仓库案例k8s-issues/rke2-master-join-fails-critical-configuration-mismatch.md和节点添加手册k8s-issues/rke2-node-addition-operation-manual.md。
server 节点数量与 etcd 仲裁:server 数量应为奇数(1/3/5),3 节点可容忍 1 台故障,5 节点可容忍 2 台。生产推荐 3 台 server。
3.6 agent 加入
agent 节点 /etc/rancher/rke2/config.yaml(本仓库 rke2/agent-config.yaml 的实战版本):
yaml
server: https://192.168.122.200:9345
token: xxx # node-token 或 agent-token 均可
node-name: rocky9-vm-05
node-ip: 192.168.122.96
kube-proxy-arg:
- "proxy-mode=ipvs"
system-default-registry: 192.168.122.156:30000bash
systemctl enable rke2-agent --now
# 在 server 上验证
kubectl get nodes -o wide注意事项(真实踩坑):新节点加入后长时间
NotReady、日志反复出现Pod for etcd not synced (pod sandbox not found),往往是离线镜像导入耗时导致的正常现象,耐心等待rke2-imagestar 包导入完成即可。详见k8s-issues/rke2-master-join-notready-image-import-delay.md。
3.7 token 管理
| token 文件 | 用途 | 说明 |
|---|---|---|
/var/lib/rancher/rke2/server/node-token | server/agent 注册 | 格式 K10<ca-hash>::server:<password>,含 CA 指纹,可防中间人 |
/var/lib/rancher/rke2/server/agent-token | agent 注册 | 仅 agent 角色权限,最小权限推荐用它注册 agent |
/var/lib/rancher/rke2/server/token | 内部 token | server 间通信用 |
bash
cat /var/lib/rancher/rke2/server/node-token
# xxx- 可在首节点 config.yaml 中用
token: xxx 预置自定义 token(本仓库install-server.sh` 即如此),后续节点使用同一 token。 - token 轮换:修改所有节点 config.yaml 中的 token 并逐台重启;旧节点在重启前仍用旧 token 通信。
第 4 章 config.yaml 配置详解
4.1 配置文件基础
- 位置:
/etc/rancher/rke2/config.yaml - 格式:YAML,
key: value;列表用-或[a, b] - 修改后必须
systemctl restart rke2-server(或rke2-agent)生效 - 几乎所有命令行 flag 都可写成配置项:
--tls-san=x→tls-san: x
4.2 常用 server 配置项
| 配置项 | 说明 | 示例 |
|---|---|---|
cluster-cidr | Pod IP 段 | 10.12.0.0/16 |
service-cidr | Service IP 段 | 10.13.0.0/16 |
cluster-dns | CoreDNS Service IP | 10.13.0.10 |
cluster-domain | 集群域名 | cluster.local |
tls-san | apiserver 证书附加 SAN | [192.168.122.200, rke2.example.com] |
cni | CNI 插件 | canal / calico / cilium / none / multus,canal |
disable | 禁用内置组件 | [rke2-ingress-nginx, rke2-servicelb] |
disable-cloud-controller | 禁用内置 CCM | true(对接外部 CCM 时) |
etcd-snapshot-schedule-cron | etcd 定时快照 | "0 */6 * * *" |
etcd-snapshot-retention | 快照保留份数 | 5 |
etcd-snapshot-dir | 快照目录 | /var/lib/rancher/rke2/server/db/snapshots |
etcd-s3 | 快照上传 S3 | 见第 7 章 |
kube-apiserver-arg | 透传 apiserver 参数 | ["audit-log-path=/var/lib/rancher/rke2/server/logs/audit.log"] |
kube-controller-manager-arg | 透传 KCM 参数 | ["node-cidr-mask-size=24"] |
kube-scheduler-arg | 透传调度器参数 | — |
kube-proxy-arg | 透传 kube-proxy 参数 | ["proxy-mode=ipvs"] |
kubelet-arg | 透传 kubelet 参数 | ["max-pods=220", "eviction-hard=memory.available<500Mi"] |
profile | 安全基线 | cis |
selinux | 强制启用 SELinux 上下文 | true |
system-default-registry | 系统镜像默认仓库 | 192.168.122.156:30000 |
node-name / node-ip | 节点名/节点 IP | 双栈时 node-ip: 192.168.1.10,fd00::10 |
node-label / node-taint | 节点标签/污点 | node-taint: ["CriticalAddonsOnly=true:NoExecute"] |
write-kubeconfig-mode | rke2.yaml 权限 | 0644(默认 0600) |
secrets-encryption | 启用 secret 静态加密 | true |
embedded-registry | 启用内嵌分布式镜像仓库 | true |
4.3 常用 agent 配置项
agent 支持的子集:server、token、node-name、node-ip、node-label、node-taint、kubelet-arg、kube-proxy-arg、container-runtime-endpoint、system-default-registry、selinux 等。与集群数据相关的项(cluster-cidr 等)只对 server 有意义。
4.4 CNI 选择
| cni 值 | 说明 |
|---|---|
canal | 默认,Flannel(VXLAN) + Calico 网络策略,开箱即用 |
calico | 纯 Calico,支持 BGP/VXLAN,网络策略强大 |
cilium | eBPF 数据面,可替代 kube-proxy,观测性强(Hubble) |
multus,canal | Multus + Canal 组合,支持多网卡 Pod |
none | 不安装 CNI,自行部署(如 Calico 官方 manifest) |
4.5 disable 内置组件
yaml
disable:
- rke2-ingress-nginx # 不用内置 ingress(改用自建 ingress 或 traefik)
- rke2-servicelb # 不用 klipper-lb(改用 MetalLB)
- rke2-metrics-server # 自建 metrics-server
- rke2-coredns # 极少见注意事项:
disable列表在所有 server 节点上必须一致。
4.6 etcd 相关参数
yaml
etcd-arg:
- "quota-backend-bytes=4294967296" # etcd 存储上限调大到 4GB(默认 2GB)
- "auto-compaction-retention=8" # 自动压缩保留 8 小时
etcd-snapshot-schedule-cron: "0 */6 * * *"
etcd-snapshot-retention: 104.7 kubelet 调优示例
yaml
kubelet-arg:
- "max-pods=220"
- "eviction-hard=memory.available<500Mi,nodefs.available<10%"
- "system-reserved=cpu=500m,memory=1Gi"
- "kube-reserved=cpu=500m,memory=1Gi"
- "image-gc-high-threshold=80"
- "serialize-image-pulls=false"4.8 镜像加速(国内环境)
方式一:system-default-registry 统一改系统镜像源(见第 6 章)。
方式二:registries.yaml 为 docker.io 配置 mirror(见第 6 章),对所有业务镜像生效。
4.9 配置加载顺序与环境变量
RKE2 参数来源优先级(后者覆盖前者):
- 内置默认值
- 配置文件
/etc/rancher/rke2/config.yaml(可用-c指定其他路径) - 环境变量(如
RKE2_TOKEN、RKE2_URL,对应token、server) - 命令行参数(如
rke2 server --cluster-cidr=...)
最佳实践:
- 集群初始化前就把
cluster-cidr/service-cidr/tls-san/cni定好——这些项集群建成后不可更改(更改会导致新 server 无法加入或网络重建)。- 用 Ansible/脚本统一渲染 config.yaml,保证所有 server 关键配置一致(参考本仓库
rke2/install-server.sh、rke2/install-agent.sh)。- config.yaml 是 YAML,布尔值写
true/false,带特殊字符的 cron 表达式务必加引号。
4.10 常见面试题(本章)
- RKE2 的 config.yaml 修改后如何生效? 重启对应 systemd 服务;集群级配置(cluster-cidr 等)建成后不可变。
- tls-san 的作用?忘记加 VIP 怎么办? apiserver 证书的 Subject Alternative Name;补加后需重启所有 server 重新签发证书。
- RKE2 token 的格式与安全意义?
K10<CA-SHA256>::server:<secret>,前置 CA 哈希让新节点可校验对端身份,防中间人。
第 5 章 私有镜像仓库:registries.yaml
5.1 为什么需要 registries.yaml
生产环境几乎都使用私有仓库(Harbor 等),常见问题:
- 仓库使用 HTTP 或自签名证书 → containerd 默认拒绝;
- docker.io 拉不动 → 需要 mirror 加速;
- 私有仓库需要认证 → 需要配置凭据。
RKE2 通过 /etc/rancher/rke2/registries.yaml 统一配置 containerd 的 registry 行为,无需重启服务即可热加载(RKE2 会 watch 该文件变更)。
5.2 registries.yaml 完整结构
yaml
# mirrors:定义"拉取某仓库镜像时,实际去哪些 endpoint 找"
mirrors:
docker.io:
endpoint:
- "https://harbor.example.com" # 优先从 Harbor 代理仓库拉
- "https://registry-1.docker.io" # 兜底回源
# rewrite: # 可选:路径重写
# "^rancher/(.*)": "library/rancher/$1"
"192.168.122.156:30000":
endpoint:
- "http://192.168.122.156:30000" # HTTP 仓库直接写 http://
# configs:定义"访问某仓库时的认证与 TLS 行为"
configs:
"harbor.example.com":
auth:
username: xxx
password: xxx
# 也可用 auth: <base64(user:pass)> 或 identitytoken
tls:
cert_file: /etc/rancher/rke2/harbor-client.crt # 双向 TLS 时
key_file: /etc/rancher/rke2/harbor-client.key
ca_file: /etc/rancher/rke2/harbor-ca.crt # 自签名 CA
insecure_skip_verify: true # 跳过证书校验(二选一)本仓库 rke2/registries.yaml 与 rke2/README.md 中的真实配置(HTTP Harbor 仓库):
yaml
configs:
"192.168.122.156:30000":
tls:
insecure_skip_verify: true
mirrors:
"192.168.122.156:30000":
endpoint:
- "http://192.168.122.156:30000"
"docker.io":
endpoint:
- "http://192.168.122.156:30000"5.3 mirror 与 endpoint 的工作机制
mirrors.<name>中的 name 是镜像引用里的仓库名(如docker.io、gcr.io、quay.io、私有仓库地址)。- 拉取
nginx:1.27(等价于docker.io/library/nginx:1.27)时,containerd 按 endpoint 顺序尝试:- 先请求
https://harbor.example.com/v2/library/nginx/manifests/1.27 - 全部 endpoint 失败后报错(不会自动回到未列出的默认源——除非你把默认源也写进 endpoint 列表)。
- 先请求
- endpoint 的 scheme 决定协议:
http://即明文 HTTP(自动视为 insecure);https://配合configs中的 TLS 设置。
5.4 system-default-registry 与 registries.yaml 的区别
| 机制 | 作用范围 | 典型用途 |
|---|---|---|
system-default-registry | 只影响 RKE2 系统组件镜像(如 rancher/hardened-coredns) | 系统镜像全部从 Harbor 拉取,离线环境必备 |
registries.yaml mirrors | 影响 所有容器镜像(系统 + 业务) | docker.io 加速、私有仓库 HTTP/自签名支持 |
最佳实践:离线环境两者都要配——
system-default-registry指向 Harbor(系统镜像已推送过去),registries.yaml 配置 Harbor 的 HTTP/TLS 访问方式。本仓库rke2/server-config.yaml就是该组合的实战样例。
5.5 底层原理:containerd 配置生成
RKE2 启动时根据 registries.yaml 生成 containerd 的 hosts 目录配置:
bash
ls /var/lib/rancher/rke2/agent/etc/containerd/certs.d/
# docker.io/ 192.168.122.156:30000/ ...
cat /var/lib/rancher/rke2/agent/etc/containerd/certs.d/docker.io/hosts.toml生成的 hosts.toml 等价于 containerd 原生的 registry hosts 配置(server、capabilities、ca/skip_verify)。理解这一点后,你可以直接用 crictl 验证:
bash
rke2 crictl pull 192.168.122.156:30000/library/nginx:1.27
# 排查拉取失败
journalctl -u rke2-server | grep -i "pulling image"
rke2 crictl images | grep nginx注意事项:registries.yaml 中仓库地址的 key 必须带端口(如
192.168.122.156:30000),与镜像引用中的写法完全一致,否则匹配不上。
第 6 章 etcd 管理与备份恢复
6.1 嵌入式 etcd
RKE2 server 节点默认运行嵌入式 etcd(静态 Pod),多个 server 自动组成 etcd 集群:
server-1 etcd ──2380(raft peer)── server-2 etcd ──2380── server-3 etcd
│ │ │
└──── 2379 (client) ──── kube-apiserver(本机) ──────────┘- etcd 数据目录:
/var/lib/rancher/rke2/server/db/etcd/ - 快照目录:
/var/lib/rancher/rke2/server/db/snapshots/ - 默认监听:
127.0.0.1:2379(本机 apiserver 访问)、节点 IP:2380(peer 通信)
查看 etcd 状态:
bash
# 使用 etcd Pod 内的 etcdctl
ETCDCTL_API=3 rke2 kubectl -n kube-system exec etcd-rocky9-vm-04 -- \
etcdctl --cacert=/var/lib/rancher/rke2/server/tls/etcd/server-ca.crt \
--cert=/var/lib/rancher/rke2/server/tls/etcd/client.crt \
--key=/var/lib/rancher/rke2/server/tls/etcd/client.key \
--endpoints=https://127.0.0.1:2379 \
endpoint status --cluster -w table
# 成员列表
... etcdctl member list -w table6.2 快照:save / list / prune
bash
# 手动快照
rke2 etcd-snapshot save --name pre-upgrade-snapshot
# 快照保存在 /var/lib/rancher/rke2/server/db/snapshots/
# 列出快照
rke2 etcd-snapshot list
# 或 etcd-snapshot ls
# 清理旧快照(保留最近 5 份)
rke2 etcd-snapshot prune --snapshot-retention 5
# 删除指定快照
rke2 etcd-snapshot delete --name pre-upgrade-snapshot定时快照(config.yaml):
yaml
etcd-snapshot-schedule-cron: "0 */6 * * *" # 每 6 小时
etcd-snapshot-retention: 10 # 保留 10 份6.3 S3 快照(异地备份)
yaml
# config.yaml
etcd-s3: true
etcd-s3-endpoint: "s3.example.com"
etcd-s3-bucket: "rke2-etcd-backup"
etcd-s3-access-key: "xxx"
etcd-s3-secret-key: "xxx"
etcd-s3-region: "us-east-1"
etcd-s3-folder: "prod-cluster"
etcd-s3-insecure: true # 自签名 https 时手动上传快照到 S3:
bash
rke2 etcd-snapshot save --name manual-s3 \
--s3 --s3-endpoint=s3.example.com --s3-bucket=rke2-etcd-backup ...最佳实践:定时本地快照 + S3 异地快照双保险;升级集群前务必手动
etcd-snapshot save。
6.4 从快照恢复
场景:整个集群数据损坏或误删,从快照回滚。
步骤(以首节点 .190 为例):
bash
# 1. 停止所有 server 节点的 rke2-server
systemctl stop rke2-server
# 2. 在首节点执行恢复(指定快照文件)
rke2 server --cluster-reset \
--cluster-reset-restore-path=/var/lib/rancher/rke2/server/db/snapshots/pre-upgrade-snapshot
# 输出提示 "Managed etcd cluster membership has been reset..." 后退出
# 3. 首节点正常启动
systemctl start rke2-server
# 4. 其余 server 节点:删除 etcd 数据目录后重新加入
systemctl stop rke2-server
rm -rf /var/lib/rancher/rke2/server/db/etcd
systemctl start rke2-server
# 5. agent 节点无需操作,自动重连
kubectl get nodes注意事项:
--cluster-reset会把 etcd 集群成员重置为单节点,其余 server 必须删掉本地 etcd 数据再加入,否则会出现成员冲突。
6.5 etcd 仲裁(quorum)丢失恢复思路
etcd 集群 3 节点容忍 1 节点故障;若 2 台以上同时宕机(或数据损坏),剩余节点因无法达成多数派(quorum),rke2-server 全部无法启动,典型报错:
text
etcdserver: request timed out
transport: authentication handshake failed: context deadline exceeded
dial tcp 127.0.0.1:2379: connect: connection refused恢复思路(详细实战见仓库 k8s-issues/rke2-disaster-recovery-control-plane-quorum-loss.md):
- 抢救数据:选一台数据最新的节点,确认其 etcd 数据目录完整(
db/etcd/member/snap/db存在且不太旧)。 - 单节点强制重置:在该节点执行
rke2 server --cluster-reset(可带--cluster-reset-restore-path指定快照;不指定则用本地现有数据重置为单成员集群)。 - 拉起首节点:
systemctl start rke2-server,验证kubectl get nodes、关键 workload 是否还在。 - 重建其余 control-plane:其余节点
rm -rf /var/lib/rancher/rke2/server/db/etcd后重新加入。 - 修复业务:恢复后检查 Deployment/DaemonSet 状态,必要时重新 rollout。
- 复盘加固:落实定时快照 + S3 备份、节点电源/网络冗余、升级前手动快照制度。
经验教训(来自真实案例):quorum 丢失是 K8s 运维的"终极大考",平时没有可验证的备份 = 没有备份。建议每季度演练一次快照恢复。
6.6 常见面试题(本章)
- RKE2 的 etcd 部署形态?与 kubeadm 有何异同? 嵌入式静态 Pod;kubeadm 也支持 stacked etcd,但 RKE2 自动管理成员引导。
- cluster-reset 的原理? 将 etcd 集群成员列表重置为仅本节点,从快照/现有数据重建单节点集群,其余节点清空数据后加入。
- etcd 为什么要求 server 节点数为奇数? Raft 多数派机制,偶数不增加容错能力却增加写入延迟。
第 7 章 升级与维护
7.1 版本与 channel
RKE2 版本格式:v<K8s版本>+rke2r<修订号>,如 v1.35.6+rke2r1。
| channel | 说明 |
|---|---|
stable | 生产推荐,经过充分验证的次新版本 |
latest | 最新版本,适合测试 |
v1.35 | 锁定到某个 K8s 小版本的通道 |
testing | 预发布版本,勿用于生产 |
bash
# 查看 channel 对应版本
curl -s https://update.rke2.io/v1-release/channels | python3 -m json.tool
# 国内镜像
curl -s https://rancher-mirror.rancher.cn/rke2-release/channels | python3 -m json.tool注意事项:Kubernetes 升级不可跨小版本(如 v1.33 → v1.35 需先升 v1.34)。
7.2 手动升级
升级顺序:先逐台 server(先升级非首节点亦可,官方推荐先升级首节点),再逐台 agent。
bash
# 1. 升级前快照
rke2 etcd-snapshot save --name before-upgrade-$(date +%F)
# 2. 在一台 server 上执行新版本安装脚本
curl -sfL https://get.rke2.io | INSTALL_RKE2_VERSION="v1.35.7+rke2r1" sh -
# 离线环境:下载新 tar 包后用 INSTALL_RKE2_ARTIFACT_PATH 安装
# 3. 重启服务(安装脚本不会自动重启正在运行的服务)
systemctl restart rke2-server
# 4. 验证后逐台重复
kubectl get nodes -o wide
kubectl -n kube-system get pods7.3 system-upgrade-controller 自动升级
Rancher 提供 system-upgrade-controller(SUC),通过 Plan CRD 声明式滚动升级集群:
bash
kubectl apply -f https://github.com/rancher/system-upgrade-controller/releases/latest/download/system-upgrade-controller.yamlyaml
# server 升级 Plan
apiVersion: upgrade.cattle.io/v1
kind: Plan
metadata:
name: rke2-server-plan
namespace: system-upgrade
spec:
concurrency: 1 # 一次只升级一台
nodeSelector:
matchExpressions:
- { key: node-role.kubernetes.io/control-plane, operator: Exists }
serviceAccountName: system-upgrade
cordon: true # 升级前 cordon
upgrade:
image: rancher/rke2-upgrade
version: v1.35.7+rke2r1
---
# agent 升级 Plan(channel 方式)
apiVersion: upgrade.cattle.io/v1
kind: Plan
metadata:
name: rke2-agent-plan
namespace: system-upgrade
spec:
concurrency: 2
nodeSelector:
matchExpressions:
- { key: node-role.kubernetes.io/control-plane, operator: DoesNotExist }
serviceAccountName: system-upgrade
prepare:
image: rancher/rke2-upgrade
args: ["prepare", "rke2-server-plan"] # 等 server 全部升完
cordon: true
upgrade:
image: rancher/rke2-upgrade
channel: https://update.rke2.io/v1-release/channels/stablebash
kubectl -n system-upgrade get plans
kubectl -n system-upgrade get jobs7.4 证书轮换
RKE2 自动生成的证书默认有效期 1 年。查看与轮换:
bash
# 查看各证书有效期
rke2 certificate rotate --help
for f in /var/lib/rancher/rke2/server/tls/*.crt; do
echo "== $f"; openssl x509 -in "$f" -noout -enddate 2>/dev/null
done
# 更直接的方式
curl --cacert /var/lib/rancher/rke2/server/tls/server-ca.crt \
https://127.0.0.1:6443 -v 2>&1 | grep "expire date"
# 轮换全部证书(需停止服务)
systemctl stop rke2-server
rke2 certificate rotate
systemctl start rke2-server
# 每台 server 都要执行;agent 证书由 server 自动签发,重启 rke2-agent 即可轮换后需重新分发 /etc/rancher/rke2/rke2.yaml(kubeconfig 内嵌证书已变化)。
7.5 节点维护:drain / cordon
bash
# 维护节点(驱逐 Pod,daemonset 除外)
kubectl drain rocky9-vm-05 --ignore-daemonsets --delete-emptydir-data
# 维护操作...
systemctl restart rke2-agent
# 恢复调度
kubectl uncordon rocky9-vm-05
# 仅禁止调度不驱逐
kubectl cordon rocky9-vm-057.6 卸载
| 脚本 | 作用 |
|---|---|
/usr/bin/rke2-killall.sh | 杀掉所有 RKE2 相关进程、卸载容器与网络(保留数据) |
/usr/bin/rke2-uninstall.sh | 完整卸载:killall + 删除二进制、数据目录、systemd 单元 |
bash
# 节点从集群下线
kubectl drain <node> --ignore-daemonsets --delete-emptydir-data
kubectl delete node <node>
# 节点上执行
rke2-uninstall.sh # server/agent 均适用注意事项:
rke2-uninstall.sh会删除/var/lib/rancher/rke2全部数据(含 etcd 数据与快照)。server 节点卸载前请确认快照已备份到其他位置。
7.7 常见面试题(本章)
- RKE2 升级顺序是什么? 先快照 → 逐台 server → 逐台 agent;不可跨 K8s 小版本。
- 证书快过期了怎么办?
rke2 certificate rotate+ 重启服务 + 重新分发 kubeconfig。 - system-upgrade-controller 的并发控制靠什么?
concurrency字段 + prepare 机制保证 server 先于 agent。
第 8 章 网络与内置组件
8.1 默认内置组件一览
| 组件 | 命名空间 | 作用 | 禁用方式 |
|---|---|---|---|
| CoreDNS | kube-system | 集群 DNS | disable: [rke2-coredns] |
| ingress-nginx | kube-system | Ingress 控制器 | disable: [rke2-ingress-nginx] |
| metrics-server | kube-system | HPA/top 指标 | disable: [rke2-metrics-server] |
| servicelb (klipper-lb) | kube-system | 裸机 LoadBalancer(占用节点主机端口) | disable: [rke2-servicelb] |
| cloud-controller-manager | kube-system | 节点生命周期/路由(无云厂商时的 stub) | disable-cloud-controller: true |
| helm-controller | kube-system | 管理 HelmChart CRD | 不建议禁用 |
| snapshot-validation / csi 相关 | kube-system | 快照 CRD 校验 | — |
8.2 helm-controller 与 HelmChart CRD
RKE2 把集群插件做成 HelmChart CRD,由 helm-controller 自动渲染部署。文件位于 /var/lib/rancher/rke2/server/manifests/。
自定义内置组件的正确姿势——HelmChartConfig:
yaml
# 例如:修改 ingress-nginx 使用 hostNetwork,并开启指标
apiVersion: helm.cattle.io/v1
kind: HelmChartConfig
metadata:
name: rke2-ingress-nginx
namespace: kube-system
spec:
valuesContent: |-
controller:
hostNetwork: true
metrics:
enabled: true
config:
use-forwarded-headers: "true"bash
kubectl apply -f ingress-nginx-config.yaml
# helm-controller 会自动重渲染 rke2-ingress-nginx 这个 HelmChart
kubectl -n kube-system get helmchart,helmchartconfig注意事项:HelmChartConfig 的
name必须与内置 HelmChart 同名(如rke2-ingress-nginx),namespace必须是kube-system。不要直接改/var/lib/rancher/rke2/server/manifests/下的文件(会被覆盖)——除非你有意覆盖整个 chart(放同名文件进去确实可以"shadow"内置清单,但不推荐,升级时容易踩坑)。
完全自定义组件:在 /var/lib/rancher/rke2/server/manifests/ 放入任意 YAML 或 HelmChart CRD,RKE2 会自动 apply 到集群(类似 kubelet 的 static manifest 机制,适合离线环境的组件部署)。
8.3 CNI 插件切换与 Cilium 集成
切换到 Cilium(config.yaml):
yaml
cni: cilium
# 可选:禁用 kube-proxy,让 Cilium eBPF 接管
# disable-kube-proxy: trueCilium 的 HelmChartConfig 示例:
yaml
apiVersion: helm.cattle.io/v1
kind: HelmChartConfig
metadata:
name: rke2-cilium
namespace: kube-system
spec:
valuesContent: |-
kubeProxyReplacement: "true"
k8sServiceHost: "192.168.122.200"
k8sServicePort: "6443"
hubble:
enabled: true
relay:
enabled: true
ui:
enabled: true注意事项:CNI 是集群初始化时决定的,建成后切换 CNI 相当于重建网络(需全部节点清空 CNI 状态),生产环境务必在首节点部署前确定。
8.4 Multus 多网卡
yaml
# config.yaml
cni:
- multus
- canal # 主网络用 canal,multus 负责附加网卡然后正常创建 NetworkAttachmentDefinition 供 Pod 注解使用:
yaml
apiVersion: k8s.cni.cncf.io/v1
kind: NetworkAttachmentDefinition
metadata:
name: macvlan-conf
spec:
config: |
{
"cniVersion": "0.3.1",
"type": "macvlan",
"master": "eth1",
"mode": "bridge",
"ipam": { "type": "static", "addresses": [ { "address": "10.10.0.100/24" } ] }
}8.5 ServiceLB(klipper-lb)与 MetalLB 的取舍
- 默认 servicelb 通过在每个节点起
svclb-*Pod 占用主机端口实现 LoadBalancer,适合测试; - 生产裸金属建议
disable: [rke2-servicelb],改用 MetalLB(L2/BGP 模式),参见本系列 metaLB 相关教材。
8.6 常见面试题(本章)
- 如何修改 RKE2 内置 ingress-nginx 的参数? HelmChartConfig CRD(name 同 chart、namespace kube-system),由 helm-controller 重渲染。
- klipper-lb 的实现原理与局限? DaemonSet 占用主机端口 + iptables 转发;端口冲突、无 IP 池管理,生产建议 MetalLB。
- RKE2 支持哪些 CNI,如何多网络? canal/calico/cilium/none,配合 multus 实现多网卡。
第 9 章 安全加固
9.1 CIS Profile
yaml
# config.yaml
profile: cis启用后 RKE2 自动完成:
- apiserver/controller-manager/scheduler/etcd 按 CIS Benchmark 设置安全参数(如
--profiling=false、审计策略、加密提供者等); - 自动应用
PodSecurity准入(restricted 级别的豁免命名空间配置); - 校验系统内核参数(
vm.panic_on_oom=0、kernel.panic=10、kernel.panic_on_oops=1),不满足时启动报错并提示。
前置系统配置(RHEL/Rocky 9):
bash
# 创建 etcd 专用用户(cis profile 要求)
useradd -r -c "etcd user" -s /sbin/nologin -M etcd -U
# 内核参数
cat > /etc/sysctl.d/90-rke2-cis.conf <<EOF
vm.panic_on_oom=0
vm.overcommit_memory=1
kernel.panic=10
kernel.panic_on_oops=1
EOF
sysctl --system9.2 SELinux 支持
RKE2 是少数原生支持 SELinux enforcing 的发行版:
bash
# RHEL/Rocky 9:保持 SELinux enforcing
getenforce # Enforcing
# config.yaml 中显式开启(新版默认根据系统状态自动启用)
selinux: truebash
# 验证容器带正确 SELinux 上下文
ps -eZ | grep containerd | head -5
# 排查 SELinux 拒绝
ausearch -m avc -ts recent9.3 Pod Security Standards
RKE2(cis profile)默认通过 Pod Security Admission 强制执行策略。手工配置示例:
yaml
# /etc/rancher/rke2/pod-security-admission-config.yaml
apiVersion: apiserver.config.k8s.io/v1
kind: AdmissionConfiguration
plugins:
- name: PodSecurity
configuration:
apiVersion: pod-security.admission.config.k8s.io/v1
kind: PodSecurityConfiguration
defaults:
enforce: "baseline"
enforce-version: "latest"
audit: "restricted"
audit-version: "latest"
warn: "restricted"
warn-version: "latest"
exemptions:
usernames: []
runtimeClasses: []
namespaces:
- kube-system
- cattle-systemyaml
# config.yaml 引用
kube-apiserver-arg:
- "admission-control-config-file=/etc/rancher/rke2/pod-security-admission-config.yaml"9.4 审计策略
bash
cat > /etc/rancher/rke2/audit-policy.yaml <<'EOF'
apiVersion: audit.k8s.io/v1
kind: Policy
rules:
- level: Metadata
omitStages:
- RequestReceived
- level: RequestResponse
verbs: ["create", "update", "patch", "delete"]
resources:
- group: ""
resources: ["secrets", "configmaps"]
EOFyaml
# config.yaml
kube-apiserver-arg:
- "audit-policy-file=/etc/rancher/rke2/audit-policy.yaml"
- "audit-log-path=/var/lib/rancher/rke2/server/logs/audit.log"
- "audit-log-maxage=30"
- "audit-log-maxbackup=10"
- "audit-log-maxsize=100"9.5 Secret 静态加密
yaml
# config.yaml(首节点初始化时或之后启用均可)
secrets-encryption: truebash
# 启用后重写所有 Secret 完成加密
kubectl get secrets --all-namespaces -o json | kubectl replace -f -
# 密钥轮换
rke2 secrets-encrypt rotate # 需先 stop rke2-server9.6 FIPS 140-2
RKE2 提供 FIPS 构建版本:Go 二进制使用通过 FIPS 140-2 认证的 BoringCrypto 模块编译。
bash
# 验证二进制是否为 FIPS 构建
rke2 --version
# 启用 FIPS 模式(需操作系统层面也启用 FIPS:fips-mode-setup --enable)
# config.yaml 无需特殊配置,系统层启用后 RKE2 自动使用 FIPS 加密适用场景:政府、金融等对加密模块有强制认证要求的环境。
9.7 加固清单速查表
| 项目 | 措施 |
|---|---|
| 合规基线 | profile: cis + 内核参数 + etcd 用户 |
| 强制访问控制 | SELinux enforcing + selinux: true |
| Pod 准入 | Pod Security restricted/baseline |
| 审计 | audit-policy + 日志轮转 + 外发日志系统 |
| 数据加密 | secrets-encryption: true + 定期密钥轮换 |
| 传输加密 | 全部组件 TLS(默认)+ FIPS 构建(可选) |
| 网络隔离 | NetworkPolicy(Calico/Cilium)+ 节点防火墙只放行必要端口 |
| 权限 | RBAC 最小化、禁用匿名访问(默认)、service account token 绑定 |
| 镜像 | 私有 Harbor + 镜像扫描(Trivy/Harbor 内置)+ 可信签名 |
第 10 章 故障排查大全
10.1 排查工具箱
| 工具 | 命令 |
|---|---|
| 服务日志 | journalctl -u rke2-server -f / journalctl -u rke2-agent -f / journalctl -u rke2-server --since "1 hour ago" |
| 容器运行时 | rke2 crictl ps -a、rke2 crictl logs <id>、rke2 crictl inspect <id> |
| Pod 日志 | kubectl logs -n kube-system <pod>、/var/log/pods/ |
| 系统日志 | /var/log/messages(RHEL 系)/ /var/log/syslog(Ubuntu) |
| 静态 Pod 清单 | /var/lib/rancher/rke2/agent/pod-manifests/ |
| etcd 健康 | 见第 6 章 etcdctl endpoint status |
| 网络 | ss -lntp(端口监听)、iptables -L -n、ipvsadm -Ln |
10.2 server 无法启动
现象:systemctl start rke2-server 卡住或反复重启。
排查步骤:
bash
journalctl -u rke2-server -n 200 --no-pager # 找 fatal/error 行
ls -lh /var/lib/rancher/rke2/agent/images/ # 离线包是否在
df -h # 磁盘是否满(etcd 敏感)
free -m # 内存是否足够(server 建议 ≥4GB)| 常见报错 | 原因 | 解决 |
|---|---|---|
failed to validate token ... dial tcp <ip>:9345: connect: no route to host | 防火墙拦截 9345 | 放行端口(见 10.6),参考 k8s-issues/rke2-master-join-fails-iptables-firewall-blocking.md |
critical configuration value mismatch between servers | 新 server 配置与集群不一致 | 对齐 cluster-cidr/service-cidr/cni/disable,参考 k8s-issues/rke2-master-join-fails-critical-configuration-mismatch.md |
etcdserver: request timed out | etcd quorum 丢失 | 走 cluster-reset 恢复流程,参考 k8s-issues/rke2-disaster-recovery-control-plane-quorum-loss.md |
failed to get CA certs | token 错误或 9345 不通 | 核对 node-token,测试 curl -k https://<server>:9345/cacerts |
| cis profile 下提示内核参数不达标 | sysctl 未配置 | 按 9.1 配置内核参数与 etcd 用户 |
10.3 节点 NotReady
现象:kubectl get nodes 显示 NotReady。
排查步骤:
bash
kubectl describe node <node> # 看 Conditions 与 Events
journalctl -u rke2-agent -n 100 # agent 节点日志
rke2 crictl ps -a | head # 容器是否拉起
kubectl -n kube-system get pods -o wide | grep <node> # CNI Pod 是否正常| 常见原因 | 特征 | 解决 |
|---|---|---|
| 镜像导入中(新节点) | 日志反复 pod sandbox not found, retrying | 耐心等待离线镜像导入完成,参考 k8s-issues/rke2-master-join-notready-image-import-delay.md |
| CNI 未就绪 | node 上无 calico/canal Pod | 查 CNI Pod 日志、镜像是否拉取成功 |
| 镜像拉取失败 | ImagePullBackOff | 检查 registries.yaml、Harbor 可达性,参考 k8s-issues/rke2-ingress-nginx-controller-ContainerCreating.md |
| 节点证书过期 | kubelet 日志证书错误 | 重启服务触发重新签发,或 rke2 certificate rotate |
| 磁盘压力 | DiskPressure 条件 | 清理镜像 rke2 crictl rmi --prune、清理日志 |
10.4 证书过期
现象:kubectl 报 x509: certificate has expired,kubelet 无法连接 apiserver。
bash
# 确认过期时间
openssl x509 -in /var/lib/rancher/rke2/server/tls/client-admin.crt -noout -enddate
# 轮换(每台 server)
systemctl stop rke2-server
rke2 certificate rotate
systemctl start rke2-server
# agent 节点
systemctl restart rke2-agent10.5 etcd 健康问题
bash
# 成员状态
ETCDCTL_API=3 kubectl -n kube-system exec -it etcd-<node> -- etcdctl \
--cacert=/var/lib/rancher/rke2/server/tls/etcd/server-ca.crt \
--cert=/var/lib/rancher/rke2/server/tls/etcd/client.crt \
--key=/var/lib/rancher/rke2/server/tls/etcd/client.key \
--endpoints=https://127.0.0.1:2379 endpoint status --cluster -w table
# 关注:DB SIZE、RAFT TERM 是否一致、IS LEADER
# 碎片整理(DB 膨胀时)
... etcdctl defrag --cluster
# 告警检查
... etcdctl alarm listNOSPACE 告警:etcd 达到 quota(默认 2GB)→ 先 compact + defrag,或调大 quota-backend-bytes。
10.6 加入失败:防火墙端口清单
RKE2 节点间所需端口(firewalld/iptables 必须放行):
| 端口 | 协议 | 方向 | 用途 |
|---|---|---|---|
| 9345 | TCP | agent/server → server | RKE2 supervisor/注册 |
| 6443 | TCP | 所有 → server | kube-apiserver |
| 10250 | TCP | server ↔ agent | kubelet API(metrics/logs/exec) |
| 2379 | TCP | server ↔ server | etcd client |
| 2380 | TCP | server ↔ server | etcd peer |
| 2381 | TCP | server | etcd metrics |
| 8472 | UDP | 所有节点间 | Canal/Flannel VXLAN |
| 51820 | UDP | 所有节点间 | WireGuard(Calico/Cilium 加密) |
| 179 | TCP | 所有节点间 | Calico BGP |
| 9099 | TCP | 节点本机 | Calico 健康检查 |
| 5001/5473 | TCP | 节点间 | 嵌入式 registry/Spegel、Calico Typha |
bash
# firewalld 放行示例(Rocky 9)
firewall-cmd --permanent --add-port={9345,6443,10250,2379,2380,2381}/tcp
firewall-cmd --permanent --add-port={8472,51820}/udp
firewall-cmd --reload
# iptables 快速验证:先临时放开判断是否为防火墙问题
iptables -I INPUT -j ACCEPT # 测试用,验证后务必恢复策略真实案例:
k8s-issues/rke2-master-join-fails-iptables-firewall-blocking.md完整记录了"9345 no route to host → iptables 默认 DROP → 放行端口后成功加入"的排查全过程。
10.7 containerd / crictl 排查
bash
# RKE2 的 containerd socket(不是默认的 /run/containerd/containerd.sock!)
rke2 crictl ps -a # 包装命令自动指定 socket
# 手动方式
export CONTAINER_RUNTIME_ENDPOINT=unix:///run/k3s/containerd/containerd.sock
crictl ps
# 镜像列表与清理
rke2 crictl images
rke2 crictl rmi --prune # 清理无用镜像
# 查看容器日志(静态 Pod 故障时 kubectl 不可用,靠这个)
rke2 crictl logs <container-id>
# containerd 命名空间
rke2 ctr namespaces ls # k8s.io
rke2 ctr -n k8s.io containers ls10.8 kubelet 证书与 token 问题
| 现象 | 原因 | 解决 |
|---|---|---|
Unauthorized (apiserver 日志) | 节点 token 失效/被轮换 | 用 server 上当前 node-token 更新 agent 配置并重启 |
kubelet 报 certificate signed by unknown authority | CA 被重建后 agent 未更新 | 删除 /var/lib/rancher/rke2/agent/ 下 kubelet 证书与 client kubeconfig,重启 agent 重新引导 |
| 节点重复注册/名字冲突 | node-name 变化 | kubectl delete node <旧名>,保持 node-name 稳定 |
10.9 日志位置速查
| 内容 | 位置 |
|---|---|
| rke2-server/agent 主日志 | journalctl -u rke2-server / -u rke2-agent |
| Pod 标准输出 | /var/log/pods/<namespace>_<pod>_<uid>/ |
| 审计日志 | /var/lib/rancher/rke2/server/logs/audit.log(需启用) |
| 系统日志 | RHEL/Rocky:/var/log/messages;Ubuntu:/var/log/syslog |
| 静态 Pod 容器日志 | rke2 crictl logs 或 /var/log/pods/kube-system_... |
| 镜像导入/启动阶段 | journalctl -u rke2-server 中的 importing images 段 |
10.10 通用排障决策树
集群异常
├─ kubectl 不可用?
│ ├─ apiserver 不通 → 检查 6443、rke2-server 状态、证书
│ └─ etcd 报错 → endpoint status → quorum? → cluster-reset
├─ 节点 NotReady?
│ ├─ 新节点 → 等镜像导入(crictl images 观察)
│ ├─ CNI Pod 异常 → describe pod / 镜像拉取
│ └─ kubelet 异常 → journalctl -u rke2-agent
├─ Pod 异常?
│ ├─ ImagePullBackOff → registries.yaml / Harbor
│ ├─ ContainerCreating → CNI、挂载、镜像
│ └─ CrashLoopBackOff → logs / describe events
└─ 网络不通?
├─ Pod 间不通 → CNI、8472/51820 端口、NetworkPolicy
└─ Service 不通 → kube-proxy(ipvsadm/iptables)、endpoints第 11 章 常见面试题(综合)
RKE2 与 RKE1、k3s 的核心区别是什么? RKE2 使用 containerd + 静态 Pod 控制平面,内置 CIS/FIPS 安全能力;RKE1 依赖 Docker;k3s 是裁剪版单二进制面向边缘。
RKE2 控制平面组件是如何运行的?如何查看它们? 以静态 Pod 形式由 kubelet 管理,清单在
/var/lib/rancher/rke2/agent/pod-manifests/,用rke2 crictl ps或kubectl -n kube-system get pods查看。RKE2 的 9345 端口是干什么的?与 6443 有什么区别? 9345 是 supervisor/注册端口(节点加入、CA 分发、引导数据),6443 是 Kubernetes API。新节点先连 9345 验证 token 拿 CA,再与 6443 建立正式通信。
HA 场景下 agent 的 server 地址应该填什么?为什么? 固定注册地址(VIP/LB),而非某台 server 的 IP;否则该 server 宕机后新节点无法加入、kubectl 不可达。
tls-san 忘记配置 VIP,事后如何补救? 在所有 server 的 config.yaml 补加 tls-san,逐台重启 rke2-server 触发 apiserver 证书重签;旧 kubeconfig 需重新分发。
registries.yaml 与 system-default-registry 的区别? 前者作用于全部镜像的仓库访问(mirror/auth/TLS);后者只把 RKE2 系统组件镜像的前缀改为私有仓库。离线环境两者配合。
RKE2 如何做 etcd 备份与恢复?
rke2 etcd-snapshot save/list/prune+ 定时 cron + S3;恢复用rke2 server --cluster-reset --cluster-reset-restore-path=...,其余 server 清 etcd 数据后重新加入。etcd quorum 丢失如何恢复? 选数据最新节点
--cluster-reset重置为单成员集群拉起,其余节点删除/var/lib/rancher/rke2/server/db/etcd再加入。参见k8s-issues/rke2-disaster-recovery-control-plane-quorum-loss.md。如何修改内置 ingress-nginx 的参数?直接改 manifests 文件可以吗? 用 HelmChartConfig CRD(kube-system 命名空间、与 HelmChart 同名);直接改
/var/lib/rancher/rke2/server/manifests/会被覆盖。RKE2 升级的正确顺序与注意事项? 快照 → 逐台 server → 逐台 agent;不可跨 K8s 小版本;离线环境提前准备新版本 tar 包;可用 system-upgrade-controller 自动化。
证书有效期多久?如何轮换? 默认 1 年;
systemctl stop rke2-server && rke2 certificate rotate && systemctl start rke2-server,agent 重启即重新签发。新增 server 报 critical configuration value mismatch 是什么原因? 新节点 config.yaml 中 cluster-cidr/service-cidr/cni/disable 等与既有集群不一致,必须完全对齐。参见
k8s-issues/rke2-master-join-fails-critical-configuration-mismatch.md。RKE2 默认容器运行时 socket 在哪里?为什么 crictl 直接连不上?
/run/k3s/containerd/containerd.sock(RKE2 与 k3s 共用路径),不是 containerd 默认路径;用rke2 crictl包装命令或设置CONTAINER_RUNTIME_ENDPOINT。CIS profile 启用前后的准备工作? 创建 etcd 用户、配置内核参数(panic/overcommit)、评估 Pod Security 对存量 workload 的影响。
节点维护的标准流程?
kubectl drain --ignore-daemonsets --delete-emptydir-data→ 维护 →kubectl uncordon;下线节点还需kubectl delete node+rke2-uninstall.sh。
附录 A 本仓库相关参考资料索引
| 资料 | 内容 |
|---|---|
rke2/README.md | RKE2 v1.35.6 完整部署文档(离线源 + Harbor) |
rke2/install-server.sh / rke2/install-agent.sh | 自动化安装脚本 |
rke2/server-config.yaml / rke2/agent-config.yaml | 真实配置样例 |
rke2/registries.yaml | Harbor HTTP 仓库配置样例 |
k8s-issues/rke2-master-join-fails-iptables-firewall-blocking.md | 防火墙导致 master 加入失败案例 |
k8s-issues/rke2-master-join-fails-critical-configuration-mismatch.md | 配置不一致导致加入失败案例 |
k8s-issues/rke2-master-join-notready-image-import-delay.md | 镜像导入耗时导致 NotReady 案例 |
k8s-issues/rke2-disaster-recovery-control-plane-quorum-loss.md | 三 control-plane 全挂后灾后恢复实录 |
k8s-issues/rke2-ingress-nginx-controller-ContainerCreating.md | ingress-nginx Pod 无法创建排查 |
k8s-issues/rke2-node-addition-operation-manual.md | 节点添加操作手册 |
附录 B 常用命令速查
bash
# 服务管理
systemctl enable rke2-server --now
journalctl -u rke2-server -f
# 集群访问
export KUBECONFIG=/etc/rancher/rke2/rke2.yaml
kubectl get nodes -o wide
# etcd
rke2 etcd-snapshot save --name snap-$(date +%F)
rke2 etcd-snapshot list
rke2 server --cluster-reset --cluster-reset-restore-path=<快照路径>
# 证书
rke2 certificate rotate
# 容器
rke2 crictl ps -a
rke2 crictl rmi --prune
# 卸载
rke2-killall.sh
rke2-uninstall.sh结语:RKE2 的学习曲线可以概括为"安装五分钟,精通三个月"。把本部分的环境亲手搭一遍(建议至少 3 server + 2 agent 的 HA 拓扑)、把每个故障案例复现一次,你对生产级 Kubernetes 发行版的理解将超过绝大多数面试者。下一部分我们将进入 K8s 辅助工具(Helm、Kustomize、Rancher、监控日志栈)的世界。