不同Kind集群中应用跨集群通信问题排查
我在本地用Kind运行了两个Go服务:
- app1部署在一个Kind集群,功能是返回调用方IP
- app2部署在另一个Kind集群,需要调用app1获取自身出口IP
从本地机器直接调用任意集群内的服务都正常,但app2跨集群调用app1时总是失败(不管同命名空间还是不同命名空间都不行)。
调用场景与错误信息
调用app2的命令:curl http://localhost:30002/ip
返回错误:Get "http://app1.example.com:30001/ip": dial tcp 127.0.0.1:30001: connect: connection refused
app2调用app1的代码:
resp, err := http.Get("http://app1.example.com:30001/ip")
直接从本地调用app1(curl http://app1.example.com:30001/ip)完全正常,搞不懂为什么app2调用就不行。
配置详情
集群端口映射(Kind配置)
app1的集群YAML(仅端口与示例不同):
kind: Cluster apiVersion: kind.x-k8s.io/v1alpha4 nodes: - role: control-plane extraPortMappings: - containerPort: 30001 hostPort: 30001
app2的集群YAML:
kind: Cluster apiVersion: kind.x-k8s.io/v1alpha4 nodes: - role: control-plane extraPortMappings: - containerPort: 30002 hostPort: 30002
Service配置
app1的Service(仅targetPort和nodePort不同):
apiVersion: v1 kind: Service metadata: name: app1service spec: type: NodePort selector: app: app1 ports: - port: 6666 targetPort: 7777 nodePort: 30001
app2的Service:
apiVersion: v1 kind: Service metadata: name: app2service spec: type: NodePort selector: app: app2 ports: - port: 6666 targetPort: 8888 nodePort: 30002
Ingress配置(app1)
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: app1ingress spec: rules: - host: "app1.example.com" http: paths: - pathType: Prefix path: "/" backend: service: name: app1service port: number: 6666
注:从集群外调用app1必须指定30001端口,不指定的话会出现默认80端口连接拒绝的错误,所以代码里加了这个端口。
核心原因
app2所在的Kind集群容器里,app1.example.com解析到了127.0.0.1,但这个地址在app2的集群容器内指向自身的localhost,并非你的本地主机,因此无法连接到app1的30001端口。
本地机器能调用成功,是因为你在本地hosts里配置了app1.example.com指向127.0.0.1,且本地30001端口通过Kind的extraPortMappings映射到了app1集群的NodePort。但app2的集群容器内部没有这个hosts配置,就算有,127.0.0.1也指向容器自身,而非你的主机。
解决办法
方法1:使用本地主机实际IP访问
找到你本地主机的局域网IP(如192.168.x.x),修改app2的调用代码,将http://app1.example.com:30001/ip改为http://[你的本地IP]:30001/ip。
同时确保本地防火墙允许30001端口的入站连接,避免app2集群容器无法访问。
方法2:配置集群间DNS解析
- 在app2集群中给
app1.example.com配置自定义DNS记录,指向本地主机IP:- 编辑CoreDNS配置:
kubectl -n kube-system edit configmap coredns - 在
Corefile中添加hosts规则:hosts { 192.168.x.x app1.example.com fallthrough } - 重启CoreDNS Pod:
kubectl -n kube-system rollout restart deployment/coredns
- 编辑CoreDNS配置:
- 修改app1集群的端口映射,添加Ingress的80端口映射:
重新创建app1集群后,app2可直接调用extraPortMappings: - containerPort: 80 hostPort: 80http://app1.example.com/ip,无需指定端口。
方法3:将两个集群加入同一Docker网络
- 创建自定义Docker网络:
docker network create kind-shared - 修改两个集群的YAML,添加网络配置(以app1集群为例):
kind: Cluster apiVersion: kind.x-k8s.io/v1alpha4 networking: apiServerAddress: "0.0.0.0" podSubnet: "10.244.0.0/16" serviceSubnet: "10.96.0.0/12" nodes: - role: control-plane extraPortMappings: - containerPort: 30001 hostPort: 30001 - 创建集群时指定网络:
kind create cluster --name app1-cluster --config app1-cluster.yaml --network kind-shared
两个集群加入同一网络后,app2可直接调用app1集群的Service ClusterIP,无需依赖本地端口映射。
内容的提问来源于stack exchange,提问作者vbnm

