英文:
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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论