
Ingress NGINX Controller Rewrite 注解实战rewrite-target、app-root 与 SSL 重定向全解析【免费下载链接】ingress-nginxIngress NGINX Controller for Kubernetes项目地址: https://gitcode.com/GitHub_Trending/in/ingress-nginx导读本文围绕 Kubernetes Ingress NGINX Controller 的 Rewrite重写能力展开系统讲解rewrite-target、app-root、ssl-redirect、force-ssl-redirect、use-regex等核心注解的语义、取值与底层实现。读完本文你将能够在 Ingress 中通过捕获组capture group精准改写请求 URI、将根路径/重定向到应用子路径、按需控制 HTTP/HTTPS 跳转并结合源码理解这些注解最终如何落入 NGINX 配置。一、前置条件先让 Ingress 正确路由到本控制器在使用 Rewrite 注解之前需要保证 Ingress 规则只命中一个 Ingress 控制器实例通过 ingress.class 注解 明确指定 Ingress 所属的控制器或在 Ingress 上使用ingressClassName字段本文示例采用ingressClassName: nginx确保集群中已经有一个 Ingress Controller 正在运行且 Ingress 与控制器处于同一集群并可正常访问。二、Rewrite 注解一览表Rewrite 行为由以下 5 个注解控制完整注解表同时维护在 annotations.md 中名称描述取值nginx.ingress.kubernetes.io/rewrite-target流量必须被重定向到的目标 URIstringnginx.ingress.kubernetes.io/ssl-redirect指示该 location 是否只能通过 SSL 访问当 Ingress 包含证书时默认为 Trueboolnginx.ingress.kubernetes.io/force-ssl-redirect即使 Ingress 未启用 TLS也强制重定向到 HTTPSboolnginx.ingress.kubernetes.io/app-root定义 Controller 在/上下文时必须重定向到的应用根路径stringnginx.ingress.kubernetes.io/use-regex指示 Ingress 上定义的路径是否使用正则表达式bool在源码 rewrite/main.go 中这些注解被定义为常量归属于rewrite注解组其中还包含一个表格之外的第六个注解preserve-trailing-slashconst ( rewriteTargetAnnotation rewrite-target sslRedirectAnnotation ssl-redirect preserveTrailingSlashAnnotation preserve-trailing-slash forceSSLRedirectAnnotation force-ssl-redirect useRegexAnnotation use-regex appRootAnnotation app-root )这些注解在解析后被统一装入Config结构体rewrite/main.go并作为每个 location 的重定向配置被 NGINX 模板消费。注意以上注解仅作用于匹配的 Ingress Location。若仅希望将 URI 重写到根路径只需在 Ingress 中指定rewrite-target注解并配置为/。三、Rewrite Target基于捕获组的 URI 改写nginx.ingress.kubernetes.io/rewrite-target用于指定流量必须被重定向到的目标 URI其值可以是普通字符串也可以携带$1、$2等编号占位符。3.1 版本兼容性警告0.22.0 起⚠️ 自Version 0.22.0起使用nginx.ingress.kubernetes.io/rewrite-target注解的 Ingress 定义不再与旧版本向后兼容。在 0.22.0 及之后的版本中请求 URI 内需要传递到改写后路径的任何子串都必须显式地在捕获组中定义。 捕获组按出现顺序保存到编号占位符中形式为$1、$2…$n。这些占位符可以直接作为参数用于rewrite-target注解。 关于 Ingress 路径path的校验规则请参见 FAQValidation of path当路径需要被解释为正则表达式时pathType应设置为ImplementationSpecific且路径只允许使用受支持的字符集。3.2 完整示例/something前缀改写创建一个带 rewrite 注解的 Ingress 规则$ echo apiVersion: networking.k8s.io/v1 kind: Ingress metadata: annotations: nginx.ingress.kubernetes.io/use-regex: true nginx.ingress.kubernetes.io/rewrite-target: /$2 name: rewrite namespace: default spec: ingressClassName: nginx rules: - host: rewrite.bar.com http: paths: - path: /something(/|$)(.*) pathType: ImplementationSpecific backend: service: name: http-svc port: number: 80 | kubectl create -f -在这个 Ingress 定义中路径/something(/|$)(.*)由两个捕获组构成第一个捕获组(/|$)匹配/或字符串结尾第二个捕获组(.*)匹配其余任意字符其捕获内容被赋给占位符$2rewrite-target: /$2表示将原始 URI 中/something之后的部分原样拼接到新的目标路径上。因此上述定义会产生如下改写结果rewrite.bar.com/something改写为rewrite.bar.com/rewrite.bar.com/something/改写为rewrite.bar.com/rewrite.bar.com/something/new改写为rewrite.bar.com/new3.3 源码级验证解析与模板渲染链路rewrite-target的校验由 validators.go 中的RegexPathWithCapture完成该正则只允许路径以/开头并包含字母数字与$用于捕获组引用RegexPathWithCapture regexp.MustCompile(^/?[ alphaNumericChars \/\$]*$)在 rewrite/main.go 中Parse会读取注解值若校验失败IsValidationErrorTarget会回退为空字符串并输出 klog 告警。改写行为在 NGINX 模板层面由 template.go 驱动func needsRewrite(location *ingress.Location) bool { if location.Rewrite.Target ! location.Rewrite.Target ! location.Path { return true } return false } // enforceRegexModifier checks if the rewrite-target or use-regex annotation // is used on any location path within a server func enforceRegexModifier(input interface{}) bool { for _, location : range locations { if needsRewrite(location) || location.Rewrite.UseRegex { return true } } return false }当检测到 location 需要改写时最终会在 NGINX 配置中输出类似rewrite (.*) / break;的指令见 nginx.tmpl配合由 buildLocation 生成的~* ^...正则 location 共同完成 URI 改写。3.4 测试用例佐证rewrite/main_test.go 中的TestRedirect验证了rewrite-target的解析结果TestSSLRedirect中更是覆盖了携带占位符的目标路径data[parser.GetAnnotationWithPrefix(rewrite-target)] /xpto/$1/abc/$2 ... if redirect.Target ! /xpto/$1/abc/$2 {同时测试还覆盖了非法值场景当rewrite-target设置为/xpto/xas{445}包含非法字符时解析结果回退为空字符串rewrite/main_test.go。四、App Root将根路径重定向到应用子路径nginx.ingress.kubernetes.io/app-root用于定义应用根路径当请求落在/上下文时Controller 会将其重定向到指定的应用根路径。4.1 完整示例创建一个带 app-root 注解的 Ingress 规则$ echo apiVersion: networking.k8s.io/v1 kind: Ingress metadata: annotations: nginx.ingress.kubernetes.io/app-root: /app1 name: approot namespace: default spec: ingressClassName: nginx rules: - host: approot.bar.com http: paths: - path: / pathType: Prefix backend: service: name: http-svc port: number: 80 | kubectl create -f -验证重写是否生效$ curl -I -k http://approot.bar.com/ HTTP/1.1 302 Moved Temporarily Server: nginx/1.11.10 Date: Mon, 13 Mar 2017 14:57:15 GMT Content-Type: text/html Content-Length: 162 Location: http://approot.bar.com/app1 Connection: keep-alive可以看到访问根路径/返回302并通过Location头指向/app1。4.2 源码级验证app-root 的取值约束在 rewrite/main.go 中app-root的解析比其它注解更严格——它必须是一个绝对路径以/开头相对路径与绝对 URL 都会被拒绝u, err : url.ParseRequestURI(config.AppRoot) if err ! nil { klog.Warningf(Annotation app-root contains an invalid value: %v, err) config.AppRoot return config, nil } if u.IsAbs() { klog.Warningf(Annotation app-root only allows absolute paths (%v), config.AppRoot) config.AppRoot return config, nil }rewrite/main_test.go 中的TestAppRoot用例组完整覆盖了这些约束输入 path期望结果说明报错空路径不允许demo报错相对路径不允许/通过AppRoot/根路径合法/demo通过AppRoot/demo绝对路径合法五、SSL 重定向ssl-redirect 与 force-ssl-redirectssl-redirect决定一个 location 是否只能通过 SSL 访问force-ssl-redirect则在 Ingress 未配置 TLS 时也强制跳转 HTTPS。二者组合可实现差异化的 HTTP→HTTPS 强制策略仅配置ssl-redirect: true当 Ingress 包含证书时默认开启 HTTPS 跳转若 Ingress 没有证书则不会跳转配置force-ssl-redirect: true无论 Ingress 是否启用 TLS都会强制 301 跳转到 HTTPS。从源码看这两个布尔注解的默认值来自defaults.Backend。在 config.go 中可以看到默认配置PreserveTrailingSlash: false, SSLRedirect: true,ssl-redirect的全局默认值为true。在 rewrite/main.go 中当注解缺失或非法时解析器会回退到GetDefaultBackend()提供的默认值例如config.SSLRedirect, err parser.GetBoolAnnotation(sslRedirectAnnotation, ing, a.annotationConfig.Annotations) if err ! nil { ... config.SSLRedirect a.r.GetDefaultBackend().SSLRedirect }相关行为在 rewrite/main_test.go 中被验证TestSSLRedirect验证了默认开启、以及ssl-redirect: false时关闭跳转TestForceSSLRedirect验证了即使 mock 后端SSLRedirectfalse设置force-ssl-redirect: true后ForceSSLRedirect仍为true。另外同一组中还包含preserve-trailing-slash注解rewrite/main.go用于控制执行 SSL 重定向时是否保留 URI 末尾的斜杠默认值为false。六、use-regex开启路径正则匹配nginx.ingress.kubernetes.io/use-regex指示 Ingress 中定义的路径是否使用正则表达式。开启后Controller 会按正则方式匹配 location 路径参见 template.go正则 location 会被渲染为~* ^...形式同时它也是enforceRegexModifier判定是否需要走正则渲染的触发条件之一。使用注意点若路径需要被解释为正则pathType必须同时设置为ImplementationSpecific见 rewrite/main.go 的注解文档说明以及 FAQ 中的相关约束该注解的解析器默认值为false非法输入同样回退为falserewrite/main.gorewrite/main_test.go 的TestUseRegex验证了use-regex: true时UseRegex为true。七、风险等级与注解校验从 rewrite/main.go 的注解元数据可以看到每个注解都被标记了作用域Scope与风险等级Risk注解ScopeRiskrewrite-targetIngressMediumssl-redirectLocationLowpreserve-trailing-slashLocationMediumforce-ssl-redirectLocationMediumuse-regexLocationLowapp-rootLocationMediumrewrite解析器实现了Validate方法rewrite/main.go会依据集群配置的annotations-risk-level对注解风险进行校验func (a rewrite) Validate(anns map[string]string) error { maxrisk : parser.StringRiskToRisk(a.r.GetSecurityConfiguration().AnnotationsRiskLevel) return parser.CheckAnnotationRisk(anns, maxrisk, rewriteAnnotations.Annotations) }这意味着在高安全要求的集群中可以通过安全配置限制高风险注解的使用rewrite-target、app-root等 Medium 风险注解会受此约束。各注解的完整风险说明可参考 annotations-risk.md。八、完整工作流程小结一次 Rewrite 请求的完整链路可以概括为Ingress 声明用户在 Ingress 的metadata.annotations中声明rewrite-target、app-root、ssl-redirect、use-regex等注解注解解析Controller 的事件循环调用 rewrite.Parse将注解解析为Config结构体含Target、SSLRedirect、ForceSSLRedirect、PreserveTrailingSlash、AppRoot、UseRegex字段非法值回退到默认值并记录告警模板渲染template.go 中的needsRewrite/enforceRegexModifier决定是否启用正则 location 与 rewrite 指令最终在 nginx.tmpl 中生成rewrite (.*) / break;等 NGINX 指令NGINX 生效nginx 进程按生成后的配置完成 URI 改写、302 重定向app-root以及 SSL 跳转单元测试保障rewrite/main_test.go 中的系列测试用例守护了解析逻辑的稳定性。参考资料注解完整清单与说明docs/user-guide/nginx-configuration/annotations.md注解风险说明docs/user-guide/nginx-configuration/annotations-risk.md多 Ingress 控制器选择docs/user-guide/multiple-ingress.md部署文档docs/deploy/index.mdFAQ路径校验docs/faq.mdRewrite 解析器源码internal/ingress/annotations/rewrite/main.goRewrite 解析器测试internal/ingress/annotations/rewrite/main_test.goNGINX 配置模板rootfs/etc/nginx/template/nginx.tmpl【免费下载链接】ingress-nginxIngress NGINX Controller for Kubernetes项目地址: https://gitcode.com/GitHub_Trending/in/ingress-nginx创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考