- API网关
- 云原生
- 负载均衡
- 可观测性
- 微服务
【免费下载链接】kubernetes-ingress
NGINX and NGINX Plus Ingress Controllers for Kubernetes
NGINX Ingress Controller(NIC)在 NGINX Plus 环境下支持 zone-sync(zone synchronization)特性,可让同一部署下的多个控制器副本之间同步共享内存 zone 状态(如限流计数),从而实现多副本间的一致性状态共享。本文基于仓库示例 examples/custom-resources/zone-sync/README.md 展开,完整覆盖最小化配置步骤、全部zone-sync-*配置键的取值与默认值、控制器自动创建的 headless Service 机制、最终生成的nginx.conf指令,以及仓库测试用例的验证方式。
特性概述与适用前提
Zone Synchronization 是 NGINX Plus 提供的高可用特性:同一 zone 的数据可以在多个 NGINX 实例之间实时同步。在 Kubernetes 场景下,当你以 Deployment 方式运行多个 NIC 副本时,开启该特性可以让各副本共享如请求限流(limit_req_zone)等基于共享内存的状态,避免每个副本各自独立计数导致的限流阈值被放大。
适用前提有两点,均由源码明确约束:
该特性仅在 NGINX Plus 下可用。在 ConfigMap 解析逻辑 中,若当前不是 Plus 模式而配置了
zone-sync,控制器会记录告警事件并直接拒绝该配置:ConfigMap <ns>/<name> key zone-sync requires NGINX Plus开启后控制器会自动创建(或清理)一个 headless Service,用于作为
zone_sync_server的服务发现入口,详见下文headless Service 自动管理 一节。
最小化配置:只写一个键
官方示例非常简洁:nginx-config.yaml 全部内容如下,只需在nginx-ingress命名空间的nginx-configConfigMap 中设置zone-sync: "true":
kind: ConfigMap apiVersion: v1 metadata: name: nginx-config namespace: nginx-ingress data: zone-sync: "true"应用方式(README 中的原始步骤):
kubectl apply -f nginx-config.yaml不指定zone-sync-port时,端口会被设置为默认值12345。这一默认值对应源码中的常量 zoneSyncDefaultPort = 12345,当 ConfigMap 中未提供zone-sync-port时,解析逻辑 会兜底填入该默认端口。
全部 zone-sync 配置键与默认值
ConfigMap 中共有 5 个相关键,均可在 parseConfigMapZoneSync 中一一对应到内存结构 ZoneSync:
| ConfigMap 键 | 含义 | 默认值 | 校验规则(源码依据) |
|---|---|---|---|
zone-sync | 布尔值,是否启用 zone synchronization | 未设置即不启用 | 必须为合法布尔值;非 Plus 模式会报错退出 |
zone-sync-port | 监听/同步端口 | 12345 | 必须是合法端口(validation.ValidatePort),非法时告警并回退到 12345 |
zone-sync-resolver-addresses | 解析 headless Service 域名用的 DNS 地址,逗号分隔多个 | kube-dns.kube-system.svc.cluster.local | 每个地址需通过validation.ValidateHost校验 |
zone-sync-resolver-valid | resolver 结果的有效期(nginx time 格式) | 5s | 必须能解析为 nginx time,如10s |
zone-sync-resolver-ipv6 | 布尔值,是否启用 IPv6 解析 | 不设置则跟随disable-ipv6全局配置 | 必须为合法布尔值 |
依赖关系值得注意:除zone-sync外的其余 4 个键都要求zone-sync已开启,否则解析器会拒绝并记录requires 'zone-sync' to be enabled的告警事件(configmaps.go#L879-L885)。
一个功能完整的配置示例(参考仓库测试数据 configmap-with-zonesync-port-resolver.yaml):
kind: ConfigMap apiVersion: v1 metadata: name: nginx-config namespace: nginx-ingress data: zone-sync: "true" zone-sync-port: "34100" zone-sync-resolver-valid: "5s" zone-sync-resolver-ipv6: "true"生成的 nginx.conf 指令
配置解析后,值会被封装为 ZoneSyncConfig 交给模板。启用时,NGINX Plus 的主配置模板 nginx-plus.tmpl 在stream上下文中追加如下 server 块:
server { listen 12345; listen [::]:12345; resolver kube-dns.kube-system.svc.cluster.local valid=5s; zone_sync; zone_sync_server nginx-ingress-headless.nginx-ingress.svc.cluster.local:12345 resolve; }其中几个细节可以直接从源码读出:
zone_sync_server的地址由 组装逻辑 拼接为<domain>-hl.<POD_NAMESPACE>.svc.cluster.local:<port>,<domain>即控制器自身的部署标识;resolve后缀表示通过 resolver 动态解析该域名,配合valid参数控制缓存时间。listen端口与zone_sync_server端口一致,即zone-sync-port的取值。resolver一行由makeResolver根据zone-sync-resolver-addresses、zone-sync-resolver-valid、zone-sync-resolver-ipv6三个键生成。- 模板测试 template_test.go 的快照(snapshots/template_test.snap)验证了默认端口、自定义端口(1337)与自定义 resolver 组合下生成的
zone_sync;与zone_sync_server ... resolve;指令均符合预期。
headless Service 的自动创建与清理
zone_sync_server指向的是一个-hl后缀的 headless Service,而这个 Service 不需要(也不应该)由用户手工创建——控制器会代劳:
- 域名的确定:createCombinedDeploymentHeadlessServiceName 从 Pod 的 OwnerReference 取 ReplicaSet/StatefulSet 名称并去掉哈希后缀,拼成
name-kind形式作为ZoneSync.Domain;启动入口 cmd/nginx-ingress/main.go 也会以combinedDeployment赋值该域名。 - 启动时预校验:主流程在 Plus 模式下,若
ZoneSync.Enable且端口非 0,会先调用 createAndValidateHeadlessService 保证 Service 可用,失败则记录事件并退出。 - 运行期自动创建:syncZoneSyncHeadlessService 发现名为
<domain>-hl的 Service 不存在时,会创建一个clusterIP: None的 headless Service,selector 复用控制器自身的 Pod 标签,并将 ConfigMap 设为 OwnerReference,从而跟随 ConfigMap 生命周期管理;若已被其他副本创建(AlreadyExists),则视为正常并继续。 - 关闭时自动清理:同函数后续分支中,当 zone-sync 被禁用且 NGINX 已就绪时,会删除该 headless Service,避免残留资源。
这套机制解释了为什么zone_sync_server可以直接用 Service DNS 域名:它始终解析到部署自身的所有副本,每个副本既是同步的服务器端也是客户端。
与限流 zone 的联动
zone-sync 的实际收益之一体现在请求限流上:当 zone synchronization 开启后,limit_req_zone会附加sync标志,使限流计数在副本间同步。模板测试用例 TestExecuteTemplate_ForIngressForNGINXPlusWithRequestRateLimitZoneSync 的快照展示了启用后的生成结果:
limit_req_zone ${binary_remote_addr} zone=default/zone1_sync:10m rate=200r/s sync;启用/禁用切换与验证方式
仓库的端到端测试 test_zone_sync.py 覆盖了完整的启停与参数变更流程,其测试数据位于 tests/data/zone-sync/,可作为操作验证清单:
- 初始不带 zone-sync 启动:使用 default-configmap.yaml,确认
nginx.conf中不存在zone_sync;与zone_sync_server,也不存在 headless Service; - 启用最小配置:应用 configmap-with-zonesync-minimal.yaml 后,校验
nginx.conf出现zone_sync;和zone_sync_server,且 headless Service 已创建; - 变更 resolver 有效期:应用 configmap-with-zonesync-resolver-valid.yaml(
zone-sync-resolver-valid: "10s")验证valid=10s生效; - 变更端口:应用 configmap-with-zonesync-minimal-changed-port.yaml 后校验新端口写入
listen与zone_sync_server; - 禁用回收:应用 configmap-with-zonesync-disabled.yaml(
zone-sync: "false")后,nginx.conf中的同步指令消失,headless Service 被删除。
除检查nginx.conf外,测试还通过 NGINX Plus API 响应断言zone_sync字段的存在与否,确认同步状态确实进入了运行中的实例。
小结
| 事项 | 说明 |
|---|---|
| 开启方式 | 在nginx-configConfigMap 中设置zone-sync: "true"即可,端口默认 12345 |
| 可选调优 | zone-sync-port、zone-sync-resolver-addresses(默认 kube-dns)、zone-sync-resolver-valid(默认 5s)、zone-sync-resolver-ipv6 |
| 前置要求 | NGINX Plus;其余配置键依赖zone-sync已启用 |
| 自动化 | 控制器自动创建/删除<deployment>-<kind>-hlheadless Service,无需手工维护 |
| 典型收益 | 多副本间共享内存 zone 同步,如limit_req_zone ... sync的限流计数一致性 |
| 可追溯路径 | 解析:internal/configs/configmaps.go#L862-L959;模板:internal/configs/version1/nginx-plus.tmpl#L326-L336;Service 管理:internal/k8s/service.go#L140-L184 |
- API网关
- 云原生
- 负载均衡
- 可观测性
- 微服务
【免费下载链接】kubernetes-ingress
NGINX and NGINX Plus Ingress Controllers for Kubernetes
相关推荐
nginx-ingress Helm Chart 实战指南:基于 ConfigMap 的 NGINX Ingress 控制器部署与配置
nginx ingress Helm Chart 实战指南:基于 ConfigMap 的 NGINX Ingress 控制器部署与配置 本文以 Kubernet
告别配置混乱:Kubernetes Ingress-Nginx ConfigMap完全指南
告别配置混乱:Kubernetes Ingress Nginx ConfigMap完全指南 在Kubernetes集群中,你是否曾因Ingress配置繁琐而头疼
后端API网关负载均衡云原生kubernetes-handbook 实战:基于 Helm 与 ConfigMap 的 nginx-ingress 控制器完整部署与配置指南
kubernetes handbook 实战:基于 Helm 与 ConfigMap 的 nginx ingress 控制器完整部署与配置指南 本篇技术指南以
教程云原生容器编排
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考