如何配置通过HAProxy虚拟IP访问Kubernetes集群
看起来你已经搭建好了高可用Kubernetes集群和HAProxy负载均衡,现在就差最后一步搞定通过VIP访问集群的问题了,我来一步步帮你梳理解决方案:
第一步:确认HAProxy的流量转发配置是否正确
首先得确保HAProxy确实能把VIP的6443端口流量转发到所有控制面节点的6443端口上。你可以检查HAProxy的配置文件(通常是/etc/haproxy/haproxy.cfg),确保包含类似下面的配置段:
frontend k8s-api bind <你的HAProxy VIP>:6443 mode tcp option tcplog default_backend k8s-api-servers backend k8s-api-servers mode tcp option tcplog option tcp-check balance roundrobin # 替换成你的5个控制面节点IP和端口 server cp1 <控制面节点1IP>:6443 check fall 3 rise 2 server cp2 <控制面节点2IP>:6443 check fall 3 rise 2 server cp3 <控制面节点3IP>:6443 check fall 3 rise 2 server cp4 <控制面节点4IP>:6443 check fall 3 rise 2 server cp5 <控制面节点5IP>:6443 check fall 3 rise 2
这里用TCP模式是因为Kubernetes API是HTTPS协议,HAProxy只需要做四层转发即可,不需要解析HTTPS内容。同时启用
tcp-check可以让HAProxy自动剔除故障的控制面节点。
配置修改后,重启HAProxy服务:systemctl restart haproxy,然后可以用telnet <你的HAProxy VIP> 6443测试端口是否能通,或者查看HAProxy的统计页面(如果启用了的话)确认后端节点状态正常。
第二步:解决API Server证书的SAN问题
你提到修改kubeconfig的endpoint后证书有问题,这是因为Kubernetes API Server的默认证书里没有包含HAProxy的VIP作为Subject Alternative Name(SAN)。Kubernetes客户端(比如kubectl)会验证API Server证书的SAN是否匹配访问的地址,所以必须把VIP添加到API Server的证书SAN中。
如果你是用kubeadm部署的集群,操作步骤如下:
- 在任意控制面节点上,先备份API Server的原有证书:
cp /etc/kubernetes/pki/apiserver.crt /etc/kubernetes/pki/apiserver.crt.bak cp /etc/kubernetes/pki/apiserver.key /etc/kubernetes/pki/apiserver.key.bak - 创建或修改kubeadm的配置文件(比如
/etc/kubernetes/kubeadm-config.yaml),添加VIP到SAN列表中:apiVersion: kubeadm.k8s.io/v1beta3 kind: ClusterConfiguration kubernetesVersion: v1.28.0 # 替换成你的集群实际版本 apiServer: certSANs: - "localhost" - "127.0.0.1" - "<控制面节点1IP>" - "<控制面节点2IP>" # 加上你的HAProxy VIP - "<你的HAProxy VIP>" # 如果有绑定的域名,也可以一起加上 - "k8s-api.yourdomain.com" - 重新生成API Server证书:
kubeadm alpha certs renew apiserver --config /etc/kubernetes/kubeadm-config.yaml - 重启kube-apiserver Pod,让新证书生效:
kubectl delete pod -n kube-system -l component=kube-apiserver - 验证证书是否包含VIP:
输出里应该能看到你的VIP地址。openssl x509 -in /etc/kubernetes/pki/apiserver.crt -text -noout | grep -A 1 "Subject Alternative Name"
第三步:修改kubeconfig文件并测试访问
现在你只需要修改本地的kubeconfig文件(比如你复制的admin.conf),将API Server的地址替换成HAProxy的VIP即可:
- 打开kubeconfig文件,找到
clusters部分,把server字段改成https://<你的HAProxy VIP>:6443:clusters: - cluster: certificate-authority-data: <原CA证书内容> server: https://<你的HAProxy VIP>:6443 # 修改这里的地址 name: kubernetes - 保存文件后,测试是否能正常访问集群:
如果能正常返回节点列表,说明配置成功了!kubectl --kubeconfig=admin.conf get nodes
注意:你不需要把任何Kubernetes证书复制到HAProxy节点,HAProxy只是做流量转发,证书验证是在客户端(kubectl)和API Server之间完成的,只要API Server证书包含VIP,且客户端kubeconfig里的CA证书正确,就能正常通信。
常见问题排查
- 如果测试时提示证书验证失败,先确认API Server证书的SAN里确实包含VIP,再检查kubeconfig里的CA证书是否和集群的CA证书一致。
- 如果HAProxy转发失败,查看HAProxy的日志(
journalctl -u haproxy),检查后端节点是否能正常连通,或者是否有防火墙规则阻止了6443端口的流量。
备注:内容来源于stack exchange,提问作者Root Loop

