后端返回404/422

时间:2019-11-07 17:42:19

标签: kubernetes google-cloud-platform google-kubernetes-engine kubernetes-ingress http-response-codes

我有一个入口,为运行在GKE上的两个微服务提供路由,并且当微服务返回404/422时,该入口间歇返回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。

如何让Ingress仅仅从后端返回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

3 个答案:

答案 0 :(得分:1)

502 errors are expected when your backend service is returning 4xx errors。如果后端返回4xx,则运行状况检查将失败。如果所有后端均发生故障,则负载均衡器将没有可用的后端将流量发送到该后端,并将返回502。

对于从负载均衡器返回的任何502错误,我强烈建议检查HTTP负载均衡器的堆栈驱动器日志。任何502错误都将包括与502响应一起输出的消息。该消息应阐明为什么重新提出502(有许多原因)。

在您当前的情况下,502 error log should mention“ failed_to_pick_backend”或“ failed_to_connect_to_backend”可以调整。如果您使用的是nginx入口,则可以看到类似的行为,但是502错误消息可能表示不同。

答案 1 :(得分:1)

tl; dr:如果来自后端的404/422没有响应主体,则GCP LoadBalancer / GKE入口将为502。

查看LoadBalancer日志,会看到以下错误:

502: backend_connection_closed_before_data_sent_to_client
404: backend_connection_closed_after_partial_response_sent

由于一切都配置正确(即使LoadBalancer都说后端运行正常)-后端按预期运行,并且运行状况检查没有失败-我做了一些尝试,并注意到我的所有404响应都为空体。

所以,我在404和422响应中添加了一个主体,并且不再看到502s!

答案 2 :(得分:0)

502是一个棘手的状态代码,它可能意味着上下文已被客户端取消,或者仅是您尝试访问的服务器中的错误网关。在kubernetes中,502通常表示您无法使用该服务。因此,我将去调试您的服务和部署doc

使用kubectl get pods -o wide获取srv窗格;检查其clusterIP IP。然后,确保服务正在平衡srv部署的负载。为此,请运行kubectl get svc并寻找srv服务。最后运行kubectl get endpoints,获取分配给srv端点的IP,并将其与您从Pod中获得的IP相匹配。如果一切正常,那么您可以正确平衡后端的负载。