ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

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

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、如何通过TypeLoadBalancer的 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 /CNnginxsvc/Onginxsvc 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 和一个 ReplicationControllerPod 运行后会返回包含客户端信息的 HTML 页面便于验证转发链路$ kubectl create -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/main/docs/examples/http-svc.yaml service http-svc created replicationcontroller http-svc created3. 精确指向单一控制器的 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 默认拿不到静态 IPIngress-NGINX Controller 的实例实际上运行在集群的节点Node上。因此默认情况下Ingress 只有在你的云厂商支持为节点分配静态 IP 时才能获得固定地址。以 GKE/GCE 为例虽然节点会被分配 IP但这些 IP在集群升级时并不会被保留升级后地址会变化导致对外暴露的访问地址不稳定。这正是本示例要解决的问题为整个控制器集群提供一个独立于节点生命周期、可长期保留的静态 IP。第一步获取 IP——为控制器创建 LoadBalancer Service为控制器获取静态 IP 的最简单方式是把它放到一个TypeLoadBalancer的 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触发云厂商创建负载均衡器为其分配外部 IPexternalTrafficPolicy: Local保留客户端源 IP避免额外的转发跳数云厂商负载均衡会对后端做健康检查时尤其推荐loadBalancerIP: 104.154.109.191请求指定的 IP。在首次创建时该字段可先省略让云厂商自动分配之后再按“将临时 IP 提升为静态 IP”一节的方法回填selector通过app.kubernetes.io/name: ingress-nginx等标签选中控制器 Pod本示例手动部署时依赖此标签匹配ports暴露 80HTTP与 443HTTPStargetPort对应控制器容器内的监听端口创建并等待它获得 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()方法中其优先级为--publish-status-address直接使用该标志指定的地址列表用逗号分隔--publish-service调用statusAddressFromService()解析 Service。当 Service 类型为LoadBalancer时从svc.Status.LoadBalancer.Ingress中提取 IP 或 Hostname见 status.go#L381-L397默认兜底遍历集群中所有 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创建示例 Ingressnginx-ingress.yamlapiVersion: 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_address10.180.1.25 commandGET real path/ querynil request_version1.1 request_urihttp://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 patched2. 在云厂商侧把该地址提升为静态地址不同云厂商的“提升”操作各不相同这里给出 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 提供稳定地址的正确姿势是维护一个TypeLoadBalancer的 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),仅供参考
返回列表