【问题标题】:Unable to connect with gRPC when deployed with kubernetes使用 kubernetes 部署时无法连接 gRPC
【发布时间】:2021-03-06 08:51:40
【问题描述】:

我正在尝试使用 kubernetes 部署 gRPC 服务器,并在集群外部连接到它。 服务器相关部分:

function main() {
  var hello_proto = grpc.loadPackageDefinition(packageDefinition).helloworld;
  var server = new grpc.Server();
  server.addService(hello_proto.Greeter.service, {sayHello: sayHello});
  const url = '0.0.0.0:50051'
  server.bindAsync(url, grpc.ServerCredentials.createInsecure(), () => {
    server.start();
    console.log("Started server! on " + url);
  });
}

function sayHello(call, callback) {
  console.log('Hello request');
  callback(null, {message: 'Hello ' + call.request.name + ' from ' + require('os').hostname()});
}

这里是客户端的相关部分:

function main() {
  var target = '0.0.0.0:50051';
  let pkg = grpc.loadPackageDefinition(packageDefinition);
  let Greeter = pkg.helloworld["Greeter"];
  var client = new Greeter(target,grpc.credentials.createInsecure());
  var user = "client";
  
  client.sayHello({name: user}, function(err, response) {
    console.log('Greeting:', response.message);
  });
}

当我使用 nodeJS 手动运行它们时,以及在 docker 容器中运行服务器时(客户端仍然在没有容器的情况下使用 node 运行),它工作得很好。

带有命令的docker文件:docker run -it -p 50051:50051 helloapp

FROM node:carbon
 
# Create app directory
WORKDIR /usr/src/appnpm 
 
COPY package.json .
COPY package-lock.json .
 
RUN npm install
 
COPY . .
 
CMD npm start

但是,当我使用 kubernetes 部署服务器时(同样,客户端不在容器中运行),我无法连接。

yaml文件如下:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: helloapp
spec:
  replicas: 1
  selector:
    matchLabels:
      app: helloapp
  strategy: {}
  template:
    metadata:
      labels:
        app: helloapp
    spec:
      containers:
        image: isolatedsushi/helloapp
        name: helloapp
        ports:
        - containerPort: 50051
          name: helloapp
        resources: {}
status: {}
---
apiVersion: v1
kind: Service
metadata:
  name: helloservice
spec:
  selector:
    app: helloapp
  ports:
  - name: grpc
    port: 50051
    targetPort: 50051

部署和服务启动正常

kubectl get svc
NAME           TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)     AGE
helloservice   ClusterIP   10.105.11.22   <none>        50051/TCP   17s


kubectl get pods      
NAME                     READY   STATUS    RESTARTS   AGE
helloapp-dbdfffb-brvdn   1/1     Running   0          45s

但是当我运行客户端时,它无法访问服务器。

任何想法我做错了什么?

【问题讨论】:

  • 原来我必须使用 minikube 服务 helloservice 运行它,然后使用它吐出的 IP 没有 http 部分。然后它起作用了,我不知道为什么我必须这样做......
  • 1.您的客户在哪里,在您的本地电脑上?如果您已将服务公开为 ClusterIP,则它仅在集群内部可见。查看服务类型here。在 minikube 上,LoadBalancer 类型可以通过minikube service 命令访问服务,使用此命令可以将服务公开到外部。看看here。 2.在ip前加http会出现什么错误?
  • @Jakub 1. 客户端确实位于我的本地电脑上。 2. 它给出一个错误:代码 14,详细信息:''目标 dns 的名称解析失败:127.0.0.1:65065'。我不明白的是,当我使用 nodePort 时,比如说 30007,它也不会让我连接到 grpc 服务器。
  • 你的 minikube 版本和驱动是什么?关于http部分我不确定是否可能?有一个关于 https 的answer,所以我认为它可能与您的问题相同。关于nodePort,它应该可以工作。您能否尝试将服务类型从 ClusterIP 更改为 nodePort 并使用 minikube service --url $SERVICE 提到的 here
  • 是的,http 部分是不可能的。关于其余的,它像以前一样工作。当我使用命令kubectl -n hellospace port-forward svc/helloservice 8080:50051 转发时,它也可以工作

标签: node.js docker kubernetes grpc


【解决方案1】:

如cmets中所述


服务类型

如果您已将服务公开为 ClusterIP,则它仅在集群内部可见,如果您不想在外部公开服务,则必须使用 nodePort负载平衡器

发布服务(ServiceTypes)

对于应用程序的某些部分(例如前端),您可能希望将服务公开到集群外部的外部 IP 地址。 Kubernetes ServiceTypes 允许你指定你想要的服务类型。默认为 ClusterIP。

类型值及其行为是:

ClusterIP:在集群内部 IP 上公开服务。选择此值使服务只能从集群内访问。这是默认的 ServiceType。

NodePort:在每个节点的 IP 上的静态端口(NodePort)上公开服务。自动创建 NodePort 服务路由到的 ClusterIP 服务。您可以通过以下请求从集群外部联系 NodePort 服务:。

LoadBalancer:使用云提供商的负载平衡器将服务公开到外部。自动创建外部负载均衡器路由到的 NodePort 和 ClusterIP 服务。

ExternalName:通过返回带有其值的 CNAME 记录,将服务映射到 externalName 字段(例如 foo.bar.example.com)的内容。未设置任何类型的代理。

相关documentation关于那个。


Minikube

使用 minikube,您可以使用 minikube service 命令实现。

关于minikube服务有documentation,还有example


grpc http/https

正如@murgatroid99 提到的here

gRPC 库无法识别地址的 https:// 方案,因此目标名称将导致它尝试解析错误的名称。您应该改用 grpc-server-xxx.com:9090 或 dns:grpc-server-xxx.com:9090 或 dns:///grpc-server-xxx.com:9090。有关 gRPC 如何解释通道目标名称的更多详细信息,请参阅此documentation page

由于它不识别 https,我认为它与 http 相同,所以这是不可能的。


kubectl 端口转发

另外正如@IsolatedSushi 提到的

当我使用命令kubectl -n hellospace port-forward svc/helloservice 8080:50051 转发时它也可以工作

如上所述here

Kubectl port-forward 允许您从本地主机访问内部 Kubernetes 集群进程并与之交互。您可以使用这种方法来调查问题并在本地调整您的服务,而无需事先公开它们。

文档中有一个example

【讨论】:

  • 哇,好答案!我现在明白我的误解了。感谢您清理它,非常感谢您的帮助!
猜你喜欢
  • 1970-01-01
  • 2021-02-10
  • 2022-06-16
  • 1970-01-01
  • 2021-08-26
  • 2022-06-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多