如何在 kubernetes 内部的自定义端口上允许 tcp 服务(不是 http)

如何在 kubernetes 内部的自定义端口上允许 tcp 服务(不是 http)

我有一个在端口 4840 上运行 OPC 服务器的容器。我正在尝试配置我的 microk8s 以允许我的 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 从端口 4840“外部”为我的 OPC 服务器提供服务。例如,如果我的服务器 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

更新守护进程集后,它会重新启动所有 pod。端口似乎已打开,如果我运行此脚本,则输出:

 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-Client 无法连接。它只是说:无法连接到服务器:BadCommunicationError。

当我尝试使用 OPC-Client 连接到服务器时,我在 ingress-daemonset-pod 日志中看到一条错误消息:

2023/02/15 09:57:32 [错误] 999#999:*63002 connect() 连接到上游时失败(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 是运行 OPC 服务器的 pod 的 IP 号码。

因此,它似乎已经理解外部端口 4840 应该代理/转发到我的服务,而我的服务又指向 OPC-server-pod。但为什么我会收到错误...

我不想使用端口转发解决方案,但我尝试了一下,只是想看看它是否有效。

kubectl port-forward service/jawcrusher-service 5000:4840 -n jawcrusher --address='0.0.0.0'

这使我能够使用 OPC 客户端通过端口 5000 连接到服务器。但我不想使用端口转发,我想要一个更永久的解决方案。

有人看到我是否在某个地方犯了错误或者知道如何在 microk8s 中做到这一点吗?

更新 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

几乎在任何情况下,IngressService设置不起作用但运行kubectl port-forward起作用,几乎总是容器在 127.0.0.1 上监听,而所有 Pod 都必须监听 0.0.0.0。kubectl port-forward始终有效的原因是它实际上使用与 Pod 的沙盒容器相同的网络 cgroup 中生成的副本socat,因此其连接性并不代表集群的连接性到 Pod

一个快速测试可以kubectl exec进入集群中的任何其他 Pod(或者也可以通过 ssh/ssm 进入节点),并向 Pod 的 IP 地址发出 curl(或 wget),看看是否可以从集群中的其他地方访问它。由于 Kubernetes 设计要求所有 Pod 都可以相互连接(模数网络策略),因此这是一个低成本的测试,可以找出任何人可以到达该容器,而不仅仅是IngressService配置

相关内容