如何创建根据端口将流量路由到不同 Pod 的 Kubernetes 服务?

如何创建根据端口将流量路由到不同 Pod 的 Kubernetes 服务?

我想要一个 LoadBalancer 类型的服务,它指向端口 80 上的 nginx,并指向端口 22 的单独 sshd pod。但是,我无法使用单个选择器根据端口进行路由。

我使用的用例类似于 github.com,它接受端口 80 到 github.com 的流量以及端口 22 到 ssh 的流量。因此,在这种情况下,DNS 将指向一组 k8s 负载均衡器,我假设它们将路由到每个端口的相应 pod。所以如果我做错了,请告诉我。我愿意接受其他解决方案。

我想避免做的是设置一个像 HAProxy 那样按端口路由的单独 pod。

我研究过使用 Ingress,但它仅适用于 HTTP 流量。

Ingress 不会公开任意端口或协议。将 HTTP 和 HTTPS 以外的服务公开到互联网通常使用 Service.Type=NodePort 或 Service.Type=LoadBalancer 类型的服务。

https://kubernetes.io/docs/concepts/services-networking/ingress/

答案1

我想避免做的是设置一个像 HAProxy 那样按端口路由的单独 pod。

您不需要设置这样的单独 Pod。

Kubernetes Ingress 默认不支持 TCP 或 UDP 服务。但是例如,ingress-nginx控制器提供了一种在不同端口上支持 TCP 或 UDP 的机制。您可以通过修改 ConfigMaps 来公开 TCP 或 UDP 端口。

因此,此 Ingress 控制器使用标志“--tcp-services-configmap”和“--udp-services-configmap”指向现有的配置映射,其中键是要使用的外部端口,值表示要使用以下格式公开的服务:

<namespace/service name>:<service port>:[PROXY]:[PROXY]

查看附加信息这里

此类 ConfigMap 应该已经可用部署 Ingress 控制器。

因此,请尝试:

1. 使用以下 TCP 服务配置创建 ConfigMap。

$ cat ingress-nginx-tcp.yml
apiVersion: v1
kind: ConfigMap
metadata:
  name: ingress-nginx-tcp
  namespace: default  
data:
  "22": targetnamespace/target-service:22

--tcp-services-configmap2. 使用配置中的标志将 Ingress 控制器指向此 ConfigMap,如下所示:

$ kubectl get deployment ingress-nginx-controller -o yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: ingress-nginx-controller
  namespace: default
spec:
...
  template:
...
    spec:
      containers:
      - args:
        - /nginx-ingress-controller
        - --tcp-services-configmap=$(POD_NAMESPACE)/ingress-nginx-tcp
...

3. 在为 Ingress 定义的服务中公开端口 22,如下所示:

$ kubectl get svc ingress-nginx-controller -o yaml 
apiVersion: v1
kind: Service
metadata:
  name: ingress-nginx-controller
  namespace: default
spec:
  ports:
  - name: tcp-22
    nodePort: 30957
    port: 22
    protocol: TCP
    targetPort: 22
...
  type: LoadBalancer
...

您可以定义任意数量的可使用此方法公开的端口。

对于那些使用ingress-nginx helm 图表。大部分配置已经完成,您只需在传输控制协议像这样的部分:
tcp: 
  2222: "default/example-tcp-svc:22"

其中2222是暴露端口,22是服务端口。

答案2

感谢@Ivan M. 为我指明了正确的方向,我只想在这里添加解决方案的代码示例:

首先,令人困惑的是,kubernetes 文档让我误以为不能使用 ingress 来处理非 http 流量。你需要知道的是,你可以使用不同的 ingress 控制器。使用 nginx ingress 控制器,你可以代理任意 tcp 甚至 udp 流量。

第二个障碍是 nginx ingress 有两个单独的存储库。它们是:

我最终使用了 kubernetes/ingress-nginx 控制器。

nginx-values.yaml

controller:
  service:
    enableHttp: true

tcp:
  "22": "other-namespace/service-name:22"

然后我们安装 helm

helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
helm repo update
helm -n nginx -f nginx-values.yaml install ingress-nginx ingress-nginx/ingress-nginx

然后我将 Ingress 安装到 k8s 中。注意ingressClassName

入口文件

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: my-ingress
  namespace: nginx
spec:
  ingressClassName: nginx
  defaultBackend:
    service:
      name: my-http-service
      port:
        number: 80

然后你使用 kubectl 命令

kubectl apply -f ingress.yaml

答案3

带着同样的问题来到这里。找到了另一个不需要独立 Ingres 控制器的解决方案。不太明显,但您的服务可以从不同的部署中选择和匹配 pod,只要它们满足选择器即可。并且服务端口将仅针对具有相应端口打开的 pod。

https://www.linkedin.com/pulse/exposing-multiple-portsservices-same-load-balancer-sunil-agarwal

相关内容