#python #kubernetes #websocket
Вопрос:
Я пытаюсь наладить связь сервер-клиент между модулями в кластере K8s, используя библиотеку python socket
.
При запуске вне кластера соединение сервер-клиент работает, однако в k8s сервер даже не настроен:
import socket
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.bind(("myApp", 30152)) # it breaks here
server_socket.listen()
А вот мои конфигурационные YAMLs:
---
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
Это означает, что соединение будет осуществляться только между модулями в одном кластере. Кто-нибудь знает, откуда может взяться проблема?
Комментарии:
1. когда вы говорите «это прерывается здесь», что именно вы имеете в виду? есть ли ошибка? время ожидания? Вы пробовали запускать в клиенте и скручивать имя службы вручную?
2. Ошибка, которую я получаю,:
[Errno -3] Temporary failure in name resolution
3. И когда я использую
curl myApp
илиcurl myApp:30152
изнутри модуля, ничего не появляется (хотя я не уверен, правильно ли я использую curl).4. Подождите секунду, ваше развертывание MyApp — это сервер или клиент? Исходя из приведенного выше кода, кажется, что это сервер, тогда каков ваш клиент? откуда вы подключаетесь? Почему вы привязываете сервер к его имени службы?
5. Даже если вы измените это на ‘0.0.0.0’, сокет. прослушивание позволяет серверу принимать подключения, но это неблокирующая операция, я думаю, что ваш код (как есть) будет завершен сразу после запуска.
Ответ №1:
Здесь я построил небольшой пример с клиентским и серверным приложениями python, взаимодействующими друг с другом через службу k8s. Почти с нуля (клонируйте все файлы отсюда, если хотите продолжить)
Сервер
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()
Dockerfile
FROM python:3-alpine
WORKDIR /app
COPY server.py .
CMD ["/usr/local/bin/python3", "/app/server.py"]
building an image, tagging, pushing to container repo (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
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 socketn')
sock.close()
Dockerfile
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 object
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
Комментарии:
1. Я следовал вашему коду, и все работает так, как должно! Добавление адреса сервера, порта в качестве переменных ENV и запуск сервера на 0.0.0.0 решили проблему. Большое вам спасибо за ваше время и помощь 😉