K8s Ingress Controller技术细节探讨


本篇内容是对的学习与记录

Nginx官方和K8s官方都维护了一个Ingress Controller,两者实现不太一样。(K8s社区基于Openresty,实现方式和Nginx官方差别很大)

Nginx集群是怎样从是K8s的etcd中拿到变更的数据,又是怎样修改Nginx的共享内存? 因为Nginx是多进程模型。

如何自动修改conf文件


Ingress Controller的工作原理


Ingress是在处理南北向带流量,尤其是集群的出口/入口流量


基于servername(其实就是域名)做第一级的匹配,之后再匹配url,即location。这就是Nginx中最核心的两级匹配

Nginx每一个请求有11个处理阶段,其中一个叫find config,这个阶段就是就是在匹配location

至于匹配域名,在接收到host头部时就开始做了。

性能很高,匹配域名是用的hash表。匹配url用的是Trie树

Linux上有个配置叫net.ipv4.ipforward,设置为1时,就有转发报文的能力,有个iptables规则。

如访问这个虚拟ip时,10%的流量给pod1,90%给pod2


Ingress Controller主要在监控5类数据,其中Endpoint是第一类,Service是第二类。


阿里云SLB的控制台页面,也是一种抽象

Nginx的location本身有很多种配置,如正则表达式匹配,前缀匹配,完全匹配等

但是k8s Ingress在抽象时实现的很有限,因为K8s认为Nginx不是其唯一选择,还可以是lvs等等。只是把一个这些同类产品的最大公约数抽象了出来

高可用(HA)

  1. 数据会不会丢?K8s中的所有数据都会放到etcd中。会通过apiserver提供的grpc,写入到etcd中(etcd提供的现在也是grpc接口)

etcd中存了5类数据

Ingress,Endpoint&Service其实就是两类yaml。当一个外部请求过来,先通过Ingress中的host做域名判断,再通过url做二次匹配。

然后就进入upstream。根据Endpoint&Service 唯一确定该路由给哪个server。


另外在K8s Nginx Ingress还需要Secret和ConfigMap。在身份认证时用到了PKI公钥体系,需要把公私钥放在Nginx上。K8s的secret就是加密后再存etcd; ConfigMap是存放配置的

Ingress Controller必须要监控这5类文件

只要宕掉的机器小于一半,那这些文件就不会丢。。


Networking CNI插件 网桥。是kubelet来管的

  1. Nginx Ingress Controller如何高可用地管理k8s中的pod

Nginx Ingress Controller不会直接通过apiserver去和k8s通信。。不现实

k8s ingress官方,Nginx Ingress Controller,Kong的 Ingress Controller,这几家都用了类似的方案,搞出一个新的进程,(几家名字都不一样),这个进程和nginx共同在一个pod里(其实违反了容器的设计原则,一般一个container里就一个进程,这样好管理)

Ingress-nginx-controller 这个进程,k8s官方和nginx官方都使用了go。 不需要很高的性能,并发能力好

(Go很适合团队协作)


nginx的reload其实不是“nice”的,有长尾效应,可能99%的请求正常,但1%的会有影响。

这也就是k8s官方用openresty的原因


work_process这些都放到ConfigMap里


go写的这个程序,通过informer模式,监听五类资源的变化。一旦有改动,apiserver立马推给store协程

k8s官方的:

有通过lua来管理

三个基于nginx开发的ingress controller的对比

第一个是nginx官方开发的,oss译为opensource

第二个是基于nginx plus(其商业化版本)实现的,不是开源的

第三个是k8s官方的


所谓的静态,即nginx.conf基本不变。

动态则是nginx.conf发生改变

官方的是去改nginx.conf

k8s推出的是基于lua去改共享内存


每秒发送3w个请求,99%的请求,时延小于50ms。

到99.9%时,k8s官方提供的ingress时延就变高了,接近100ms (因为lua,有个balance by lua,即从C语言跳到lua)

nginx官方的因为是纯C语言的,不支持动态修改(改了就要reload)

什么是 balance by lua

“balance by lua” 是指使用 Lua 脚本来实现负载均衡的一种方法。

负载均衡是在分布式系统中常用的技术,用于将流量均匀地分发到多个后端服务实例上,以提高系统的性能和可靠性。在某些情况下,简单的负载均衡策略(如轮询)可能无法满足特定的需求,因此需要一种更灵活的方法来实现。

Lua 是一种轻量级的脚本语言,可以嵌入到其他应用程序中使用。在负载均衡中,可以使用 Lua 脚本来编写自定义的负载均衡算法和逻辑。这种方法称为 “balance by lua”。

使用 Lua 脚本可以获取请求的相关信息(如请求头、请求参数等),并基于这些信息进行动态的负载均衡决策。Lua 脚本可以让负载均衡器更加灵活,能够根据实际业务需求进行定制化的流量分发策略。

负载均衡器通常会将请求传递给预配置的 Lua 脚本进行处理。Lua 脚本可以根据自定义逻辑选择合适的后端服务实例,并将请求转发给选定的实例。这种方式允许负载均衡器根据实时的请求特征、后端服务的状态或其他因素来动态地选择目标实例。

总之,”balance by lua” 是一种使用 Lua 脚本来实现自定义负载均衡逻辑的方法。它提供了更大的灵活性和定制化能力,以满足特定场景下的负载均衡需求。


动态测试: 每隔10-12s对pod做一次调整,一会儿调成5个,一会儿调成7个。

即会不停地启停nginx

k8s官方的,走的是balance by lua,根本不执行reload,所以不会有啥变化

而nginx官方提供的,因为需要重启,就非常差了,最高能时延超过1分钟…(只要不重启,性能就相当好)


https://www.tencentcloud.com/zh/document/product/457/40957


Ingress Controller与Master的通信机制