Ingress 在 gRPC 调用上抛出 404,但能够通过常规 HTTP GET/POST 进行解析

问题描述 投票:0回答:1

我在 GCP Kubernetes 上为我们的 golang 服务进行的部署遇到了一个相当奇怪的问题,该服务通过 gRPC 端点以及 HTTP 1.1 调用进行连接。这些配置对于 http 调用工作正常,但是,一旦我使用 gRPC 应用程序点击它,入口就会在访问日志中显示 404 响应,请检查我的 YAML 并告诉我是否缺少任何导致此行为的内容

SA 配置

apiVersion: v1
kind: ServiceAccount
metadata:
  name: "service-qa"
  namespace: service-qa
  labels:
    helm.sh/chart: service-0.0.1
    app.kubernetes.io/name: service
    app.kubernetes.io/instance: release-name
    app.kubernetes.io/version: "1.0.0"
    app.kubernetes.io/managed-by: Helm

服务配置

apiVersion: v1
kind: Service
metadata:
  name: "service-qa"
  namespace: service-qa
  annotations:
    cloud.google.com/app-protocols: '{"http2":"HTTP2", "http": "HTTP"}'
    cloud.google.com/neg: '{"ingress": true}'
    service.alpha.kubernetes.io/app-protocols: '{"http2":"HTTP2", "http": "HTTP"}'
    cloud.google.com/backend-config: '{"default": "service-qa"}'
  labels:
    helm.sh/chart: service-0.0.1
    app.kubernetes.io/name: service
    app.kubernetes.io/instance: release-name
    app.kubernetes.io/version: "1.0.0"
    app.kubernetes.io/managed-by: Helm
spec:
  type: ClusterIP
  ports:
    - port: 443
      targetPort: 8080
      protocol: TCP
      name: http
  selector:
    app.kubernetes.io/name: service
    app.kubernetes.io/instance: release-name

部署配置

apiVersion: apps/v1
kind: Deployment
metadata:
  name: "service-qa"
  labels:
    helm.sh/chart: service-0.0.1
    app.kubernetes.io/name: service
    app.kubernetes.io/instance: release-name
    app.kubernetes.io/version: "1.0.0"
    app.kubernetes.io/managed-by: Helm
  namespace: service-qa
spec:
  replicas: 5
  selector:
    matchLabels:
      app.kubernetes.io/name: service
      app.kubernetes.io/instance: release-name
  template:
    metadata:
      labels:
        app.kubernetes.io/name: service
        app.kubernetes.io/instance: release-name
    spec:
      securityContext:
        {}
      containers:
        - name: service
          securityContext:
            {}
          image: "REDACTED/service:1.0.0_202310170507"
          env:
            - name: IS_LIVE
              value: "false"
            - name: PROFILE
              value: "qa"
            - name: TOKEN
              valueFrom:
                    secretKeyRef:
                      key: token
                      name: service-access-token
          imagePullPolicy: IfNotPresent
          ports:
            - name: http
              containerPort: 8080
              protocol: TCP
          resources:
            limits:
              cpu: 100m
              memory: 200Mi
            requests:
              cpu: 50m
              memory: 100Mi
      nodeSelector:
        iam.gke.io/gke-metadata-server-enabled: "true"

入口配置


apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: "service-qa"
  namespace: service-qa
  labels:
    helm.sh/chart: service-0.0.1
    app.kubernetes.io/name: service
    app.kubernetes.io/instance: release-name
    app.kubernetes.io/version: "1.0.0"
    app.kubernetes.io/managed-by: Helm
  annotations:
    ingress.gcp.kubernetes.io/pre-shared-cert: cert
    kubernetes.io/ingress.allow-http: "false"
    kubernetes.io/ingress.class: gce-internal
    kubernetes.io/ingress.regional-static-ip-name: ilb
spec:
  tls:
    - hosts:
      - REDACTED
      secretName: cert-qa
  rules:
    - host: "REDACTED"
      http:
        paths:
          - path: /*
            pathType: ImplementationSpecific
            backend:
              service:
                name: service-qa
                port:
                  number: 443

后端配置

apiVersion: cloud.google.com/v1
kind: BackendConfig
metadata:
  name: "service-qa"
  namespace: service-qa
spec:
  timeoutSec: 400
  healthCheck:
    checkIntervalSec: 30
    port: 8080
    type: HTTP
    requestPath: /healthcheck

让我还附上我的入口的一些屏幕截图,其中显示了传入的请求,但最终出现了 404,而当我用 Postman 调用击中它时,我得到了正确的响应

现在通过邮递员拨打同样的电话可以正常工作,

我还想指出,关于我调用服务的方式没有拼写错误或任何问题,因为相同的代码在虚拟机上运行良好 - 只是带有 Google 内部负载均衡器的 Kubernetes 无法接听调用转发至服务。

提前致谢,非常感谢您的帮助,因为我已经努力寻找解决方案相当长一段时间了。

kubernetes google-kubernetes-engine grpc kubernetes-ingress
1个回答
0
投票

据我了解,你有:

Client
  |
  | HTTP GET/POST Request (Works)
  | gRPC Request (Fails)
  v
Google Cloud Internal Load Balancer (GCE ILB)
  |
  | Ingress (service-qa)
  v
Kubernetes Cluster (GCP GKE)
  |
  | (Namespace: service-qa)
  v
Service (service-qa)
  | Port: 443  TargetPort: 8080
  v
Pods (Deployment: service-qa)
  |
  | Container: service
  | Image: REDACTED/service:1.0.0_202310170507
  | Ports: ContainerPort: 8080 (Protocol: TCP)
  v
gRPC Server / HTTP Server (listening on port 8080)
  |
  | Response (HTTP: 200 OK)
  | (gRPC: 404 Not Found)
  v
Back to Client
  • 对于 HTTP GET/POST 请求,从客户端到您的服务并返回的路径工作正常,并且会向客户端返回
    200 OK
    响应。
  • 对于 gRPC 请求,请求会发送到您的服务,但会向客户端返回
    404 Not Found
    错误。

激活日志:对于 gRPC 日志记录,您可以在服务的部署配置中设置

GRPC_VERBOSITY
GRPC_TRACE
环境变量:

env:
    - name: GRPC_VERBOSITY
    value: DEBUG
    - name: GRPC_TRACE
    value: all

如果 gRPC 客户端正确配置为连接到端口 443,则流量应根据您的服务配置转发到服务器上的端口 8080。但是,如果 Ingress 或服务配置存在问题,或者 gRPC 客户端错误地尝试使用 HTTP/1.1 而不是 HTTP/2(gRPC 需要)进行通信,则可能会导致您看到的

404 Not Found
错误。

查看 Ingress 控制器的日志,看看是否有任何错误消息或有关 gRPC 调用失败原因的其他信息。

测试您的服务连接入口:您可以执行集群内的 pod,并使用

curl
grpcurl
测试与服务的连接:

kubectl run -i --tty --rm debug --image=radial/busyboxplus:curl --restart=Never -- sh
# Then from within the container:
grpcurl -plaintext service-qa.service-qa.svc.cluster.local:8080 list

验证客户端配置涉及确保客户端正确设置为与 gRPC 服务器通信,特别是在所使用的地址、端口和协议方面。根据 gRPC 客户端实现的环境和语言,您可以使用以下几个步骤和命令:

检查创建 gRPC 客户端的代码,确保地址和端口正确设置为您的服务地址和端口

443

// In Go, for example, it would look something like this:
conn, err := grpc.Dial("your-service-address:443", grpc.WithInsecure())
if err != nil {
    log.Fatalf("did not connect: %v", err)
}
defer conn.Close()
© www.soinside.com 2019 - 2024. All rights reserved.