Skip to content

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
2system/kube Reserved均未配置系统组件(sshd/journald/containerd)与 kubelet 组件和业务 Pod 裸抢资源
3CP 节点隔离CP=etcd+control-plane+worker 混跑(4C/7.5G)031 内存已 61%,业务突发可拖垮 apiserver/etcd
4etcd 参数全默认(quota 2GiB、无显式压缩/碎片整理策略)长期运行 DB 膨胀触发 NOSPACE 告警
5etcd 快照异地备份默认 12h/留 5 份,仅存本机CP 磁盘损坏即丢快照
6apiserver 审计日志未开启无操作审计追溯
7容器日志限额默认 10Mi×5 已生效偏小,排障时历史不足;保持或微调即可
8Pod requests/limits17/26 业务 Pod 未设,无 LimitRange驱逐/调度无依据,单 Pod 可吃光节点
9journald 限额未配置系统日志理论上可占满系统盘

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 evictionHard

2. 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. 日志限额(三层)

配置建议值现状
容器 stdoutkubelet container-log-max-size/files50Mi × 3默认 10Mi × 5(已有限额,可调大便于排障)
apiserver 审计audit-log-max*(§4)100MB × 5 × 7天未开启
系统/journald/etc/systemd/journald.conf SystemMaxUse1G未限制

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,驱逐事件 (kubeleteviction_manager 指标、节点 MemoryPressure/DiskPressure 条件)会自然进入告警链路

8. 实施顺序

  1. Worker 逐台改 kubelet 配置(§1.2)→ 观察 1 天
  2. CP 逐台改 kubelet + etcd + apiserver 配置(§1.1/§2/§4)→ 每台间隔 ≥5 分钟,改前手动打一次 etcd 快照
  3. CP 隔离污点(§3 方案 A)→ 观察业务迁移
  4. LimitRange 逐 namespace(§6)
  5. 快照异地备份 cron(§2)、journald(§5)

每步回滚方式:恢复 config.yaml 原值再 restart 对应服务;污点用 kubectl taint nodes <n> node-role.kubernetes.io/control-plane:NoSchedule- 去除。