Nginx Ingress配置URL重写规则
在一些使用场景中后端服务提供访问的URL与Ingress规则中指定的路径不同,而Ingress会将访问路径直接转发到后端相同路径,如果不进行URL重写配置,所有访问都将返回404。例如,Ingress规则中的访问路径设置为/app/demo,而后端服务提供的访问路径为/demo,在实际访问Ingress时会直接转发到后端服务的/app/demo路径,与后端实际提供的访问路径(/demo)不匹配,导致404的情况发生。
此时,您可以通过Rewrite方法实现URL重写,即使用“nginx.ingress.kubernetes.io/rewrite-target”注解可以实现不同路径的重写规则。
配置重写规则
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: ingress-test namespace: default annotations: nginx.ingress.kubernetes.io/rewrite-target: /$2 spec: rules: - host: 'rewrite.bar.com' http: paths: - path: '/something(/|$)(.*)' backend: service: name: <your_service_name> #替换为您的目标服务名称 port: number: <your_service_port> #替换为您的目标服务端口 property: ingress.beta.kubernetes.io/url-match-mode: STARTS_WITH pathType: ImplementationSpecific ingressClassName: nginx
apiVersion: networking.k8s.io/v1beta1 kind: Ingress metadata: name: ingress-test namespace: default annotations: kubernetes.io/ingress.class: nginx nginx.ingress.kubernetes.io/rewrite-target: /$2 spec: rules: - host: 'rewrite.bar.com' http: paths: - path: '/something(/|$)(.*)' backend: serviceName: <your_service_name> #替换为您的目标服务名称 servicePort: <your_service_port> #替换为您的目标服务端口
只要有一个Ingress使用了rewrite-target,则所有Ingress定义下同一个host下所有path都会正则大小写敏感,包括没有使用rewrite-target的Ingress。
以上示例中,占位符$2表示将第二个括号即(.*)中匹配到的所有字符填写到“nginx.ingress.kubernetes.io/rewrite-target”注解中。
- rewrite.bar.com/something 重写为 rewrite.bar.com/
- rewrite.bar.com/something/ 重写为 rewrite.bar.com/
- rewrite.bar.com/something/new 重写为 rewrite.bar.com/new
nginx-ingress-controller容器中,“/etc/nginx”路径下的nginx.conf文件可查看所有Ingress配置。以上示例中的重写规则将生成一条Rewrite指令,并写入到nginx.conf的location字段中,如下所示:
## start server rewrite.bar.com server { server_name rewrite.bar.com ; ... location ~* "^/something(/|$)(.*)" { set $namespace "default"; set $ingress_name "ingress-test"; set $service_name "<your_service_name>"; set $service_port "80"; ... rewrite "(?i)/something(/|$)(.*)" /$2 break; ... } } ## end server rewrite.bar.com
rewrite regex replacement [flag];
- regex:匹配URI的正则表达式。在上述例子中,“(?i)/something(/|$)(.*)”即为匹配URI的正则表达式,其中“(?i)”表示不区分大小写。
- replacement:重写内容。在上述例子中,“/$2”即为重写内容,表示把路径重写为第二个括号“(.*)”中匹配到的所有字符。
- flag:表示重写形式的标记,包括:
- last:表示本条规则匹配完成后继续向下匹配。
- break:表示本条规则匹配完成后停止匹配。
- redirect:表示临时重定向,返回状态码302。
- permanent:表示永久重定向,返回状态码301。
高级Rewrite配置
对于一些复杂高级的Rewrite需求,可以通过如下注解来实现,其本质也是修改Nginx的配置文件(nginx.conf),可以实现上面提到的“nginx.ingress.kubernetes.io/rewrite-target”注解的功能,但是自定义程度更高,适合更加复杂的Rewrite需求。
- nginx.ingress.kubernetes.io/server-snippet:在nginx.conf的“server”字段中添加自定义配置。
- nginx.ingress.kubernetes.io/configuration-snippet:在nginx.conf的“location”字段中添加自定义配置。
通过以上两个注解可以在nginx.conf中的“server”或“location”字段中插入Rewrite指令,完成URL的重写,示例如下:
annotations: kubernetes.io/ingress.class: "nginx" nginx.ingress.kubernetes.io/configuration-snippet: | rewrite ^/stylesheets/(.*)$ /something/stylesheets/$1 redirect; # 添加 /something 前缀 rewrite ^/images/(.*)$ /something/images/$1 redirect; # 添加 /something 前缀
- 当用户访问rewrite.bar.com/stylesheets/new.css时,重写为rewrite.bar.com/something/stylesheets/new.css
- 当用户访问rewrite.bar.com/images/new.jpg时,重写为rewrite.bar.com/something/images/new.jpg
HTTP重定向到HTTPS
默认情况下,若Ingress使用了TLS,通过HTTP访问时,请求将会被重定向(状态码为308)到HTTPS。您也可以通过以下注解强制重定向至HTTPS。
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: ingress-test namespace: default annotations: nginx.ingress.kubernetes.io/ssl-redirect: 'true' spec: rules: - host: '' http: paths: - path: / backend: service: name: <your_service_name> #替换为您的目标服务名称 port: number: <your_service_port> #替换为您的目标服务端口 property: ingress.beta.kubernetes.io/url-match-mode: STARTS_WITH pathType: ImplementationSpecific ingressClassName: nginx
apiVersion: networking.k8s.io/v1beta1 kind: Ingress metadata: name: ingress-test namespace: default annotations: kubernetes.io/ingress.class: nginx nginx.ingress.kubernetes.io/ssl-redirect: 'true' spec: rules: - host: '' http: paths: - path: / backend: serviceName: <your_service_name> #替换为您的目标服务名称 servicePort: <your_service_port> #替换为您的目标服务端口