主题
RKE2 集群配置优化清单(3 CP + 3 Worker)
基于 2026-08-01 对生产集群(RKE2 v1.35.6+rke2r1,sza122023/24/31 为 CP,sza122028/29/30 为 Worker)的实体检。 除标注「可直接 kubectl 执行」的项外,均需修改节点
/etc/rancher/rke2/config.yaml后重启服务生效。
0. 体检结论(问题清单)
| # | 检查项 | 现状 | 风险 |
|---|---|---|---|
| 1 | 内存硬驱逐 | 未配置(只有 nodefs/imagefs <5%) | 内存耗尽时无优雅驱逐,直接 OOM 杀进程、节点 NotReady |
| 2 | system/kube Reserved | 均未配置 | 系统组件(sshd/journald/containerd)与 kubelet 组件和业务 Pod 裸抢资源 |
| 3 | CP 节点隔离 | CP=etcd+control-plane+worker 混跑(4C/7.5G) | 031 内存已 61%,业务突发可拖垮 apiserver/etcd |
| 4 | etcd 参数 | 全默认(quota 2GiB、无显式压缩/碎片整理策略) | 长期运行 DB 膨胀触发 NOSPACE 告警 |
| 5 | etcd 快照异地备份 | 默认 12h/留 5 份,仅存本机 | CP 磁盘损坏即丢快照 |
| 6 | apiserver 审计日志 | 未开启 | 无操作审计追溯 |
| 7 | 容器日志限额 | 默认 10Mi×5 已生效 | 偏小,排障时历史不足;保持或微调即可 |
| 8 | Pod requests/limits | 17/26 业务 Pod 未设,无 LimitRange | 驱逐/调度无依据,单 Pod 可吃光节点 |
| 9 | journald 限额 | 未配置 | 系统日志理论上可占满系统盘 |
1. kubelet:资源预留 + 驱逐(最高优先级)
1.1 CP 节点(7.5G 内存,/etc/rancher/rke2/config.yaml)
yaml
kubelet-arg:
# 预留:系统守护进程 + k8s 组件,7.5G 节点各留 768Mi
- "system-reserved=cpu=500m,memory=768Mi"
- "kube-reserved=cpu=500m,memory=768Mi"
- "enforce-node-allocatable=pods,system-reserved,kube-reserved"
# 驱逐:内存硬驱逐必须补上(当前完全没有)
- "eviction-hard=memory.available<600Mi,nodefs.available<10%,imagefs.available<15%,nodefs.inodesFree<5%"
# 软驱逐提前 1.5Gi 开始腾挪,避免直接撞硬线
- "eviction-soft=memory.available<1Gi,nodefs.available<15%"
- "eviction-soft-grace-period=memory.available=1m30s,nodefs.available=2m"
- "eviction-minimum-reclaim=memory.available=300Mi,nodefs.available=2Gi,imagefs.available=3Gi"
# 日志限额(见 §5)
- "container-log-max-size=50Mi"
- "container-log-max-files=3"1.2 Worker 节点(31G 内存)
yaml
kubelet-arg:
- "system-reserved=cpu=500m,memory=1Gi"
- "kube-reserved=cpu=500m,memory=1Gi"
- "eviction-hard=memory.available<1Gi,nodefs.available<10%,imagefs.available<15%,nodefs.inodesFree<5%"
- "eviction-soft=memory.available<2Gi,nodefs.available<15%"
- "eviction-soft-grace-period=memory.available=2m,nodefs.available=2m"
- "eviction-minimum-reclaim=memory.available=512Mi,nodefs.available=3Gi,imagefs.available=5Gi"
- "container-log-max-size=50Mi"
- "container-log-max-files=3"要点说明:
enforce-node-allocatable加上system-reserved,kube-reserved才会真正 cgroup 限制系统组件, 否则预留只是调度计算值;代价是突发时系统服务也可能被限,生产谨慎——资源紧张的 7.5G CP 节点建议加。- 磁盘驱逐线从默认 5% 提到 10%/15%:100G 盘 5% 只剩 5G 才动,镜像+日志叠加时来不及; imagefs 比 nodefs 宽松是因为镜像 GC 回收快。
- inodes 驱逐
nodefs.inodesFree<5%:大量小文件(如日志碎片)会先耗尽 inode 而非容量。
生效方式(逐台滚动,CP 之间间隔 ≥5 分钟保 etcd 法定人数):
bash
sudo systemctl restart rke2-server # CP 节点
sudo systemctl restart rke2-agent # Worker 节点
# 验证
kubectl get --raw /api/v1/nodes/<节点>/proxy/configz | python3 -m json.tool | grep -A4 evictionHard2. etcd 优化
CP 节点 config.yaml 追加:
yaml
# DB 上限 2→4GiB(开了 rancher-monitoring 后对象/事件更多),配合压缩防 NOSPACE
etcd-arg:
- "quota-backend-bytes=4294967296"
- "auto-compaction-mode=periodic"
- "auto-compaction-retention=8h"
# 快照:6h 一次、留 10 份(默认 12h/5 份偏稀疏)
etcd-snapshot-schedule-cron: "0 */6 * * *"
etcd-snapshot-retention: 10快照异地备份(快照只在本机 /var/lib/rancher/rke2/server/db/snapshots,磁盘坏即丢): 任选一台 CP 加 crontab,把快照 rsync 到已有 NFS(192.168.122.1):
bash
# /etc/cron.d/etcd-snapshot-sync,每小时同步
0 * * * * root rsync -a --delete /var/lib/rancher/rke2/server/db/snapshots/ /mnt/nfs-etcd-backup/snapshots/碎片整理(可选):长期运行后 DB 实际占用远大于数据量。可部署每月一次的 etcdctl defrag CronJob(需同步 bitnamilegacy/etcd 镜像到内部 Harbor,挂主机 etcd 证书目录,hostNetwork 连 127.0.0.1:2379, 三节点轮流执行)。小集群快照+压缩已够用,DB 涨到 GiB 级再做。
磁盘 IO:etcd 对 fsync 延迟敏感,确认 CP 虚拟机磁盘落在 SSD、 宿主机 qemu 磁盘 cache 用 none/writeback 而非 writethrough。
3. CP 节点隔离(二选一)
CP 只有 4C/7.5G 还混跑业务,建议隔离让 etcd/apiserver 独占:
方案 A(推荐):打污点,业务全部漂到 3 个 Worker(8C/31G 充足):
bash
kubectl taint nodes sza122023.local sza122024.local sza122031.local \
node-role.kubernetes.io/control-plane=:NoSchedule打之前确认系统 DaemonSet 容忍(calico-node、node-exporter、cattle-agent 一般自带 toleration, kubectl get ds -A -o yaml | grep -B5 tolerations 抽查);若有个别业务必须留 CP,给 Pod 加对应 toleration。
方案 B(保守):不隔离,靠 §1.1 的 reserved + 驱逐兜底,CP 只跑轻量系统件(现状基本如此), 禁止往 CP 调度 MySQL/Redis 等有状态负载(用 nodeAffinity 显式排除)。
4. kube-apiserver 审计日志
CP config.yaml 追加(策略文件放主机 /etc/rancher/rke2/audit-policy.yaml):
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-maxsize=100" # 单文件 100MB 滚动
- "audit-log-maxbackup=5"
- "audit-log-maxage=7" # 留 7 天最小策略示例(只记敏感操作,避免量太大):
yaml
apiVersion: audit.k8s.io/v1
kind: Policy
rules:
- level: Metadata
verbs: ["create", "update", "patch", "delete"]
omitStages: ["ResponseStarted"]
- level: None # 高频只读不记
verbs: ["get", "list", "watch"]5. 日志限额(三层)
| 层 | 配置 | 建议值 | 现状 |
|---|---|---|---|
| 容器 stdout | kubelet container-log-max-size/files | 50Mi × 3 | 默认 10Mi × 5(已有限额,可调大便于排障) |
| apiserver 审计 | audit-log-max*(§4) | 100MB × 5 × 7天 | 未开启 |
| 系统/journald | /etc/systemd/journald.conf SystemMaxUse | 1G | 未限制 |
journald 生效:sudo systemctl restart systemd-journald(rke2 组件日志都走 journal, 不限制时长跑可能占系统盘数 GB)。
6. 工作负载治理(可直接 kubectl 执行)
17/26 业务 Pod 无 requests/limits。给每个业务 namespace 加默认 LimitRange 兜底:
yaml
apiVersion: v1
kind: LimitRange
metadata:
name: default-limits
namespace: <业务ns> # mysql/redis/k8sgpt 等逐个 apply
spec:
limits:
- type: Container
default: # 未写 limits 时注入
cpu: "1"
memory: 1Gi
defaultRequest: # 未写 requests 时注入
cpu: 100m
memory: 256Mi注意:已有显式 requests/limits 的 Pod 不受影响;MySQL/Redis 等有状态负载应继续显式配置, LimitRange 只兜底。配额收紧后再视情况加 ResourceQuota 防 namespace 总量失控。
7. 其他建议(低优先级)
- image GC:默认 85%/80% 对 100G 盘够用;CP 节点镜像少可降到 75%/70%
- NTP:确认 chrony 同步(etcd 对时钟偏移敏感,
chronyc tracking) - 内核/limits:沿用现有 Rocky 9.8 初始化脚本(已含 conntrack/tcp 参数)
- 监控:已有 rancher-monitoring + Alertmanager + K8sGPT,驱逐事件 (
kubelet的eviction_manager指标、节点 MemoryPressure/DiskPressure 条件)会自然进入告警链路
8. 实施顺序
- Worker 逐台改 kubelet 配置(§1.2)→ 观察 1 天
- CP 逐台改 kubelet + etcd + apiserver 配置(§1.1/§2/§4)→ 每台间隔 ≥5 分钟,改前手动打一次 etcd 快照
- CP 隔离污点(§3 方案 A)→ 观察业务迁移
- LimitRange 逐 namespace(§6)
- 快照异地备份 cron(§2)、journald(§5)
每步回滚方式:恢复 config.yaml 原值再 restart 对应服务;污点用 kubectl taint nodes <n> node-role.kubernetes.io/control-plane:NoSchedule- 去除。