ingress-nginx 很多高级的用法可以通过 Ingress 对象的 annotation 进行配置,比如常用的 URL Rewrite 功能。很多时候我们会将 ingress-nginx 当成网关使用,比如对访问的服务加上 /app 这样的前缀,在 nginx 的配置里面我们知道有一个 proxy_pass 指令可以实现:
location /app/ {
proxy_pass http://127.0.0.1/remote/;
}
proxy_pass 后面加了 /remote
这个路径,此时会将匹配到该规则路径中的 /app
用 /remote
替换掉,相当于截掉路径中的 /app
。同样的在 Kubernetes 中使用 ingress-nginx 又该如何来实现呢?我们可以使用 rewrite-target 的注解来实现这个需求,比如现在我们想要通过 demo.gl.sh.cn/gateway/
来访问到 Nginx 服务,则我们需要对访问的 URL 路径做一个 Rewrite,在 PATH 中添加一个 gateway 的前缀,关于 Rewrite 的操作在 ingress-nginx 官方文档中也给出对应的说明:
按照要求我们需要在 path 中匹配前缀 gateway,然后通过 rewrite-target 指定目标,Ingress 对象如下所示:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: rewrite
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /$2
spec:
ingressClassName: nginx
rules:
- host: demo.gl.sh.cn
http:
paths:
- path: /gateway(/|$)(.*)
pathType: Prefix
backend:
service:
name: my-nginx
port:
number: 80
更新后,我们可以预见到直接访问域名肯定是不行了,因为我们没有匹配 /
的 path 路径:
curl demo.gl.sh.cn
default backend - 404
但是我们带上 gateway 的前缀再去访问
我们可以看到已经可以访问到了,这是因为我们在 path 中通过正则表达式 /gateway(/|$)(.*)
将匹配的路径设置成了 rewrite-target 的目标路径了,所以我们访问 demo.gl.sh.cn/gateway/
的时候实际上相当于访问的就是后端服务的 /
路径。
要解决我们访问主域名出现 404 的问题,我们可以给应用设置一个 app-root
的注解,这样当我们访问主域名的时候会自动跳转到我们指定的 app-root
目录下面,如下所示:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: rewrite
annotations:
nginx.ingress.kubernetes.io/app-root: /gateway/
nginx.ingress.kubernetes.io/rewrite-target: /$2
spec:
ingressClassName: nginx
rules:
- host: demo.gl.sh.cn
http:
paths:
- path: /gateway(/|$)(.*)
pathType: Prefix
backend:
service:
name: my-nginx
port:
number: 80
这个时候我们更新应用后访问主域名 demo.gl.sh.cn
就会自动跳转到 demo.gl.sh.cn/gateway/
路径下面去了。但是还有一个问题是我们的 path 路径其实也匹配了 /app
这样的路径,可能我们更加希望我们的应用在最后添加一个 /
这样的 slash,同样我们可以通过 configuration-snippet 配置来完成,如下 Ingress 对象:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: rewrite
annotations:
nginx.ingress.kubernetes.io/app-root: /gateway/
nginx.ingress.kubernetes.io/rewrite-target: /$2
nginx.ingress.kubernetes.io/configuration-snippet: |
rewrite ^(/gateway)$ $1/ redirect;
spec:
ingressClassName: nginx
rules:
- host: demo.gl.sh.cn
http:
paths:
- path: /gateway(/|$)(.*)
pathType: Prefix
backend:
service:
name: my-nginx
port:
number: 80
更新后我们的应用就都会以 /
这样的 slash 结尾了。这样就完成了我们的需求,如果你原本对 nginx 的配置就非常熟悉的话应该可以很快就能理解这种配置方式了。