Kubernetes Ingress 控制器的技术选型技巧

在 Kubernetes 中,服务跟 Pod IP 主要供服务在集群内访问使用,对于集群外的应用是不可见的。 怎么解决这个问题呢? 为了让外部的应用能够访问 Kubernetes 集群中的服务,通常解决办法是 NodePort 和 LoadBalancer。

这两种方案其实各自都存在一些缺点:

  • NodePort 的缺点是一个端口只能挂载一个 Service,而且为了更高的可用性,需要额外搭建一个负载均衡。

  • LoadBalancer 的缺点则是每个服务都必须要有一个自己的 IP,不论是内网 IP 或者外网 IP。 更多情况下,为了保证 LoadBalancer 的能力,一般需要依赖于云服务商。

在Kubernetes的实践、部署中,为了解决像 Pod 迁移、Node Pod 端口、域名动态分配,或者是 Pod 后台地址动态更新这种问题,就产生了 Ingress 解决方案

Nginx Ingress 的缺点

Ingress 是Kubernetes中非常重要的外网流量入口。 在Kubernetes中所推荐的默认值为Nginx Ingress,为了与后面Nginx 提供的商业版 Ingress 区分开来,我就称它为Kubernetes Ingress。

Kubernetes Ingress,顾名思义基于 Nginx 的平台,Nginx 现在是世界上最流行的 Nginx HTTP Sever,相信大家都对 Nginx 也比较熟悉,这是一个优点。 它还有一个优点是 Nginx Ingress 接入 Kubernetes 集群所需的配置非常少,而且有很多文档来指引你如何使用它。 这对于大部分刚接触 Kubernetes 的人或者创业公司来说,Nginx Ingress 的确是一个非常好的选择。

但是当 Nginx Ingress 在一些大环境上使用时,就会出现很多问题:

  • 第一个问题: Nginx Ingress用了一些 OpenResty 的特性,但最终配置加载还是依赖于原有的 Nginx config reload。 当路由配置非常大时,Nginx reload 会耗时很久,时间长达几秒甚至十几秒,这样就会严重影响业务,甚至造成业务中断。

  • 第二个问题: Nginx Ingress 的插件开发非常困难。 如果你认为 Nginx Ingress 本身插件不够用,需要使用一些定制化插件,这个额外的开发任务对程序员来说是十分痛苦的。 因为Nginx Ingress自身的插件能力和可扩展性非常差。

Ingress 选型原则

既然发现了 Nginx Ingress 有很多问题,那是不是考虑选择其他开源的、更好用的 Ingress? 市场上比 Kubernetes Ingress 好用的Ingress起码有十几家,那么如何从这么多 Ingress 中选择适合自己的呢?

Ingress 自身是基于 HTTP 网关的,市面上 HTTP 网关主要有这么几种: Nginx、Golang 原生的网关,以及新崛起的 Envoy 。 但是每个开发人员所擅长的技术栈不同,所以适合的 Ingress 也会不一样。

那么问题来了,我们如何选择一个更加好用的 Ingress 呢? 或者缩小点范围,熟悉 Nginx 或 OpenResty 的开发人员,应该选择哪一个 Ingress 呢?

下面来介绍一下我对 Ingress 控制器选型的一些经验。

选型原则


1.基本特点

首先我认为Ingress 控制器应该具备以下基本功能,如果连这些功能都没有,那完全可以直接pass。

  • 必须开源的,不开源的无法使用。

  • Kubernetes 中Pod 变化非常频繁,服务发现非常重要。

  • 现在 HTTPS 已经很普及了,TLS 或者 SSL 的能力也非常重要,比如证书管理的功能。

  • 支持 WebSocket 等常见协议,在某些情况下,可能还需要支持 HTTP2 、QUIC 等协议。

2.基础软件

前面有提到,每个人擅长的技术平台不一样,所以选择自己更加熟悉的 HTTP 网关也显得至关重要。 比如 Nginx、HAProxy、Envoy 或者是 Golang 原生网关。 因为你熟悉它的原理,在使用中可以实现快速落地。

在生产环境上,高性能是一个很重要的特性,但比之更重要的是高可用。 这意味着你选择的网关,它的可用性、稳定性一定要非常强,只有这样,服务才能稳定。

3.功能需求

抛开上述两点,就是公司业务对网关的特殊需求。你选择一个开源产品,最好肯定是开箱能用的。比如你需要 GRPC 协议转换的能力,那当然希望选的网关具备这样的功能。这里简单列一下影响选择的因素:

  • 协议: 是否支持 HTTP2、HTTP3;

  • 负载均衡算法: 最基本的WRR、一致性哈希负载均衡算法是否能够满足需求,还是需要更加复杂的类似EWMA负载均衡算法。

  • 鉴权限流: 仅需要简单的鉴权,或更进阶的鉴权方式。 又或者需要集成,能够快速的开发出像腾讯云 IM 的鉴权功能。 Kubernetes Ingress除了前面我们提到的存在Nginx reload 耗时长、插件扩展能力差的问题,另外它还存在后端节点调整权重的能力不够灵活的问题。

选择 APISIX

相比Kubernetes Ingress,我个人更推荐 APISIX 作为Ingress  controller。 虽然它在功能上比 Kong 会少很多,但是 APISIX 很好的路由能力、灵活的插件能力,以及本身的高性能,能够弥补在 Ingress 选型上的一些缺点。 对于基于 Nginx 或 Openresty 开发的程序员,如果对现在的 Ingress 不满意,我推荐你们去使用 APISIX 作为 Ingress。

如何将 APISIX 作为 Ingress 呢? 我们首先要做出一个区分,Ingress 是 Kubernetes 名称的定义或者规则定义,Ingress controller 是将 Kubernetes 集群状态同步到网关的一个组件。 但 APISIX 本身只是 API 网关,怎么把 APISIX 实现成 Ingress controller 呢? 我们先来简要了解一下如何实现 Ingress。

实现 Ingress,本质上就只有两部分内容:

  • 第一部分: 需要将 Kubernetes 集群中的配置、或 Kubernetes 集群中的状态同步到 APISIX 集群。

  • 第二部分: 需要将 APISIX中 的一些概念,比如像服务、upstream 等概念定义为 Kubernetes 中的 CRD。

如果实现了第二部分,通过 Kubernetes Ingress 的配置,便可以很快的产生 APISIX。 通过 APISIX Ingress controller 就可以产生 APISIX 相关的配置。 当前为了快速的将 APISIX 落地为能够支持 Kubernetes 的 Ingress ,我们创建了一个开源项目,叫 Ingress Controller。