在某些情况下,后端服务中的公开URI与Ingress规则中的指定路径不同。如果没有rewrite,任何请求都将返回404,可以将Ingress里annotations设置nginx.ingress.kubernetes.io/rewrite-target为服务所需的路径。
通过annotations做rewrite基本配置:
以下操作在k8s 1.13.2版本;ingress-nginx控制器0.24.1版本上进行。
示例一
apiVersion: extensions/v1beta1kind: Ingressmetadata: annotations: nginx.ingress.kubernetes.io/rewrite-target: https://www.jianshu.com/u/33c582f040ae name: nginx-ingress-1 namespace: defaultspec: rules: - host: bb.test.com http: paths: - backend: serviceName: nginx-svc servicePort: 8080 path: /aaa
当访问http://bb.test.com:8088/aaa时,会被重定向到简书主页https://www.jianshu.com/u/33c582f040ae,如果有多个path,每个都会被rewrite,所以如果只需要替换单个path(也就是location)的时候单独使用一个ingress写。
这里没有配置kubernetes.io/ingress.class将会使用启动参数中没有加--ingress-class的ingress-nginx(同一k8s集群中可能会有多个负载ingress-nginx,这个启动参数用于标识标记了kubernetes.io/ingress.class的ingress将会被哪个ingress-nginx处理)
创建该ingress后,可以在ingress-nginx容器内nginx.conf中看到,location中多了rewrite配置
server { server_name bb.test.com ; listen 80; set $proxy_upstream_name "-"; set $pass_access_scheme $scheme; set $pass_server_port $server_port; set $best_http_host $http_host; set $pass_port $pass_server_port; location ~* "^/aaa" { set $namespace "default"; set $ingress_name "nginx-ingress-1"; set $service_name "nginx-svc"; set $service_port "80"; set $location_path "/aaa"; rewrite_by_lua_block { lua_ingress.rewrite({ force_ssl_redirect = false, use_port_in_redirects = false, }) balancer.rewrite() plugins.run() } ##此处省略 rewrite "(?i)/aaa" https://www.jianshu.com/u/33c582f040ae break; proxy_pass http://upstream_balancer; proxy_redirect off; } location ~* "^/" { set $namespace ""; set $ingress_name ""; set $service_name ""; set $service_port "0"; set $location_path "/"; rewrite_by_lua_block { lua_ingress.rewrite({ force_ssl_redirect = false, use_port_in_redirects = false, }) balancer.rewrite() plugins.run() } header_filter_by_lua_block { plugins.run() } body_filter_by_lua_block { } log_by_lua_block { balancer.log() monitor.call() plugins.run() } ##此处省略 rewrite "(?i)/" https://www.jianshu.com/u/33c582f040ae break; proxy_pass http://upstream_balancer; proxy_redirect off; } }
访问
配置hosts文件:
192.168.1.103为负载均衡器IP;bb.test.com为上面ingress中配置的host
以上软件为switchhost(方便管理,灵活切换hosts的一款开源软件)
当访问http://bb.test.com:8088/aaa时,会被重定向到简书主页:
其中8088为ingress-nginx的http端口(hostPort方式暴露)
示例二
从版本0.22.0开始,使用注释的入口定义nginx.ingress.kubernetes.io/rewrite-target不向后兼容以前的版本。在版本0.22.0及更高版本中,必须在捕获组中
(https://www.regular-expressions.info/refcapture.html)
明确定义需要传递到重写路径的请求URI中的任何子字符串。
捕获组保存在编号占位符,按时间顺序,形式$1,$2... $n。这些占位符可用作rewrite-target注释中的参数。
创建以下ingress:
$ echo 'apiVersion: extensions/v1beta1kind: Ingressmetadata: annotations: nginx.ingress.kubernetes.io/rewrite-target: /$2 name: rewrite namespace: defaultspec: rules: - host: rewrite.bar.com http: paths: - backend: serviceName: http-svc servicePort: 80 path: /something(/|$)(.*)' | kubectl create -f -
在此入口定义中,(.*)将捕获的任何字符都将分配给占位符$2,然后将其用作rewrite-target注释中的参数。
生成的nginx.conf内容如下:
server { server_name rewrite.bar.com ; listen 80; set $proxy_upstream_name "-"; set $pass_access_scheme $scheme; set $pass_server_port $server_port; set $best_http_host $http_host; set $pass_port $pass_server_port; location ~* "^/something(/|$)(.*)" { set $namespace "default"; set $ingress_name "rewrite"; set $service_name "http-svc"; set $service_port "80"; set $location_path "/something(/|${literal_dollar})(.*)"; rewrite_by_lua_block { lua_ingress.rewrite({ force_ssl_redirect = false, use_port_in_redirects = false, }) balancer.rewrite() plugins.run() } header_filter_by_lua_block { plugins.run() } body_filter_by_lua_block { } log_by_lua_block { balancer.log() monitor.call() plugins.run() } ## 此处省略 rewrite "(?i)/something(/|$)(.*)" /$2 break; proxy_pass http://upstream_balancer; proxy_redirect off; } location ~* "^/" { set $namespace ""; set $ingress_name ""; set $service_name ""; set $service_port "0"; set $location_path "/"; rewrite_by_lua_block { lua_ingress.rewrite({ force_ssl_redirect = false, use_port_in_redirects = false, }) balancer.rewrite() plugins.run() } header_filter_by_lua_block { plugins.run() } body_filter_by_lua_block { } log_by_lua_block { balancer.log() monitor.call() plugins.run() } ## 此处省略 rewrite "(?i)/" /$2 break; proxy_pass http://upstream_balancer; proxy_redirect off; } }
上面的ingress定义结果将会是如下结果:
- rewrite.bar.com/something重写为rewrite.bar.com/
- rewrite.bar.com/something/重写为rewrite.bar.com/
- rewrite.bar.com/something/new重写为rewrite.bar.com/new