如何在Python中使用Kubernetes端口转发中的socket



给出端口转发对象

from kubernetes.stream import stream, portforward

pf = portforward(
k8s_client_v1.connect_get_namespaced_pod_portforward,
pod_name,
name_space,
ports=port
)

pf.socket(port)

pfAF_UNIX族的socket对象。

我需要更好地理解是否另一个AF_INET家族套接字必须实例化,以实现与kubectl客户端相同的功能,例如:kubectl port-forward $pod_name $port

如果有人能分享这种类型实现的任何片段,我将提前表示感谢。

在这一刻创建端口转发对象的灵感来自这里

我不是套接字方面的专家,但我设法用http.client.HTTPConnection包装端口转发的套接字。我想修补requests,但我不能使它工作。

无论如何,这样http请求可以更方便地以高级方式实现。不确定你是不是在找那个,但我是。要查询pod名称、端口和更多信息,可以查看kubernetes的api参考,并在python包中查找相应的方法。
from http.client import HTTPConnection
from kubernetes import client, config
from kubernetes.stream import portforward
from kubernetes.stream.ws_client import PortForward
class ForwardedKubernetesHTTPConnection(HTTPConnection):
def __init__(self, forwarding: PortForward, port: int):
super().__init__("127.0.0.1", port)
self.sock = forwarding.socket(port)
def connect(self) -> None:
pass
def close(self) -> None:
pass
if __name__ == "__main__":
config.load_kube_config()
client_v1 = client.CoreV1Api()
name_space = "my-namespace"  # or get from api somehow
pod_name = "my-pod"  # or get from api somehow
port = 80

pf = portforward(
client_v1.connect_get_namespaced_pod_portforward,
pod_name,
name_space,
ports=str(port)
)
conn = ForwardedKubernetesHTTPConnection(pf, port)
conn.request("GET", "/my/url")  # will fail for other methods
resp = conn.getresponse()
print(resp.status)
print(resp.headers)
print(resp.read())
conn.request("GET", "/my/other/url")
# ...

多亏了你的代码片段,我可以让它为我工作-这意味着你的代码基本上工作:我已经成功地使用它在自定义端口上发送TCP数据到kubernetes服务(虽然还没有尝试过UDP)。它的工作原理似乎与kubectl port-forward非常相似,但并不完全相同。

主要区别在于它实际上没有打开系统上的AF_INET套接字,而是打开AF_UNIX套接字,这意味着它基本上是通过文件名寻址的,而不是IP地址和端口号的元组。所以这真的取决于你想达到什么目标。

如果您只是想从连接到服务的特定端口的Python脚本中写入套接字:这是解决方案。kubernetes API是否提供AF_UNIX套接字对您来说并没有什么区别。

然而,如果你想打开一个连接到kubernetes服务端口的本地端口(例如,使用本地工具连接到kubernetes服务,如基于CLI的数据库管理工具),这只是你想要实现的一半。经过一段时间的尝试,包括尝试像socket.fromfd(unix_sock.fileno(), socket.AF_INET, socket.SOCK_STREAM)这样的hack,我得出的结论是,一个直接的方法来"转换"。Unix套接字到Internet套接字是不可能的。

我建议的一个解决方案是在Python中实现一个简单的端口转发。这意味着运行一个线程,在您想要使用的本地端口上打开一个internet套接字,接收该套接字上的数据并简单地将其转发给unix套接字。它感觉不是很优雅,可能也不是很有效,但它应该可以完成工作。

另一种选择是使用外部工具,如socat,如果可以连接两个套接字。

最新更新