今年 2 月,社区曾推送了一篇文章:《在 K8s 中,如何选择合适的 Ingress 控制器》。但当时只介绍了两种解决方案。为了帮助读者对 Ingress Controler 建立更完整的认识,今天,社区对现下流行的十种方案做了具体介绍。
作者:Flant
翻译:bot(才云)
技术校对:星空下的文仔(才云)
为特定的应用部署 Kubernetes 集群时,我们通常需要实现来自应用程序本身、业务和开发人员的需求。了解这些后,我们就可以进行架构选择,并为 Kubernetes 选择合适的 Ingress 控制器。
为了方便工程师高效选用合适的 Ingress 控制器,本文对业内的 Ingress 控制器做了整理和功能梳理,最后总结成一篇综述。借助这篇文章,希望读者能找到一个好的起点,然后开始自己的实践。
为了进行客观对比并得到有用的结果,首先我们需要一套特定的标准来确定研究方向。注意,以下评测并不能涵盖所有 Kubernetes Ingress、API 网关、服务网格用例,但会尽可能覆盖常见要求。如果读者希望把评测结果用于自己的案例,建议结合自己的实践再研究一下细节和特殊性。
首先是一些非常普遍的功能,所有解决方案都已实现了它们,所以你不需要对它们过多关注:
开源;
动态服务发现;
SSL 终止;
对 WebSocket 的支持。
这就像是工程师选择 Ingress 控制器时的基本“参数”。常规的 HTTP(S) 代理能够满足软件要求吗?还是需要通过 gRPC、HTTP/2.0?或是需要 TCP(带有 SNI)、UDP?如果你的情况不是特别常规,建议仔细考虑这些问题,防止以后需要重新配置集群。每个控制器都有自己的一组受支持的协议。
控制器的核心可以有几种类型的应用程序,比如最受欢迎的 NGINX、Traefik、HAProxy 和 Envoy 等。通常情况下,这些选择不会对你的流量处理方式产生巨大影响,但是了解“底层”的潜在特性和习惯总是有用的。
将流量路由到特定服务的决策依据是什么?通常你可以用 host 和 path,但也有其他的可能性。匹配这些值是否也支持 RegEx(正则表达式)?
命名空间提供了一种逻辑上分离 Kubernetes 中资源的方法。有些 Ingress 控制器必须被装在不同的命名空间中,它们的作用是仅允许流量进入属于该命名空间的 Pod。而大多数 Ingress 控制器是针对整个集群进行全局操作的,在这种情况下,流量可以到达任何 Pod,而无需考虑其命名空间。
如何将流量定向到应用程序及其服务的正常实例?通常你有主动和被动检查、重试、断路器、自定义运行状况检查等解决方案。如果你对可用性有严格的要求,并希望迅速从负载均衡中删除失败的服务,这个功能非常重要。
对于负载均衡我们有很多选择,从传统的 round-robin 到非传统的 rdp-cookie。粘滞会话(Sticky Sessions)在这里也很常见。
控制器支持哪些认证方式?Basic、digest、OAuth、external auth……如果你为开发人员使用了许多环境(层),或仅通过 Ingress 访问的私有层,这是个值得注意的功能。
控制器是否支持常用的流量分配机制,如金丝雀部署、A/B 测试、镜像?对于需要精确流量管理、高效测试、最小影响进行错误调试、流量管理的应用来说,这个功能非常敏感。
控制器是否有带扩展功能或技术支持的付费版本?
有用于控制器配置的图形界面吗?这个功能对于那些喜欢简单方便,或是需要对 Ingress 配置做一些更改的人很有用。如果开发人员希望“即时”测试流量,它也非常有用。
是否有内置的 JSON Web 令牌验证,用于对最终应用程序的用户进行验证和确认?
模板是否具备可扩展性,允许你将自己的指令、参数等添加到标准配置模板上?
基本请求速率,或基于地址、白名单、国家/地区等的流量过滤的更复杂变体。
能够通过 OpenTracing 或其他选项监视、跟踪、调试从 Ingress 到特定服务、Pod(最好是在服务和 Pod 之间)的请求。
支持 Web 应用程序防火墙。
这一节将从 Kubernetes 官方控制器开始,逐渐扩展到其他广为人知的 Ingress 控制器。
github.com/kubernetes/ingress-nginx
实现:Go/Lua(nginx 是用 C 写的)
许可证:Apache 2.0
Kubernetes 的“官方”控制器(之所以称为官方,是想把它区别于 NGINX 公司的控制器)。这是社区开发的控制器,它基于 nginx Web 服务器,并补充了一组用于实现额外功能的 Lua 插件。
由于 NGINX 十分流行,再加上把它用作控制器时所需的修改较少,它对于 K8s 普通工程师来说,可能是最简单和最直接的选择。
github.com/nginxinc/kubernetes-ingress
实现:Go
许可证:Apache 2.0
这是 NGINX 公司开发的官方产品,它也有一个基于 NGINX Plus 的商业版。NGINX 的控制器具有很高的稳定性、持续的向后兼容性,且没有任何第三方模块。
由于消除了 Lua 代码,和官方控制器相比,它保证了较高的速度,但也因此受到较大限制。相较之下,它的付费版本有更广泛的附加功能,如实时指标、JWT 验证、主动健康检查等。
NGINX Ingress 重要的优势是对 TCP/UDP 流量的全面支持,最主要缺点是缺乏流量分配功能。
github.com/Kong/kubernetes-ingress-controller
实现:Go
许可证:Apache 2.0
Kong Ingress 由 Kong Inc 开发,有两个版本:商业版和免费版。它基于 NGINX 构建,并增加了扩展其功能的 Lua 模块。
最初,Kong Ingress 主要用作 API 网关,用于 API 请求的处理和路由。现在,它已经成为成熟的 Ingress 控制器,主要优点是拥有大量易于安装和配置的附加模块、插件(包括第三方插件)。它开启了控制器具备大量附加功能的先河,其内置函数也提供了许多可能性。Kong Ingress 配置是用 CRD 执行的。
Kong Ingress 的一个重要特性是它只能在一个环境中运行(而不支持跨命名空间)。这是一个颇有争议的话题:有些人认为这是一个缺点,因为必须为每个环境生成实例;而另一些人认为这是一个特殊特性,因为它是更高级别的隔离,控制器故障的影响仅限于其所在的环境。
github.com/containous/traefik
实现:Go
许可证:MIT
最初,这个代理是为微服务请求及其动态环境的路由而创建的,因此具有许多有用的功能:连续更新配置(不重新启动)、支持多种负载均衡算法、Web UI、指标导出、对各种服务的支持协议、REST API、Canary 版本等。
支持开箱即用的 Let’s Encrypt 是它的另一个不错的功能,但它的主要缺点也很明显,就是为了控制器的高可用性,你必须安装并连接其 Key-value store。
在 2019 年 9 月发布的 Traefik v2.0 中,虽然它增加许多不错的新功能,如带有 SNI 的 TCP/SSL、金丝雀部署、流量镜像/shadowing 和经过改进的 Web UI,但一些功能(如 WAF 支持)还在策划讨论中。
与新版本同期推出的还有一个名叫 Maesh 的服务网格,它建在 Traefik 之上。
github.com/jcmoraisjr/haproxy-ingress
实现:Go(HAProxy 是用 C 写的)
许可证:Apache 2.0
HAProxy 是众所周知的代理服务器和负载均衡器。作为 Kubernetes 集群的一部分,它提供了“软”配置更新(无流量损失)、基于 DNS 的服务发现和通过 API 进行动态配置。 HAProxy 还支持完全自定义配置文件模板(通过替换 ConfigMap)以及在其中使用 Spring Boot 函数。
通常,工程师会把重点放在已消耗资源的高速、优化和效率上。而 HAProxy 的优点之一正是支持大量负载均衡算法。值得一提的是,在今年 6 月发布的 v2.0 中,HAProxy 增加了许多新功能,其即将推出的 v2.1 有望带来更多新功能(包括 OpenTracing 支持)。
github.com/appscode/voyager
实现:Go
许可证:Apache 2.0
Voyager 基于 HAProxy,并作为一个通用的解决方案提供给大量供应商。它最具代表性的功能包括 L7 和 L4 上的流量负载均衡,其中,TCP L4 流量负载均衡称得上是该解决方案最关键的功能之一。
在今年早些时候,尽管 Voyager 在 v9.0.0 中推出了对 HTTP/2 和 gRPC 协议的全面支持,但总的来看,对证书管理(Let’s Encrypt 证书)的支持仍是 Voyager 集成的最突出的新功能。
github.com/heptio/contour
实现:Go
许可证:Apache 2.0
Contour 和 Envoy 由同一个作者开发,它基于 Envoy。它最特别的功能是可以通过 CRD(IngressRoute)管理 Ingress 资源,对于多团队需要同时使用一个集群的组织来说,这有助于保护相邻环境中的流量,使它们免受 Ingress 资源更改的影响。
它还提供了一组扩展的负载均衡算法(镜像、自动重复、限制请求率等),以及详细的流量和故障监控。对某些工程师而言,它不支持粘滞会话可能是一个严重缺陷。
istio.io/docs/tasks/traffic-management/ingress
实现:Go
许可证:Apache 2.0
Istio 是 IBM、Google 和 Lyft 的联合开发项目,它是一个全面的服务网格解决方案——不仅可以管理所有传入的外部流量(作为 Ingress 控制器),还可以控制集群内部的所有流量。
Istio 将 Envoy 用作每种服务的辅助代理。从本质上讲,它是一个可以执行几乎所有操作的大型处理器,其中心思想是最大程度的控制、可扩展性、安全性和透明性。
通过 Istio Ingress,你可以对流量路由、服务之间的访问授权、均衡、监控、金丝雀发布等进行优化。
github.com/datawire/ambassador
实现:Python
许可证:Apache 2.0
Ambassador 也是一个基于 Envoy 的解决方案,它有免费版和商业版两个版本。
Ambassador 被称为“Kubernetes 原生 API 微服务网关”,它与 K8s 原语紧密集成,拥有你所期望的从 Ingress controller 获得的功能包,它还可以与各种服务网格解决方案,如 Linkerd、Istio 等一起使用。
顺便提一下,Ambassador 博客日前发布了一份基准测试结果,比较了 Envoy、HAProxy 和 NGINX 的基础性能。
github.com/solo-io/gloo
实现:Go
许可证:Apache 2.0
Gloo 是在 Envoy 之上构建的新软件(于 2018 年 3 月发布),由于它的作者坚持认为“网关应该从功能而不是服务中构建 API”,它也被称为“功能网关”。其“功能级路由”的意思是它可以为后端实现是微服务、无服务器功能和遗留应用的混合应用路由流量。
由于拥有可插拔的体系结构,Gloo 提供了工程师期望的大部分功能,但是其中一些功能仅在其商业版本(Gloo Enterprise)中可用。
github.com/zalando/skipper
实现:Go
许可证:Apache 2.0
Skipper 是 HTTP 路由器和反向代理,因此不支持各种协议。从技术上讲,它使用 Endpoints API(而不是 Kubernetes Services)将流量路由到 Pod。它的优点在于其丰富的过滤器集所提供的高级 HTTP 路由功能,工程师可以借此创建、更新和删除所有 HTTP 数据。
Skipper 的路由规则可以在不停机的情况下更新。正如它的作者所述,Skipper 可以很好地与其他解决方案一起使用,比如 AWS ELB。
文章介绍了 Traefik 和 Istio,却没有详细介绍另一个流行的服务网格解决方案 Linkerd。这是为什么呢?
为简单起见,Linkerd 没有提供自己的 Ingress 控制器,而是旨在和工程师选用的控制器兼容使用。
下表是各种 Ingress 控制器的摘要:
本文旨在尽可能让读者对 Ingress 控制器形成更完整的理解,因为每种控制器都有其优点和缺点。
社区官方的 Ingress 控制器成熟、易于使用,并提供了足以满足大多数情况的出色功能;
如果对可靠性和功能实现的质量有很高的要求,NGINX Ingress 的商业版会是一个合适的选择;
Kong 拥有最丰富的插件集,在其商业版本中也提供了更多功能,它还拥有基于自定义资源的动态配置;
如果比较关注负载均衡和授权,请看看 Traefik 和 HAProxy。它们是开源项目,功能已经经过社区多年验证,非常稳定,而且还在不断发展;
Contour 虽然只有两岁,但它已经具备 Envoy 之上的基础功能;
基于 Envoy 的解决方案拥有最丰富的功能集,尤其是 Istio。但这是一个复杂的解决方案,意味着工程师需要具备更多相关经验来配置、运行、操作它们;
在某些其他情况下,Gloo 的许多功能可能只在付费版本中提供;
如果你的应用程序需要高级或经常更改的 HTTP 路由表,那么 Skipper 可能是一个很合适的解决方案。
如果比较的是全球社区的选择趋势,那么 Istio(20k+⭐)和 Traefik(超过 25k⭐)的优势就显而易见了。即使是社区官方控制器,它也明显处于下风(不到 6k⭐)。相对的,Kong Ingress 和 HAProxy Ingress 最不热门,只有不到 1k⭐。