Kubernetes Ingress(GCE)不断回复502错误

时间:2017-03-23 05:15:50

标签: kubernetes google-cloud-platform google-kubernetes-engine google-compute-engine

我正在尝试在GCE Kubernetes中设置Ingress。但是当我访问Ingress中定义的IP地址和路径组合时,我不断收到以下502错误:

Ingress 502 error

这是我跑步时得到的结果:kubectl describe ing --namespace dpl-staging

Name:           dpl-identity
Namespace:      dpl-staging
Address:        35.186.221.153
Default backend:    default-http-backend:80 (10.0.8.5:8080)
TLS:
  dpl-identity terminates
Rules:
  Host  Path    Backends
  ----  ----    --------
  *
        /api/identity/*     dpl-identity:4000 (<none>)
Annotations:
  https-forwarding-rule:    k8s-fws-dpl-staging-dpl-identity--5fc40252fadea594
  https-target-proxy:       k8s-tps-dpl-staging-dpl-identity--5fc40252fadea594
  url-map:          k8s-um-dpl-staging-dpl-identity--5fc40252fadea594
  backends:         {"k8s-be-31962--5fc40252fadea594":"HEALTHY","k8s-be-32396--5fc40252fadea594":"UNHEALTHY"}
Events:
  FirstSeen LastSeen    Count   From                SubObjectPath   Type        Reason  Message
  --------- --------    -----   ----                -------------   --------    ------  -------
  15m       15m     1   {loadbalancer-controller }          Normal      ADD dpl-staging/dpl-identity
  15m       15m     1   {loadbalancer-controller }          Normal      CREATE  ip: 35.186.221.153
  15m       6m      4   {loadbalancer-controller }          Normal      Service no user specified default backend, using system default

我认为问题是dpl-identity:4000 (<none>)。我不应该看到dpl-identity服务的IP地址而不是<none>吗?

以下是我的服务说明:kubectl describe svc --namespace dpl-staging

Name:           dpl-identity
Namespace:      dpl-staging
Labels:         app=dpl-identity
Selector:       app=dpl-identity
Type:           NodePort
IP:             10.3.254.194
Port:           http    4000/TCP
NodePort:       http    32396/TCP
Endpoints:      10.0.2.29:8000,10.0.2.30:8000
Session Affinity:   None
No events.

此外,这是执行结果:kubectl describe ep -n dpl-staging dpl-identity

Name:       dpl-identity
Namespace:  dpl-staging
Labels:     app=dpl-identity
Subsets:
  Addresses:        10.0.2.29,10.0.2.30
  NotReadyAddresses:    <none>
  Ports:
    Name    Port    Protocol
    ----    ----    --------
    http    8000    TCP

No events.

这是我的deployment.yaml:

apiVersion: v1
kind: Secret
metadata:
  namespace: dpl-staging
  name: dpl-identity
type: Opaque
data:
  tls.key: <base64 key>
  tls.crt: <base64 crt>
---
apiVersion: v1
kind: Service
metadata:
  namespace: dpl-staging
  name: dpl-identity
  labels:
    app: dpl-identity
spec:
  type: NodePort
  ports:
    - port: 4000
      targetPort: 8000
      protocol: TCP
      name: http
  selector:
    app: dpl-identity
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  namespace: dpl-staging
  name: dpl-identity
  labels:
    app: dpl-identity
  annotations:
    kubernetes.io/ingress.allow-http: "false"
spec:
  tls:
  - secretName: dpl-identity
  rules:
  - http:
      paths:
        - path: /api/identity/*
          backend:
            serviceName: dpl-identity
            servicePort: 4000
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  namespace: dpl-staging
  name: dpl-identity
kind: Ingress
metadata:
  namespace: dpl-staging
  name: dpl-identity
  labels:
    app: dpl-identity
  annotations:
    kubernetes.io/ingress.allow-http: "false"
spec:
  tls:
  - secretName: dpl-identity
  rules:
  - http:
      paths:
        - path: /api/identity/*
          backend:
            serviceName: dpl-identity
            servicePort: 4000
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  namespace: dpl-staging
  name: dpl-identity
  labels:
    app: dpl-identity
spec:
  replicas: 2
  strategy:
    type: RollingUpdate
  template:
    metadata:
      labels:
        app: dpl-identity
    spec:
      containers:
      - image: gcr.io/munpat-container-engine/dpl/identity:0.4.9
        name: dpl-identity
        ports:
        - containerPort: 8000
          name: http
        volumeMounts:
        - name: dpl-identity
          mountPath: /data
      volumes:
      - name: dpl-identity
        secret:
          secretName: dpl-identity

9 个答案:

答案 0 :(得分:25)

您的后端k8s-be-32396--5fc40252fadea594显示为"UNHEALTHY"

如果后端处于不健康状态,Ingress将不会转发流量,这将导致您看到的502错误。

它将被标记为不健康,因为它没有通过它的健康检查,您可以检查k8s-be-32396--5fc40252fadea594的健康检查设置,看看它们是否适合您的吊舱,它可能正在轮询未返回200响应的URI或端口。您可以在Compute Engine&gt;下找到这些设置。健康检查。

如果它们是正确的,那么您的浏览器和容器之间有许多步骤可能会错误地传递流量,您可以尝试kubectl exec -it PODID -- bash(如果您使用的是Alpine,则使用ash),然后尝试将localhost卷入查看容器是否按预期响应,如果是,并且还正确配置了运行状况检查,那么这可能会将问题缩小到您的服务范围,然后您可以尝试将服务从NodePort类型更改为LoadBalancer并查看如果直接从您的浏览器访问服务IP。

答案 1 :(得分:1)

我遇到了同样的问题,在我启用livenessProbe readinessPorbe之后它仍然存在。 这转变为与基本认证有关。我已将基本身份验证添加到livenessProbereadinessPorbe,但结果显示GCE HTTP(S)负载均衡器没有配置选项。

似乎还有一些其他类型的问题,例如将容器端口设置为8080,将服务端口设置为80不能与GKE入口控制器一起工作(但我不会清楚地指出问题是什么)。从广义上讲,我认为可见度非常低,在可视性方面运行自己的入口容器是一个更好的选择。

我为我的项目选择Traefik,它开箱即用,我想启用Let的加密集成。我必须对Traefik清单进行的唯一更改是调整服务对象以禁止从集群外部访问UI,并通过外部负载均衡器(GCE TCP LB)公开我的应用程序。此外,Traefik更像Kubernetes。我尝试了Heptio Contour,但是开箱即用的东西没有用(下次新版本发布的时候就会有用)。

答案 2 :(得分:0)

问题确实是健康检查,似乎是随机的&#34;对于我的应用程序,我使用基于名称的虚拟主机来反转从入口通过域到两个单独的后端服务的代理请求。两者都使用Lets Encrypt和kube-lego进行保护。我的解决方案是标准化共享入口的所有服务的运行状况检查路径,并在readinessProbe文件中声明livenessProbedeployment.yml配置。

我在使用Google云集群节点版本1.7.8时遇到了这个问题,发现这个问题与我的经历非常相似:  * https://github.com/jetstack/kube-lego/issues/27

我正在使用gcekube-lego,我的后端服务运行状况检查位于/,而kube-lego位于/healthz。可能是因为gce ingress可能导致健康检查的路径不同,因此可能值得更新后端服务以匹配/healthz模式,因此所有使用相同(或者作为Github问题中的一个评论者声明他们更新了kube -lego传递/)。

答案 3 :(得分:0)

我遇到了同样的问题。事实证明,我必须在进入之前等待几分钟才能验证服务运行状况。如果有人要进行同样的操作并完成readinessProbelinvenessProbe等所有步骤,请确保您的入口指向的服务是NodePort,并等待几分钟直到黄色警告图标变为绿色警告图标。另外,检查StackDriver上的日志以更好地了解正在发生的事情。对于readinessProbe类,我的livenessProbe/login位于gce。所以我不认为它必须在/healthz上。

答案 4 :(得分:0)

kubernetes文档的"Limitations"部分指出:

  

所有Kubernetes服务必须在'/'或您通过GLBC --health-check-path argument指定的任何自定义值上提供200页的页面。

https://github.com/kubernetes/kubernetes/tree/master/cluster/addons/cluster-loadbalancing/glbc#limitations

答案 5 :(得分:0)

我通过

解决了问题
  1. 从入口定义中删除服务
  2. 部署入口kubectl apply -f ingress.yaml
  3. 将服务添加到入口定义
  4. 再次部署入口

从本质上讲,我遵循罗伊(Roy)的建议,并尝试将其关闭然后再打开。

答案 6 :(得分:0)

可以从Stackdriver Logging中读取日志,在我的情况下,这是backend_timeout错误。通过BackendConfig增加默认超时(30s)后,即使在负载下也不会返回502。

更多信息: https://cloud.google.com/kubernetes-engine/docs/how-to/configure-backend-service#creating_a_backendconfig

答案 7 :(得分:0)

我有同样的问题。我发现该Pod本身运行正常,通过端口转发并访问了运行状况检查URL对此进行了测试。

可以在控制台中按以下方式激活端口转发:

$    kubectl port-forward <pod-name> local-port:pod-port

因此,如果Pod运行正常,并且入口仍显示不正常状态,则可能是您的服务配置存在问题。在我的情况下,我的应用选择器不正确,导致选择了一个不存在的Pod。有趣的是,这不会在Google控制台中显示为错误或警报。

豆荚的定义:

#pod-definition.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: <pod-name>
  namespace: <namespace>
spec:
  selector:
    matchLabels:
      app: **<pod-name>**
  template:
    metadata:
      labels:
        app: <pod-name>
    spec:
    #spec-definition follows

#service.yaml    
apiVersion: v1
    kind: Service
    metadata:
      name: <name-of-service-here>
      namespace: <namespace>
    spec:
      type: NodePort
      selector:
        app: **<pod-name>**
      ports:
      - protocol: TCP
        port: 8080
        targetPort: 8080
        name: <port-name-here>

答案 8 :(得分:0)

在使用 successThreshold: 1 和 failureThreshold: 3 添加以下就绪和活跃度探测后,我已经解决了这个问题。此外,我将 initialDelaySeconds 保持为 70,因为有时应用程序响应有点晚,它可能因应用程序而异。

注意: 还要确保 httpGet 中的路径应该存在于您的应用程序中(例如我的情况 /api/books),否则 GCP ping /healthz 路径并不会不保证返回 200 OK。

    readinessProbe:
      httpGet:
        path: /api/books
        port: 80
      periodSeconds: 5
      successThreshold: 1
      failureThreshold: 3
      initialDelaySeconds: 70
      timeoutSeconds: 60
    livenessProbe:
      httpGet:
        path: /api/books
        port: 80
      initialDelaySeconds: 70
      periodSeconds: 5
      successThreshold: 1
      failureThreshold: 3 
      timeoutSeconds: 60

在经历了很多挣扎并尝试了很多事情之后,我终于能够理清头绪了。

保持学习和分享