news 2026/11/3 13:03:30

Kubernetes Ingress YAML 配置核心四锚点与排错指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Kubernetes Ingress YAML 配置核心四锚点与排错指南

1. 项目概述:一份真正能跑通的 Ingress YAML 配置,到底要写对哪几处?

Ingress 的 YAML 配置文件,是 Kubernetes 生产环境中绕不开的一道坎。它不是“写完就能用”的模板填空,而是连接外部流量与集群内服务的关键协议翻译器——把 HTTP/HTTPS 请求的 Host、Path、TLS 证书这些“人话”,精准转译成 kube-proxy 和 CNI 插件能听懂的路由指令。我见过太多团队卡在这一环:明明 Service 已就绪、Pod 全部 Running,但 curl 域名却返回 503 或 Connection refused;也见过运维同学反复修改 YAML,却始终无法触发 TLS 重定向,最后发现只是 annotation 里少了一个连字符。核心关键词就是Ingress YAML 配置文件,它背后牵扯的是七层负载均衡策略、Ingress Controller 的实现差异、证书生命周期管理、以及 Kubernetes 网络模型中 Service、Endpoint、EndpointSlice 三者之间的联动逻辑。这份配置不是静态文档,而是一份运行时契约:它声明了“谁可以访问什么路径”,也隐含了“由哪个控制器执行”“用什么规则匹配”“证书从哪来”等关键决策。适合正在搭建第一个生产级 Web 应用的 DevOps 工程师、刚接手线上集群的 SRE 新手,以及需要快速验证灰度发布或蓝绿部署流程的后端开发同学。它不教你怎么部署 Nginx Ingress Controller(那是前置动作),而是聚焦于你手头那份即将 apply 的 YAML 文件——逐行拆解每一字段的真实含义、常见误写、生效条件和调试线索。下面所有内容,都基于真实集群中反复验证过的最小可运行单元展开,没有抽象概念,只有可复制、可排查、可回滚的具体写法。

2. 内容整体设计与思路拆解:为什么不能直接套用官网示例?

2.1 Ingress 不是独立组件,而是“契约型资源”

很多人初学时有个根本性误解:以为 Ingress 是一个自带转发能力的“网关服务”。其实恰恰相反——Ingress 是一个纯声明式资源(Custom Resource Definition),它本身不处理任何网络包,也不监听 80/443 端口。它的全部价值,只在被某个 Ingress Controller “看见并执行”时才激活。这就决定了 YAML 设计的第一原则:必须与你实际部署的 Ingress Controller 类型严格对齐。目前主流有三类实现:Nginx Ingress Controller(最成熟)、Traefik(Go 原生、自动发现强)、HAProxy Ingress(企业级高可用场景)。它们对同一份 YAML 的解析逻辑存在实质性差异。比如:

  • nginx.ingress.kubernetes.io/rewrite-target这个 annotation,在 Nginx Controller 中用于路径重写,但在 Traefik 中完全无效,它用的是traefik.http.routers.myrouter.middlewares+StripPrefix;
  • kubernetes.io/ingress.class字段在旧版(<1.18)中是必需的,新版(1.19+)已废弃,改用ingressClassName字段,但如果你集群里跑的是 v1.17 的 Nginx Controller,漏掉ingress.class就会导致 Ingress 资源被完全忽略;
  • TLS 配置中,secretName指向的 Secret 必须存在于与 Ingress 相同的命名空间(Namespace),这是硬性约束,但很多新手会误以为可以跨命名空间引用,结果证书永远加载失败。

所以,我的设计思路从来不是“写一个通用模板”,而是“先锁定你的 Controller 版本,再反向推导 YAML 结构”。我会以当前社区最广泛使用的Nginx Ingress Controller v1.9.5(对应 Kubernetes v1.24+)为基准,因为它的文档最全、问题反馈最多、排错路径最清晰。所有后续字段解释、参数选择、实操步骤,都以此版本为锚点。如果你用的是 Traefik 或其他实现,只需替换 annotation 前缀和部分字段名,核心结构(如 rules、http、paths)保持一致——这正是 Kubernetes API 设计的优雅之处:底层协议统一,上层策略可插拔。

2.2 最小可行配置(MVP)必须包含四个不可省略的“锚点”

一份能真正让流量进来的 Ingress YAML,绝不是把官网示例 copy 过来改改域名就行。它必须同时满足四个运行时锚点,缺一不可:

  1. Controller 可识别性锚点:通过ingressClassName明确指定控制器名称(如nginx),而非依赖默认值。默认值在多 Controller 共存集群中极易引发歧义。
  2. 路由可达性锚点:rules下至少定义一条host+http.paths规则,且path必须以/开头(Kubernetes 强制要求),pathType必须显式设置为Prefix或Exact(v1 API 中ImplementationSpecific已弃用)。
  3. 后端服务绑定锚点:backend.service.name和backend.service.port.name(或.port.number)必须与目标 Service 的metadata.name和spec.ports[0].name(或port)完全一致,包括大小写和连字符。Service 名称错误是 503 错误的头号原因。
  4. TLS 安全性锚点(若启用 HTTPS):tls数组中hosts列表必须与rules.host完全匹配,且secretName指向的 Secret 必须已存在、类型为kubernetes.io/tls、且包含tls.crt和tls.key两个 key。

这四个锚点,就像电路中的四个接线端子——任意一个松动,整个回路就断开。我在某次故障复盘中发现,一个持续 3 小时的 502 错误,根源竟是backend.service.port.name写成了http,而实际 Service 中定义的是web。Kubernetes 不报错,Ingress Controller 日志只显示 “no endpoints found”,但没人去核对 Service 的 port name。因此,我的 YAML 设计始终围绕这四个锚点做显式强化:每个字段都加注释说明校验逻辑,关键值用# ← 必须与 Service.spec.ports[0].name 一致这类强提示标注,避免“看起来像对的,其实错了”。

2.3 为什么拒绝“全功能大而全”模板?

网上流传的很多 Ingress YAML 示例,动辄上百行,堆砌了金丝雀发布、速率限制、CORS 头、重试策略等高级特性。这对新手是灾难——你还没搞懂基础路由,就被迫面对nginx.ingress.kubernetes.io/canary-by-header这种复杂 annotation。更危险的是,这些高级功能往往依赖 Controller 的特定编译选项或额外 CRD(如IngressClassParams),在默认安装的 Controller 上根本不可用。我曾帮某团队排查一个“重定向不生效”问题,最终发现他们复制的 YAML 中用了nginx.ingress.kubernetes.io/force-ssl-redirect: "true",但集群里的 Controller 是用--enable-ssl-passthrough=false启动的,该 annotation 完全被忽略,日志里连 warning 都没有。

所以,我的思路是“分层演进”:第一版只解决“HTTP 流量能进来”,第二版叠加“HTTPS 自动跳转”,第三版加入“路径重写”,第四版才引入“灰度路由”。每一步都确保前一步稳定运行,且每步的 YAML 都能独立 apply、独立验证。这种做法看似慢,实则最快——它把排错范围从“整个 YAML”压缩到“新增的 2 行”,极大降低认知负荷。下面所有实操细节,都遵循这个渐进式设计哲学。

3. 核心细节解析与实操要点:字段、Annotation、Secret 的生死线

3.1apiVersion与kind:版本错配是静默失效的元凶

Ingress 资源在 Kubernetes 中经历了两次重大 API 演进:

  • networking.k8s.io/v1beta1(已废弃):Kubernetes v1.14–v1.19 使用,ingress.class字段在此版本中为必需;
  • networking.k8s.io/v1(当前标准):Kubernetes v1.19+ 强制使用,ingressClassName字段替代ingress.class,pathType字段变为必需。

很多团队仍在用 v1beta1 的 YAML,却升级到了 v1.24 集群,结果kubectl apply成功,但kubectl get ingress查不到资源——因为 v1.24 的 API Server 默认不启用 v1beta1 组。这不是 bug,是 Kubernetes 的明确弃用策略。实操中,必须用kubectl api-versions | grep networking确认集群支持的版本,再选择对应 API。我的经验是:只要集群是 v1.19 或更新,无条件使用networking.k8s.io/v1。v1 版本的pathType字段尤其关键:它定义了路径匹配方式,Prefix表示前缀匹配(如/api匹配/api/users),Exact表示精确匹配(仅/healthz),ImplementationSpecific已被移除。漏写pathType会导致kubectl apply报错pathType is required,这是 Kubernetes 的强校验,必须直面。

3.2metadata.name与metadata.namespace:命名空间隔离的铁律

Ingress 资源必须与它要代理的 Service 处于同一命名空间。这是 Kubernetes 网络模型的硬性设计,不是 Ingress Controller 的限制。例如,你的 Web 应用 Service 部署在prod命名空间,那么 Ingress 也必须创建在prod中。如果误建在default命名空间,Controller 会日志报错service "my-app" not found in namespace "default",即使my-app在prod中真实存在。更隐蔽的坑是metadata.name的长度限制:Kubernetes 对资源名有 63 字符上限,且只能包含小写字母、数字、连字符。我见过一个名字叫my-super-duper-long-app-name-for-production-v2-2024-q3的 Ingress,apply 时直接失败,因为超长。建议命名遵循appname-env模式,如blog-prod、api-staging,既清晰又安全。

3.3spec.ingressClassName:Controller 的“身份证号”

这个字段是 Ingress 能被正确调度的唯一凭证。它的值必须与集群中已部署的IngressClass资源的metadata.name完全一致。例如,你用 Helm 安装 Nginx Controller 时指定了controller.ingressClassResource.name=nginx,那么此处就必须写nginx。如果写成nginx-ingress或my-nginx,Controller 就不会处理该 Ingress。验证方法很简单:kubectl get ingressclass,看输出列表中是否有你期望的 name。如果没有,说明 Controller 未正确注册 IngressClass,需检查其启动参数是否包含--ingress-class=nginx。这是一个典型的“配置未生效”问题,但错误表现却是“流量不通”,排查路径容易走偏。

3.4spec.rules:Host 与 Path 的双重门禁

rules是 Ingress 的核心逻辑块,它定义了“谁(Host)能在哪条路(Path)上通行”。这里有两个致命细节:

  • host字段是可选的,但如果省略,表示匹配所有 Host(即*),这在生产环境极不安全,应始终显式指定,如blog.example.com;
  • http.paths数组中,每个path必须以/开头,且pathType必须为Prefix或Exact。Prefix是最常用的选择,但要注意:/api会匹配/api/、/api/users,但不会匹配/apis(因为s不是/api的前缀)。如果需要更灵活的匹配,必须用Exact或借助 annotation 做重写。

backend.service的绑定是另一个高频雷区。name必须与 Service 的metadata.name一字不差;port.name必须与 Service 的spec.ports[0].name一致(如 Service 定义name: http,这里就不能写port: 80,除非你明确用port.number: 80)。我习惯在 Service YAML 中强制定义name,并在 Ingress 中用port.name引用,这样 IDE 能做基础校验,比记端口号可靠得多。

3.5 TLS 配置:Secret 是证书的“保险柜”,不是“展示柜”

spec.tls块负责 HTTPS 流量。它有三个必填字段:

  • hosts:字符串数组,必须与rules.host完全一致。例如,rules.host: blog.example.com,则tls.hosts: ["blog.example.com"]。多域名证书需全部列出;
  • secretName:指向一个Secret资源的名称,该 Secret 必须存在于同一命名空间;
  • Secret 本身必须是kubernetes.io/tls类型,且包含两个 key:tls.crt(PEM 格式证书)和tls.key(PEM 格式私钥)。

生成这个 Secret 的命令是kubectl create secret tls my-tls-secret --cert=path/to/cert.pem --key=path/to/key.pem -n prod。注意:--cert和--key参数必须指向本地文件,不能是 base64 字符串。如果证书链不完整(比如缺少中间 CA),浏览器会报NET::ERR_CERT_AUTHORITY_INVALID,但 Ingress Controller 日志可能只显示failed to load SSL certificate,非常难定位。我的实操心得是:用openssl x509 -in cert.pem -text -noout | grep "Issuer\|Subject"检查证书链层级,确保Issuer是公认的根 CA(如 Let's Encrypt),而不是自签名 CA。

3.6 Annotation:Ingress Controller 的“方言词典”

Annotation 是 Ingress 的灵魂扩展点,它让声明式配置具备了命令式控制力。但每个 Controller 的 annotation 前缀不同,用错等于没写。以下是 Nginx Ingress Controller v1.9.5 中最常用、最易出错的几个:

  • nginx.ingress.kubernetes.io/rewrite-target: /$2:用于路径重写。例如,path: /api(/|$)(.*)匹配/api/users,重写为/users。关键点在于$2是正则捕获组,必须与path中的括号数量和顺序严格对应。写成$1就会把整个/api/users当作$1,导致后端收到错误路径;
  • nginx.ingress.kubernetes.io/ssl-redirect: "true":强制 HTTP 流量重定向到 HTTPS。它依赖 Controller 的--enable-ssl-redirect=true启动参数(默认开启),但必须配合spec.tls存在才生效。如果只写了 annotation 却没配 TLS,重定向不会发生;
  • nginx.ingress.kubernetes.io/configuration-snippet:插入原生 Nginx 配置片段,功能强大但风险极高。例如添加more_set_headers "X-Frame-Options: DENY";。错误的语法会导致 Controller Pod CrashLoopBackOff,整个集群的 Ingress 功能瘫痪。我的建议是:非必要不用,必须用时,先在测试集群验证 snippet 语法(用kubectl exec -it <nginx-pod> -- nginx -t)。

Annotation 的调试技巧是:kubectl describe ingress <name>输出的 Events 中,会显示 Controller 是否成功解析了 annotation。如果看到Failed to extract annotations,说明格式或前缀有误。

4. 实操过程与核心环节实现:从零构建一份可验证的 Ingress YAML

4.1 前置准备:确认 Controller 状态与版本

在写任何 YAML 之前,必须确认你的集群已就绪。执行以下三步:

  1. 检查 IngressClass 是否存在:

    kubectl get ingressclass # 正常输出应类似: # NAME CONTROLLER PARAMETERS AGE # nginx k8s.io/ingress-nginx <none> 5d

    如果为空,说明 Controller 未安装或未注册 IngressClass,需先部署 Controller。

  2. 检查 Controller Pod 状态:

    kubectl get pods -n ingress-nginx # 所有 Pod 必须为 Running 状态,且 READY 为 1/1 或 2/2(取决于是否启用了 metrics) # 如果是 Pending,检查节点资源;如果是 CrashLoopBackOff,`kubectl logs -n ingress-nginx <pod-name>` 查看启动错误
  3. 确认 Controller 版本:

    kubectl exec -n ingress-nginx deploy/ingress-nginx-controller -- nginx -v # 输出应为 nginx version: nginx/1.21.6(对应 v1.9.5 Controller) # 版本不匹配可能导致 annotation 不识别

这三步耗时不到 1 分钟,但能避免 80% 的“配置写了却没反应”问题。我坚持在每次新集群部署后,都把这三步做成一个 shell 脚本check-ingress-ready.sh,作为 CI/CD 流水线的前置检查项。

4.2 第一阶段:HTTP 基础路由(5 行核心 YAML)

目标:让curl http://test.example.com返回应用首页。这是所有后续功能的基石。

apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: test-http namespace: default spec: ingressClassName: nginx # ← Controller 的身份证号,必须与 kubectl get ingressclass 输出一致 rules: - host: test.example.com # ← 必须是你能解析到集群 Ingress Controller NodePort 或 LoadBalancer IP 的域名 http: paths: - path: / # ← 必须以 / 开头 pathType: Prefix # ← v1 API 强制要求,Prefix 表示前缀匹配 backend: service: name: test-app # ← 必须与你的 Service 名称完全一致 port: name: http # ← 必须与 Service.spec.ports[0].name 一致

关键操作与验证:

  • 将test.example.com替换为你自己的测试域名,并在本地/etc/hosts中添加映射:<Ingress-Controller-IP> test.example.com。Ingress Controller 的 IP 可通过kubectl get svc -n ingress-nginx ingress-nginx-controller获取EXTERNAL-IP(LoadBalancer 类型)或NODE-PORT(NodePort 类型);
  • test-appService 必须已存在,且spec.ports[0].name为http;
  • kubectl apply -f ingress-http.yaml;
  • 验证:curl -H "Host: test.example.com" http://<Ingress-Controller-IP>。如果返回应用响应,说明基础路由成功;如果返回default backend - 404,说明host或path匹配失败;如果返回503 Service Temporarily Unavailable,说明backend.service.name或port.name错误。

提示:curl -H "Host: ..."是绕过 DNS 的最直接验证方式,比改 hosts 更快。它模拟了真实请求的 Host 头,是调试 Ingress 的黄金命令。

4.3 第二阶段:HTTPS 强制跳转(增加 8 行,含 TLS 配置)

目标:curl http://test.example.com自动 308 重定向到https://test.example.com,且 HTTPS 访问正常。

首先,创建 TLS Secret:

# 生成自签名证书(仅测试用,生产请用 Let's Encrypt) openssl req -x509 -nodes -days 365 -newkey rsa:2048 \ -keyout tls.key -out tls.crt -subj "/CN=test.example.com/O=Test" # 创建 Secret kubectl create secret tls test-tls-secret --cert=tls.crt --key=tls.key -n default

然后,更新 Ingress YAML:

apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: test-https namespace: default annotations: nginx.ingress.kubernetes.io/ssl-redirect: "true" # ← 启用 HTTP→HTTPS 重定向 spec: ingressClassName: nginx tls: # ← TLS 配置块,必须与 rules.host 匹配 - hosts: - test.example.com # ← 必须与 rules.host 完全一致 secretName: test-tls-secret # ← 必须与 kubectl create secret 时的 name 一致 rules: - host: test.example.com http: paths: - path: / pathType: Prefix backend: service: name: test-app port: name: http

关键操作与验证:

  • kubectl apply -f ingress-https.yaml;
  • 验证 HTTP 重定向:curl -I http://test.example.com,应返回HTTP/1.1 308 Permanent Redirect和Location: https://test.example.com/;
  • 验证 HTTPS 访问:curl -k https://test.example.com(-k忽略自签名证书警告),应返回应用响应;
  • 检查 Controller 日志:kubectl logs -n ingress-nginx deploy/ingress-nginx-controller | grep "test.example.com",应看到SSL certificate "default/test-tls-secret" -> ...加载成功的日志。

注意:nginx.ingress.kubernetes.io/ssl-redirect: "true"必须与spec.tls同时存在才生效。单独写 annotation 不会触发重定向。

4.4 第三阶段:路径重写(增加 2 行 annotation,改造 path)

目标:将https://test.example.com/api/v1/users的请求,重写为https://test.example.com/users发送给后端。

修改paths部分:

- path: /api/v1(/|$)(.*) # ← 正则匹配 /api/v1/ 或 /api/v1 开头的路径 pathType: Prefix backend: service: name: test-app port: name: http # ← 在 backend 同级添加 annotation annotations: nginx.ingress.kubernetes.io/rewrite-target: /$2 # ← $2 是第二个捕获组,即 (.*) 部分

关键操作与验证:

  • kubectl apply -f ingress-rewrite.yaml;
  • 验证:curl -k https://test.example.com/api/v1/users,后端应用日志应显示收到/users路径的请求;
  • 调试技巧:如果重写失败,kubectl describe ingress test-rewrite查看 Events,或kubectl logs -n ingress-nginx deploy/ingress-nginx-controller | grep "rewrite"查看重写日志。

4.5 第四阶段:生产级加固(增加 5 行,防滥用与可观测)

目标:为 Ingress 添加基本防护和监控能力。

metadata: annotations: # 防暴力请求 nginx.ingress.kubernetes.io/limit-rps: "10" # ← 每秒最多 10 个请求 # 启用 Prometheus metrics nginx.ingress.kubernetes.io/enable-access-log-for-default-backend: "true" # 自定义错误页 nginx.ingress.kubernetes.io/custom-http-errors: "404,500,502,503,504" spec: # ... 其他配置不变

这些 annotation 无需额外部署,Controller 默认支持。limit-rps是最简单的限流手段,能有效缓解爬虫或误配置的轮询请求。custom-http-errors需要提前在 Controller 配置中挂载自定义错误页文件,但即使不挂载,它也能让 Controller 返回标准的 Nginx 错误页,比空白 503 更友好。

5. 常见问题与排查技巧实录:那些年踩过的坑与速查表

5.1 503 Service Temporarily Unavailable:后端服务“失联”的九种可能

这是 Ingress 故障中最常见的状态码,表面是“服务不可用”,实则是“找不到后端”。根据我的实战记录,原因分布如下:

排查方向具体原因验证命令解决方案
Service 名称错误backend.service.name与实际 Service 名不一致(大小写、连字符、拼写)kubectl get svc -n <namespace>核对 Service 名称,确保完全一致
Service 端口错误backend.service.port.name与 Service 的spec.ports[0].name不匹配kubectl get svc <svc-name> -o yaml | grep -A 5 ports修改 Ingress 中的port.name,或在 Service 中统一name
Service 无 EndpointService 的 selector 未匹配到任何 Pod,或 Pod 处于 NotReady 状态kubectl get endpoints <svc-name>检查 Pod 状态、Service selector、Pod labels
命名空间不一致Ingress 与 Service 不在同一命名空间kubectl get ingress -n <ingress-ns>和kubectl get svc -n <svc-ns>将 Ingress 移动到 Service 所在命名空间
IngressClass 不存在spec.ingressClassName指向的 IngressClass 未注册kubectl get ingressclass安装或修复 Ingress Controller
Controller 未监听该命名空间Controller 启动时指定了--watch-namespace,但未包含 Ingress 所在 NSkubectl logs -n ingress-nginx <controller-pod> | grep watch修改 Controller 启动参数,或移除--watch-namespace
Backend Service 类型错误Service 类型为ClusterIP(正确),但误设为ExternalName或Nonekubectl get svc <svc-name> -o yaml | grep type:将 Service type 改为ClusterIP
NetworkPolicy 阻断命名空间启用了 NetworkPolicy,禁止了 Controller 到 Service 的流量kubectl get networkpolicy -n <namespace>检查并调整 NetworkPolicy 规则
EndpointSlice 未生成Kubernetes v1.21+ 启用 EndpointSlice,但 Controller 版本过低不支持kubectl get endpointslice -n <namespace>升级 Ingress Controller 到 v1.0+

我的独家技巧:当遇到 503 时,第一时间执行kubectl get endpoints <svc-name> -n <namespace>。如果输出为空或ENDPOINTS列为<none>,问题 100% 出在 Service 层,与 Ingress YAML 无关。此时应停止修改 Ingress,转而检查 Service 和 Pod。

5.2 502 Bad Gateway:Controller 与后端通信失败

502 表示 Controller 成功找到了后端 Service,但无法与之建立 TCP 连接或收到有效 HTTP 响应。常见于:

  • 后端应用启动慢:Pod 已 Running,但应用进程尚未监听端口。Controller 的健康检查(readiness probe)失败,Endpoint 被移除。解决方案:为 Pod 配置合理的readinessProbe,如initialDelaySeconds: 30;
  • 后端端口未开放:容器内应用监听localhost:8080,但未监听0.0.0.0:8080,导致 ClusterIP 流量无法进入。解决方案:检查应用配置,确保绑定0.0.0.0;
  • TLS 证书不匹配:如果后端是 HTTPS 服务,且 Ingress 启用了ssl-passthrough,但证书域名与请求 Host 不符,会返回 502。解决方案:关闭ssl-passthrough,或确保证书覆盖所有 Host。

5.3 TLS 相关错误:证书链、SNI、重定向的三角困局

  • NET::ERR_CERT_INVALID(浏览器):通常因证书链不完整。用openssl s_client -connect test.example.com:443 -servername test.example.com 2>/dev/null \| openssl x509 -noout -text \| grep "CA Issuers"检查是否包含中间 CA URL。缺失则需在tls.crt中追加中间证书;
  • curl: (60) SSL certificate problem:curl默认校验证书链,而自签名证书无根 CA。解决方案:curl -k(测试)或curl --cacert ca-bundle.crt(生产);
  • HTTP 不重定向到 HTTPS:检查nginx.ingress.kubernetes.io/ssl-redirect: "true"是否存在,且spec.tls块已正确定义。kubectl describe ingress的 Events 应显示Successfully validated configuration;
  • SNI 不匹配:当一个 Secret 包含多个域名证书时,Controller 会根据 SNI(Server Name Indication)选择证书。确保tls.hosts数组包含所有需要支持的域名。

5.4 Ingress Controller 日志:读懂它的“抱怨”

Controller 日志是排错的终极依据。关键日志模式:

  • successfully validated configuration:配置语法正确,Controller 已加载;
  • no object matching key "default/test-app":后端 Servicetest-app在default命名空间不存在;
  • error obtaining service from store:Service 存在,但 Controller 无法从 API Server 获取其信息(权限或网络问题);
  • SSL certificate "default/my-secret" -> ...:TLS 证书加载成功;
  • invalid ingress spec: pathType must be one of ...:pathType字段值错误,必须是Prefix或Exact。

我的习惯是:kubectl logs -n ingress-nginx deploy/ingress-nginx-controller --since=1m \| grep -E "(error|warn|test.example.com)",聚焦最近 1 分钟内与目标域名相关的错误和警告。

5.5 YAML 语法与校验:让错误在 apply 前暴露

Kubernetes 的 YAML 校验非常严格。常见语法错误:

  • 缩进错误:YAML 对空格敏感,spec:和rules:必须顶格,- host:必须比rules:多 2 个空格;
  • 冒号后缺少空格:name:test-app是错误的,必须是name: test-app;
  • 字符串未加引号:当值包含/或-时,如path: /api/v1,最好写成path: "/api/v1",避免解析歧义;
  • null值误写:Kubernetes 不支持null,应写成""(空字符串)或直接省略字段。

我推荐在 VS Code 中安装YAML插件,并配置yaml.schemas关联 Kubernetes Schema,它能实时标红语法错误和字段非法值,比kubectl apply报错早 5 分钟。

6. 实操心得与避坑指南:十年一线总结的十三条军规

6.1 军规一:永远用kubectl apply -f,绝不手敲kubectl create ingress

kubectl create ingress是命令式创建,它会忽略 YAML 中的metadata.annotations和spec.tls等复杂字段,只创建最简结构。而apply是声明式,能完整同步所有字段。我见过太多人用create创建后,再edit加 annotation,结果edit保存时触发了kubectl replace,导致ingressClassName被重置为默认值,整个路由失效。

6.2 军规二:ingressClassName字段宁可多写,不可省略

即使集群只有一个 Controller,也必须显式写ingressClassName: nginx。理由有三:一是未来扩容多 Controller 时无需重构 YAML;二是避免 Kubernetes 版本升级后默认行为变更(如 v1.19+ 移除了默认 IngressClass);三是kubectl get ingress输出中能清晰看到绑定关系,便于审计。

6.3 军规三:pathType: Prefix是安全起点,Exact是精准手术刀

Prefix覆盖面广,适合/、/api等主干路径;Exact用于/healthz、/metrics等需要严格隔离的探针路径。混用时,Exact优先级高于Prefix,所以/healthz的Exact规则会拦截/healthz/anything的Prefix请求。我的实践是:主路径用Prefix,探针路径用Exact,并放在paths数组的前面。

6.4 军规四:TLS Secret 必须与 Ingress 同名空间,且类型为kubernetes.io/tls

这是硬性规定,没有例外。kubectl create secret tls命令会自动设置类型,但如果你用kubectl create secret generic手动创建,必须加上--type=kubernetes.io/tls参数。否则 Controller 会静默忽略该 Secret。

6.5 军规五:nginx.ingress.kubernetes.io/rewrite-target的$1、$2是正则捕获组,不是路径索引

path: /api(/|$)(.*)

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

从零手搓AI工程:深入理解Transformer、Tokenizer与推理优化

1. 这个项目到底在解决什么问题第一次看到 "ai-engineering-from-scratch" 这个标题&#xff0c;我脑子里蹦出来的第一个念头是&#xff1a;又是一个教你怎么调库的教程仓库&#xff1f;但翻了一圈之后发现&#xff0c;它想做的事情比"调包"要硬核得多——…

作者头像 李华
网站建设 2026/11/3 13:02:06

paperclip:基于Node.js与React的AI agents编排框架实战

1. 从 paperclip 这个名字说起&#xff1a;它到底想解决什么问题 第一次看到 paperclip 这个项目名&#xff0c;我脑子里蹦出来的画面是那个经典的 Office 助手——一个会跳出来问“需要帮忙吗”的小回形针。但真正翻完它的代码结构和设计文档之后&#xff0c;我发现这个名字…

作者头像 李华
网站建设 2026/11/3 13:02:05

TensorFlow安装与实战:从环境搭建到模型部署的完整指南

1. 从一次环境搭建翻车说起&#xff1a;为什么TensorFlow的安装总让人头疼如果你问一个刚接触深度学习的人&#xff0c;第一个卡住他的地方是什么&#xff0c;十有八九不是反向传播的数学推导&#xff0c;而是装环境。我自己当年第一次装TensorFlow&#xff0c;折腾了整整一个下…

作者头像 李华
网站建设 2026/11/3 13:01:19

伺服系统响应带宽的本质与工程计算方法

简介&#xff1a;本资源是一份面向电机控制工程师、自动化专业学生及伺服系统研发人员的深度技术文档&#xff0c;聚焦机电系统响应带宽的核心定义、理论推导与工程计算方法&#xff0c;解决实际项目中带宽评估不准、环路设计缺乏量化依据等关键问题。文档以伺服电机控制为典型…

作者头像 李华
网站建设 2026/11/3 13:01:07

Oracle RAC、DG与双机热备:RTO/RPO高可用选型指南

把 RAC、Data Guard、双机热备这几个词摆在一张桌子上问“哪个更好”&#xff0c;是这些年被问得最频繁的一类问题&#xff0c;也是最容易问偏的一类问题。问的人通常已经知道几个关键词&#xff1a;Oracle RAC能做到多节点同时读写、DG能把数据同步到异地、双机热备&#xff0…

作者头像 李华
网站建设 2026/11/3 13:00:47

从越权改密看管理平台账户权限校验与系统口令加固

凌晨两点&#xff0c;一个做综合管理平台运维的朋友发来消息&#xff1a;审计报表里出现了一条不该出现的记录——一个只有实时预览权限的普通操作账号&#xff0c;在十分钟内完成了一次系统级口令变更。他第一反应是账号被盗&#xff0c;查完登录日志发现来源地址没变、设备指…

作者头像 李华