如何使用 nginx-ingress 控制器通过 TCP 公开多个服务?

Posted

技术标签:

【中文标题】如何使用 nginx-ingress 控制器通过 TCP 公开多个服务?【英文标题】:How to expose multiple services with TCP using nginx-ingress controller? 【发布时间】:2021-07-21 21:12:15 【问题描述】:

我有多个运行 RDP 应用程序的部署,它们都通过 ClusterIP 服务公开。我在我的 k8s 集群中有 nginx-ingress 控制器,为了允许 tcp,我在 nginx-ingress 控制器部署中添加了--tcp-services-configmap 标志,并为其创建了一个配置映射,如下所示

apiVersion: v1 
kind: ConfigMap
metadata:
name: tcp-services
namespace: ingress-nginx
data:
  3389: “demo/rdp-service1:3389”

这将公开“rdp-service1”服务。而且我还有 10 个这样的服务需要在同一个端口号上公开,但是如果我像这样在同一个 configmap 中添加更多服务

...
data
  3389: “demo/rdp-service1:3389”
  3389: “demo/rdp-service2:3389”

然后它会删除之前的服务数据,因为这里我也在k8s中部署了external-dns,所以ingress使用host: ...创建的所有记录都将开始指向configmap中新添加的服务所附加的部署。

现在我的最终要求是,只要我在入口中附加新创建的部署(RDP 应用程序)的规则,它就会开始允许 TCP 连接,那么有什么方法可以实现这一点。或者有没有其他可用的 Ingress 控制器可以解决这种类型的用例并且也可以很容易地与 external-dns 集成?

注意:- 我正在使用 AWS EKS 集群和带有外部 DNS 的 Route53。

【问题讨论】:

如果我对您的理解正确,您想公开多个DeploymentsRDP 应用,这些应用在单端口上使用TCP 流量和nginx-ingress .您是否考虑过创建一个包含所有内容的Service?您可以通过为每个Deployment 添加标签来做到这一点,例如connect: true,并将其用作Configmap (big-rdp-service:3389) 中Service 的选择器。 @DawidKruk 在这里我也想做基于虚拟名称主机的路由,为此我必须在入口中创建一个规则来指定后端服务和主机名,所以在这里我无法创建服务这包括所有部署。 【参考方案1】:

将此答案发布为社区 wiki,以解释问题中的一些主题,并希望指出解决方案。

随意扩展/编辑它。


NGINX Ingress主要职责是转发HTTP/HTTPS流量。通过添加tcp-services/udp-services,它还可以将TCP/UDP 流量转发到各自的端​​点:

Kubernetes.github.io: Ingress nginx: User guide: Exposing tcp udp services

主要问题是 Kubernetes 中 Ingress 资源的基于 Host 的路由专门针对 HTTP/HTTPS 流量,而不是 TCP (RDP)。

您可以实现以下场景:

Ingress controller: 3389 - RDP Deployment #1 3390 - RDP Deployment #2 3391 - RDP Deployment #3

没有基于Host 的路由。它更像是端口转发。

附注! 此设置还取决于LoadBalancer 分配端口的能力(这可能会受到云提供商规范的限制)


至于可能不太直接的解决方案,我会看看以下资源:

***.com: Questions: Nxing TCP forwarding based on hostname Doc.traefik.io: Traefik: Routing: Routers: Configuring TCP routers Github.com: Bolkedebruin: Rdpgw

我还会检查以下链接:

Aws.amazon.con: Quickstart: Architecture: Rd gateway - AWS 特定

Docs.konghq.com: Kubernetes ingress controller: 1.2.X: Guides: Using tcpingress

代理:

Haproxy.com: Documentation: Aloha: 12-0: Deployment guides: Remote desktop: RDP gateway Haproxy.com: Documentation: Aloha: 10-5: Deployment guides: Remote desktop Haproxy.com: Blog: Microsoft remote desktop services rds load balancing and protection

【讨论】:

感谢您的回复。实际上,我开始了解其他支持基于主机名使用 SNI SSL/TLS 终止的 TCP 路由的入口控制器。我已经尝试了这些入口控制器(Ambassador、Traefik、Kong)并设置了我的用例所需的所有东西,但仍然无法实现,因为我的 docker 映像是 RDP 服务器,所以当我尝试使用 DNS 连接 RDP 客户端时记录(即主机名)然后它无法连接。所以现在我很困惑RDP客户端是否将数据包中的SNI(即主机名)发送到服务器。 @AjayPathak 我无法回答你这个问题,但我认为这个关于 RDP 的问题可以在 Serverfault 上提出。【参考方案2】:

其实,我真的不知道你为什么要使用那个 configmap。

据我所知,nginx-ingress-controller 正在路由来自同一端口的流量并基于主机进行路由。因此,如果您想在同一个端口上公开您的应用程序,请尝试使用:

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name:  .Chart.Name -ingress
  namespace: your-namespace
  annotations:
    kubernetes.io/ingress.class: nginx
spec:
  rules:
  - host: your-hostname
    http:
      paths:
      - pathType: Prefix
        path: "/"
        backend:
          serviceName:  .Chart.Name -service
          servicePort:  .Values.service.nodeport.port 

看你的需求,我觉得你需要一个LoadBalancer而不是Ingress

【讨论】:

感谢您的回复,但这并不能解决我的用例。实际上我有数百个部署,所以我不想用 LoadBalancer 公开每个部署。而且由于我的 docker 镜像是 RDP 桌面,所以使用 nginx-ingress 控制器我不能通过在 ingress 中创建正常规则来直接访问它,为此在 nginx-ingress 控制器中我们必须创建一个配置映射以允许 tcp 连接。这里的问题是,在一个 configmap 中,我们可以为一个 tcp 端口编写一项服务。 嗨@AjayPathak,所以你想通过1个端口公开你的一些部署。如果我理解正确,您可以创建一个 Nodeport 类型的服务,并通过填写“Selector”和“matchLabels”字段来注册要公开的部署 是的@AshBlake 我也试过了,但是如果我在 NodePort 上公开每个部署,那么我无法连接 pod 中的 RDP 应用程序,因为 RDP 客户端应用程序只能连接 3389 端口。跨度> 是的,我认为您应该找到一种方法来改变您的部署。因为您想公开具有 1 个端口、1 个 DNS 的多个部署,这是不可能的。

以上是关于如何使用 nginx-ingress 控制器通过 TCP 公开多个服务?的主要内容,如果未能解决你的问题,请参考以下文章

安装nginx-ingress控制器,使用

GKE 是不是支持带有静态 ip 的 nginx-ingress?

nginx.conf 忽略了 nginx-ingress 配置映射片段

如何使用一个负载均衡器为两个域的两个入口配置 nginx-ingress

k8s集群通过nginx-ingress做tcpudp 4层网络转发

Kubernetes Nginx-Ingress oauth_proxy如何将信息/令牌传递给服务