本文共 3357 字,大约阅读时间需要 11 分钟。
在Kubernetes集群中,Ingress作为集群内服务对外暴露的访问接入点,承载着几乎所有集群内服务访问的流量。Nginx Ingress Controller作为Kubernetes社区重要的子项目,通过将Kubernetes Ingress资源对象映射为Nginx配置规则,实时化地为集群内服务提供高性能的外网访问入口。然而,随着Kubernetes集群中微服务数量的增加,Ingress路由规则的复杂度和后端Endpoint的频繁变更,导致Nginx配置文件的更频繁的变化,这直接引发了Nginx频繁Reload的需求。
Nginx的核心架构设计决定了其处理配置文件变化时的工作流程。每当Nginx配置文件发生变化时,Master进程接收Reload信号后,会从指定路径重新加载配置文件并校验其有效性。若校验通过,Master进程会根据配置中的worker_processes值fork出新的Nginx Worker进程,并将新配置文件中的Listen Socket FD注册到EPOLL事件监听中。同时,Master进程会向旧Nginx Worker进程发送QUIT信号,要求其平滑退出。旧Worker进程在接收到QUIT信号后,会移除已注册的EPOLL事件,不再处理新的客户端请求,并根据worker_shutdown_timeout值设置定时器处理完剩余请求。若在定时器前处理完所有请求,则旧Worker进程自动退出;否则,会被强制Kill退出,导致客户端请求响应异常。
频繁ReloadNginx配置文件会导致以下问题:
QPS抖动与访问失败:Nginx Worker进程频繁Reload导致的配置规则变化会引发客户端请求处理中的中断,导致QPS抖动和部分访问失败。
长连接服务断开:频繁的Reload操作会导致长连接服务被频繁中断,影响用户体验。
Nginx Worker进程处于shutdown状态:大量处于shutdown状态的Nginx Worker进程会导致内存膨胀,影响系统性能。
针对上述问题,我们需要通过动态更新的方式加载Nginx配置规则,而不需要再次Fork新的Nginx Worker进程。这种方式的关键在于在不Fork新进程的情况下,实时更新已加载到内存中的Nginx配置规则。
Nginx配置文件主要包含以下几个部分:
在Kubernetes集群中,Ingress资源对象映射到Nginx的HTTP Main Block、Server Block、Upstream Block和Location Block等配置章节。因此,我们可以将这些频繁变化的配置内容以Shared Memory的方式统一维持在内存中,同时在Ingress Controller内部暴露管控端口,通过API的方式实时管理Nginx路由规则配置。
当Kubernetes集群中的Ingress及相关资源发生变化时,Ingress Controller会通过Internal API将最新的Nginx配置规则推送到统一的共享内存配置中。这样,当Nginx处理任何新接收的客户端请求时,都能基于最新的共享内存中的配置进行规则匹配和路由转发。
Upstream动态更新:阿里云容器服务Kubernetes集群中的Nginx Ingress Controller组件默认已开启Upstream的动态更新,支持应用服务的灰度发布和蓝绿发布功能。具体配置可参考官方文档。
HTTPS证书动态更新:开启Nginx Ingress Controller的证书动态更新功能后,Ingress的TLS证书统一维护在Nginx的共享内存中。通过以下命令可以查看当前共享内存中配置的证书列表:
kubectl -n kube-system exec -it nginx-ingress-controller-pod-name -- curl http://127.0.0.1:18080/configuration/certs
kubectl -n kube-system exec -it nginx-ingress-controller-pod-name -- curl http://127.0.0.1:18080/configuration/servers
注意事项:开启Server动态更新功能时,部分Ingress Annotation配置暂不支持,正在逐步优化支持中。建议通过直接方式进行配置。
默认配置:阿里云容器服务Kubernetes集群中的Nginx Ingress Controller组件默认已开启Upstream、证书和Server/Location的动态更新功能。
查看配置:
kubectl -n kube-system exec -it nginx-ingress-controller-pod-name -- curl http://127.0.0.1:18080/configuration/backends
kubectl -n kube-system exec -it nginx-ingress-controller-pod-name -- curl http://127.0.0.1:18080/configuration/certs
kubectl -n kube-system exec -it nginx-ingress-controller-pod-name -- curl http://127.0.0.1:18080/configuration/servers
动态更新开关:通过修改nginx-ingress-controller deployment的args参数可以开启或关闭动态更新功能。以下是启用动态证书更新和动态Server/Location更新的示例:
- args: - /nginx-ingress-controller - --configmap=$(POD_NAMESPACE)/nginx-configuration - --tcp-services-configmap=$(POD_NAMESPACE)/tcp-services - --udp-services-configmap=$(POD_NAMESPACE)/udp-services - --annotations-prefix=nginx.ingress.kubernetes.io - --publish-service=$(POD_NAMESPACE)/nginx-ingress-lb - --enable-dynamic-certificates=true - --v=2
通过上述方法,我们可以在不Fork新Nginx Worker进程的情况下,实时更新Nginx配置规则,避免了频繁Reload带来的性能问题。这种动态更新方式不仅提升了集群的整体性能,还确保了Ingress资源对外暴露的稳定性和可靠性。
转载地址:http://lxgb.baihongyu.com/