如何基于Nginx Ingress的ssl_client_verify结果动态路由至不同上游?
问题分析与解决方案
你的问题核心不是$proxy_host设置错误,而是整体配置逻辑和必要的MTLS验证前提没做对,导致路由规则不生效。下面是具体原因和修正方案:
关键问题点
- 缺少CA证书配置:你只设置了
auth-tls-verify-client: optional,但没通过nginx.ingress.kubernetes.io/auth-tls-secret注解指定用于验证客户端证书的CA证书Secret。没有CA证书的话,Nginx根本无法验证客户端证书,$ssl_client_verify的值永远是NONE,不会触发SUCCESS分支。 - 错误使用
$proxy_host:$proxy_host是Nginx内置变量,代表请求的Host头部值,不是用来指定上游服务的。动态路由上游需要用自定义变量结合proxy_pass实现。 - Ingress规则未结合Nginx配置片段:K8s原生Ingress资源不支持直接写Nginx的条件路由逻辑,必须通过
server-snippet或configuration-snippet注解注入Nginx配置代码。
正确的Ingress配置示例
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: mtls-routing-ingress annotations: # 开启可选的客户端证书验证 nginx.ingress.kubernetes.io/auth-tls-verify-client: "optional" # 指定存储CA证书的Secret(需提前创建,包含ca.crt文件) nginx.ingress.kubernetes.io/auth-tls-secret: "default/ca-cert-secret" # 注入Nginx服务器级配置,实现动态路由 nginx.ingress.kubernetes.io/server-snippet: | # 默认路由到无MTLS验证的后端 set $upstream_service "no-mtls-backend:80"; # 验证成功时切换到MTLS后端 if ($ssl_client_verify = SUCCESS) { set $upstream_service "yes-mtls-backend:80"; } # 动态转发到上游服务 proxy_pass http://$upstream_service; spec: tls: - hosts: - your-app-domain.com # 替换为你的业务域名 secretName: app-tls-secret # 替换为你的域名SSL证书Secret rules: - host: your-app-domain.com http: paths: - path: / pathType: Prefix backend: # 这里填默认后端,会被server-snippet中的配置覆盖 service: name: no-mtls-backend port: number: 80
额外注意事项
- 提前创建CA证书Secret:Secret中必须包含
ca.crt文件,内容为用于签发客户端证书的CA公钥。 - 客户端证书有效性:客户端提供的证书必须是由上述CA签发的,否则
$ssl_client_verify会返回FAILED,仍路由到no-mtls-backend。 - Ingress Controller版本:确保使用的Nginx Ingress Controller版本支持
auth-tls-*系列注解(v1.0及以上版本均支持)。
内容的提问来源于stack exchange,提问作者fardin
相关产品推荐
相关产品推荐

