如何从外部访问跨云服务商Linux节点的Kubernetes集群?
我有1个Master节点和2个Worker节点,不想使用托管式Kubernetes解决方案,服务器分布在不同云服务商(不确定是否有影响)。我需要访问Web应用,但不确定直接连接Pod还是使用负载均衡方案更合适。目前应用仅运行在一个节点上,但后续需要扩容,因此需要支持动态查找的方案。尚未尝试Ingress,不确定其是否有用。
曾尝试使用NodePort(因为当前仅运行一个副本)但未成功,且了解到NodePort存在安全风险。之后尝试使用MetalLB(由于未使用云负载均衡器),已分配<External-IP>(从两个Worker节点的IP范围中分配的私有IP),本以为可以通过集群内任意节点(例如Worker1访问Worker2)连接应用,但仍然无法连接。优先希望使用MetalLB,若不可行也可以退回NodePort方案。
我知道遗漏了某些配置,可能是iptables规则(未调整过,不清楚需要更新哪个链)或者Service配置错误。当前使用Flannel CNI作为容器网络接口,已安装tcpdump和arping工具,仅在承载负载均衡器的节点上arping可用,其他节点均无法正常使用。作为Kubernetes初学者,肯定存在配置错误,感觉无论是NodePort还是负载均衡方案都接近成功了。
最终目标:
从任意位置执行 curl http://<some-ip>:8000
参考资料:
- MetalLB相关教程(已更新为最新IPAddressPool CRD)
- Kubernetes官方NodePort文档
- 《The Kubernetes Book》及补充阅读材料
我的MetalLB配置:
apiVersion: metallb.io/v1beta1 kind: L2Advertisement metadata: name: dispatch namespace: metallb-system spec: ipAddressPools: - config
apiVersion: metallb.io/v1beta1 kind: IPAddressPool metadata: namespace: metallb-system name: config spec: addresses: - <worker1的IP范围> # 基于worker1的IP - <worker2的IP范围> # 基于worker2的IP
apiVersion: v1 kind: Service metadata: name: app-balancer spec: type: LoadBalancer ports: - name: app port: 8000 protocol: TCP targetPort: 8000 selector: app: my-app
一、MetalLB问题排查与修复
1. 修正IP地址池配置
MetalLB的L2模式要求分配的IP必须是集群节点所在网络中未被占用的空闲IP段,不能直接使用Worker节点自身的IP(节点已占用该IP)。例如如果Worker1是192.168.1.10、Worker2是192.168.1.11,可配置192.168.1.20-192.168.1.30这类未被使用的IP范围。
2. 验证MetalLB资源状态
执行以下命令检查资源是否正常关联:
kubectl get ipaddresspools -n metallb-system kubectl get l2advertisements -n metallb-system
确保config IPAddressPool状态为Ready,L2Advertisement的ipAddressPools字段确实关联了该Pool名称。
3. 兼容Flannel网络配置
Flannel默认配置可能影响MetalLB的L2广播,需开启hairpinMode:
编辑Flannel的ConfigMap:
kubectl edit cm kube-flannel-cfg -n kube-system
在net-conf.json中添加"hairpinMode": true,随后重启Flannel DaemonSet:
kubectl rollout restart ds kube-flannel-ds -n kube-system
4. 节点网络与iptables检查
- 所有节点防火墙需放行8000端口,以及MetalLB集群通信端口:7946/TCP/UDP、4789/UDP。
- 检查Kubernetes的iptables规则是否包含MetalLB Service条目:
iptables-save | grep app-balancer
若无相关规则,重启kubelet服务:
systemctl restart kubelet
5. 确认Service与Pod标签匹配
检查Service的selectorapp: my-app是否和Pod的标签完全一致:
kubectl get pods --show-labels kubectl describe service app-balancer
查看Service的Endpoints字段,若为空则说明标签不匹配,需修正Pod或Service的标签。
二、NodePort方案修复
如果MetalLB暂时无法解决,可先让NodePort正常运行:
1. 配置正确的NodePort Service
修改Service为NodePort类型:
apiVersion: v1 kind: Service metadata: name: app-nodeport spec: type: NodePort ports: - name: app port: 8000 protocol: TCP targetPort: 8000 nodePort: 30000 # 可选,指定30000-32767之间的端口 selector: app: my-app
2. 网络连通性检查
- 所有Worker节点防火墙放行指定的NodePort(如30000)。
- 确认Pod的8000端口正在监听:
kubectl exec <pod-name> -- netstat -tulpn | grep 8000
- 从集群内节点测试:
curl http://<worker-ip>:30000,若不通则检查kube-proxy状态:
kubectl get pods -n kube-system | grep kube-proxy kubectl logs <kube-proxy-pod-name> -n kube-system
三、Ingress的作用(后续扩容建议)
当后续应用扩容多副本后,Ingress可统一管理域名、路径转发、SSL证书等,比直接使用Service更灵活。不过Ingress需要搭配Ingress Controller(如nginx-ingress),可等Service正常运行后再部署。
内容的提问来源于stack exchange,提问作者enjoi4life411

