GKE basic-ingress 间歇性 returns 502 当后端 returns 404/422
GKE basic-ingress intermittently returns 502 when backend returns 404/422
我有一个入口为 GKE 上的两个微服务 运行ning 提供路由,当微服务 return 是 404/422 时,入口 return 是 502。
这是我的入口定义:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: basic-ingress
annotations:
kubernetes.io/ingress.global-static-ip-name: develop-static-ip
ingress.gcp.kubernetes.io/pre-shared-cert: dev-ssl-cert
spec:
rules:
- http:
paths:
- path: /*
backend:
serviceName: srv
servicePort: 80
- path: /c/*
backend:
serviceName: collection
servicePort: 80
- path: /w/*
backend:
serviceName: collection
servicePort: 80
我 运行 测试命中了 srv
后端,我希望得到 404 或 422 响应。当我直接点击 srv
后端(绕过入口)时,我已经验证该服务使用 404/422 正确响应。
当我通过入口发出相同的请求时,入口会间歇性地响应 502 而不是来自后端的 404/422。
如何让入口仅 return 来自后端的 404/422 响应?
下面是一些示例代码,用于演示我所看到的行为(预期状态为 404):
>>> for i in range(10):
resp = requests.get('https://<server>/a/v0.11/accounts/junk', cookies=<token>)
print(resp.status_code)
502
502
404
502
502
404
404
502
404
404
这里是从 pod 中的 python 提示发出的相同请求,即绕过入口:
>>> for i in range(10):
... resp = requests.get('http://0.0.0.0/a/v0.11/accounts/junk', cookies=<token>)
... print(resp.status_code)
...
404
404
404
404
404
404
404
404
404
404
这是 kubectl 命令的输出,用于证明负载均衡器设置正确(我从未从微服务获得 2xx/3xx 响应的 502):
$ kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
srv-799976fbcb-4dxs7 2/2 Running 0 19m 10.24.3.8 gke-develop-default-pool-ea507abc-43h7 <none> <none>
srv-799976fbcb-5lh9m 2/2 Running 0 19m 10.24.1.7 gke-develop-default-pool-ea507abc-q0j3 <none> <none>
srv-799976fbcb-5zvmv 2/2 Running 0 19m 10.24.2.9 gke-develop-default-pool-ea507abc-jjzg <none> <none>
collection-5d9f8586d8-4zngz 2/2 Running 0 19m 10.24.1.6 gke-develop-default-pool-ea507abc-q0j3 <none> <none>
collection-5d9f8586d8-cxvgb 2/2 Running 0 19m 10.24.2.7 gke-develop-default-pool-ea507abc-jjzg <none> <none>
collection-5d9f8586d8-tzwjc 2/2 Running 0 19m 10.24.2.8 gke-develop-default-pool-ea507abc-jjzg <none> <none>
parser-7df86f57bb-9qzpn 1/1 Running 0 19m 10.24.0.8 gke-develop-parser-pool-5931b06f-6mcq <none> <none>
parser-7df86f57bb-g6d4q 1/1 Running 0 19m 10.24.5.5 gke-develop-parser-pool-5931b06f-9xd5 <none> <none>
parser-7df86f57bb-jchjv 1/1 Running 0 19m 10.24.0.9 gke-develop-parser-pool-5931b06f-6mcq <none> <none>
$ kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
srv NodePort 10.0.2.110 <none> 80:30141/TCP 129d
collection NodePort 10.0.4.237 <none> 80:30270/TCP 129d
kubernetes ClusterIP 10.0.0.1 <none> 443/TCP 130d
$ kubectl get endpoints
NAME ENDPOINTS AGE
srv 10.24.1.7:80,10.24.2.9:80,10.24.3.8:80 129d
collection 10.24.1.6:80,10.24.2.7:80,10.24.2.8:80 129d
kubernetes 35.237.239.186:443 130d
502 是一个棘手的状态代码,它可能意味着上下文被客户端取消,或者只是您尝试访问的服务器的错误网关。在 kubernetes 中,502 通常意味着您无法访问该服务。因此,我会调试您的服务和部署 doc。
使用 kubectl get pods -o wide
获取您的 srv
连播;检查其 clusterIP IP。然后确保服务正在对 srv
部署进行负载平衡。为此,运行 kubectl get svc
并查找 srv
服务。最后 运行 kubectl get endpoints
,获取分配给 srv
端点的 IP,并将其与您从 pod 获取的 IP 进行匹配。如果一切正常,那么您就正确地对后端进行了负载平衡。
502 errors are expected when your backend service is returning 4xx errors。如果后端是 returning 4xx,健康检查将失败。如果所有后端都出现故障,负载均衡器将没有可用的后端来发送流量,并将 return 502.
对于来自负载均衡器的任何 502 错误 return,我强烈建议检查 HTTP 负载均衡器的堆栈驱动程序日志。任何 502 错误都将包含一条消息输出以及 502 响应。该消息应阐明 502 被重新登录的原因(原因有很多)。
在您当前的情况下,502 error log should mention "failed_to_pick_backend" 或 "failed_to_connect_to_backend" 就是这样。如果您使用的是 nginx ingress,可以看到类似的行为,但 502 错误消息可能表示不同的内容。
tl;dr: GCP LoadBalancer/GKE 如果来自后端的 404/422 没有响应主体,入口将是 502。
查看 LoadBalancer 日志,我会看到以下错误:
502: backend_connection_closed_before_data_sent_to_client
404: backend_connection_closed_after_partial_response_sent
由于一切都已正确配置(甚至 LoadBalancer 表示后端是健康的)——后端按预期工作并且没有失败的健康检查——我尝试了一些东西并注意到我的所有 404 响应都是空的机构。
太棒了,我在 404 和 422 响应中添加了正文,你看,没有更多的 502 了!
我有一个入口为 GKE 上的两个微服务 运行ning 提供路由,当微服务 return 是 404/422 时,入口 return 是 502。
这是我的入口定义:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: basic-ingress
annotations:
kubernetes.io/ingress.global-static-ip-name: develop-static-ip
ingress.gcp.kubernetes.io/pre-shared-cert: dev-ssl-cert
spec:
rules:
- http:
paths:
- path: /*
backend:
serviceName: srv
servicePort: 80
- path: /c/*
backend:
serviceName: collection
servicePort: 80
- path: /w/*
backend:
serviceName: collection
servicePort: 80
我 运行 测试命中了 srv
后端,我希望得到 404 或 422 响应。当我直接点击 srv
后端(绕过入口)时,我已经验证该服务使用 404/422 正确响应。
当我通过入口发出相同的请求时,入口会间歇性地响应 502 而不是来自后端的 404/422。
如何让入口仅 return 来自后端的 404/422 响应?
下面是一些示例代码,用于演示我所看到的行为(预期状态为 404):
>>> for i in range(10):
resp = requests.get('https://<server>/a/v0.11/accounts/junk', cookies=<token>)
print(resp.status_code)
502
502
404
502
502
404
404
502
404
404
这里是从 pod 中的 python 提示发出的相同请求,即绕过入口:
>>> for i in range(10):
... resp = requests.get('http://0.0.0.0/a/v0.11/accounts/junk', cookies=<token>)
... print(resp.status_code)
...
404
404
404
404
404
404
404
404
404
404
这是 kubectl 命令的输出,用于证明负载均衡器设置正确(我从未从微服务获得 2xx/3xx 响应的 502):
$ kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
srv-799976fbcb-4dxs7 2/2 Running 0 19m 10.24.3.8 gke-develop-default-pool-ea507abc-43h7 <none> <none>
srv-799976fbcb-5lh9m 2/2 Running 0 19m 10.24.1.7 gke-develop-default-pool-ea507abc-q0j3 <none> <none>
srv-799976fbcb-5zvmv 2/2 Running 0 19m 10.24.2.9 gke-develop-default-pool-ea507abc-jjzg <none> <none>
collection-5d9f8586d8-4zngz 2/2 Running 0 19m 10.24.1.6 gke-develop-default-pool-ea507abc-q0j3 <none> <none>
collection-5d9f8586d8-cxvgb 2/2 Running 0 19m 10.24.2.7 gke-develop-default-pool-ea507abc-jjzg <none> <none>
collection-5d9f8586d8-tzwjc 2/2 Running 0 19m 10.24.2.8 gke-develop-default-pool-ea507abc-jjzg <none> <none>
parser-7df86f57bb-9qzpn 1/1 Running 0 19m 10.24.0.8 gke-develop-parser-pool-5931b06f-6mcq <none> <none>
parser-7df86f57bb-g6d4q 1/1 Running 0 19m 10.24.5.5 gke-develop-parser-pool-5931b06f-9xd5 <none> <none>
parser-7df86f57bb-jchjv 1/1 Running 0 19m 10.24.0.9 gke-develop-parser-pool-5931b06f-6mcq <none> <none>
$ kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
srv NodePort 10.0.2.110 <none> 80:30141/TCP 129d
collection NodePort 10.0.4.237 <none> 80:30270/TCP 129d
kubernetes ClusterIP 10.0.0.1 <none> 443/TCP 130d
$ kubectl get endpoints
NAME ENDPOINTS AGE
srv 10.24.1.7:80,10.24.2.9:80,10.24.3.8:80 129d
collection 10.24.1.6:80,10.24.2.7:80,10.24.2.8:80 129d
kubernetes 35.237.239.186:443 130d
502 是一个棘手的状态代码,它可能意味着上下文被客户端取消,或者只是您尝试访问的服务器的错误网关。在 kubernetes 中,502 通常意味着您无法访问该服务。因此,我会调试您的服务和部署 doc。
使用 kubectl get pods -o wide
获取您的 srv
连播;检查其 clusterIP IP。然后确保服务正在对 srv
部署进行负载平衡。为此,运行 kubectl get svc
并查找 srv
服务。最后 运行 kubectl get endpoints
,获取分配给 srv
端点的 IP,并将其与您从 pod 获取的 IP 进行匹配。如果一切正常,那么您就正确地对后端进行了负载平衡。
502 errors are expected when your backend service is returning 4xx errors。如果后端是 returning 4xx,健康检查将失败。如果所有后端都出现故障,负载均衡器将没有可用的后端来发送流量,并将 return 502.
对于来自负载均衡器的任何 502 错误 return,我强烈建议检查 HTTP 负载均衡器的堆栈驱动程序日志。任何 502 错误都将包含一条消息输出以及 502 响应。该消息应阐明 502 被重新登录的原因(原因有很多)。
在您当前的情况下,502 error log should mention "failed_to_pick_backend" 或 "failed_to_connect_to_backend" 就是这样。如果您使用的是 nginx ingress,可以看到类似的行为,但 502 错误消息可能表示不同的内容。
tl;dr: GCP LoadBalancer/GKE 如果来自后端的 404/422 没有响应主体,入口将是 502。
查看 LoadBalancer 日志,我会看到以下错误:
502: backend_connection_closed_before_data_sent_to_client
404: backend_connection_closed_after_partial_response_sent
由于一切都已正确配置(甚至 LoadBalancer 表示后端是健康的)——后端按预期工作并且没有失败的健康检查——我尝试了一些东西并注意到我的所有 404 响应都是空的机构。
太棒了,我在 404 和 422 响应中添加了正文,你看,没有更多的 502 了!