Kubernetes 集群中的服务器-客户端连接使用 Python 套接字
Server-client connection in Kubernetes cluster using Python socket
我正在尝试使用 python socket
库在 K8s 集群中的 pods 之间进行服务器-客户端通信。
当 运行 在集群外部时,服务器-客户端连接有效,但是在 k8s 中,服务器甚至没有设置:
import socket
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.bind(("myApp", 30152)) # it breaks here
server_socket.listen()
这是我的配置 YAML:
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: myApp
labels:
app: myApp
spec:
replicas: 1
selector:
matchLabels:
app: myApp
template:
metadata:
labels:
app: myApp
spec:
containers:
- name: myApp
image: app_image:version
ports:
- containerPort: 30152
imagePullPolicy: Always
---
apiVersion: v1
kind: Service
metadata:
name: myApp
labels:
app: myApp
spec:
selector:
app: myApp
ports:
- name: myApp
protocol: TCP
port: 30152
type: ClusterIP
---
service type
是一个 ClusterIP
,因为连接只会在同一集群中的 pods 之间。有谁知道问题出在哪里?
在这里,我构建了一些示例,其中包含客户端和服务器 python 应用程序,它们通过 k8s 服务相互通信。几乎从零开始
(如果您想继续,请从 here 克隆所有文件)
服务器
server.py
import socket
import sys
import os
PORT = int(os.getenv('LISTEN_PORT'))
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_address = ('0.0.0.0', PORT)
print('Starting up on {} port {}'.format(*server_address))
sock.bind(server_address)
sock.listen()
while True:
print('\nWaiting for a connection')
connection, client_address = sock.accept()
try:
print('Connection from', client_address)
while True:
data = connection.recv(64)
print('Received {!r}'.format(data))
if data:
print('Sending data back to the client')
connection.sendall(data)
else:
print('No data from', client_address)
break
finally:
connection.close()
Docker 文件
FROM python:3-alpine
WORKDIR /app
COPY server.py .
CMD ["/usr/local/bin/python3", "/app/server.py"]
构建镜像、标记、推送到容器存储库 (GCP):
docker build --no-cache -t q69936079-server .
docker tag q69936079-server gcr.io/<project_id>/q69936079-server
docker push gcr.io/<project_id>/q69936079-server
客户
client.py
import socket
import os
import sys
import time
counter = 0
SRV = os.getenv('SERVER_ADDRESS')
PORT = int(os.getenv('SERVER_PORT'))
while 1:
if counter != 0:
time.sleep(5)
counter += 1
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_address = (SRV, PORT)
print("Connection #{}".format(counter))
print('Connecting to {} port {}'.format(*server_address))
try:
sock.connect(server_address)
except Exception as e:
print("Cannot connect to the server,", e)
continue
try:
message = b'This is the message. It will be repeated.'
print('Sending: {!r}'.format(message))
sock.sendall(message)
amount_received = 0
amount_expected = len(message)
while amount_received < amount_expected:
data = sock.recv(64)
amount_received += len(data)
print('Received: {!r}'.format(data))
finally:
print('Closing socket\n')
sock.close()
Docker 文件
FROM python:3-alpine
WORKDIR /app
COPY client.py .
CMD ["/usr/local/bin/python3", "/app/client.py"]
构建镜像、标记、推送到容器存储库(在我的例子中是 GCP):
docker build --no-cache -t q69936079-client .
docker tag q69936079-client gcr.io/<project_id>/q69936079-client
docker push gcr.io/<project_id>/q69936079-client
K8S
服务器部署
apiVersion: apps/v1
kind: Deployment
metadata:
name: server-deployment
spec:
selector:
matchLabels:
app: server
replicas: 1
template:
metadata:
labels:
app: server
spec:
containers:
- name: server
image: "gcr.io/<project_id>/q69936079-server:latest"
env:
- name: PYTHONUNBUFFERED
value: "1"
- name: LISTEN_PORT
value: "30152"
客户端部署
apiVersion: apps/v1
kind: Deployment
metadata:
name: client-deployment
spec:
selector:
matchLabels:
app: client
replicas: 1
template:
metadata:
labels:
app: client
spec:
containers:
- name: client
image: "gcr.io/<project_id>/q69936079-client:latest"
env:
- name: PYTHONUNBUFFERED
value: "1"
- name: SERVER_ADDRESS
value: my-server-service
- name: SERVER_PORT
value: "30152"
服务器服务
apiVersion: v1
kind: Service
metadata:
name: my-server-service
spec:
type: ClusterIP
selector:
app: server
ports:
- protocol: TCP
port: 30152
验证
k8s 对象
k get all
NAME READY STATUS RESTARTS AGE
pod/client-deployment-7dd5d675ff-pvwd4 1/1 Running 0 14m
pod/server-deployment-56bd44cc68-w6jns 1/1 Running 0 13m
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/kubernetes ClusterIP 10.140.0.1 <none> 443/TCP 12h
service/my-server-service ClusterIP 10.140.13.183 <none> 30152/TCP 38m
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/client-deployment 1/1 1 1 14m
deployment.apps/server-deployment 1/1 1 1 13m
NAME DESIRED CURRENT READY AGE
replicaset.apps/client-deployment-7dd5d675ff 1 1 1 14m
replicaset.apps/server-deployment-56bd44cc68 1 1 1 13m
服务器日志
k logs -f deployment.apps/server-deployment
Starting up on 0.0.0.0 port 30152
Waiting for a connection
Connection from ('10.136.1.11', 48234)
Received b'This is the message. It will be repeated.'
Sending data back to the client
Received b''
No data from ('10.136.1.11', 48234)
Waiting for a connection
Connection from ('10.136.1.11', 48246)
Received b'This is the message. It will be repeated.'
Sending data back to the client
Received b''
No data from ('10.136.1.11', 48246)
客户端日志
k logs -f deployment.apps/client-deployment
Connection #1
Connecting to my-server-service port 30152
Cannot connect to the server, [Errno 111] Connection refused
Connection #2
Connecting to my-server-service port 30152
Cannot connect to the server, [Errno 111] Connection refused
Connection #3
Connecting to my-server-service port 30152
Sending: b'This is the message. It will be repeated.'
Received: b'This is the message. It will be repeated.'
Closing socket
Connection #4
Connecting to my-server-service port 30152
Sending: b'This is the message. It will be repeated.'
Received: b'This is the message. It will be repeated.'
Closing socket
我正在尝试使用 python socket
库在 K8s 集群中的 pods 之间进行服务器-客户端通信。
当 运行 在集群外部时,服务器-客户端连接有效,但是在 k8s 中,服务器甚至没有设置:
import socket
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.bind(("myApp", 30152)) # it breaks here
server_socket.listen()
这是我的配置 YAML:
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: myApp
labels:
app: myApp
spec:
replicas: 1
selector:
matchLabels:
app: myApp
template:
metadata:
labels:
app: myApp
spec:
containers:
- name: myApp
image: app_image:version
ports:
- containerPort: 30152
imagePullPolicy: Always
---
apiVersion: v1
kind: Service
metadata:
name: myApp
labels:
app: myApp
spec:
selector:
app: myApp
ports:
- name: myApp
protocol: TCP
port: 30152
type: ClusterIP
---
service type
是一个 ClusterIP
,因为连接只会在同一集群中的 pods 之间。有谁知道问题出在哪里?
在这里,我构建了一些示例,其中包含客户端和服务器 python 应用程序,它们通过 k8s 服务相互通信。几乎从零开始 (如果您想继续,请从 here 克隆所有文件)
服务器
server.py
import socket
import sys
import os
PORT = int(os.getenv('LISTEN_PORT'))
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_address = ('0.0.0.0', PORT)
print('Starting up on {} port {}'.format(*server_address))
sock.bind(server_address)
sock.listen()
while True:
print('\nWaiting for a connection')
connection, client_address = sock.accept()
try:
print('Connection from', client_address)
while True:
data = connection.recv(64)
print('Received {!r}'.format(data))
if data:
print('Sending data back to the client')
connection.sendall(data)
else:
print('No data from', client_address)
break
finally:
connection.close()
Docker 文件
FROM python:3-alpine
WORKDIR /app
COPY server.py .
CMD ["/usr/local/bin/python3", "/app/server.py"]
构建镜像、标记、推送到容器存储库 (GCP):
docker build --no-cache -t q69936079-server .
docker tag q69936079-server gcr.io/<project_id>/q69936079-server
docker push gcr.io/<project_id>/q69936079-server
客户
client.py
import socket
import os
import sys
import time
counter = 0
SRV = os.getenv('SERVER_ADDRESS')
PORT = int(os.getenv('SERVER_PORT'))
while 1:
if counter != 0:
time.sleep(5)
counter += 1
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_address = (SRV, PORT)
print("Connection #{}".format(counter))
print('Connecting to {} port {}'.format(*server_address))
try:
sock.connect(server_address)
except Exception as e:
print("Cannot connect to the server,", e)
continue
try:
message = b'This is the message. It will be repeated.'
print('Sending: {!r}'.format(message))
sock.sendall(message)
amount_received = 0
amount_expected = len(message)
while amount_received < amount_expected:
data = sock.recv(64)
amount_received += len(data)
print('Received: {!r}'.format(data))
finally:
print('Closing socket\n')
sock.close()
Docker 文件
FROM python:3-alpine
WORKDIR /app
COPY client.py .
CMD ["/usr/local/bin/python3", "/app/client.py"]
构建镜像、标记、推送到容器存储库(在我的例子中是 GCP):
docker build --no-cache -t q69936079-client .
docker tag q69936079-client gcr.io/<project_id>/q69936079-client
docker push gcr.io/<project_id>/q69936079-client
K8S
服务器部署
apiVersion: apps/v1
kind: Deployment
metadata:
name: server-deployment
spec:
selector:
matchLabels:
app: server
replicas: 1
template:
metadata:
labels:
app: server
spec:
containers:
- name: server
image: "gcr.io/<project_id>/q69936079-server:latest"
env:
- name: PYTHONUNBUFFERED
value: "1"
- name: LISTEN_PORT
value: "30152"
客户端部署
apiVersion: apps/v1
kind: Deployment
metadata:
name: client-deployment
spec:
selector:
matchLabels:
app: client
replicas: 1
template:
metadata:
labels:
app: client
spec:
containers:
- name: client
image: "gcr.io/<project_id>/q69936079-client:latest"
env:
- name: PYTHONUNBUFFERED
value: "1"
- name: SERVER_ADDRESS
value: my-server-service
- name: SERVER_PORT
value: "30152"
服务器服务
apiVersion: v1
kind: Service
metadata:
name: my-server-service
spec:
type: ClusterIP
selector:
app: server
ports:
- protocol: TCP
port: 30152
验证
k8s 对象
k get all
NAME READY STATUS RESTARTS AGE
pod/client-deployment-7dd5d675ff-pvwd4 1/1 Running 0 14m
pod/server-deployment-56bd44cc68-w6jns 1/1 Running 0 13m
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/kubernetes ClusterIP 10.140.0.1 <none> 443/TCP 12h
service/my-server-service ClusterIP 10.140.13.183 <none> 30152/TCP 38m
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/client-deployment 1/1 1 1 14m
deployment.apps/server-deployment 1/1 1 1 13m
NAME DESIRED CURRENT READY AGE
replicaset.apps/client-deployment-7dd5d675ff 1 1 1 14m
replicaset.apps/server-deployment-56bd44cc68 1 1 1 13m
服务器日志
k logs -f deployment.apps/server-deployment
Starting up on 0.0.0.0 port 30152
Waiting for a connection
Connection from ('10.136.1.11', 48234)
Received b'This is the message. It will be repeated.'
Sending data back to the client
Received b''
No data from ('10.136.1.11', 48234)
Waiting for a connection
Connection from ('10.136.1.11', 48246)
Received b'This is the message. It will be repeated.'
Sending data back to the client
Received b''
No data from ('10.136.1.11', 48246)
客户端日志
k logs -f deployment.apps/client-deployment
Connection #1
Connecting to my-server-service port 30152
Cannot connect to the server, [Errno 111] Connection refused
Connection #2
Connecting to my-server-service port 30152
Cannot connect to the server, [Errno 111] Connection refused
Connection #3
Connecting to my-server-service port 30152
Sending: b'This is the message. It will be repeated.'
Received: b'This is the message. It will be repeated.'
Closing socket
Connection #4
Connecting to my-server-service port 30152
Sending: b'This is the message. It will be repeated.'
Received: b'This is the message. It will be repeated.'
Closing socket