Kubernetes跨Pod部署Python TCP服务端客户端通信配置方案
问题场景
同一Kubernetes集群节点上部署2个Pod,分别运行Python编写的TCP服务端、客户端程序,配套创建了TCP协议、ClusterIP类型的Service暴露服务端端口,期望通过Service实现两个Pod的网络通信,当前端口为硬编码配置。
当前异常现象:
- 服务端绑定
0.0.0.0地址可正常启动,但客户端无论配置什么地址都无法成功连接服务端 - 尝试通过
os.getenv('SERVER_ADDRESS')、int(os.getenv('SERVER_PORT'))读取环境变量获取服务端地址时,两个接口均返回None
相关代码
服务端代码
import socket def start_server(): s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.bind(("0.0.0.0", 6666)) s.listen(1) c, a = s.accept() filetodown = open("output_received.txt", "wb") while True: print("Receiving....") data = c.recv(1024) if not data: print("Done Receiving.") break filetodown.write(data) filetodown.flush() print(type(filetodown)) filetodown.close() s.close() #...
客户端代码
import socket def send_transaction_file(): file_to_send = open('output.txt', 'rb') s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect(("0.0.0.0", 6666)) data = file_to_send.read(1024) while data: print("Sending...") print(str(data)) s.send(data) data = file_to_send.read(1024) file_to_send.close() print("Done") s.shutdown(2) s.close()
Pod定义代码(基于Kubernetes Python客户端实现)
import time from kubernetes import config, client from kubernetes.client import Configuration from kubernetes.client.api import core_v1_api from kubernetes.client.rest import ApiException from kubernetes.stream import stream def exec_commands(api_instance, podName, app_name, python_script): name = podName resp = None try: resp = api_instance.read_namespaced_pod(name=name, namespace='default') except ApiException as e: if e.status != 404: print("Unknown error: %s" % e) exit(1) if not resp: print("Pod %s does not exist. Creating it..." % name) pod_manifest = { 'apiVersion': 'v1', 'kind': 'Pod', 'metadata': { 'name': name, 'labels': { 'app': app_name} }, 'spec': { 'hostname': podName, 'subdomain': app_name, 'containers': [{ 'image': 'python', 'name': name, "args": [ "/bin/sh", "-c", "pip install kubernetes google-api-python-client google-cloud-container python-hosts && while true;do date;sleep 5; done" #"python3 " + python_script ] }] } } resp = api_instance.create_namespaced_pod(body=pod_manifest, namespace='default') while True: resp = api_instance.read_namespaced_pod(name=name, namespace='default') if resp.status.phase != 'Pending': break time.sleep(1) print("Done.")
Service定义代码
def create_service(core_v1_api): body = kube_setup.client.V1Service( api_version="v1", kind="Service", metadata=kube_setup.client.V1ObjectMeta( name="banking-svc" ), spec=kube_setup.client.V1ServiceSpec( selector={"app": "banking"}, type="ClusterIP", ports=[kube_setup.client.V1ServicePort( port=6666, target_port=6666, protocol="TCP" )] ) ) core_v1_api.create_namespaced_service(namespace="default", body =body)
问题根因与修复方法
一共4个明确的配置错误,逐一修正即可恢复通信:
- 客户端目标地址配置错误
0.0.0.0是专用于服务端绑定监听的通配地址,不能作为客户端主动连接的目标地址。同命名空间下客户端直接连接Service短域名banking-svc即可,不需要写全集群FQDN。把客户端代码里的s.connect(("0.0.0.0", 6666))改成s.connect(("banking-svc", 6666))。 - Service与Pod标签不匹配
Service配置的选择器是app: banking,但Pod的app标签值是调用exec_commands时传入的app_name参数,如果创建服务端Pod时传入的app_name不是banking,Service无法选中后端Pod,没有可用转发端点自然连接失败。创建完服务端Pod和Service后,可执行kubectl get endpoints banking-svc验证,返回结果中能看到服务端Pod的IP+端口才代表标签匹配正常。 - 业务进程未实际启动
当前Pod的启动命令中,运行Python业务脚本的行被注释,容器启动后只会无限循环打印日期、休眠5秒,根本没有运行TCP服务端/客户端代码,端口没有进程监听,不可能连接成功。把args里的循环命令替换成实际的Python启动命令,放开"python3 " + python_script的注释即可。 - 环境变量未手动注入
Kubernetes不会自动注入名为SERVER_ADDRESS、SERVER_PORT的自定义环境变量,直接调用os.getenv读取必然返回None。如果要通过环境变量传递服务地址,需要在Pod的容器配置中显式添加env字段,示例配置:
"containers": [{ "image": "python", "name": name, "env": [ {"name": "SERVER_ADDRESS", "value": "banking-svc"}, {"name": "SERVER_PORT", "value": "6666"} ], "args": [ # 实际启动命令 ] }]
日常使用更推荐直接通过Kubernetes DNS解析Service域名通信,不需要额外配置环境变量,维护成本更低。
内容的提问来源于stack exchange,提问作者topkek
相关产品推荐
相关产品推荐

