服务之间的 Kubernetes GRPC 内部通信连接被拒绝

Kubernetes GRPC internal communication between services Connection refused

我正在尝试通过 grpc 在 kubernetes 内部的两个微服务之间进行通信,但我收到连接被拒绝的错误。

这些是尝试通信的服务的 yaml 文件。

---
apiVersion: v1
kind: Service
metadata:
  labels:
    app.kubernetes.io/name: source-api
    app.kubernetes.io/part-of: liop
    app.kubernetes.io/version: latest
  name: source-api
spec:
  ports:
  - name: grpc-server
    port: 8081
    protocol: TCP
    targetPort: 8081
  - name: http
    port: 8080
    protocol: TCP
    targetPort: 8080
  selector:
    app.kubernetes.io/name: source-api
    app.kubernetes.io/part-of: liop
    app.kubernetes.io/version: latest
  type: ClusterIP
---
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app.kubernetes.io/name: source-api
    app.kubernetes.io/part-of: liop
    app.kubernetes.io/version: latest
  name: source-api
spec:
  replicas: 1
  selector:
    matchLabels:
      app.kubernetes.io/name: source-api
      app.kubernetes.io/part-of: liop
      app.kubernetes.io/version: latest
  template:
    metadata:
      labels:
        app.kubernetes.io/name: source-api
        app.kubernetes.io/part-of: liop
        app.kubernetes.io/version: latest
    spec:
      containers:
      - env:
        - name: QUARKUS_GRPC_CLIENTS_STORE_PORT
          value: "8081"
        - name: QUARKUS_DATASOURCE_PASSWORD
          valueFrom:
            secretKeyRef:
              key: datasourcePassword
              name: liop
        - name: KAFKA_BOOTSTRAP_SERVERS
          value: kafka-service:9092
        - name: QUARKUS_DATASOURCE_USERNAME
          valueFrom:
            secretKeyRef:
              key: datasourceUsername
              name: liop
        - name: QUARKUS_HTTP_PORT
          value: "8080"
        - name: QUARKUS_GRPC_SERVER_PORT
          value: "8081"
        - name: QUARKUS_GRPC_SERVER_HOST
          value: localhost
        - name: QUARKUS_DATASOURCE_JDBC_URL
          value: jdbc:mysql://mysql:3306/product
        - name: QUARKUS_GRPC_CLIENTS_STORE_HOST
          value: store-api
        image: tools_source-api:latest
        imagePullPolicy: Never
        name: source-api
        ports:
        - containerPort: 8081
          name: grpc-server
          protocol: TCP
        - containerPort: 8080
          name: http
          protocol: TCP
      imagePullSecrets:
      - name: gitlab-registry

---
apiVersion: v1
kind: Service
metadata:
  labels:
    app.kubernetes.io/name: product-api
    app.kubernetes.io/part-of: liop
    app.kubernetes.io/version: latest
  name: product-api
spec:
  ports:
  - name: http
    port: 8080
    protocol: TCP
    targetPort: 8080
  selector:
    app.kubernetes.io/name: product-api
    app.kubernetes.io/part-of: liop
    app.kubernetes.io/version: latest
  type: ClusterIP
---
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app.kubernetes.io/name: product-api
    app.kubernetes.io/part-of: liop
    app.kubernetes.io/version: latest
  name: product-api
spec:
  replicas: 1
  selector:
    matchLabels:
      app.kubernetes.io/name: product-api
      app.kubernetes.io/part-of: liop
      app.kubernetes.io/version: latest
  template:
    metadata:
      labels:
        app.kubernetes.io/name: product-api
        app.kubernetes.io/part-of: liop
        app.kubernetes.io/version: latest
    spec:
      containers:
      - env:
        - name: KAFKA_BOOTSTRAP_SERVERS
          value: kafka-service:9092
        - name: QUARKUS_DATASOURCE_JDBC_URL
          value: jdbc:mysql://mysql:3306/product
        - name: QUARKUS_GRPC_CLIENTS_IMAGE_PORT
          value: "8081"
        - name: QUARKUS_GRPC_CLIENTS_SOURCE_HOST
          value: source-api
        - name: QUARKUS_DATASOURCE_PASSWORD
          valueFrom:
            secretKeyRef:
              key: datasourcePassword
              name: liop
        - name: QUARKUS_DATASOURCE_USERNAME
          valueFrom:
            secretKeyRef:
              key: datasourceUsername
              name: liop
        - name: QUARKUS_GRPC_CLIENTS_SOURCE_PORT
          value: "8081"
        - name: QUARKUS_GRPC_CLIENTS_IMAGE_HOST
          value: media-api
        image: tools_product-api:latest
        imagePullPolicy: Always
        name: product-api
        ports:
        - containerPort: 8080
          name: http
          protocol: TCP
      imagePullSecrets:
      - name: gitlab-registry

这是我的 API-gateway 的 yaml,它确实通过 HTTP 与微服务正确通信:

apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app.kubernetes.io/version: latest
    app.kubernetes.io/part-of: liop
    app.kubernetes.io/name: api-gateway
  name: api-gateway
spec:
  replicas: 1
  selector:
    matchLabels:
      app.kubernetes.io/version: latest
      app.kubernetes.io/part-of: liop
      app.kubernetes.io/name: api-gateway
  template:
    metadata:
      labels:
        app.kubernetes.io/version: latest
        app.kubernetes.io/part-of: liop
        app.kubernetes.io/name: api-gateway
    spec:
      containers:
      - env:
        - name: product_api
          value: http://product-api:8080/api/products/v1/
        - name: source_api
          value: http://source-api:8080/api/sources/v1/
        - name: store_api
          value: http://store-api:8080/api/stores/v1/
        - name: report_api
          value: http://report-api:8080/api/reports/v1/
        - name: category_api
          value: http://category-api:8080/api/categories/v1/
        - name: AUTH0_ISSUER_URL
          value: xxxx
        - name: AUTH0_AUDIENCE
          value: xxxxxxx
        - name: PORT
          value: "7000"
        image: tools_webgateway:latest
        imagePullPolicy: Never
        name: api-gateway
        ports:
        - containerPort: 7000
          hostPort: 7000
          name: http
          protocol: TCP
      imagePullSecrets:
      - name: gitlab-registry
---
apiVersion: v1
kind: Service
metadata:
  labels:
    app.kubernetes.io/name: api-gateway
    app.kubernetes.io/part-of: liop
    app.kubernetes.io/version: latest
  name: api-gateway
spec:
  ports:
  - name: http
    port: 7000
    protocol: TCP
    targetPort: 7000
  selector:
    app.kubernetes.io/name: api-gateway
    app.kubernetes.io/part-of: liop
    app.kubernetes.io/version: latest

错误产品-api抛出:

Caused by: java.net.ConnectException: Connection refused
        at java.base/sun.nio.ch.SocketChannelImpl.checkConnect(Native Method)
        at java.base/sun.nio.ch.SocketChannelImpl.finishConnect(SocketChannelImpl.java:779)
        at io.netty.channel.socket.nio.NioSocketChannel.doFinishConnect(NioSocketChannel.java:330)
        at io.netty.channel.nio.AbstractNioChannel$AbstractNioUnsafe.finishConnect(AbstractNioChannel.java:334)
        at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:702)
        at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:650)
        at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:576)
        at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:493)
        at io.netty.util.concurrent.SingleThreadEventExecutor.run(SingleThreadEventExecutor.java:989)
        at io.netty.util.internal.ThreadExecutorMap.run(ThreadExecutorMap.java:74)
        at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
        at java.base/java.lang.Thread.run(Thread.java:834)
io.grpc.StatusRuntimeException: UNAVAILABLE: io exception
        at io.grpc.Status.asRuntimeException(Status.java:533)
        at io.grpc.stub.ClientCalls$StreamObserverToCallListenerAdapter.onClose(ClientCalls.java:478)
        at io.grpc.PartialForwardingClientCallListener.onClose(PartialForwardingClientCallListener.java:39)
        at io.grpc.ForwardingClientCallListener.onClose(ForwardingClientCallListener.java:23)
        at io.grpc.ForwardingClientCallListener$SimpleForwardingClientCallListener.onClose(ForwardingClientCallListener.java:40)
        at io.quarkus.grpc.runtime.supports.IOThreadClientInterceptor.onClose(IOThreadClientInterceptor.java:68)
        at io.grpc.internal.ClientCallImpl.closeObserver(ClientCallImpl.java:617)
        at io.grpc.internal.ClientCallImpl.access0(ClientCallImpl.java:70)
        at io.grpc.internal.ClientCallImpl$ClientStreamListenerImplStreamClosed.runInternal(ClientCallImpl.java:803)
        at io.grpc.internal.ClientCallImpl$ClientStreamListenerImplStreamClosed.runInContext(ClientCallImpl.java:782)
        at io.grpc.internal.ContextRunnable.run(ContextRunnable.java:37)
        at io.grpc.internal.SerializingExecutor.run(SerializingExecutor.java:123)
        at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)        at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)        at java.base/java.lang.Thread.run(Thread.java:834)
Caused by: io.netty.channel.AbstractChannel$AnnotatedConnectException: Connection refused: source-api/10.101.237.82:8081
Caused by: java.net.ConnectException: Connection refused
        at java.base/sun.nio.ch.SocketChannelImpl.checkConnect(Native Method)
        at java.base/sun.nio.ch.SocketChannelImpl.finishConnect(SocketChannelImpl.java:779)
        at io.netty.channel.socket.nio.NioSocketChannel.doFinishConnect(NioSocketChannel.java:330)
        at io.netty.channel.nio.AbstractNioChannel$AbstractNioUnsafe.finishConnect(AbstractNioChannel.java:334)
        at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:702)
        at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:650)
        at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:576)
        at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:493)
        at io.netty.util.concurrent.SingleThreadEventExecutor.run(SingleThreadEventExecutor.java:989)
        at io.netty.util.internal.ThreadExecutorMap.run(ThreadExecutorMap.java:74)
        at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
        at java.base/java.lang.Thread.run(Thread.java:834)

来源-api:

source-api                ClusterIP      10.101.237.82    <none>          8081/TCP,8080/TCP
2021-04-01 06:38:08,973 INFO  [io.qua.grp.run.GrpcServerRecorder] (vert.x-eventloop-thread-1) gRPC Server started on localhost:8081 [SSL enabled: false]

在内部使用 grpcurl 也会给我一个连接被拒绝的错误。但是转发 source-api:8081 的端口确实允许我做请求。

QUARKUS_GRPC_SERVER_HOST 应该是 0.0.0.0 而不是 localhost