跳转至

SOP — 清理 haproxy backend 中已永久关闭的 master-02/03

变更主题:删去 haproxy 后端列表里指向已关闭虚机(192.168.31.11/.12)的两条记录 执行时间:2026-09-29 20:51(CST)|主机:k8s-master-01(192.168.31.10) 承接:k8s-restart-16443-selinux-20260929/SOP.md 第 8 章遗留项

目录

  1. 背景 2. 目标 3. 前置条件 4. 影响范围 5. 分步操作 6. 验证 7. 回滚 8. 风险说明

附录 A:备份与留档|附录 B:交付物清单

1. 背景

2026-09-16 集群按计划缩容为单控制面后(见 k8s_136_cluster_deploy/docs/SOP.md 5.10), k8s-master-02(.11) 与 k8s-master-03(.12) 两台虚机已关闭,并禁用 libvirt autostart (避免宿主机重启后自动拉起残缺控制面)。

但 /etc/haproxy/haproxy.cfg 的 backend 仍保留三条 server 记录,其中两条指向这两台已不存在的虚机:

backend k8s-api-backend
  option tcp-check
  server master-1 192.168.31.10:6443 check inter 2000 fall 2 rise 2
  server master-2 192.168.31.11:6443 check inter 2000 fall 2 rise 2   ← 目标不存在
  server master-3 192.168.31.12:6443 check inter 2000 fall 2 rise 2   ← 目标不存在

后果:haproxy 每 2 秒对两个不可达目标做一次健康检查,持续产生 Layer4 connection problem / is DOWN 告警,污染 journalctl -u haproxy 日志,也让运维难以从日志中辨认真正的后端异常。

2. 目标

  1. backend 只保留 master-1(192.168.31.10:6443);
  2. haproxy -c 配置校验通过;
  3. reload 生效后 haproxy 仍 active 且监听 0.0.0.0:16443;
  4. curl -sk https://192.168.31.8:16443/healthz 返回 ok;
  5. 日志中不再出现 master-2/3 相关告警。

3. 前置条件

项 要求
权限 本机 root 免密 ssh 到 k8s-master-01
现状 systemctl is-active haproxy 为 active(入口正常,见上一份 SOP)
前提确认 .11/.12 确实不可达(虚机已关闭,非临时故障)
工具 haproxy(-c 校验)、sed、systemctl
依赖 无。apiserver 与业务不受影响

4. 影响范围

  • 主机:仅 k8s-master-01。
  • 组件:haproxy 配置与进程。
  • 是否停服:否。采用 systemctl reload(unit 的 ExecReload 为 kill -USR2,平滑重载), 已建立的 API 连接不断开。
  • 业务影响:无。剩余后端 master-1 即当前唯一 apiserver,负载能力不变。
  • 窗口:以秒计,无停机窗口要求。

5. 分步操作

步骤 1:确认两条后端确实不可达

删除前必须确认不是"临时不可达"。若虚机只是暂时关机、日后计划恢复,应改走"标记 disabled"而非删除。

ping -c1 -W2 192.168.31.11; ping -c1 -W2 192.168.31.12
# 预期:均不可达(本环境两虚机已关闭且禁用 autostart)

步骤 2:备份原配置(原位 .bak)

坑:该文件含 haproxy stats 口令明文,不在项目目录留副本,备份保持在 /etc/haproxy/ 原位, 并在 backup/README.md 登记位置与用途(见附录 A)。

TS=$(date +%Y%m%d-%H%M%S)
ssh root@192.168.31.10 "cp -a /etc/haproxy/haproxy.cfg /etc/haproxy/haproxy.cfg.bak.$TS"
# 实测生成:/etc/haproxy/haproxy.cfg.bak.20260929-205100(585 字节,变更前版本)

步骤 3:删除 master-2 / master-3 两条记录

ssh root@192.168.31.10 "sed -i '/^  server master-[23] /d' /etc/haproxy/haproxy.cfg"
ssh root@192.168.31.10 "grep -nE 'backend|server' /etc/haproxy/haproxy.cfg"
# 预期:仅剩 server master-1 192.168.31.10:6443 ...

失败判断:若 grep 仍能看到 master-2/3 → 匹配模式与实际缩进不符,先恢复备份再核对原文重做。

步骤 4:配置校验

reload 前先校验,避免用坏配置打断入口。

ssh root@192.168.31.10 "haproxy -c -f /etc/haproxy/haproxy.cfg -f /etc/haproxy/conf.d"
# 预期:Configuration file is valid(Warnings 为日志格式告警,与本次无关)

步骤 5:平滑重载

ssh root@192.168.31.10 "systemctl reload haproxy && sleep 2 && systemctl is-active haproxy"
ssh root@192.168.31.10 "ss -lntp | grep 16443"
# 预期:active;0.0.0.0:16443 LISTEN

6. 验证

# 1) 仅剩 master-1,且无 master-2/3 告警
ssh root@192.168.31.10 "journalctl -u haproxy --since '-3min' --no-pager -l | grep -E 'UP|DOWN|Reloaded'"
# 实测:Reloaded HAProxy Load Balancer + Loading success;无 DOWN
# 2) 入口健康
ssh root@192.168.31.10 "curl -sk --max-time 6 https://192.168.31.8:16443/healthz"     # 预期:ok
# 3) 集群可见
kubectl get nodes                                                                      # 预期:4 节点 Ready

实测结果:以上三项全部通过;配置由 585 字节缩为 449 字节,reload 后 haproxy 仍 active 并监听 16443。

7. 回滚

ssh root@192.168.31.10 "cp -a /etc/haproxy/haproxy.cfg.bak.20260929-205100 /etc/haproxy/haproxy.cfg"
ssh root@192.168.31.10 "haproxy -c -f /etc/haproxy/haproxy.cfg -f /etc/haproxy/conf.d && systemctl reload haproxy"

回滚后验证:配置恢复为 585 字节、含三条 server 记录;haproxy active、16443 监听正常。

备份存放位置:k8s-master-01:/etc/haproxy/haproxy.cfg.bak.20260929-205100(原位,含口令,不落项目目录); 对应的远端 haproxy.cfg 变更前快照已在本 SOP 第 1 章写明内容结构。台账见本主题 backup/README.md。

8. 风险说明

风险 说明 缓解
日后扩回 3 控制面时需重新添加后端 本次删除后,扩回需补 master-2/3 两条记录 扩回流程本就由部署工程重跑生成配置(k8s_136_cluster_deploy/docs/RUNBOOK.md 第 5 章),手工配置被覆盖,不构成额外负担
误删有效后端 若 .11/.12 其实只是临时关机,删除会削弱冗余 步骤 1 先确认不可达;备份可一键回滚
备份含明文口令 .bak 文件含 stats auth 口令 保持在 /etc/haproxy/(root 600 权限目录),不复制到项目目录,不在文档中记录口令内容
配置与工程定义漂移 手工改动未同步回 deploy.yaml 模板 本次属"与现状对齐"的清理;若部署工程会重写该文件,重跑后仍会带出 master-2/3——待确认项(见附录 B)

附录 A:备份与留档

  • 原位备份:k8s-master-01:/etc/haproxy/haproxy.cfg.bak.20260929-205100
  • 未在项目目录留副本的原因:文件含 stats 口令明文(stats auth),按凭据管理约定不落交付物目录
  • 登记位置:k8s-followup-20260929/backup/README.md

附录 B:交付物清单与待确认项

文件 内容
SOP.md 本文件:backend 清理的实施、验证与回滚
20260929-K8s全节点-SELinux-AVC巡检报告.md 同批执行的只读巡检结论
backup/README.md 备份台账(登记远程原位备份)

已确认(2026-09-29 20:54 复查工程源码):k8s_136_cluster_deploy/deployer.py 的 _render_haproxy_cfg() 按 config/deploy.yaml 中全部 role=master 节点(3 台)渲染后端列表; 写入函数 _write() 的语义为「哈希一致跳过,不一致先备份再覆盖」。故:

  • 重跑部署工程会把本 SOP 删除的 master-2/3 两条后端写回,本次清理属临时性;
  • 缩容/扩回工具 control_plane_scale.py 不写该文件(其注释声明"保留后端列表"是设计意图),不受影响。

决策(用户确认):保持本次清理现状,不做工程侧收敛(不在 _render_haproxy_cfg 中增加"只渲染启用 master"的逻辑)。 重跑工程后如再需消除噪音,按本 SOP 步骤 3 重做一次即可。


来源:/home/rain/Documents/k8s_ins/k8s-followup-20260929/SOP.md | 最后更新:2026-09-29 20:54(由 build/sync.py 同步,请勿在站点侧修改)