如何在创建来自其他 Pod 的 gRPC 客户端时解析 Kubernetes Pod 的主机名?

huangapple go评论143阅读模式
英文:

How to resolve host name of kubernetes pod while creating grpc client from other pod?

问题

问题:

如何解析 Kubernetes Pod 的主机名?

我有以下需求:我们正在使用 Java 的 gRPC,在一个应用中运行 gRPC 服务器,在另一个应用中创建 gRPC 客户端并连接到 gRPC 服务器(该服务器在另一个 Pod 上运行)。


我们有三个运行着 gRPC 服务器的 Kubernetes Pod。

假设:
my-service-0、my-service-1、my-service-2

my-service 的集群 IP 为:10.44.5.11


我们还有另外三个运行着 gRPC 客户端的 Kubernetes Pod。

假设:
my-client-0、my-client-1、my-client-2


无需安全性:

我尝试连接 gRPC 服务器 Pod 和 gRPC 客户端 Pod,它可以正常工作。

gRPC 客户端(POD -> my-client) ----------------> gRPC 服务器(POD -> my-service)

因此,在没有安全性的情况下,我将主机名设置为 my-service,可以正常工作,没有任何问题。

ManagedChannel channel = ManagedChannelBuilder.forAddress("my-service", 50052)
                .usePlaintext()
                .build();

使用 SSL 安全性:

如果我尝试连接 gRPC 服务器,它将抛出主机名不匹配的错误。
我们已经创建了一个带有通配符 *.default.pod.cluster.local 的证书。

将会抛出以下错误:

java.security.cert.CertificateException: No name matching my-service found
	at java.base/sun.security.util.HostnameChecker.matchDNS(HostnameChecker.java:225) ~[na:na]
	at java.base/sun.security.util.HostnameChecker.match(HostnameChecker.java:98) ~[na:na]
	at java.base/sun.security.ssl.X509TrustManagerImpl.checkIdentity(X509TrustManagerImpl.java:455) ~[na:na]

不工作的代码:
     ManagedChannel channel = NettyChannelBuilder.forAddress("my-service", 50052)
                    .sslContext(GrpcSslContexts.forClient().trustManager(new File(System.getenv("GRPC_CLIENT_CA_CERT_LOCATION"))).build())
                    .build();

但是,如果我将主机名设置为 ==> 10-44-5-11.default.pod.cluster.local,则可以正常工作。

工作的代码:
      ManagedChannel channel = NettyChannelBuilder.forAddress("10-44-5-11.default.pod.cluster.local", 50052)
                        .sslContext(GrpcSslContexts.forClient().trustManager(new File(System.getenv("GRPC_CLIENT_CA_CERT_LOCATION"))).build())
                        .build();

现在,我的问题是 Pod 的集群 IP 是动态的,每次应用部署时都会更改。解决这个主机名的正确方法是什么?

如果我提供主机名,它是否可能返回 IP,然后我将 default.pod.cluster.local 添加到主机名,并尝试连接到 gRPC 服务器?

英文:

Problem:

how to resolve host name of kubernetes pod?

I have the Following requirement we are using grpc with java where we have one app where we are running out grpc server other app where we are creating grpc client and connecting to grpc server (that is running on another pod).


We have three kubernetes pod running where our grpc server is running.

lets say :
my-service-0, my-service-1, my-service-2

my-service has a cluster IP as: 10.44.5.11


We have another three kubernetes pod running where our gprc client is running.

lets say:
my-client-0, my-client-1, my-client-2


Without Security:

i am try to connect grpc server pod with grpc client pod and it work fine.

grpc client (POD -> my-client) ----------------> groc server(POD -> my-service)

So without security i am giving host name as my-service and it's working fine without any problem..

ManagedChannel channel = ManagedChannelBuilder.forAddress("my-service", 50052)
                .usePlaintext()
                .build();

With SSL Security:

if i try to connect grpc server it will throw host name not match.
we have created a certificate with wild card *.default.pod.cluster.local

it will throw the below error:

java.security.cert.CertificateException: No name matching my-service found
	at java.base/sun.security.util.HostnameChecker.matchDNS(HostnameChecker.java:225) ~[na:na]
	at java.base/sun.security.util.HostnameChecker.match(HostnameChecker.java:98) ~[na:na]
	at java.base/sun.security.ssl.X509TrustManagerImpl.checkIdentity(X509TrustManagerImpl.java:455) ~[na:na]

Not Working Code:
     ManagedChannel channel = NettyChannelBuilder.forAddress("my-service", 50052)
                    .sslContext(GrpcSslContexts.forClient().trustManager(new File(System.getenv("GRPC_CLIENT_CA_CERT_LOCATION"))).build())
                    .build();

but if i give the host name as like this ==> 10-44-5-11.default.pod.cluster.local it will work fine correctly.

Working Code
      ManagedChannel channel = NettyChannelBuilder.forAddress("10-44-5-11.default.pod.cluster.local", 50052)
                        .sslContext(GrpcSslContexts.forClient().trustManager(new File(System.getenv("GRPC_CLIENT_CA_CERT_LOCATION"))).build())
                        .build();

Now my problem is cluster ip of pod is dynamic and it will change every time during app deploy. what is the right way to resolve this host name?

is it possible if i give host name and it will return me the ip then i will append default.pod.cluster.local to hostname and try to connect to grpc server?

答案1

得分: 2

直接寻址您的 Pod 并不是一个好的解决方案,因为 Kubernetes 可能需要将您的 Pod 在集群中进行移动。这可能是因为节点故障等原因。

为了让您的客户端/流量能够轻松找到所需的容器,您可以将它们放在一个带有单一静态 IP 地址的 Service 后面。Service IP 可以通过 DNS 进行查找。

以下是如何通过完全限定域名(FQDN)连接到该服务:

my-service.default.svc.cluster.local

其中,my-service 是您的服务名称,default 是您的命名空间,svc.cluster.local 是一个可配置的集群域名后缀,用于所有集群服务。

值得注意的是,如果 Pod 在相同的命名空间中,您甚至可以省略 svc.cluster.local 后缀和命名空间,因此您只需引用服务名为 my-service

如需了解更多信息,您可以查阅 Kubernetes 的文档关于 DNS 的内容。

英文:

Addressing your pod directly is not a good solution since Kubernetes may need to move your pods around the cluster. This can occur for example because of the failing node.

To allow you clients/traffic to easy find desired containers you can place them behind a service with single static IP address. Service IP can be look up through DNS.

This is how you can connect to the service through it`s FQDN:

my-service.default.svc.cluster.local 

Where my-service is your service name, default for your namespace and svc.cluster.local is a configurable cluster domain suffix used in all cluster services.

It's worth to know that you can skip svc.cluster.local suffix and even the namespace if the pods are in the same namespace. So you'll just refer to the service as my-service.

For more you can check K8s documents about DNS.

huangapple
  • 本文由 发表于 2020年8月22日 01:46:42
  • 转载请务必保留本文链接:https://go.coder-hub.com/63527709.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定