news 2026/9/14 6:50:16

在 Kubernetes 中运行多个 Ingress 控制器:ingress-nginx 的 IngressClass 隔离部署指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
在 Kubernetes 中运行多个 Ingress 控制器:ingress-nginx 的 IngressClass 隔离部署指南

在 Kubernetes 中运行多个 Ingress 控制器:ingress-nginx 的 IngressClass 隔离部署指南

【免费下载链接】ingress-nginxIngress NGINX Controller for Kubernetes项目地址: https://gitcode.com/GitHub_Trending/in/ingress-nginx

本篇技术指南聚焦于 ingress-nginx 项目中"多 Ingress 控制器共存"的经典难题,系统讲解通过 Kubernetes 原生IngressClass机制(推荐方案)与已弃用的kubernetes.io/ingress.class注解(兼容方案)将多个 Ingress 控制器(如内部/外部 ingress-nginx、GCE 等)隔离共存、各司其职的完整部署方法与参数配置。读完本文,你将掌握--controller-class--ingress-class--election-id等关键启动参数的作用原理,能够安全地在一个集群中同时运行两套甚至多套 ingress-nginx 控制器,并理解其底层判类逻辑(依据 pkg/flags/flags.go 与 internal/ingress/controller/ingressclass/ingressclass.go 的源码实现)。

问题的根源:多个控制器互相"抢" Ingress

在默认情况下,如果在一个集群中部署多个 Ingress 控制器(例如同时部署ingress-nginxgce),由于它们都没有经过任何类隔离配置,所有控制器都会同时监听集群中的全部 Ingress 对象,并竞相更新 Ingress 的status.loadBalancer字段,产生令人困惑的互相覆盖、反复改写现象(例如 A 控制器写入自己的负载均衡地址,B 控制器随即又改写成自己的)。这是多控制器共存必须首先解决的问题。

为解决这一问题,官方推荐使用 Kubernetes 的IngressClass机制。而传统的kubernetes.io/ingress.class注解不再被推荐使用[IN DEPRECATION],见 pkg/flags/flags.go 中的参数注释),因为它未来可能被弃用;更优的做法是使用 Ingress 规范中的字段spec.ingressClassName

需要注意一个例外场景:当通过 Helm 以scope.enabled(限制控制器只监听某个命名空间)方式部署时,IngressClass 资源中的spec.controller字段不会被用于判类,此时判定逻辑另走命名空间作用域路径(scope配置见 charts/ingress-nginx/values.yaml)。

方案一:使用 IngressClass 隔离多个控制器(推荐)

如果所有 Ingress 控制器都支持 IngressClass(例如多个 ingress-nginx v1.0+ 实例),可以部署两套控制器,分别授权它们管理两个不同的 IngressClass,然后通过ingressClassName字段在 Ingress 上显式选择由哪套控制器接管。

第一步:为每个控制器分配不同的启动参数

在每套控制器的 Deployment / StatefulSet 中,确保--controller-class--ingress-class设置为互不相同的值。如果新部署的控制器所在命名空间已经存在一个或多个 ingress-nginx 控制器,还必须为新实例指定一个唯一的--election-id,避免多个实例共用同一个 Leader Election 标识导致状态更新异常。

# ingress-nginx Deployment/Statefulset spec: template: spec: containers: - name: ingress-nginx-internal-controller args: - /nginx-ingress-controller - '--election-id=ingress-controller-leader' - '--controller-class=k8s.io/internal-ingress-nginx' - '--ingress-class=k8s.io/internal-nginx' ...

参数含义(默认值均可在 pkg/flags/flags.go 中确认):

启动参数默认值作用
--controller-classk8s.io/ingress-nginx本控制器满足的 IngressClassspec.controller取值,用于匹配 Ingress 引用的 IngressClass 资源
--ingress-classnginx(已弃用路径)本控制器满足的注解类名,对应kubernetes.io/ingress.class注解值
--election-idingress-controller-leader用于 Ingress 状态更新的 Leader Election 标识,多实例共存时必须唯一

第二步:创建与--controller-class对应的 IngressClass 资源

IngressClass 的spec.controller字段值必须与控制器启动参数--controller-class完全一致,这样该控制器才会接管引用此 IngressClass 的 Ingress:

# ingress-nginx IngressClass apiVersion: networking.k8s.io/v1 kind: IngressClass metadata: name: internal-nginx spec: controller: k8s.io/internal-ingress-nginx ...

第三步:在 Ingress 中通过ingressClassName引用目标类

apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: my-ingress spec: ingressClassName: internal-nginx ...

使用 Helm 安装时的等价配置

如果通过 Helm Chart 安装(对应 Chart 位置 charts/ingress-nginx),使用以下 values 片段即可达到与上述手工配置相同的效果:

controller: electionID: ingress-controller-leader ingressClass: internal-nginx # default: nginx ingressClassResource: name: internal-nginx # default: nginx enabled: true default: false controllerValue: "k8s.io/internal-ingress-nginx" # default: k8s.io/ingress-nginx

这里需要特别说明 Chart 中两个易混淆字段的关系(依据 charts/ingress-nginx/values.yaml 的注释):

  • ingressClassResource.controllerValue:创建 IngressClass 资源时写入spec.controller的值,同时也会作为--controller-class参数传入控制器
  • ingressClassResource.name:创建的 IngressClass 资源的名称;
  • ingressClass:向后兼容ingress.class注解时使用的类名(默认nginx)。判类算法为:优先考虑ingressClassName字段,若不存在,再回退查找ingress.class注解
  • ingressClassResource.default: true:将此类标记为集群默认 IngressClass,使未指定ingressClassName的 Ingress 在创建时被自动分配;但若存在多个默认类,Ingress 的创建会被拒绝。

重要:无类注解 Ingress 的处理规则

在多控制器场景下,必须理解"未设置类"的 Ingress 会被谁处理(这一点直接决定了隔离是否生效):

  • 当运行多个 ingress-nginx 控制器时,只有使用了默认--controller-class(即k8s.io/ingress-nginx)的控制器才会处理未设置类注解的 Ingress,否则类注解/类字段变成必填项(对应internal/ingress/controller/ingressclass/ingressclass.go中的Configuration结构及其常量DefaultControllerName = "k8s.io/ingress-nginx"DefaultAnnotationValue = "nginx");
  • --controller-class保持默认值k8s.io/ingress-nginx时,该控制器会同时监控无类注解的 Ingress类注解设置为nginx的 Ingress
  • 若希望控制器只接管特定类的 Ingress,就必须把--controller-class设为非默认值(如上述示例中的k8s.io/internal-ingress-nginx),从而确保它仅满足指定类别的 Ingress。

从源码实现看,判类逻辑在 internal/ingress/controller/store/store.go 中收口:当启用--watch-ingress-without-class(对应 Helm 的controller.watchIngressWithoutClass,默认false,见 values.yaml)时,无类 Ingress 会以"_"作为通配符名称被接受;否则将返回"ingress does not contain a valid IngressClass"错误,即该 Ingress 不被任何严格按类隔离的控制器接管。

方案二:使用 kubernetes.io/ingress.class 注解(已弃用,仅作兼容)

如果同时运行的多个 Ingress 控制器中,有一个或多个尚不支持 IngressClass 机制(例如较老版本的 GCE 控制器),则必须退回到注解方式:在所有希望由 ingress-nginx 接管的 Ingress 上显式标注kubernetes.io/ingress.class: "nginx"

例如,下面的 Ingress 会命中 GCE 控制器,从而被 Ingress-NGINX 控制器主动忽略:

metadata: name: foo annotations: kubernetes.io/ingress.class: "gce"

而下面的 Ingress 则会命中 Ingress-NGINX 控制器,使 GCE 控制器忽略它:

metadata: name: foo annotations: kubernetes.io/ingress.class: "nginx"

自定义注解类名

默认的类名"nginx"可以通过--ingress-class启动参数改为任意其他值:

spec: template: spec: containers: - name: ingress-nginx-internal-controller args: - /nginx-ingress-controller - --ingress-class=internal-nginx

然后在 Ingress 上设置与之对应的注解:

metadata: name: foo annotations: kubernetes.io/ingress.class: "internal-nginx"

注解方式的关键行为

  • 注解值不匹配任何有效类 ⇒ 控制器忽略该 Ingress:将注解设置为任何与有效 ingress class 不匹配的值,都会强制 Ingress-NGINX 控制器忽略该 Ingress;
  • 单控制器场景下的用法:如果你只运行一个 Ingress-NGINX 控制器,但仍希望与其他 Ingress 控制器同时使用,可将注解设置为除"nginx"或空字符串以外的任意值,即可让 NGINX 控制器跳过该 Ingress;
  • 该注解方式本质上依赖 internal/ingress/controller/ingressclass/ingressclass.go 中定义的注解键IngressKey = "kubernetes.io/ingress.class"与默认值DefaultAnnotationValue = "nginx",其注解参数在 pkg/flags/flags.go 中被明确标注为[IN DEPRECATION],且注解判定优先级低于--controller-class(源码注释原文:The parameter --controller-class has precedence over this.)。

补充:辅助判定参数与验证手段

相关启动参数速查

除上述三个核心参数外,多控制器隔离场景下还常涉及以下参数(完整参数表见 docs/user-guide/cli-arguments.md):

参数默认值说明
--watch-ingress-without-classfalse是否额外监控不带 IngressClass / 注解的 Ingress
--ingress-class-by-namefalse是否除spec.controller外,再按 IngressClass 的.metadata.name进行匹配
--disable-leader-electionfalse禁用 Leader Election(多实例共存时谨慎使用)

测试用例佐证

仓库在 test/e2e/settings/ingress_class.go 中提供了针对 IngressClass 行为的端到端测试(覆盖无类 Ingress 处理、WatchWithoutClass等场景),同时在 internal/ingress/controller/store/store_test.go 中通过单元测试验证了WatchWithoutClass: true/false两种配置下 Ingress 过滤逻辑的差异,可作为理解判类行为与回归验证的参考。

总结与最佳实践

场景推荐做法
所有控制器均支持 IngressClass(如同为 ingress-nginx v1.0+)使用--controller-class+ingressClassName隔离,避免使用注解
同命名空间部署第二个 ingress-nginx 控制器额外设置唯一的--election-id
存在不支持 IngressClass 的旧控制器(如 GCE)使用kubernetes.io/ingress.class注解隔离
希望某个控制器只处理特定类--controller-class设为非默认值,并配套创建对应 IngressClass
单控制器但想与其他控制器共存在被忽略的 Ingress 上设置非nginx/ 非空字符串的类注解
限制控制器仅监听单个命名空间开启scope.enabled(注意此时 IngressClass 的spec.controller不参与判类)

核心结论可以概括为:多控制器共存的本质是"类隔离 + 选举隔离"——类隔离决定"哪个控制器接管哪个 Ingress"(IngressClass 优先、注解回退),选举隔离(唯一的--election-id)保证"同一状态更新不被多个控制器互相覆盖"。在部署时优先采用 IngressClass 机制,并始终为非默认控制器使用非默认的--controller-class值,即可获得清晰、可预期的多控制器行为。

【免费下载链接】ingress-nginxIngress NGINX Controller for Kubernetes项目地址: https://gitcode.com/GitHub_Trending/in/ingress-nginx

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/14 6:43:32

AI新闻预测系统:核心技术架构与实现

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/14 6:41:20

MQTT已连接但语音无响应?一文拆解语音助手音频链路排查要点

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/14 6:37:55

嵌入式工程师的避坑指南:Linux、RTOS与调试工具的深刻教训

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华