Kubernetes入口错误:服务器遇到临时错误,无法完成您的请求

时间:2018-07-23 20:01:10

标签: kubernetes google-cloud-platform

在我们的GKE中,我们有一项名为php-services的服务。定义如下:

apiVersion: v1
kind: Service
metadata:
  name: php-services
  labels:
    name: php-services
spec:
  type: NodePort
  ports:
  - port: 80
  selector:
    name: php-services

我可以从集群内部访问此服务。如果我在我们的其中一个pod上(在Default命名空间中)运行这些命令,将会得到预期的结果:

bash-4.4$ nslookup 'php-services'
   Name:      php-services
   Address 1: 10.15.250.136 php-services.default.svc.cluster.local

bash-4.4$ wget -q -O- 'php-services/health'
   {"status":"ok"}

因此,该服务已准备就绪,可以正确响应。我需要将此服务暴露给国外流量。我正在尝试通过以下配置使用Ingress:

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: ingress-tls
  annotations:
    kubernetes.io/ingress.class: "gce"
    kubernetes.io/tls-acme: "true"
    kubernetes.io/ingress.global-static-ip-name: "kubernetes-ingress"
    kubernetes.io/ingress.allow-http: "false"
    external-dns.alpha.kubernetes.io/hostname: "gke-ingress.goout.net"
  namespace: default
spec:
  tls:
  - hosts:
     - php.service.goout.net
    secretName: router-tls
  rules:
  - host: php.service.goout.net
    http:
      paths:
      - backend:
          serviceName: php-services
          servicePort: 80
        path: /*

但是访问http://php.service.goout.net/health时会出现502错误:

  

错误:服务器错误服务器遇到临时错误,并且可能
  未完成您的请求。
  请在30秒后重试。

我们还有其他配置相同的服务,它们可以正常运行并且可以从外部访问。

我找到了similar question,但这也没有带来足够的答案。
我也一直在关注Debug Service文章,但由于服务本身还可以,因此也没有帮助。

任何对此问题的帮助都非常感谢。

1 个答案:

答案 0 :(得分:5)

好的,所以我们找出了问题所在。

看看php-services服务的部署的yaml定义:(缩短)

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: php-services
  namespace: default
spec:
  replicas: 1
  selector:
    matchLabels:
      name: php-services
  template:
    metadata:
      labels:
        name: php-services
    spec:
      containers:
        - name: php-services
          image: IMAGE_TAG
          livenessProbe:
            failureThreshold: 3
            httpGet:
              path: /health
              port: 80
              scheme: HTTP
            initialDelaySeconds: 60
            periodSeconds: 60
            successThreshold: 1
            timeoutSeconds: 10
          readinessProbe:
            failureThreshold: 3
            httpGet:
              path: /health
              port: 80
              scheme: HTTP
            initialDelaySeconds: 60
            periodSeconds: 60
            successThreshold: 1
            timeoutSeconds: 10
          ports:
          - containerPort: 80

映像中的Apache aerver的配置方式是,它从路径重定向而不会在路径末尾加斜杠。因此,当您请求/health时,实际上得到的HTTP状态301指向/health/,然后返回200。

在kubernetes健康检查的范围内,可以将其设为“ Any code greater than or equal to 200 and less than 400 indicates success.

但是问题出在GKE负载平衡器上。它也具有自己的GKE健康检查,这些健康检查是从Deployment定义中的检查得出的。重要的区别在于it only accepts HTTP status 200。而且,如果负载平衡器没有发现健康的后端服务,它将不会传递任何外部流量。

因此,我们有两个解决方案:

  • 使容器内的服务器以HTTPS状态200响应两个请求 /health/health/(或更确切地说,仅/health
  • 或将readinessProbe和livenessProbe路径定义更改为/health/

我们选择了后者,它解决了问题。