Как разрешить службу TCP (не http) на пользовательском порту внутри Kubernetes
У меня есть контейнер, на котором работает OPC-сервер на порту 4840. Я пытаюсь настроить свои microk8, чтобы мой OPC-клиент мог подключаться к порту 4840. Вот примеры моего развертывания и обслуживания:
(Здесь не определено пространство имен, но они развертываются через конвейеры Azure, и именно там определяется пространство имен, пространство имен для развертывания и службы — «jawcrusher»).
развертывание.yml
apiVersion: apps/v1
kind: Deployment
metadata:
name: jawcrusher
spec:
replicas: 1
selector:
matchLabels:
app: jawcrusher
strategy: {}
template:
metadata:
labels:
app: jawcrusher
spec:
volumes:
- name: jawcrusher-config
configMap:
name: jawcrusher-config
containers:
- image: XXXmicrok8scontainerregistry.azurecr.io/jawcrusher:#{Version}#
name: jawcrusher
ports:
- containerPort: 4840
volumeMounts:
- name: jawcrusher-config
mountPath: "/jawcrusher/config/config.yml"
subPath: "config.yml"
imagePullSecrets:
- name: acrsecret
сервис.yml
apiVersion: v1
kind: Service
metadata:
name: jawcrusher-service
spec:
ports:
- name: 4840-4840
port: 4840
protocol: TCP
targetPort: 4840
selector:
app: jawcrusher
type: ClusterIP
status:
loadBalancer: {}
Итак, теперь я хочу сказать microk8s, чтобы они обслуживали мой OPC-сервер через порт 4840 «извне». Например, если мой DNS для сервера — microk8s.xxxx.internal, я хотел бы подключиться к моему OPC-клиенту к microk8s.xxxx.internal:4840.
Я последовал этому примеру: https://microk8s.io/docs/addon-ingress (прокрутите немного вниз, чтобы увидеть tcp-часть)
Там написано обновить tcp-конфигурацию для входа, вот как это выглядит после того, как я ее обновил:
nginx-ingress-tcp-microk8s-conf:
apiVersion: v1
kind: ConfigMap
metadata:
name: nginx-ingress-tcp-microk8s-conf
namespace: ingress
......
data:
'4840': jawcrusher/jawcrusher-service:4840
binaryData: {}
Также говорится, что нужно открыть порт во входном контроллере. Вот как это выглядит после добавления нового порта:
nginx-ingress-microk8s-контроллер:
spec:
containers:
- name: nginx-ingress-microk8s
image: registry.k8s.io/ingress-nginx/controller:v1.2.0
args:
- /nginx-ingress-controller
- '--configmap=$(POD_NAMESPACE)/nginx-load-balancer-microk8s-conf'
- >-
--tcp-services-configmap=$(POD_NAMESPACE)/nginx-ingress-tcp-microk8s-conf
- >-
--udp-services-configmap=$(POD_NAMESPACE)/nginx-ingress-udp-microk8s-conf
- '--ingress-class=public'
- ' '
- '--publish-status-address=127.0.0.1'
ports:
- name: http
hostPort: 80
containerPort: 80
protocol: TCP
- name: https
hostPort: 443
containerPort: 443
protocol: TCP
- name: health
hostPort: 10254
containerPort: 10254
protocol: TCP
####THIS IS WHAT I ADDED####
- name: jawcrusher
hostPort: 4840
containerPort: 4840
protocol: TCP
После обновления демонсета он перезапускает все модули. Порт кажется открытым, если я запустил этот скрипт, он выведет:
Test-NetConnection -ComputerName microk8s.xxxx.internal -Port 4840
ComputerName : microk8s.xxxx.internal
RemoteAddress : 10.161.64.124
RemotePort : 4840
InterfaceAlias : Ethernet 2
SourceAddress : 10.53.226.55
TcpTestSucceeded : True
Прежде чем я внес изменения, было написано TcpTestSucceeded: False.
Но OPC-клиент не может подключиться. Просто пишет: Не удалось подключиться к серверу: BadCommunicationError.
Я вижу сообщение об ошибке в журналах ingress-daemonset-pod, когда пытаюсь подключиться к серверу с помощью моего OPC-клиента:
2023/02/15 09:57:32 [ошибка] 999#999: *63002 ошибка подключения() (111: Соединение отклонено) при подключении к восходящему каналу, клиент:10.53.225.232, сервер: 0.0.0.0:4840, восходящий поток: «10.1.98.125:4840», байты от/к клиенту:0/0, байты от/к восходящему потоку:0/0
10.53.225.232 — это IP-адрес клиентских компьютеров (где запущен OPC-клиент), а 10.1.98.125 — это IP-номер модуля, на котором работает OPC-сервер.
Похоже, он понял, что внешний порт 4840 должен быть проксирован/перенаправлен на мою службу, которая, в свою очередь, указывает на модуль OPC-сервера. Но почему я получаю ошибку...
Я не хочу использовать решение с переадресацией портов, но я попробовал это, просто чтобы посмотреть, сработает ли оно.
kubectl port-forward service/jawcrusher-service 5000:4840 -n jawcrusher --address='0.0.0.0'
Это позволяет мне подключиться к моему OPC-клиенту к серверу через порт 5000. Но я не хочу использовать переадресацию порта, мне нужно более постоянное решение.
Кто-нибудь видит, я где-то ошибся или знает, как это сделать в микрок8с.
Обновление 1: Вот что выводит netstat:
root@jawcrusher-7787464c5-8w5ww:/jawcrusher# netstat -tulpn
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 127.0.0.1:4840 0.0.0.0:* LISTEN 1/python
tcp6 0 0 ::1:4840 :::* LISTEN 1/python
1 ответ
Практически в любых обстоятельствах, когда настройки не работают, а работа работает, почти всегда контейнер прослушивает 127.0.0.1, тогда как все поды должны прослушивать 0.0.0.0. Причинаkubectl port-forward
работает все время, заключается в том, что он фактически использует копиюsocat
создается в той же сетевой контрольной группе, что и контейнер песочницы пода, поэтому его подключение не отражает подключение кластера к поду.
Быстрый тест может состоять в том, чтобыkubectl exec
в любой другой под в кластере (или подключение к узлу по ssh/ssm также должно работать) и выдачу завитка (или wget) на IP-адрес пода и проверку, доступен ли он из другого места в кластере. Поскольку конструкция kubernetes требует, чтобы все поды могли соединяться друг с другом (сетевая политика по модулю), это дешевый тест, позволяющий выяснить, может ли кто-нибудь получить доступ к этому контейнеру, а не толькоIngress
илиService
конфигурации