2026/10/12 22:02:57

k8s集群搭建(四)-------- Ingress-Nginx 路由规则与 TLS 配置实战

k8s集群搭建(四)-------- Ingress-Nginx 路由规则与 TLS 配置实战 1. 从 Service 到外部访问Ingress-Nginx 到底解决了什么问题集群里 Pod 跑起来了Service 也能在集群内部互相访问但一到「让外面的人打开浏览器访问」这一步很多人就卡住了。NodePort 要记端口号LoadBalancer 在自建环境里又没有云厂商给你分配公网 IPService 数量一多端口和 IP 就彻底乱套。Ingress-Nginx 就是来解决这最后一公里的它本质是一个跑在集群里的 Nginx通过监听 Ingress 资源的变化动态生成 Nginx 配置并热加载把外部请求按域名和路径转发到不同的 Service 上。一句话概括它的能力七层路由转发 负载均衡 TLS 终止 静态资源托管 限流。适合谁适合已经用 kubeadm 或二进制方式搭好集群、正在做自建环境对外暴露服务的同学。它和 Service 的分工是Service 负责集群内部的四层寻址Ingress 负责集群边缘的七层入口。你不需要给每个服务都开一个 LoadBalancer只需要一个 Ingress-Nginx 的入口 IP剩下的靠 Host 和 Path 规则分流。这一篇是 k8s 集群搭建系列的第四篇前三篇我们把控制面、工作节点、网络插件、Dashboard 都搞定了。现在集群是就绪状态接下来要做的就是把 Dashboard 以及后续的业务服务通过 Ingress-Nginx 暴露成一个带域名的 HTTPS 地址。整个过程分四步装 MetalLB 拿到入口 IP、装 Ingress-Nginx 控制器、写 Ingress 资源定义路由、配 TLS 证书并用 curl 和 kubectl describe 验证。每一步我都会给出可直接复制的 YAML 和命令你跟着敲就行。先说清楚一个容易混淆的点Ingress 是 k8s 的一种资源类型规则声明Ingress-Nginx 是具体实现这个规则的控制器干活的人。你写的是 Ingress YAML真正让它生效的是 Ingress-Nginx Controller。市面上还有 Traefik、HAProxy Ingress 等实现本文只讲 Ingress-Nginx因为它是目前社区最主流、文档最全、踩坑资料最多的一个。2. 前置准备MetalLB 分配入口 IP 与 Ingress-Nginx 控制器部署在自建内网环境里Ingress-Nginx 的 Service 类型是 LoadBalancer但裸机集群没有云厂商的 LB 实现这个 Service 会一直卡在pending状态拿不到 external-ip。MetalLB 就是填补这个空缺的它用 L2 或 BGP 模式从一个你规划的 IP 地址池里给 LoadBalancer 类型的 Service 分配地址。如果你的服务器本身已经绑定了固定公网 IP这一步可以跳过但实验环境是内网所以必须装。装 MetalLB 之前有个前置动作把 kube-proxy 的 IPVS 模式设为 strict ARP。执行kubectl edit configmap -n kube-system kube-proxy找到mode和ipvs部分改成下面这样apiVersion: kubeproxy.config.k8s.io/v1alpha1 kind: KubeProxyConfiguration mode: ipvs ipvs: strictARP: true改完保存退出然后重启 kube-proxy 让配置生效kubectl rollout restart daemonset kube-proxy -n kube-system。这一步不做的话MetalLB 的 L2 模式可能无法正常响应 ARP 请求表现为 IP 分配了但 ping 不通。接着部署 MetalLB 本体。官方安装清单比较大我把它精简成关键部分你直接 apply 即可。核心是命名空间、CRD、controller Deployment、speaker DaemonSet 和 webhook。注意镜像地址要换成你自己的私有仓库 tagkubectl apply -f metallb-native.yaml kubectl get pods -n metallb-system看到 controller 和每个节点上的 speaker 都是 Running就说明装好了。然后配置地址池写一个metallb-layer2-config.yamlapiVersion: metallb.io/v1beta1 kind: IPAddressPool metadata: name: default-pool namespace: metallb-system spec: addresses: - 10.150.1.90-10.150.1.91 --- apiVersion: metallb.io/v1beta1 kind: L2Advertisement metadata: name: default-l2-advertisement namespace: metallb-system spec: ipAddressPools: - default-pooladdresses换成你内网里一段没人用的空闲 IP我这里是 10.150.1.90 到 91 两个地址。执行kubectl apply -f metallb-layer2-config.yaml应用。L2 模式不需要路由器支持 BGP配置最简单适合实验环境。接下来装 Ingress-Nginx。可以用 helm也可以直接 apply 官方 yaml。我用后者方便控制镜像来源。官方清单里包含 Namespace、ServiceAccount、RBAC、ConfigMap、两个 Servicecontroller 和 admission、Deployment、两个 Job生成和 patch webhook 证书、IngressClass 和 ValidatingWebhookConfiguration。关键点在于 controller 的 Service 类型是 LoadBalancerMetalLB 会从这里分配 external-ipkubectl apply -f ingress-nginx.yaml kubectl get svc -n ingress-nginx等一会儿你会看到ingress-nginx-controller的 EXTERNAL-IP 变成了 10.150.1.90这就是集群的统一入口。同时确认 IngressClass 存在kubectl get ingressclass应该有一个名为 nginx 的类controller 字段是k8s.io/ingress-nginx。这个类名后面写 Ingress 资源时要用到。3. 可复制的 Ingress 资源与 TLS 证书配置现在入口有了开始写路由规则。我拿第三篇里部署的 Kubernetes Dashboard 做例子把它通过k8s.test.com/dashboard暴露出来。Dashboard 后端本身是 HTTPS 的所以 Ingress 这里要加一个backend-protocol: HTTPS的注解否则会 502。先创建 TLS 证书。自签一张就行生产环境换成正式证书openssl req -x509 -nodes -days 365 -newkey rsa:2048 \ -keyout dashboard.key -out dashboard.crt \ -subj /CNk8s.test.com/Odashboard kubectl create secret tls dashboard-tls-secret \ --key dashboard.key --cert dashboard.crt \ -n kubernetes-dashboard这里 Secret 必须建在 Dashboard 所在的kubernetes-dashboard命名空间因为 Ingress 资源也在那个命名空间TLS 引用是同命名空间的。创建完用kubectl get secret -n kubernetes-dashboard dashboard-tls-secret确认类型是kubernetes.io/tls。然后写 Ingress 资源ingress-dashboard-config.yamlapiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: kubernetes-dashboard-ingress namespace: kubernetes-dashboard annotations: nginx.ingress.kubernetes.io/backend-protocol: HTTPS nginx.ingress.kubernetes.io/rewrite-target: /$2 spec: ingressClassName: nginx tls: - hosts: - k8s.test.com secretName: dashboard-tls-secret rules: - host: k8s.test.com http: paths: - path: /dashboard(/|$)(.*) pathType: ImplementationSpecific backend: service: name: kubernetes-dashboard-kong-proxy port: number: 443几个关键字段解释一下。ingressClassName: nginx指定用哪个控制器必须和 IngressClass 名字一致。rewrite-target: /$2配合正则路径/dashboard(/|$)(.*)把/dashboard/xxx重写成/xxx再转发给后端因为 Dashboard 后端不认识/dashboard这个前缀。backend-protocol: HTTPS告诉 Nginx 用 HTTPS 去连后端。pathType: ImplementationSpecific是因为用了正则必须用这个类型。如果你要配多个域名或多个路径就在rules下面继续加。比如再加一个api.test.com指向另一个 Service- host: api.test.com http: paths: - path: / pathType: Prefix backend: service: name: my-api-service port: number: 8080Prefix类型做前缀匹配适合普通 HTTP 服务。多个 Ingress 资源可以共存控制器会把它们合并成一份 Nginx 配置。写完执行kubectl apply -f ingress-dashboard-config.yaml。4. 验证路由生效curl 与 kubectl describe 实操配置提交后先看 Ingress 资源本身的状态kubectl describe ingress kubernetes-dashboard-ingress -n kubernetes-dashboard输出里重点看三块Rules段确认 Host 和 Path 解析正确TLS段确认 secretName 是 dashboard-tls-secretEvents段如果没有报错就说明控制器接受了这份配置。如果 Events 里有invalid ingress class或admission webhook denied说明类名写错或 webhook 校验没过。接着验证控制器有没有真正生成 Nginx 配置。看 controller 的日志kubectl logs -n ingress-nginx deploy/ingress-nginx-controller --tail50正常会看到类似Adding ingress kubernetes-dashboard/kubernetes-dashboard-ingress和Reloading nginx configuration的日志。如果日志里出现error obtaining ingress class或unexpected error就要回头检查 IngressClass。然后从集群外部你的办公电脑验证。先在 hosts 文件里加一行把域名指到入口 IP# Linux/macOS: /etc/hosts # Windows: C:\Windows\System32\drivers\etc\hosts 10.150.1.90 k8s.test.com用 curl 带-k跳过自签证书校验验证 HTTPS 路由curl -k -I https://k8s.test.com/dashboard期望看到HTTP/2 200或者HTTP/1.1 302Dashboard 可能重定向到登录页。如果返回 404说明 rewrite 规则没匹配上返回 502说明后端协议或端口不对返回 503说明后端 Service 没有可用 Endpoint。再验证一下 HTTP 到 HTTPS 的跳转如果你配了强制跳转注解的话以及不带路径的根访问curl -k -I https://k8s.test.com/还可以直接绕过域名用入口 IP 加 Host 头测试排除 DNS 干扰curl -k -I https://10.150.1.90/dashboard -H Host: k8s.test.com这个命令能直接验证 Ingress 的 Host 匹配逻辑如果它通了但域名访问不通问题就在 DNS 或 hosts 配置上。最后浏览器打开https://k8s.test.com/dashboard能看到 Dashboard 登录页就大功告成了。5. 常见报错排查从 401 到 local proxy failed 的对照表Ingress-Nginx 的报错大多集中在几个固定位置我把踩过的坑整理成对照表你按现象查。现象可能原因排查动作Service 一直 pending无 external-ipMetalLB 未装或地址池未配kubectl get pods -n metallb-system检查 IPAddressPool访问返回 404Path 或 rewrite 规则不匹配kubectl describe ingress看 Rules核对正则访问返回 502后端协议/端口错误检查backend-protocol注解和 Service port访问返回 503后端无可用 Endpointkubectl get endpoints -n ns svc报错local proxy failed后端 Pod 未就绪或探针失败看后端 Pod 的 readinessProbe报错reading choices证书 Secret 格式错误确认 Secret 类型是kubernetes.io/tls报错401 UnauthorizedDashboard token 过期或 RBAC 不足重新生成 token检查 ServiceAccount报错OAuth相关后端要求 OAuth 认证检查后端服务自身的认证配置webhook 拒绝创建 Ingress类名错误或 webhook 证书失效kubectl get ingressclass重启 admission Job重点说几个高频的。local proxy failed通常不是 Ingress 本身的问题而是后端 Pod 没通过就绪探针Endpoints 列表是空的Nginx 转发过去没人接。用kubectl get endpoints -n kubernetes-dashboard kubernetes-dashboard-kong-proxy一看便知如果 ENDPOINTS 是none就去查后端 Pod 的 readinessProbe。reading choices这个报错一般出现在 TLS 配置上多半是 Secret 里的 crt 或 key 内容不对或者 Secret 类型不是kubernetes.io/tls。用kubectl get secret dashboard-tls-secret -n kubernetes-dashboard -o yaml看 data 里有没有 tls.crt 和 tls.key 两个键。401 Unauthorized在 Dashboard 场景很常见那是 Dashboard 自己的登录认证不是 Ingress 的问题。你需要用kubectl create token生成一个 token 去登录。如果确认是 Ingress 层面的 401检查有没有配auth-type或auth-secret注解。还有一个隐蔽的坑如果你用了rewrite-target但路径正则写错请求会被重写成空路径后端收到/返回 404。调试时把rewrite-target临时去掉看原始路径能不能通能通就说明是 rewrite 的问题。6. 把 AI 编码助手接进你的集群工作流集群搭好、Ingress 通了之后日常写 YAML、调 Ingress 注解、排查报错这些活儿其实可以交给 AI 编码助手来加速。我现在的习惯是遇到不熟悉的注解组合先让助手生成一版草稿再自己核对官方文档。这里推荐用 TaoToken 作为统一的模型接入层它把多家模型的 API 收敛成一个 OpenAI 兼容的入口配置一次就能在 Claude Code、Cline、Codex 这些工具里切换模型。接入方式很简单以 Claude Code 为例核心是三件套Base URL、API Key、Model ID。Base URL 填https://taotoken.net/apiAPI Key 在控制台的 API Keys 页面生成Model ID 按你需要的模型填。如果你用的是 Cline 或 Codex配置逻辑一样只是配置文件位置不同——Codex 改auth.jsonCline 在 MCP 设置里填 Base URL 和 Key。具体操作路径先去 API Keys 页面 生成一个 Key然后参考接入文档 把 Base URL 和 Key 填进你的工具。想先试试模型效果可以直接在模型对话 里问几个 Ingress 注解的问题验证通了再配到本地工具。如果你长期做编码和 Agent 任务Coding Plan 会更划算。配好之后你可以直接让助手帮你生成 Ingress YAML、解释kubectl describe的输出、或者根据报错日志给出排查方向。比如把local proxy failed的日志贴进去它能快速定位到是 Endpoint 为空还是探针失败。但记住一点助手给的是草稿最终 apply 到集群前注解和路径正则一定要自己核对一遍尤其是rewrite-target这种容易写错的地方。集群操作不可逆多一层人工确认不亏。