跳到主要内容

常见 Ingress 对比

· 阅读需 6 分钟

本次来对比一下k8s集群中经常使用到的一些 ingress 组件,ingress 它充当了集群中 HTTP 和 HTTPS 流量的入口点。Ingress 可以将流量路由到 Kubernetes 集群内的不同 Service 上,从而实现负载均衡和流量控制的功能。

为什么要关注 Ingress

集群内的服务默认只能在集群内部互相访问。想把服务暴露到外部,最直接的办法是 NodePort 或 LoadBalancer 类型的 Service,但这两种方式各有局限:NodePort 端口范围受限、不好管理域名和路径;LoadBalancer 则每暴露一个服务就要占用一个负载均衡器,在云上意味着实打实的费用。

Ingress 解决的正是这个问题:用一个统一的入口承接所有外部 HTTP/HTTPS 流量,再按域名和路径分发到集群内的各个 Service。选哪个 Ingress 控制器,直接决定了后续路由配置、TLS 管理、四层暴露这些日常运维工作的体验,所以值得在选型阶段就把几个主流方案摆在一起比较。

工作原理

Ingress 的工作原理是通过将 HTTP 和 HTTPS 请求映射到 Service 上来实现的。在 Kubernetes 中,Service 是一种用于将流量路由到 Pod 的资源对象。当 Ingress 接收到来自外部的 HTTP 或 HTTPS 请求时,它会根据请求中的主机名和路径信息,在 Ingress 规则中进行匹配,并将请求路由到相应的 Service 上。

这里有一个容易混淆的点:Ingress 资源本身只是一份声明式的路由规则,写进去并不会自动生效。真正干活的是 Ingress 控制器——它以 Pod 的形式跑在集群里,持续 watch API Server 上的 Ingress、Service、Endpoint 等资源变化,把这些规则翻译成自己底层代理(比如 Nginx、Envoy、Traefik 自带的代理)的配置,然后热加载生效。也就是说:

  1. Ingress 资源:声明"哪个域名的哪个路径转发到哪个 Service";
  2. Ingress 控制器:监听规则变化,生成并加载代理配置;
  3. 底层代理:实际接收外部请求并做转发。

请求匹配时,控制器先按 Host 匹配虚拟主机,再按 Path 匹配路由规则,最后把请求转发到对应 Service 背后的 Pod。TLS 证书通常以 Secret 的形式挂到 Ingress 规则上,由控制器负责在入口处完成卸载。

常见 Ingress 控制器

要使用 Ingress,需要先安装 Ingress 控制器。Kubernetes 并没有提供默认的 Ingress 控制器,但有许多第三方的 Ingress 控制器可供选择:

简单说说几个常见方案的取舍:

  1. Nginx Ingress Controller:社区最常见的选择,基于 Nginx 做反向代理,文档和案例丰富,大量配置通过 annotation 完成,适合作为默认选项;
  2. Traefik:自带 Dashboard,配置动态生效,不需要像 Nginx 那样 reload,对接 Let's Encrypt 自动签发证书也比较顺手;
  3. Istio Ingress Gateway:如果集群已经上了 Istio 服务网格,用它的 Gateway 做入口可以和网格内的流量治理(灰度、熔断、遥测)打通,但单独为了做入口而引入 Istio 就太重了;
  4. 其他如 HAProxy、Kong 等,分别在性能和 API 网关能力上有自己的侧重。

选型思路可以很朴素:没有特殊需求就用 Nginx Ingress;想要动态配置和更现代的运维体验可以看 Traefik;已经在用服务网格就顺势用网格自带的 Gateway。

暴露四层服务

其中,我们会经常想要暴露一些服务到集群外部提供访问,不仅仅是HTTP的7层协议,也有一些基于4层协议,例如Mysql,Redis,Mongdb等服务。

但 Kubernetes 的 Ingress 规范本身只支持 HTTP 和 HTTPS 协议,因此默认的 Ingress 控制器也只支持这两种协议。但是,一些第三方的 Ingress 控制器可以通过扩展来支持 TCP 和 UDP 协议的暴露。

  1. Traefik:Traefik 支持 TCP 协议的暴露,可以通过在 Ingress 规则中指定 traefik.tcp.routerstraefik.tcp.services 来配置 TCP 服务和路由。
  2. Istio:Istio 是一个服务网格框架,它可以通过其 Ingress Gateway 组件支持 TCP 协议的暴露。可以通过在 Ingress Gateway 中定义 VirtualService 来配置 TCP 服务和路由。

补充一点,Nginx Ingress Controller 也能暴露 TCP/UDP 服务,做法是维护 tcp-servicesudp-services 两个 ConfigMap,把"对外端口 → 命名空间/Service:端口"的映射写进去,再在控制器的 Service 上放开对应端口。这不走 Ingress 资源,而是控制器自己的扩展机制。

四层暴露和七层有个本质区别:TCP 层没有 Host 和 Path 的概念,无法像 HTTP 那样靠域名区分后端,只能靠端口号区分服务。所以每暴露一个 TCP 服务就要占用入口的一个端口,服务多了之后端口管理会变得琐碎。

踩坑与注意

  1. 装了 Ingress 资源却不生效,多半是集群里根本没装控制器,或者 Ingress 上的 ingressClassName 和控制器不匹配——集群里跑多个控制器时尤其容易踩这个坑;
  2. 数据库类服务(MySQL、Redis 等)通过 Ingress 暴露到公网要慎重,四层转发不带任何认证加固,更稳妥的方式是走内网、VPN 或跳板机;
  3. 不同控制器的 annotation 互不通用,从 Nginx 迁到 Traefik 时,原来靠 annotation 实现的重写、限流、超时配置都要逐条翻译;
  4. 长连接类的四层服务要留意代理的空闲超时配置,默认值往往比数据库客户端的连接池预期短,容易出现连接被中途掐断的现象。

小结

Ingress 是集群南北向流量的统一入口,规则由 Ingress 资源声明,实际转发由控制器完成。七层场景下几个主流控制器都能胜任,差异主要在配置方式和生态;四层暴露则超出了 Ingress 规范本身,需要依赖 Traefik、Istio Gateway 或 Nginx Ingress 的 ConfigMap 这类各家自己的扩展机制。选型时结合团队已有技术栈和运维习惯来定,比追求功能列表更实际。

评论 / COMMENTS