一文详解Ingress-nginx工作原理
一 背景
Kubernetes 引入了资源对象 Ingress,Ingress 为 Service 提供了可直接被集群外部访问的虚拟主机、负载均衡、SSL 代理、HTTP 路由等应用层转发功能。
ingress-nginx为Kubernetes官方提供的基于nginx实现的ingress。nginx-ingress则为nginx官方提供的实现K8s ingress资源的方案。
Nginx Ingress 由资源对象 Ingress、Ingress 控制器、Nginx 三部分组成。
二 Nginx Configuration
这个 Ingress 控制器的目标是组装一个配置文件(nginx.conf)。对此的实现主要通过检测配置文件发生改变后重载NGINX。但并不是仅在upstream更改时重载Nginx(宕部署应用程序时修改Endpoints)。使用lua-nginx-module实现。
三 Nginx Model
通常,Kubernetes 控制器利用同步循环模式来检查控制器中所需的状态是否更新或需要更改。为此,我们需要使用集群中的不同对象来构建模型,特别是(没有特殊顺序)Ingresses, Services, Endpoints, Secrets, and Configmaps 来生成一个反映集群状态的时间点配置文件。
为了从集群中获得这个对象,我们使用了 Kubernetes Informers,特别是 FilteredSharedInformer。当添加、修改或删除一个新对象时,该informer允许对使用回调对单个更改的更改作出反应。不幸的是,没有办法知道某个特定的更改是否会影响最终的配置文件。因此,对于每一个变化,我们必须根据集群的状态从零开始重建一个新的模型,并与当前的模型进行比较。如果新模型等于当前模型,那么我们就避免生成新的 NGINX 配置并触发重新加载。否则,我们将检查差异是否仅限于 Endpoints。如果是这样,那么我们就使用 HTTP POST 请求将 Endpoints 的新列表发送给在 NGINX 中运行的 Lua 处理程序,同样避免生成新的 NGINX 配置并触发重新加载。如果运行和新模型之间的差异不仅仅是 Endpoints,那么我们将基于新模型创建一个新的 NGINX 配置,替换当前模型并触发重新加载。
该模型的一个用途是避免不必要的重载,当状态没有变化时,并检测定义中的冲突。NGINX 配置的最终表示是从一个 Go 模板生成的,该模板使用新模型作为模板所需变量的输入。
四 Building the NGINX model
构建模型是一个代价高昂的操作,因此必须使用同步循环。通过使用工作队列,可以不丢失更改并删除同步的使用。互斥强制同步循环执行一次,此外还可以在同步循环的开始和结束之间创建一个时间窗口,这样我们就可以丢弃不必要的更新。必须理解的是,集群中的任何更改都可能生成告密者将发送给控制器的事件,这也是生成工作队列的原因之一。
- 通过 CreationTimestamp 字段实现订单入口规则,即,先实现旧规则。
- 如果同一主机的相同路径在多个入口中定义,则最早的规则胜出。
- 如果多个入口包含同一主机的 TLS 部分,则最早的规则胜出。
- 如果多个 Ingresses 定义了影响 Server 块配置的注释,那么最早的规则胜出。
- 创建一个 NGINX 服务器列表(每个主机名)
- 创建一个 NGINX 上行流列表如果多个 Ingresses 为同一个主机定义不同的路径,入口控制器将合并定义。
- 注释应用于入口中的所有路径。
- 多重入口可以定义不同的注释。这些定义在 Ingresses 之间并不共享。
五 When a reload is required¶
下一个列表描述了需要重新加载时的场景:
- 创建新的入口资源。
- TLS 部分添加到现有的入口。
- 改变入口注释,影响不仅仅是上游配置。例如,负载平衡注释不需要重新加载。
- 从入口添加/删除路径。
- 一个进入,服务,秘密被删除。
- 一些来自入口的引用对象可用,如服务或秘密。秘密被更新了。
六 避免重载
在某些情况下,可以避免重载,特别是当端点发生变化时,例如,启动或替换一个 pod。完全删除重载超出了这个入口控制器的范围。这将需要大量的工作,在某种程度上是没有意义的。只有当 NGINX 改变了读取新配置的方式时,这种情况才会改变。基本上,新的改变不会取代辅助进程。
6.1 当endpoints改变避免重载
在每次endpoints更改时,控制器都会从它看到的所有服务中提取端点,并生成相应的后端对象。然后,它将这些对象发送到运行在Nginx中的Lua处理程序。Lua代码又将这些后端存储在共享内存区域中。然后,对于每个请求,运行在balancer_by_lua上下文中的Lua代码检测应该从哪个端点选择上游对等点,并应用配置的负载平衡算法来选择对等点。然后Nginx会处理剩下的事情。这样我们就避免了在端点更改时重新加载Nginx。请注意,这包括只影响Nginx中上游配置的注释更改。
在一个应用程序频繁部署的相对较大的集群中,该功能节省了大量的Nginx重新加载,否则这些重新加载会影响响应延迟、负载平衡质量(每次重新加载后,Nginx都会重置负载平衡状态)等。
6.2 避免错误配置导致的停机¶
因为入口控制器使用同步循环模式工作,所以它将配置应用于所有匹配的对象。如果某些入口对象的配置中断,例如nginx.Ingress.kubernetes.io/configuration-snippet注释中的语法错误,则生成的配置将无效,不会重新加载,因此不会考虑更多的入口。
为了防止这种情况发生,nginx入口控制器可选地公开一个验证接纳webhook服务器,以确保传入的入口对象的有效性。该webhook将传入的入口对象追加到入口列表中,生成配置并调用nginx以确保配置没有语法错误。
参考链接
- 点赞
- 收藏
- 关注作者
评论(0)