Kubernetes集群跨Pod应用内部API调用配置及报错排查
问题背景
现有Kubernetes集群部署两套工作负载:
ui-service-app、user-service-app两个Deployment,分别对应ui-service-svc、user-service-svc两个ClusterIP类型Service暴露服务- 配置了Nginx Ingress实现集群外部访问,Ingress规则中
/user路径前缀转发到user服务,其余路径默认转发到ui服务
需求是从ui-service-app侧发起对user-service-app的API调用,当前使用Ingress IP加/user路径调用,尝试直接改请求地址为http://user-service-svc时报错。
现有集群资源配置如下:
apiVersion: apps/v1 kind: Deployment metadata: name: user-service-app labels: app: user-service-app spec: replicas: 1 selector: matchLabels: app: user-service-app template: metadata: labels: app: user-service-app spec: containers: - name: user-service-app image: <MY-IMAGE-URL> imagePullPolicy: Always ports: - containerPort: 3000 livenessProbe: httpGet: path: /ping port: 3000 readinessProbe: httpGet: path: /ping port: 3000 --- apiVersion: "v1" kind: "Service" metadata: name: "user-service-svc" namespace: "default" labels: app: "user-service-app" spec: type: "ClusterIP" selector: app: "user-service-app" ports: - protocol: "TCP" port: 80 targetPort: 3000 --- apiVersion: apps/v1 kind: Deployment metadata: name: ui-service-app labels: app: ui-service-app spec: replicas: 1 selector: matchLabels: app: ui-service-app template: metadata: labels: app: ui-service-app spec: containers: - name: ui-service-app image: <MY-IMAGE-URL> imagePullPolicy: Always ports: - containerPort: 3000 --- apiVersion: "v1" kind: "Service" metadata: name: "ui-service-svc" namespace: "default" labels: app: "ui-service-app" spec: type: "ClusterIP" selector: app: "ui-service-app" ports: - protocol: "TCP" port: 80 targetPort: 3000 --- apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: awesome-ingress annotations: nginx.ingress.kubernetes.io/rewrite-target: /$2 spec: ingressClassName: nginx defaultBackend: service: name: ui-service-svc port: number: 80 rules: - http: paths: - path: /login pathType: Prefix backend: service: name: ui-service-svc port: number: 80 - path: /user(/|$)(.*) pathType: Prefix backend: service: name: user-service-svc port: number: 80
报错根因
直接在React代码中写http://user-service-svc发起请求报错的核心原因:
React是运行在终端用户浏览器中的前端代码,不是在ui-service-app Pod内部执行。ClusterIP类型的Service以及对应的内部域名user-service-svc仅在Kubernetes集群内部网络可解析、可访问,用户浏览器处于集群外部,自然无法访问这个内部地址。
正确实现方式
根据代码运行位置的不同,分两种场景处理:
场景1:Pod内部后端代码之间调用
如果是运行在ui-service-app容器内的后端服务(比如Node/Java/Go写的服务端接口)需要调用user-service,直接走集群内Service访问即可,不需要经过Ingress,性能和稳定性更高:
- 同命名空间下(你的两个服务都在default命名空间),直接用Service名访问:请求地址写
http://user-service-svc/<实际接口路径>即可,Service的80端口会自动转发到user-service-app容器的3000端口 - 跨命名空间访问时使用全限定域名:格式为
<service-name>.<namespace>.svc.cluster.local,对应你的服务地址为http://user-service-svc.default.svc.cluster.local
可以进入任意集群内Pod执行curl命令验证连通性:
curl http://user-service-svc/ping
正常会返回user服务的健康检查响应。
场景2:前端React代码调用user服务
前端代码运行在用户浏览器,属于集群外访问,不能直接使用集群内Service地址,有两种成熟方案:
- 方案一(推荐):使用相对路径发起请求,前端代码中请求地址写
/user/<实际接口路径>即可,不需要写死域名或IP。浏览器会自动将请求发送到当前访问ui服务的域名/IP下,由你已经配置好的Ingress规则匹配/user前缀,转发到user-service-svc,同时Ingress已经配置了rewrite规则,会自动把路径前缀/user去掉后转发给后端user服务,和你之前用Ingress IP访问的逻辑一致,适配任意部署环境。 - 方案二:给user-service单独配置一个公网可解析的Ingress域名,前端代码中写死这个对外域名发起请求,本质还是走Ingress流量入口,无法绕过Ingress直接访问集群内Service。
内容的提问来源于stack exchange,提问作者Yashvardhan Nathawat
相关产品推荐
相关产品推荐

