发送 gRPC 请求时查找端点(服务器)地址

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

Finding endpoint (server) address when sending gRPC requests

问题

在客户端发送gRPC请求时,有没有办法获取端点(服务器)地址?我有一个客户端部署,通过gRPC与Kubernetes集群中的服务器部署进行通信。服务器部署位于一个clusterIP后面。我使用clusterIP的名称和端口来建立客户端和服务器之间的连接。如果我使用多个服务器(将副本数设置为大于1),在客户端发送gRPC请求时,有没有办法获取目标服务器地址?我想选择一个特定的服务器,并且我需要它的IP地址。如何在客户端找到它?

我认为grpc/xds可以自动完成这个操作。然而,似乎这样的信息是隐藏的,并且没有API可以访问它。

我正在使用golang。

英文:

Is there anyway to get the endpoint (server) address when sending gRPC requests in client? I have a client deployment talking to a server deployment in a kubernetes cluster through gRPC. Server deployment sits behind a clusterIP. I use clusterIP's name and port to establish a connection between my client and server. If I use more than one server (setting replicas to more than 1), is there any way to get targeted server address when sending gRPC requests at the client side? I want to chose an specific server, and I need its IP address. How can I find it at client side?

I think grpc/xds somehow does this by itself. However, It seems such information is hidden and there is no API to access it.

I am using golang.

答案1

得分: 1

导入 (
"context"
"fmt"
"google.golang.org/grpc"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/rest"
"k8s.io/client-go/tools/clientcmd"
"k8s.io/client-go/util/retry"
"k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/api/resource"
"k8s.io/apimachinery/pkg/apis/meta/v1"
)

var kubeClient kubernetes.Interface
var kubeConfig *rest.Config

func init() {
var err error

  1. kubeConfig, err = clientcmd.BuildConfigFromFlags("", "/path/to/kubeconfig")
  2. if err != nil {
  3. // 处理错误
  4. }
  5. kubeClient, err = kubernetes.NewForConfig(kubeConfig)
  6. if err != nil {
  7. // 处理错误
  8. }

}

func main() {
r := manual.NewBuilderWithScheme("grpc")

  1. // 获取 gRPC 服务的 Pod 的 IP 和端口
  2. address, port, err := GetPodIPAndPort("grpc-service")
  3. if err != nil {
  4. // 处理错误
  5. }
  6. // 将服务器地址添加到解析器
  7. r.InitialState(resolver.State{Addresses: []resolver.Address{
  8. {Addr: fmt.Sprintf("%s:%d", address, port)},
  9. }})
  10. dialer := grpc.WithResolver(r).DialContext
  11. // 使用拨号器创建与服务器的连接
  12. conn, err := grpc.DialContext(ctx, "grpc://service-name", dialer)
  13. if err != nil {
  14. // 处理错误
  15. }
  16. // 进行 gRPC 操作

}

func GetPodIPAndPort(serviceName string) (string, int32, error) {
// 获取服务的端点
endpoints, err := kubeClient.CoreV1().Endpoints("default").Get(context.TODO(), serviceName, v1.GetOptions{})
if err != nil {
if errors.IsNotFound(err) {
return "", 0, fmt.Errorf("未找到服务:%s", serviceName)
} else {
return "", 0, err
}
}

  1. // 获取端点列表中第一个 Pod 的 IP 和端口
  2. if len(endpoints.Subsets) == 0 {
  3. return "", 0, fmt.Errorf("未找到服务的 Pod:%s", serviceName)
  4. }
  5. address := endpoints.Subsets[0].Addresses[0].IP
  6. port := endpoints.Subsets[0].Ports[0].Port
  7. return address, port, nil

}

要获取特定 Pod 的详细信息,我们需要使用 Kubernetes API。

英文:
  1. import (
  2. "context"
  3. "fmt"
  4. "google.golang.org/grpc"
  5. "k8s.io/client-go/kubernetes"
  6. "k8s.io/client-go/rest"
  7. "k8s.io/client-go/tools/clientcmd"
  8. "k8s.io/client-go/util/retry"
  9. "k8s.io/apimachinery/pkg/api/errors"
  10. "k8s.io/apimachinery/pkg/api/resource"
  11. "k8s.io/apimachinery/pkg/apis/meta/v1"
  12. )
  13. var kubeClient kubernetes.Interface
  14. var kubeConfig *rest.Config
  15. func init() {
  16. var err error
  17. kubeConfig, err = clientcmd.BuildConfigFromFlags("", "/path/to/kubeconfig")
  18. if err != nil {
  19. // handle error
  20. }
  21. kubeClient, err = kubernetes.NewForConfig(kubeConfig)
  22. if err != nil {
  23. // handle error
  24. }
  25. }
  26. func main() {
  27. r := manual.NewBuilderWithScheme("grpc")
  28. // get the IP and port of the pod for the gRPC service
  29. address, port, err := GetPodIPAndPort("grpc-service")
  30. if err != nil {
  31. // handle error
  32. }
  33. // add the server address to the resolver
  34. r.InitialState(resolver.State{Addresses: []resolver.Address{
  35. {Addr: fmt.Sprintf("%s:%d", address, port)},
  36. }})
  37. dialer := grpc.WithResolver(r).DialContext
  38. // use the dialer to create a connection to the server
  39. conn, err := grpc.DialContext(ctx, "grpc://service-name", dialer)
  40. if err != nil {
  41. // handle error
  42. }
  43. // do gRPC
  44. }
  45. func GetPodIPAndPort(serviceName string) (string, int32, error) {
  46. // get the endpoints for the service
  47. endpoints, err := kubeClient.CoreV1().Endpoints("default").Get(context.TODO(), serviceName, v1.GetOptions{})
  48. if err != nil {
  49. if errors.IsNotFound(err) {
  50. return "", 0, fmt.Errorf("service not found: %s", serviceName)
  51. } else {
  52. return "", 0, err
  53. }
  54. }
  55. // get the IP and port of the first pod in the endpoints list
  56. if len(endpoints.Subsets) == 0 {
  57. return "", 0, fmt.Errorf("no pods found for service: %s", serviceName)
  58. }
  59. address := endpoints.Subsets[0].Addresses[0].IP
  60. port := endpoints.Subsets[0].Ports[0].Port
  61. return address, port, nil
  62. }

For getting specific pod details we need to use kubernetes apis.

huangapple
  • 本文由 发表于 2023年3月30日 12:30:35
  • 转载请务必保留本文链接:https://go.coder-hub.com/75884146.html
匿名

发表评论

匿名网友

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

确定