GKE Ingress 上的 gRPC 和 HTTP 服务器未能通过 gRPC 后端的健康检查

gRPC & HTTP servers on GKE Ingress failing healthcheck for gRPC backend

我想在 GKE 上使用 HTTP/2 和双向 TLS 部署一个 gRPC + HTTP 服务器。我的部署既有就绪探测器,也有带有自定义路径的活动探测器。我通过 Ingress 公开了 gRPC 和 HTTP 服务器。

部署的探测和暴露的端口:

    livenessProbe:
      failureThreshold: 3
      httpGet:
        path: /_ah/health
        port: 8443
        scheme: HTTPS
      periodSeconds: 10
      successThreshold: 1
      timeoutSeconds: 1
    readinessProbe:
      failureThreshold: 3
      httpGet:
        path: /_ah/health
        port: 8443
        scheme: HTTPS
    name: grpc-gke
    ports:
    - containerPort: 8443
      protocol: TCP
    - containerPort: 50052
      protocol: TCP

节点端口服务:

apiVersion: v1
kind: Service
metadata:
  name: grpc-gke-nodeport
  labels:
    app: grpc-gke
  annotations:
    cloud.google.com/app-protocols: '{"grpc":"HTTP2","http":"HTTP2"}'
    service.alpha.kubernetes.io/app-protocols: '{"grpc":"HTTP2", "http": "HTTP2"}'
spec:
  type: NodePort
  ports:
  - name: grpc
    port: 50052
    protocol: TCP
    targetPort: 50052
  - name: http
    port: 443
    protocol: TCP
    targetPort: 8443
  selector:
    app: grpc-gke

入口:

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: grpc-gke-ingress
  annotations:
    kubernetes.io/ingress.allow-http: "false"
    #kubernetes.io/ingress.global-static-ip-name: "grpc-gke-ip"
  labels:
    app: grpc-gke
spec:
  rules:
  - http:
      paths:
      - path: /_ah/*
        backend:
          serviceName: grpc-gke-nodeport
          servicePort: 443
  backend:
    serviceName: grpc-gke-nodeport
    servicePort: 50052

在创建活动性和就绪性探测之前,pod 确实存在,并且具有 "green" 状态。我在我的服务器上看到常规日志,其中 /_ah/live/_ah/ready 都被 kube-probe 调用并且服务器响应 200 响应。

我在负载平衡器 (LB) 上使用 Google 托管 TLS 证书。我的 HTTP 服务器创建了一个自签名证书——灵感来自 this blog.

我在开始查看探测器日志后创建了 Ingress。之后,它会创建一个具有两个后端的 LB,一个用于 HTTP,一个用于 gRPC。 HTTP 后端的健康检查正常,并且可以从 Internet 访问 HTTP 服务器。 gRPC 后端的健康检查失败,因此 LB 没有路由 gRPC 协议,我收到 502 错误响应。

这是 GKE 主站 1.12.7-gke.10。我还尝试了更新的 1.13 和更早的 1.11 masters。集群启用了 HTTP 负载均衡和 VPC-native。有防火墙规则允许从 LB 访问我的 pods(我什至尝试允许来自所有 IP 地址的所有端口)。延迟探测也无济于事。

有趣的是我部署了几乎相同的设置,只是服务器的 Docker 映像不同,几个月前它是 运行 没有任何问题。我什至可以部署服务器的新 Docker 图像,一切都很棒。我找不到这两者之间的任何区别。

还有一个问题,Ingress 卡在 "Creating Ingress" 状态好几天了。它永远不会完成,也永远不会看到 LB。 Ingress 的 LB 从来没有前端,我总是必须手动添加具有静态 IP 和 Google 托管 TLS 证书的 HTTP/2 前端。这应该只发生在没有 "HTTP load balancing" 的情况下创建的集群,但在我的情况下,每次我的所有 "HTTP load balancing enabled" 集群都会发生。工作部署已处于此状态数月。

知道为什么 gRPC 后端的健康检查可能会失败,即使我看到日志显示 kube-probe 调用了就绪性和活跃性端点吗?

编辑:

describe svc grpc-gke-nodeport

Name:                     grpc-gke-nodeport
Namespace:                default
Labels:                   app=grpc-gke
Annotations:              cloud.google.com/app-protocols: {"grpc":"HTTP2","http":"HTTP2"}
                        kubectl.kubernetes.io/last-applied-configuration:
                            {"apiVersion":"v1","kind":"Service","metadata":{"annotations":{"cloud.google.com/app-protocols":"{\"grpc\":\"HTTP2\",\"http\":\"HTTP2\"}",...
                        service.alpha.kubernetes.io/app-protocols: {"grpc":"HTTP2", "http": "HTTP2"}
Selector:                 app=grpc-gke
Type:                     NodePort
IP:                       10.4.8.188
Port:                     grpc  50052/TCP
TargetPort:               50052/TCP
NodePort:                 grpc  32148/TCP
Endpoints:                10.0.0.25:50052
Port:                     http  443/TCP
TargetPort:               8443/TCP
NodePort:                 http  30863/TCP
Endpoints:                10.0.0.25:8443
Session Affinity:         None
External Traffic Policy:  Cluster
Events:                   <none>

并且 gRPC 后端的健康检查是 HTTP/2 GET 使用端口 32148 上的路径 /。它的描述是 "Default kubernetes L7 Loadbalancing health check.",其中 HTTP 后端健康检查的描述是 "Kubernetes L7 health check generated with readiness probe settings."。因此,gRPC 后端的健康检查不是从就绪探测器创建的。

编辑运行状况检查以指向端口 30863 并更改就绪探测的路径可解决问题。

GKE ingress 最近刚刚开始在测试版中支持完整的 gRPC 支持(而过去使用 HTTP2 到 HTTP1.1 转换)。但是,要使用 gRCP,您需要向入口 "cloud.google.com/app-protocols: '{"http2-service":"HTTP2"}'" 添加注释。 Refer to this how-to doc 了解更多详情。

编辑运行状况检查以指向就绪探测的路径并将端口更改为 HTTP back-end 之一修复了此问题(在 HTTP back-end 的运行状况中查找端口检查。它是 NodePort 的。)。它可以毫无问题地运行。

对 gRPC back-end 使用与 HTTP back-end 相同的健康检查没有用,它被重置回它自己的健康检查。即使删除 gRPC back-end 的健康检查也无济于事,它被重新创建了。只有编辑它以使用不同的端口和路径才有帮助。