Kubernetes LoadBalancer服务集群内可访问,外部报502错误求助
从你给出的kubectl describe svc ui输出里,我一眼看到了一个核心问题——TargetPort字段显示为%!d(string=ui-port),这是典型的字符串格式化错误,说明你在定义Service的时候,可能用了字符串类型的变量来指定TargetPort,但Kubernetes对TargetPort的要求是:要么是整数型的端口号,要么是容器中定义的端口名称(字符串,但必须和容器Port的name字段完全匹配)。
结合你的Pod描述,容器只暴露了80端口且没有指定端口名称,咱们一步步来排查修复:
1. 先修复Service的TargetPort配置
首先检查你的Service YAML定义,找到TargetPort的配置项。如果是用模板变量渲染的,确保变量解析后是正确的数值(比如80),或者直接硬编码成80(因为容器暴露的就是80端口)。修改后的Service示例如下:
apiVersion: v1 kind: Service metadata: name: ui namespace: default annotations: service.beta.kubernetes.io/aws-load-balancer-ssl-cert: arn:aws:acm:eu-west-1:somecertid spec: type: LoadBalancer selector: els-pod: ui ports: - name: http port: 80 targetPort: 80 # 直接指定容器暴露的端口号 protocol: TCP - name: https port: 443 targetPort: 80 # 注意这里你当前配置是把443转发到80,确认是否符合你的业务预期 protocol: TCP externalTrafficPolicy: Cluster
应用修改后的配置:
kubectl apply -f your-service-definition.yaml
2. 验证Service的转发配置是否正常
修复后重新查看Service状态:
kubectl describe svc ui
确认TargetPort字段不再出现%!d(string=ui-port)的错误,Endpoints显示正确的Pod IP和端口(比如10.42.179.14:80)。
接下来在集群节点上直接访问NodePort测试:
curl localhost:30854 # 对应http的NodePort curl localhost:31404 # 对应https的NodePort
如果这两个请求能正常返回内容,说明Service到Pod的转发链路没问题,问题可能出在AWS负载均衡器的层面。
3. 检查AWS负载均衡器的配置细节
因为你用了AWS ACM证书,咱们得确认负载均衡器的配置是否正确:
- 登录AWS控制台,找到对应的负载均衡器,检查监听规则:80端口是否转发到NodePort 30854,443端口是否转发到NodePort 31404,并且SSL证书关联正确。
- 查看负载均衡器的目标组健康检查:确认健康检查的路径(比如
/)是否正确,Pod是否能通过健康检查。如果健康检查失败,负载均衡器会直接返回502,因为它认为后端目标不可用。
另外,你的Service设置了External Traffic Policy: Cluster,流量会被转发到集群内任意节点的NodePort再转发到Pod。可以检查节点上的iptables规则,确认转发是否正常:
iptables-save | grep 30854
应该能看到对应的DNAT规则,确保这些规则存在且正确。
4. 确认Pod本身的可用性
虽然集群内访问正常,但Pod的Restart Count是5,说明之前有过多次重启,建议查看Pod日志排查是否有应用层面的问题:
kubectl logs <pod_id> kubectl logs <pod_id> --previous # 查看上一次启动的日志
确认应用是否能正常处理请求,比如是否有端口监听异常、请求超时等问题。
内容的提问来源于stack exchange,提问作者pkaramol




