HAProxy 没监听 6443,端口不通、nc 报 Connection refused;
端口通了以后加入新控制平面节点报错:APIServer 证书 SAN 里没有负载均衡 IP
192.168.31.2,TLS 校验失败;后面给出的全套操作,就是修复证书缺少 LB IP 的完整流程,中间又遇到了 kubeadm 执行证书重生成时 CRI 多容器运行时冲突报错。
先看懂抓包 + HAProxy 排查日志(前半段)
1. tcpdump 抓包内容解读
plaintext
IP 192.168.31.6.xxx > aishitou(192.168.31.2).6443 Flags [R.]
[R.]= TCP Reset 重置包,收到连接直接断开;192.168.31.6 是新要加入的 Master 节点,主动发 SYN 去连 31.2:6443;
但 31.2 机器直接回 RST,拒绝所有连 6443 的请求。
2. 你在 192.168.31.2(aishitou,HAProxy LB 节点)排查
plaintext
sudo ss -tulpn | grep 6443
# 输出里只有 6433、8081 是haproxy监听,没有 6443
问题根源:haproxy.cfg 配置写错 / 漏了 6443 监听段,HAProxy 正常运行但根本没绑定 6443 端口。
nc -zv 192.168.31.2 6443→ Connection refused:端口无程序监听,内核直接回 RST,对应抓包大量 [R.] 包;你执行启停 haproxy、确认进程,最终修正配置后 ss 能看到
0.0.0.0:6443 LISTEN,nc 连通正常。
二、端口通了,但 kubeadm join 新 Master 报错核心原因
报错原文关键:
plaintext
tls: failed to verify certificate: x509: certificate is valid for 10.96.0.1, 192.168.31.19, not 192.168.31.2
原始集群初始化
kubeadm init时,只把原 Master 物理 IP 192.168.31.19、ServiceIP 10.96.0.1 写入 APIServer 证书的Subject Alternative Name(SAN);现在你通过 LB 地址
192.168.31.2访问 apiserver;TLS 握手时客户端(新节点 kubeadm)校验服务端证书:证书里没写 192.168.31.2,判定证书无效,直接拒绝加入集群。
简单类比:证书好比门牌号,只登记了 19 号房,现在你从 2 号门进来,系统不认这个地址,不让进门。
三、给出的整套修复操作分步解释
步骤 1:备份 + 删除旧 apiserver 证书
plaintext
sudo mkdir -p /etc/kubernetes/pki/backup
sudo cp apiserver.* 备份目录
sudo rm apiserver.crt apiserver.key
备份:防止改错证书集群彻底瘫痪;
删除旧公私钥:让 kubeadm 可以重新生成全新证书。
步骤 2:创建临时 kubeadm 配置,追加 LB IP 到 certSANs
yaml
apiVersion: kubeadm.k8s.io/v1beta3
kind: ClusterConfiguration
kubernetesVersion: stable-1.28
apiServer:
certSANs:
- "127.0.0.1"
- "10.96.0.1"
- "192.168.31.19"
- "192.168.31.2" # 关键:把负载均衡IP加入证书信任列表
certSANs 就是证书里允许访问 apiserver 的 IP / 域名清单,新增 LB 地址后,新证书会带上这个 IP。
步骤 3:执行命令重新生成 apiserver 证书(这里抛出新报错)
plaintext
sudo kubeadm init phase certs apiserver --config /tmp/apiserver-san.yaml
报错:
plaintext
Found multiple CRI endpoints on the host. Please define which one do you wish to use by setting the 'criSocket' field
unix:///var/run/containerd/containerd.sock, unix:///var/run/cri-dockerd.sock
你的 Master 机器同时装了 containerd + cri-dockerd 两套容器运行时;
kubeadm 不知道该连哪个 CRI,缺少
criSocket配置字段,命令执行中断;解决办法:临时 yaml 里补充
criSocket: unix:///var/run/containerd/containerd.sock。
步骤 4:重启 kube-apiserver 容器加载新证书
apiserver 是静态 Pod,证书文件变更后不会自动重载,必须重启容器:
crictl 列出正在运行的 kube-apiserver 容器;
crictl restart 重启容器;
openssl 命令校验证书内容,确认输出包含
192.168.31.2,证明修复成功。
步骤 5:重新生成集群加入凭证
kubeadm init phase upload-certs --upload-certs:把控制平面证书加密上传到集群 secret,新增 Master 节点需要这个密钥同步全部证书;kubeadm token create --print-join-command:生成新的集群加入命令(token 会过期,旧 token 失效要重建)。
步骤 6:新节点重新执行 join 命令
携带 4 个关键参数:
LB 地址
192.168.31.2:6443(统一接入入口);集群临时 token;
CA 证书 hash,校验根证书合法性;
--control-plane:代表这台节点也要成为 Master 控制平面;--certificate-key:同步集群所有控制平面证书。
四、核心原理通俗翻译
K8s APIServer TLS 证书校验机制
kubeadm 初始化集群时,会生成 apiserver 专用 TLS 证书,证书里会记录所有合法访问地址(SAN 列表)。客户端无论 kubectl、kubeadm、节点,连接 apiserver 时都会校验:你访问的 IP / 域名必须出现在证书 SAN 里,否则判定中间人攻击,直接断开连接。
搭建高可用集群引入 LB 后,LB IP 不在原始 SAN 列表,就会出现你遇到的 x509 证书校验失败。
kubeadm 证书管理逻辑
kubeadm 提供
init phase certs apiserver子命令,支持单独重建 apiserver 证书,无需重新初始化整个集群;通过自定义 ClusterConfiguration 配置修改 certSANs,就能给证书追加新增负载均衡 IP。多 Master 集群证书同步逻辑
加入新控制平面节点和普通 worker 节点不同:Master 需要完整一套集群 CA、etcd、apiserver 证书。
--certificate-key参数就是用来解密集群内加密存储的证书 secret,让新 Master 同步全部证书文件。HAProxy 6443 端口作用
多 Master 场景下每个节点都跑 apiserver,HAProxy 监听 6443 做四层 TCP 转发,对外提供统一接入点,所有节点、kubectl、新 Master 都只连 LB 地址,不用区分单个 MasterIP,实现故障自动切换。
K8s 多 Master 高可用集群
本文采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。
评论交流
欢迎留下你的想法