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



在我们的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"}

因此,服务已准备就绪并正确响应。我需要将此服务公开给国外流量。我正在尝试使用以下配置使用入口执行此操作:

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 秒后重试。

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

我发现了一个类似的问题,但这也没有带来足够的答案。
我也一直在关注调试服务文章,但这也没有帮助,因为服务本身还可以。

非常感谢有关此问题的任何帮助。

编辑 TLDR

GKE 负载均衡器仅接受 HTTP 状态 200,而 Kubernetes 运行状况检查接受任何大于或等于 200 且小于 400 的代码。

原始答案

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

查看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 服务器的配置方式是,它从路径重定向,而不尾随斜杠到带有它的路径。因此,当您请求/health时,您实际上得到了指向/health/的HTTP状态301,然后以200响应。

在 Kubernetes 健康检查的范围内,这是可以的,因为"任何大于或等于 200 且小于 400 的代码都表示成功。

但是,问题出在 GKE 负载均衡器上。它还具有自己的 GKE 运行状况检查,这些检查派生自部署定义中的检查。重要的区别在于它只接受HTTP状态200。如果负载均衡器找不到正常运行的后端服务,它不会向其传递任何外部流量。

因此,我们有两种选择来解决此问题:

  • 使容器内的服务器以 HTTPS 状态 200 响应两者/health/health/(或者更准确地说只是/health)
  • 或将readinessProbelivenessProbe路径定义更改为/health/

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

最新更新