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

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

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

kubeConfig, err = clientcmd.BuildConfigFromFlags("", "/path/to/kubeconfig")
if err != nil {
    // 处理错误
}

kubeClient, err = kubernetes.NewForConfig(kubeConfig)
if err != nil {
    // 处理错误
}

}

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

// 获取 gRPC 服务的 Pod 的 IP 和端口
address, port, err := GetPodIPAndPort("grpc-service")
if err != nil {
    // 处理错误
}

// 将服务器地址添加到解析器
r.InitialState(resolver.State{Addresses: []resolver.Address{
    {Addr: fmt.Sprintf("%s:%d", address, port)},
}})

dialer := grpc.WithResolver(r).DialContext

// 使用拨号器创建与服务器的连接
conn, err := grpc.DialContext(ctx, "grpc://service-name", dialer)
if err != nil {
    // 处理错误
}

// 进行 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
}
}

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

return address, port, nil

}

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

英文:
    import (
    "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

    kubeConfig, err = clientcmd.BuildConfigFromFlags("", "/path/to/kubeconfig")
    if err != nil {
        // handle error
    }

    kubeClient, err = kubernetes.NewForConfig(kubeConfig)
    if err != nil {
        // handle error
    }
}

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

    // get the IP and port of the pod for the gRPC service
    address, port, err := GetPodIPAndPort("grpc-service")
    if err != nil {
        // handle error
    }

    // add the server address to the resolver
    r.InitialState(resolver.State{Addresses: []resolver.Address{
        {Addr: fmt.Sprintf("%s:%d", address, port)},
    }})

    dialer := grpc.WithResolver(r).DialContext

    // use the dialer to create a connection to the server
    conn, err := grpc.DialContext(ctx, "grpc://service-name", dialer)
    if err != nil {
        // handle error
    }

    // do gRPC 
}

func GetPodIPAndPort(serviceName string) (string, int32, error) {
    // get the endpoints for the service
    endpoints, err := kubeClient.CoreV1().Endpoints("default").Get(context.TODO(), serviceName, v1.GetOptions{})
    if err != nil {
        if errors.IsNotFound(err) {
            return "", 0, fmt.Errorf("service not found: %s", serviceName)
        } else {
            return "", 0, err
        }
    }

    // get the IP and port of the first pod in the endpoints list
    if len(endpoints.Subsets) == 0 {
        return "", 0, fmt.Errorf("no pods found for service: %s", serviceName)
    }
    address := endpoints.Subsets[0].Addresses[0].IP
    port := endpoints.Subsets[0].Ports[0].Port

    return address, port, nil
}

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:

确定