【问题标题】:Ingress gives 502 errorIngress 出现 502 错误
【发布时间】:2017-06-25 09:40:29
【问题描述】:

如果我运行http load balancer example,它在我的谷歌容器引擎项目中运行良好。当我运行“kubectl describe ing”时,后端是“健康”。如果我然后将 svc 更改为指向我的应用程序的一个,如下所示:

apiVersion: v1
kind: Service
metadata:
  name: app
  labels:
    name: app
spec:
  ports:
  - port: 8000
    name: http
    targetPort: 8000
  selector:
    name: app
  type: NodePort

我正在运行的应用程序是 gunicorn 后面的 django,如果我将其设置为负载均衡器而不是 NodePort,则可以正常工作。

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: main-ingress
spec:
  backend:
    serviceName: app
    servicePort: 8000

现在,当我运行“kubectl describe ing”时,后端被列为“不健康”,并且所有对入口 IP 的请求都会给出 502。

  1. 502 是健康检查不佳的症状吗?
  2. 我必须做什么才能使健康检查通过?我很确定运行我的应用程序的容器实际上是健康的。我从来没有设置过健康检查,所以我假设我必须配置一些未配置的东西,但我的谷歌搜索并没有让我到任何地方。

【问题讨论】:

    标签: redirect kubernetes google-cloud-platform


    【解决方案1】:

    经过大量挖掘,我找到了答案: 根据这里的要求:https://github.com/kubernetes/kubernetes/tree/master/cluster/addons/cluster-loadbalancing/glbc#prerequisites 应用程序必须在“/”处返回 200 状态码。因为我的应用程序返回 302(重定向到登录),所以运行状况检查失败。当健康检查失败时,入口资源返回502。

    【讨论】:

    • 我想你可以接受你的回答。我面临同样的问题并通过您的方法解决了它。谢谢!
    • URL 不需要是 / - 这可以使用 pod 上的 readinessProbelivenessProbe 选项进行配置。但是,这必须在创建入口之前进行配置。
    • @kai,我试过了,不幸的是它对我没有用,即使在重新创建入口之后也是如此。
    • 你拯救了我的一天,谢谢!但是您如何处理登录重定向?
    • 我对此没有特别的经验,但我想关键在于@kai 的评论。将运行状况检查设置为使用用户从未访问过的专用运行状况检查 URL,这样您仍然可以在 / 处进行重定向。
    【解决方案2】:

    我只是想用更具体的解释来补充已接受的答案,说明为什么需要对 / 进行健康检查,即使 livenessProbereadinessProbe 可能已设置并在 pod 中的容器上工作。

    我原本以为它们是同一个东西,但事实并非如此。

    kubernetes 引擎使用探针来管理服务中的各个容器。而/ 上的运行状况检查处于服务 级别,并且是 GCP 负载均衡器 合同的一部分。它与 kubernetes 或容器本身无关。

    GKE 需要它的原因是 GCP 负载平衡器是默认的入口控制器。正如docs 中所述,默认情况下,GCP 负载平衡器要求支持服务在 / 上返回 200,以检查它们是否处于活动状态,以便管理要路由到哪些服务。

    如果要配置此健康检查端点:

    1. 从 GKE 集群版本 1.17.6-gke.11目前处于测试阶段)您可以在 GCP 负载平衡器上对其进行配置。 See docs here
    2. 1.17.6-gke.11 之下,您无法在 GCP 负载平衡器上配置它。 / 上必须是 200。配置它的唯一选择是使用不同的、更可配置的入口控制器,如 nginx 控制器。我自己没有使用过这个,所以不能指出任何细节。

    【讨论】:

    • 我认为你是对的。我得出了同样的结论。不管我的readinessProbelivenessProbe 说什么,我的LB 总是发现后端不健康,因为后端/ 不返回200。它返回重定向。 :|
    • 可能,如果你使用不同的入口控制器,比如 nginx 控制器,你也许可以配置它。 .. 有人知道怎么做吗?跨度>
    • @Nawaz 我不使用 nginx 控制器,所以无法指出任何具体的内容,但是 GCP 负载均衡器现在是可配置的(来自版本 @987654336 @)。
    【解决方案3】:

    在我们的例子中,外部端口和内部端口在 values.yaml 中被提及为 5000,但服务正在侦听 3000 端口(在查看 pod 日志后才知道),因此已显示 502 bad gateway。

    一旦我将外部端口和内部端口更新为 3000 并升级该特定服务的部署,就能看到所需的输出。

    【讨论】:

      【解决方案4】:

      在我的情况下,原因是集群崩溃后没有运行 ingress-controller pod。 检测它的最简单方法是列出入口

      kubectl get ingress
      

      字段地址应该填写,在我的情况下是空值

      我列出了 ingress-nginx 命名空间的 pod

      kubectl get pods -n ingress-nginx
      

      发现 pod 没有运行

      NAME                                       READY   STATUS             RESTARTS   AGE
      nginx-ingress-controller-95db98cc5-rp5c4   0/1     CrashLoopBackOff   218        18h
      

      原因是 pod 调度到主节点,端口 80 正忙于外部 nginx。 我只是用

      删除了pod
      kubectl delete pod nginx-ingress-controller-95db98cc5-rp5c4 -n ingress-nginx
      

      并重新安排到工作节点。 而已。 502 错误消失了

      【讨论】:

        【解决方案5】:

        AWS ALB Ingress:Deployment POD 终止 TLS/SSL 的情况

        有一点很重要:如果后端完全使用自签名 CERTS 实现并且是终止 TLS 的实体,则 Ingress 对象必须知道这一事实才能使其运行状况检查正常工作,因为默认的运行状况检查是 HTTP。例如,AWS 的 ALB 需要知道这一点才能正确验证自己的 Healthcheck。

        • 验证由 NodePort 服务选择的部署是否正在终止 TLS/SSL(443 或任何其他端口)
        • 如果 pod 本身具有运行状况检查规范,则应包含该规范。
        • 如果 POD 中没有指定健康检查,那么您可以验证入口对象是否为入口健康检查本身设置了正确的协议。
          • 对于 AWS Ingress,应使用注解 alb.ingress.kubernetes.io/healthcheck-protocol: HTTPSalb.ingress.kubernetes.io/healthcheck-path: /

        入口

        • 对于此示例,其服务将流量转发到终止 TSL 的 Deployment(Pod 本身使用自签名证书为流量提供服务)。
        • 因此,/ 上的运行状况检查必须指定正确的协议和路径。
        # Example from https://docs.aws.amazon.com/eks/latest/userguide/alb-ingress.html
        apiVersion: networking.k8s.io/v1
        kind: Ingress
        metadata:
          annotations:
            # https://kubernetes-sigs.github.io/aws-load-balancer-controller/guide/ingress/annotations/
            kubernetes.io/ingress.class: alb
            alb.ingress.kubernetes.io/load-balancer-attributes: access_logs.s3.enabled=false
            alb.ingress.kubernetes.io/backend-protocol: HTTPS
            alb.ingress.kubernetes.io/scheme: internet-facing
            alb.ingress.kubernetes.io/listen-ports: '[{"HTTPS": 443}]'
            alb.ingress.kubernetes.io/certificate-arn: arn:aws:acm:sa-east-1:806101772216:certificate/3db92ed3-5439-44e8-843d-fec0c9709501
        
            #### SOLUTION TO HTTPS Healthcheck From AWS ALB Ingress
            # https://stackoverflow.com/questions/64264889/argo-workflows-ui-not-working-with-aws-ingress-controller/64268995#64268995
            # As the backend is implemented with certificates, it MUST include the healthcheck using HTTPS
            alb.ingress.kubernetes.io/healthcheck-protocol: HTTPS
            alb.ingress.kubernetes.io/healthcheck-path: /
          name: argo-server-ingress
        spec:
          rules:
          - host: argoflows-my-server.com
            http:
              paths:
              - pathType: Prefix
                path: "/*"
                backend:
                  service:
                    name: argo-server
                    port:
                      number: 2746
          tls:
          - hosts:
            secretName: argo-workflows-data-tls
        

        【讨论】:

          【解决方案6】:

          有两种健康检查

          1. Kubernetes 运行状况检查
          2. GKE(或 GCP)入口/负载均衡器运行状况检查

          Kubernetes 运行状况检查

          Kubernetes 使用 liveness、readiness 和启动探测来检查容器的健康状况。 https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/

          在 Web 应用程序中,通常会在健康检查探测中使用为 HTTP GET 请求返回成功代码的路径。任何大于或等于 200 且小于 400 的代码都表示成功。任何其他代码都表示失败。

          GKE 入口/负载均衡器运行状况检查

          根据 GCP 文档

          在 GKE 中,Ingress 对象定义了将 HTTP(S) 流量路由到集群中运行的应用程序的规则。一个 Ingress 对象与一个或多个 Service 对象相关联,每个 Service 对象都与一组 Pod 相关联。当您创建 Ingress 对象时,GKE Ingress 控制器会创建一个 Google Cloud HTTP(S) 负载均衡器,并根据 Ingress 及其关联服务中的信息对其进行配置。此负载均衡器支持单个 URL 映射上的多个后端服务。每个后端服务对应一个 Kubernetes Service,每个后端服务都必须引用一个 Google Cloud 健康检查。 此运行状况检查不同于 Kubernetes 活跃度或就绪性探测,因为运行状况检查是在集群外部实施的

          GKE 使用以下过程为与 Kubernetes Service 对应的每个后端服务创建健康检查:

          • 如果服务使用 healthCheck 引用 BackendConfig CRD 信息,GKE 使用它来创建运行状况检查
          • 如果服务没有引用BackendConfig CRD:
            • 如果 Serving Pod 使用带有容器的 Pod 模板,则 GKE 可以推断出部分或全部参数进行健康检查,该容器的就绪探测具有可解释为健康检查参数的属性 (see inferred parameters)。为此,需要满足以下条件

              • 就绪探测的端口号必须与服务 Pod 的 containerPort 匹配

              • 服务 Pod 的 containerPort 与 Service 的 targetPort 匹配

              • Service 的 port 必须与 Ingress 对象的 backend.servicePort 匹配

            • 如果 Service 的服务 Pod 的 Pod 模板没有有一个带有就绪探针的容器,其属性可以解释为健康检查参数,default values 用于创建健康检查

              • 使用默认值进行 GKE 运行状况检查时,对 / 路径的 HTTP GET 请求必须返回 200 状态代码。所以一定要定义应用程序的/

              • 即使在健康检查中使用默认值,Pod 的 containerPort 、Service 的 targetPort 和 Ingress 对象的 backend.servicePort 也必须匹配。也尝试使用端口号而不是端口名称来引用端口。

          注意:

          在 Kubernetes 健康检查中,任何大于或等于 200 且小于 400 的代码都视为成功。但在 GKE 入口运行状况检查中,只有状态码 200 被视为成功。因此,您可能会注意到应用程序已部署并运行良好,但您会收到 502。

          确保应用程序的运行状况端点为未经身份验证的请求返回 200。如果为健康端点启用了身份验证,则请求将被重定向并返回 300 状态代码。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2019-10-21
            • 2017-08-15
            • 2016-02-16
            • 2012-07-10
            • 2015-06-28
            • 1970-01-01
            • 1970-01-01
            • 2020-12-09
            相关资源
            最近更新 更多