news 2026/9/14 6:11:38

Ingress-NGINX Controller 静态 IP 分配实战指南:为 Kubernetes Ingress 绑定固定访问地址

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Ingress-NGINX Controller 静态 IP 分配实战指南:为 Kubernetes Ingress 绑定固定访问地址

Ingress-NGINX Controller 静态 IP 分配实战指南:为 Kubernetes Ingress 绑定固定访问地址

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

导读

本文基于 Ingress-NGINX Controller 官方示例(docs/examples/static-ip),完整讲解如何为集群中的 Ingress 资源分配并长期保留一个静态 IP 地址。你将学会:为什么 Ingress 默认拿不到固定 IP、如何通过Type=LoadBalancer的 Service 获取外部 IP、如何用--publish-service让控制器把该 IP 写入所有 Ingress 的status.address,以及如何把临时分配的 IP 提升为永久保留的静态 IP。文中示例配套清单位于 docs/examples/static-ip,可直接复制使用。

前置条件

动手之前,需要先准备以下三样东西,并确保集群内已经运行着 Ingress-NGINX Controller。

1. TLS 证书(用于示例 Ingress)

本示例的 Ingress 使用 TLS,因此需要一个证书 Secret。可以用openssl生成一个自签名证书并导入为tls-secret

$ openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:2048 -keyout tls.key -out tls.crt -subj "/CN=nginxsvc/O=nginxsvc" Generating a 2048 bit RSA private key ................+++ ................+++ writing new private key to 'tls.key' ----- $ kubectl create secret tls tls-secret --key tls.key --cert tls.crt secret "tls-secret" created

更完整的证书与客户端证书认证(双向 TLS)说明见 docs/examples/PREREQUISITES.md。

2. 测试用的 HTTP 后端服务

示例 Ingress 会把流量转发到一个名为http-svc的服务上。你可以使用仓库中的 docs/examples/http-svc.yaml 部署它(该文件会创建一个 Service 和一个 ReplicationController,Pod 运行后会返回包含客户端信息的 HTML 页面,便于验证转发链路):

$ kubectl create -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/main/docs/examples/http-svc.yaml service "http-svc" created replicationcontroller "http-svc" created

3. 精确指向单一控制器的 Ingress 与运行中的控制器

  • Ingress 归类:必须确保你的 Ingress 只被 Ingress-NGINX Controller 接管,避免与其他控制器(如 GCE Ingress)同时争抢。推荐使用ingressClassName: nginx字段(本示例的 nginx-ingress.yaml 即采用该写法),旧的kubernetes.io/ingress.class: "nginx"注解仍可用但已被建议弃用。多控制器共存时的详细配置见 docs/user-guide/multiple-ingress.md。
  • 控制器运行中:集群内需已部署 Ingress-NGINX Controller,安装方式(Helm /kubectl apply/ 云厂商 addon)见 docs/deploy/index.md。

为什么 Ingress 默认拿不到静态 IP

Ingress-NGINX Controller 的实例实际上运行在集群的节点(Node)上。因此默认情况下,Ingress 只有在你的云厂商支持为节点分配静态 IP 时才能获得固定地址。以 GKE/GCE 为例:虽然节点会被分配 IP,但这些 IP在集群升级时并不会被保留,升级后地址会变化,导致对外暴露的访问地址不稳定。

这正是本示例要解决的问题:为整个控制器集群提供一个独立于节点生命周期、可长期保留的静态 IP

第一步:获取 IP——为控制器创建 LoadBalancer Service

为控制器获取静态 IP 的最简单方式,是把它放到一个Type=LoadBalancer的 Service 后面。云厂商的负载均衡器会为 Service 分配一个外部 IP(或域名)。

仓库示例 static-ip-svc.yaml 内容如下:

# This is the backend service apiVersion: v1 kind: Service metadata: name: ingress-nginx-lb labels: app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx spec: externalTrafficPolicy: Local type: LoadBalancer loadBalancerIP: 104.154.109.191 ports: - port: 80 name: http targetPort: 80 - port: 443 name: https targetPort: 443 selector: # Selects ingress-nginx-controller pods app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx

其中几个关键字段的说明:

字段作用
type: LoadBalancer触发云厂商创建负载均衡器,为其分配外部 IP
externalTrafficPolicy: Local保留客户端源 IP,避免额外的转发跳数(云厂商负载均衡会对后端做健康检查时尤其推荐)
loadBalancerIP: 104.154.109.191请求指定的 IP。在首次创建时该字段可先省略(让云厂商自动分配),之后再按“将临时 IP 提升为静态 IP”一节的方法回填
selector通过app.kubernetes.io/name: ingress-nginx等标签选中控制器 Pod,本示例手动部署时依赖此标签匹配
ports暴露 80(HTTP)与 443(HTTPS),targetPort对应控制器容器内的监听端口

创建并等待它获得 IP:

$ kubectl create -f static-ip-svc.yaml service "ingress-nginx-lb" created $ kubectl get svc ingress-nginx-lb NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE ingress-nginx-lb 10.0.138.113 104.154.109.191 80:31457/TCP,443:32240/TCP 15m

如果EXTERNAL-IP一直显示<pending>,说明当前集群不支持LoadBalancer类型服务(常见于本地开发集群或裸金属环境),此时无法通过本方式获取外部 IP。

第二步:分配 IP 给 Ingress——--publish-service标志

拿到外部 IP 后,需要让 Ingress-NGINX Controller 把这个 IP 写入所有 Ingress 的status字段(即kubectl get ing看到的ADDRESS列)。这一步通过给控制器传入--publish-service启动参数完成,参数值为命名空间/Service名

仓库示例 nginx-ingress-controller.yaml 已经包含该参数:

apiVersion: apps/v1 kind: Deployment metadata: name: ingress-nginx-controller labels: app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx spec: replicas: 1 selector: matchLabels: app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx template: metadata: labels: app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx spec: terminationGracePeriodSeconds: 60 containers: - image: registry.k8s.io/ingress-nginx/controller:v1.0.5 name: controller readinessProbe: httpGet: path: /healthz port: 10254 scheme: HTTP livenessProbe: httpGet: path: /healthz port: 10254 scheme: HTTP initialDelaySeconds: 10 timeoutSeconds: 1 ports: - containerPort: 80 hostPort: 80 - containerPort: 443 hostPort: 443 env: - name: POD_NAME valueFrom: fieldRef: fieldPath: metadata.name - name: POD_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace args: - /nginx-ingress-controller - --publish-service=$(POD_NAMESPACE)/ingress-nginx-lb

注意这里的两个细节:

  • --publish-service=$(POD_NAMESPACE)/ingress-nginx-lb使用环境变量动态拼接命名空间,配合fieldRef注入的POD_NAMESPACE,可以保证控制器与 Service 同命名空间时始终指向正确的对象;
  • 该示例清单中hostNetwork被注释掉,且未设置hostPort依赖(hostPort在 CNI 环境下存在已知问题,参见清单内注释),适合大多数托管云集群。

创建控制器 Deployment:

$ kubectl create -f ingress-nginx-controller.yaml deployment "ingress-nginx-controller" created

底层原理:状态同步器如何选择地址

--publish-service的解析与校验位于 pkg/flags/flags.go,控制器启动时还会校验它不能与--publish-status-address同时使用(二者互斥,见 flags.go#L303)。

地址来源的真正实现在 internal/ingress/status/status.go 的runningAddresses()方法中,其优先级为:

  1. --publish-status-address:直接使用该标志指定的地址列表(用逗号分隔);
  2. --publish-service:调用statusAddressFromService()解析 Service。当 Service 类型为LoadBalancer时,从svc.Status.LoadBalancer.Ingress中提取 IP 或 Hostname(见 status.go#L381-L397);
  3. 默认兜底:遍历集群中所有 Running 且 Ready 的控制器 Pod,取其所在节点的 IP(结合--use-node-internal-ip决定用内网还是外网地址)。

状态更新由statusSync负责:通过 leader election 保证同一时刻只有一个实例执行更新;默认每 60 秒(UpdateInterval = 60,见 status.go#L43-L45)周期性地把当前地址同步到所有 Ingress 的status.loadBalancer.ingress字段,地址发生变化时才调用UpdateStatus写回(见 status.go#L272-L320)。这解释了为什么本示例能“一次性”把同一 IP 批量赋予所有归属于该控制器的 Ingress。

第三步:验证 Ingress 获得 IP

创建示例 Ingress(nginx-ingress.yaml):

apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: ingress-nginx spec: ingressClassName: nginx tls: # This assumes tls-secret exists. - secretName: tls-secret rules: - http: paths: - path: / pathType: Prefix backend: # This assumes http-svc exists and routes to healthy endpoints. service: name: http-svc port: number: 80

创建并验证:

$ kubectl create -f ingress-nginx.yaml ingress "ingress-nginx" created $ kubectl get ing ingress-nginx NAME HOSTS ADDRESS PORTS AGE ingress-nginx * 104.154.109.191 80, 443 13m

可以看到ADDRESS列已经显示为前面 LoadBalancer Service 分配的 IP。用curl验证实际访问链路(-kL表示忽略自签名证书校验并跟随重定向):

$ curl 104.154.109.191 -kL CLIENT VALUES: client_address=10.180.1.25 command=GET real path=/ query=nil request_version=1.1 request_uri=http://104.154.109.191:8080/ ...

返回内容来自http-svc后端的响应,说明请求已经完整走通了「外部 IP → LoadBalancer Service → 控制器 → http-svc」整条链路。

从此以后,所有设置了ingressClassName: nginx(或旧式ingress.class: nginx注解)的 Ingress 都会自动获得这个 IP。

一个需要理解的取舍:所有 Ingress 共享同一 IP

与原生的 GCE Ingress(每个 Ingress 独占一个负载均衡器 IP)不同,Ingress-NGINX Controller 的所有请求都经由同一组 NGINX 控制器 Pod 代理,因此同一个 LoadBalancer IP 会被所有 Ingress 共享。Ingress 之间通过域名(Host)与路径规则区分流量,这既是本方案成本低的原因,也意味着你需要依赖 Host 头来路由不同站点。

第四步:保留 IP——删除与重建 Ingress 验证地址不变

Ingress 资源本身可以被随时删除重建,只要 LoadBalancer Service 及其 IP 还存在,新的 Ingress 依然会获得同一地址。验证如下:

$ kubectl delete ing ingress-nginx ingress "ingress-nginx" deleted $ kubectl create -f ingress-nginx.yaml ingress "ingress-nginx" created $ kubectl get ing ingress-nginx NAME HOSTS ADDRESS PORTS AGE ingress-nginx * 104.154.109.191 80, 443 13m

删除后重建的 Ingress 拿到了完全相同的104.154.109.191。这是因为地址来源是 Service,只要控制器持续运行且--publish-service指向的 Service 存在,状态同步器就会周期性地把地址写回(包括新创建的 Ingress)。

第五步:把临时 IP 提升为静态 IP

云厂商自动分配的 IP 通常是“临时”的:如果 Service 被删除或负载均衡器被重建,IP 可能被释放并重新分配。若要让 IP 永久保留,需要把它在云厂商侧提升为静态地址,并把该地址显式写回 Service 清单。

1. 把当前 IP 写入 Service 的loadBalancerIP字段

$ kubectl patch svc ingress-nginx-lb -p '{"spec": {"loadBalancerIP": "104.154.109.191"}}' "ingress-nginx-lb" patched

2. 在云厂商侧把该地址提升为静态地址

不同云厂商的“提升”操作各不相同,这里给出 GKE/GCE 的示例——用gcloud compute addresses create将该地址注册为区域静态地址:

$ gcloud compute addresses create ingress-nginx-lb --addresses 104.154.109.191 --region us-central1 Created [https://www.googleapis.com/compute/v1/projects/kubernetesdev/regions/us-central1/addresses/ingress-nginx-lb]. --- address: 104.154.109.191 creationTimestamp: '2017-01-31T16:34:50.089-08:00' description: '' id: '5208037144487826373' kind: compute#address name: ingress-nginx-lb region: us-central1 selfLink: https://www.googleapis.com/compute/v1/projects/kubernetesdev/regions/us-central1/addresses/ingress-nginx-lb status: IN_USE users: - us-central1/forwardingRules/a09f6913ae80e11e6a8c542010af0000

输出中status: IN_USE表示该地址已被转发规则占用,提升成功。

3. 永久保留

提升为静态后,即使 Service 被删除,IP 也会被云厂商保留。之后你可以随时用spec.loadBalancerIP: 104.154.109.191重建 Service,地址依然生效(static-ip-svc.yaml 中已经预置了这一字段,正好可以直接复用)。

小结与最佳实践

  • 固定地址的载体是 Service,而不是 Ingress:为 Ingress-NGINX Controller 提供稳定地址的正确姿势是维护一个Type=LoadBalancer的 Service,并让控制器通过--publish-service=命名空间/Service名引用它;
  • 地址优先级:控制器状态同步器依次取--publish-status-address--publish-service→ 节点 IP,三选一,前两者互斥(internal/ingress/status/status.go);
  • 保留 IP 必须“云厂商侧静态化 + 清单回填”两步走,只改清单不提升地址、或只提升地址不回填清单,都无法获得可靠、可复用的固定 IP;
  • 多控制器场景:如果集群中存在多个 Ingress 控制器,务必为 Ingress 显式指定ingressClassName: nginx,确保地址同步与流量路由只由 Ingress-NGINX 接管,详见 docs/user-guide/multiple-ingress.md。

按上述步骤操作,你就获得了一个删除重建 Ingress 也不会变化的稳定入口地址,可以放心把 DNS 记录 A 记录指向它。

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

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

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

2026年论文降重工具评测与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:07:52

Vibe Coding工具选型指南:从自然语言驱动到人机协作的评估方法

/* 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:05:40

高斯噪声在数据增强中的核心优势与应用实践

/* 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:05:33

腾讯云OpenClaw部署指南:广告营销Agent基础设施构建与成本优化

做了多年营销技术相关的架构&#xff0c;我对“Agent重构行业”这类说法一直持保留态度。直到我们团队真正把一套开源Agent框架部署到腾讯云&#xff0c;用OpenClaw做了广告营销业务的自动化底座&#xff0c;我才意识到“重构”不是概念包装&#xff0c;而是一套从算力、模型、…

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

全球财经资讯日报的价值与数据分析技术

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

作者头像 李华