Kubernetes集群中controller manager与scheduler频繁重启的根因排查与优化实践
1. 问题现象与初步诊断
最近在维护一个Kubernetes生产集群时,发现控制平面的两个关键组件——controller manager和scheduler频繁重启。这个问题看似简单,但背后可能隐藏着严重的性能隐患。先来看下我们当时观察到的具体现象:
- 通过
kubectl get pods -n kube-system命令发现kube-controller-manager和kube-scheduler的RESTARTS计数不断增长 - 查看组件日志时发现大量"leader election lost"、"failed to renew lease"等错误信息
- 执行
kubectl get cs命令显示controller-manager和scheduler状态间歇性变为"Unknown"
这种情况在大型集群中尤为常见。我记得第一次遇到这个问题时,第一反应是去检查这两个组件的资源配额。但通过kubectl top pod查看资源使用情况后,发现CPU和内存消耗都在合理范围内。这说明问题可能不在组件本身,而是其依赖的服务出现了异常。
2. 深入排查etcd性能问题
2.1 etcd与控制器组件的关联机制
Controller manager和scheduler都需要通过API Server与etcd交互。具体来说:
- Controller manager需要持续监控集群状态变化(如Deployment副本数变化),这些信息都存储在etcd中
- Scheduler需要获取Node资源信息,这些数据同样来自etcd
- 两者都使用watch机制监听资源变更,而watch依赖于etcd的事件流
当etcd响应变慢时,这些组件的健康检查就会超时,导致kubelet认为组件异常而触发重启。这就像餐厅里服务员(controller manager/scheduler)需要不断向厨房(etcd)确认订单状态,如果厨房响应太慢,经理(kubelet)就会认为服务员出了问题。
2.2 关键指标分析与诊断
我们主要通过以下几个etcd指标来诊断性能问题:
wal_fsync_duration_seconds:WAL日志同步到磁盘的耗时
- 健康值:P99 < 10ms
- 问题值:持续 > 25ms
backend_commit_duration_seconds:事务提交耗时
- 健康值:P99 < 100ms
- 问题值:持续 > 250ms
etcd_disk_wal_fsync_duration_seconds_bucket:磁盘同步耗时分布
通过Prometheus查询这些指标,我们发现wal_fsync的P99值达到了58ms,明显高于正常水平。这提示可能存在磁盘I/O瓶颈。
3. 常见根因与解决方案
3.1 磁盘I/O性能不足
这是我们在生产环境遇到最多的情况。etcd对磁盘延迟极其敏感,特别是对于:
- 虚拟机使用的共享存储
- 机械硬盘(HDD)
- 没有隔离I/O的云盘
优化方案:
# 1. 使用高性能SSD并独占磁盘 fio --name=etcd-test --ioengine=libaio --rw=write --bs=4k \ --numjobs=1 --size=8G --runtime=60 --time_based --direct=1 # 2. 调整etcd数据目录mount参数(/etc/fstab) /dev/nvme0n1 /var/lib/etcd ext4 defaults,discard,noatime,nodiratime 0 0 # 3. 分离WAL目录与数据目录 # etcd.yaml ... - --wal-dir=/mnt/etcd-wal - --data-dir=/mnt/etcd-data ...3.2 网络延迟问题
跨可用区部署etcd节点时,网络延迟会导致:
- 心跳包传输延迟
- 提案提交超时
- 快照同步缓慢
优化方案:
# 调整etcd网络相关参数 # etcd.env ETCD_HEARTBEAT_INTERVAL=500 ETCD_ELECTION_TIMEOUT=2500 ETCD_SNAPSHOT_COUNT=10000 # 使用专用网络接口 ethtool -K eth0 tx off rx off tso off gso off3.3 资源竞争问题
当etcd与其他高负载服务(如数据库)混部时,会出现:
- CPU调度延迟
- 内存交换
- 磁盘I/O竞争
优化方案:
# 使用cgroups限制资源 mkdir /sys/fs/cgroup/cpu/etcd echo "100000" > /sys/fs/cgroup/cpu/etcd/cpu.cfs_period_us echo "80000" > /sys/fs/cgroup/cpu/etcd/cpu.cfs_quota_us echo "1234" > /sys/fs/cgroup/cpu/etcd/tasks # 调整进程优先级 renice -n -10 -p $(pgrep etcd)4. 参数调优实践
4.1 etcd核心参数优化
根据我们的经验,生产环境推荐以下参数配置:
| 参数 | 默认值 | 推荐值 | 说明 |
|---|---|---|---|
| heartbeat-interval | 100ms | 500ms | 适当降低心跳频率 |
| election-timeout | 1000ms | 2500ms | 超时时间需为心跳间隔的5倍 |
| snapshot-count | 10000 | 50000 | 减少快照频率 |
| max-request-bytes | 1.5MB | 10MB | 提高大请求处理能力 |
| quota-backend-bytes | 2GB | 8GB | 根据数据量调整 |
配置示例:
# /etc/etcd/etcd.conf heartbeat-interval: 500 election-timeout: 2500 snapshot-count: 50000 max-request-bytes: 10485760 quota-backend-bytes: 85899345924.2 Kubernetes组件调优
Controller manager和scheduler也需要相应调整:
# kube-controller-manager.yaml - --leader-elect=true - --leader-elect-lease-duration=30s - --leader-elect-renew-deadline=15s - --leader-elect-retry-period=5s - --node-monitor-period=5s - --node-monitor-grace-period=40s # kube-scheduler.yaml - --leader-elect=true - --leader-elect-lease-duration=30s - --leader-elect-renew-deadline=15s - --leader-elect-retry-period=5s5. 监控与告警配置
完善的监控体系能帮助我们提前发现问题。以下是我们使用的关键告警规则:
# prometheus-rules.yaml - alert: HighEtcdWalLatency expr: histogram_quantile(0.99, sum(rate(etcd_disk_wal_fsync_duration_seconds_bucket[5m])) by (le)) > 0.025 for: 5m labels: severity: critical annotations: summary: "etcd high WAL sync latency (instance {{ $labels.instance }})" description: "etcd is taking {{ $value }}s to sync WAL files" - alert: EtcdLeaderChanges expr: rate(etcd_server_leader_changes_seen_total[1h]) > 3 for: 10m labels: severity: warning annotations: summary: "etcd frequent leader changes (instance {{ $labels.instance }})" description: "etcd cluster is unstable with {{ $value }} leader changes per hour"6. 硬件选型建议
根据我们管理多个大型集群的经验,etcd服务器的硬件配置应满足:
小型集群(<50节点):
- CPU:4核+
- 内存:16GB+
- 存储:NVMe SSD 200GB+
中型集群(50-200节点):
- CPU:8核+
- 内存:32GB+
- 存储:NVMe SSD 500GB+
大型集群(>200节点):
- 专用etcd集群(3-5节点)
- 每节点:
- CPU:16核+
- 内存:64GB+
- 存储:NVMe SSD 1TB+
特别提醒:避免使用云平台的共享存储,实测发现其I/O延迟波动很大。我们曾在一个客户环境中将etcd迁移到本地NVMe SSD后,wal_fsync延迟从平均35ms降到了3ms。
7. 问题复现与测试方法
为了验证优化效果,我们设计了一套压力测试方案:
# 1. 安装etcd基准测试工具 go get go.etcd.io/etcd/tools/benchmark # 2. 运行写入测试 benchmark --endpoints=http://etcd1:2379,http://etcd2:2379,http://etcd3:2379 \ --target-latency=10ms --conns=100 --clients=1000 \ put --key-size=32 --val-size=256 --total=1000000 # 3. 监控关键指标 watch -n 1 'curl -s http://localhost:2379/metrics | grep -E "wal_fsync|backend_commit|leader_changes"' # 4. 模拟网络延迟(在测试环境) tc qdisc add dev eth0 root netem delay 50ms 20ms distribution normal这套测试方案帮助我们复现了生产环境的类似问题,验证了参数调整的有效性。在优化后的集群上,即使模拟50ms网络延迟,etcd仍能保持稳定运行。
