K8s 多 Master 重启:流程梳理与问题排查
·
K8s 多 Master 重启:流程梳理与问题排查
引言在 Kubernetes 集群中,多 Master 架构是保证高可用的核心设计。然而,当我们需要对多个 Master 节点进行重启(比如升级内核、修复证书、硬件维护等),如果操作不当,轻则导致集群短暂不可用,重则引发数据丢失或选举死锁。本文将从流程梳理到问题排查,为你揭开多 Master 重启的底层逻辑,并附上可运行的代码示例,帮助你安全度过重启期。## 一、多 Master 架构核心原理在理解重启流程前,必须掌握两个关键组件:- etcd:分布式键值存储,保存集群所有状态数据。多 Master 模式下,etcd 通常以 3 或 5 个节点构成 Raft 集群,保证数据一致性。- kube-apiserver:集群入口,负责处理 RESTful API 请求,并将状态写入 etcd。重启 Master 时,实际上是在重启 kube-apiserver、kube-controller-manager、kube-scheduler 以及 etcd 进程(如果 etcd 部署在 Master 上)。## 二、标准重启流程### 2.1 前置检查在重启任何 Master 之前,必须确认集群健康状况。以下是一个使用 Python 编写的检查脚本示例:python#!/usr/bin/env python3"""集群健康检查脚本用于在重启 Master 前验证 etcd 和 API Server 状态"""import subprocessimport jsonimport sysdef check_etcd_health(): """检查 etcd 集群健康状态""" try: # 使用 etcdctl 命令检查成员列表 result = subprocess.run( ["etcdctl", "member", "list", "--write-out=json"], capture_output=True, text=True, check=True ) members = json.loads(result.stdout)["members"] # 统计健康节点数 healthy_count = sum(1 for m in members if m["status"] == "started") total_count = len(members) print(f"etcd 成员总数: {total_count}, 健康节点数: {healthy_count}") # 检查是否存在 leader leader_check = subprocess.run( ["etcdctl", "endpoint", "status", "--write-out=json"], capture_output=True, text=True, check=True ) endpoints = json.loads(leader_check.stdout) leader_id = None for ep in endpoints: if ep["Status"]["leader"]: leader_id = ep["Status"]["leader"] break if leader_id is None: print("[WARNING] 未找到 etcd leader,集群可能不可用") return False # 健康条件:健康节点数 > 总节点数/2 if healthy_count > total_count / 2: print("[OK] etcd 集群健康") return True else: print("[ERROR] etcd 集群不健康,无法安全重启") return False except subprocess.CalledProcessError as e: print(f"检查失败: {e.stderr}") return Falsedef check_kube_api(): """检查 kube-apiserver 状态""" try: result = subprocess.run( ["kubectl", "get", "componentstatuses", "--no-headers", "-o", "custom-columns=NAME:.metadata.name,HEALTHY:.conditions[0].status"], capture_output=True, text=True, check=True ) print("API Server 组件状态:") print(result.stdout) # 解析输出,检查所有组件是否健康 for line in result.stdout.strip().split("\n"): if "True" not in line: print(f"[WARNING] 组件 {line.split()[0]} 不健康") return False return True except subprocess.CalledProcessError as e: print(f"API Server 检查失败: {e.stderr}") return Falseif __name__ == "__main__": print("===== 集群健康检查报告 =====") etcd_ok = check_etcd_health() api_ok = check_kube_api() if etcd_ok and api_ok: print("\n[PASS] 集群健康,可以安全重启 Master") else: print("\n[FAIL] 集群存在问题,请修复后再重启") sys.exit(1)### 2.2 重启顺序原则1. 先重启非 Leader 节点:优先重启不担任 etcd leader 的 Master 节点。可以通过 etcdctl endpoint status 查看 leader 地址。2. 逐个重启,间隔观察:每次只重启一个节点,等待该节点的 kube-apiserver 和 etcd 完全恢复后再进行下一个。3. 最后重启 Leader:Leader 节点重启后,etcd 会触发选举,此时需要确保其他节点已稳定运行。## 三、典型问题排查### 3.1 问题一:etcd 选举死锁现象:重启多个 Master 后,kube-apiserver 无法连接 etcd,集群完全不可用。原因:如果同时重启了超过半数的 etcd 节点,Raft 集群无法形成多数派,导致选举死锁。解决方案:使用 etcdctl 强制恢复。python#!/usr/bin/env python3"""etcd 恢复脚本当 etcd 集群因重启导致选举失败时使用"""import osimport subprocessimport jsondef recover_etcd(): """强制恢复 etcd 集群""" # 步骤1:在所有 etcd 节点上停止 etcd 服务 print("1. 停止所有节点的 etcd 服务") os.system("systemctl stop etcd") # 步骤2:从任意一个节点备份数据 print("2. 备份 etcd 数据") backup_dir = "/tmp/etcd_backup_" + str(int(time.time())) subprocess.run( ["etcdctl", "snapshot", "save", f"{backup_dir}/snapshot.db"], check=True ) # 步骤3:使用 --force-new-cluster 参数启动一个节点 print("3. 启动单节点集群") new_cluster_cmd = ( "etcd --name=node1 " "--data-dir=/var/lib/etcd " "--initial-cluster=node1=http://localhost:2380 " "--initial-cluster-token=etcd-cluster " "--force-new-cluster" ) # 实际生产中建议使用 systemd 或容器运行 subprocess.Popen(new_cluster_cmd.split()) # 步骤4:验证单节点运行 print("4. 验证单节点集群") subprocess.run(["etcdctl", "endpoint", "health", "--cluster"], check=True) # 步骤5:添加其他节点 print("5. 添加其他节点到集群") member_add_cmd = ( "etcdctl member add node2 " "--peer-urls=http://192.168.1.102:2380" ) subprocess.run(member_add_cmd.split(), check=True) print("恢复完成!请手动将其他节点加入集群")if __name__ == "__main__": import time recover_etcd()### 3.2 问题二:kube-apiserver 证书过期现象:重启后 kube-apiserver 启动失败,日志显示证书错误。排查命令:bash# 查看 API Server 日志journalctl -u kube-apiserver -n 100# 检查证书有效期openssl x509 -in /etc/kubernetes/pki/apiserver.crt -noout -text | grep "Not After"解决方案:重新生成证书并重启服务。注意在多 Master 环境中,证书需要在所有节点保持一致。## 四、最佳实践总结1. 灰度重启:使用 kubectl cordon 和 kubectl drain 先隔离节点,避免调度中断。2. 监控就绪:重启前确保监控系统(如 Prometheus)能正常检测集群状态。3. 回滚预案:准备快速回滚脚本,一旦发现问题可以立即恢复配置。4. 文档记录:每次重启后记录操作日志,方便后续排查。## 五、总结多 Master 重启不只是简单停止服务再启动,它涉及 etcd 的 Raft 协议、API Server 的无状态重启、以及集群组件的协调。通过本文介绍的流程梳理和问题排查方法,你可以:- 使用健康检查脚本前置验证集群状态- 遵循“非 Leader 优先,逐个重启”的原则- 遇到 etcd 选举死锁时,通过快照恢复与强制重建集群- 针对证书问题快速定位并修复记住,重启操作的黄金法则是:永远不要同时重启超过半数的 Master 节点。遵循这个原则,再配合本文提供的工具和思路,你的 Kubernetes 集群就能在维护中保持高可用。
更多推荐


所有评论(0)