在某些情况下,后端服务中的公开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/v1beta1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/rewrite-target: https://www.jianshu.com/u/33c582f040ae
name: nginx-ingress-1
namespace: default
spec:
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/v1beta1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /$2
name: rewrite
namespace: default
spec:
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