在使用 minikube ingress 时,我必须写
nginx.ingress.kubernetes.io/rewrite-target: /$1
。我一直在努力理解为什么我们需要这个注释以及如何使用它。
我知道doc说了以下内容:
在某些场景下,后端服务中暴露的URL与Ingress规则中指定的路径不同。如果没有重写,任何请求都将返回 404。将注释 nginx.ingress.kubernetes.io/rewrite-target 设置为服务期望的路径。
但我无法准确理解
the exposed URL in the backend service differs from the specified path in the Ingress rule
的确切含义。我无法清楚地理解这个想法。
此外,在尝试使用服务执行入口文件时:
代码1:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: example-ingress
namespace: example-namespace
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /$1
spec:
rules:
- host: myexample.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: example-service
port:
number: 80
代码2:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: example-ingress
namespace: example-namespace
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
rules:
- host: myexample.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: example-service
port:
number: 80
代码3:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: example-ingress
namespace: example-namespace
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /$1
spec:
rules:
- host: myexample.com
http:
paths:
- path: /index
pathType: Prefix
backend:
service:
name: example-service
port:
number: 80
上述 3 个代码片段中的每对相对于上面提到的重写目标和路径到底有什么区别?
PS:我是 minikube 的新手,正在尝试弄清楚事情的确切工作方式。请帮忙。
我不知道新版本的 Ingress 资源或新版本的 Nginx Ingress 控制器是否会改变情况,但我认为它是这样工作的。
假设我想通过 Ingress 在同一域下为 2 个不同的 Web 应用程序提供服务。
/
/
因此,两个应用程序都期望它们的请求直接在根目录下,这(乍一看)似乎使它们不可能在同一域中提供服务。
除了重写目标之外,我可以。我可以在不同的路径下为它们提供服务,但将目标重写为
/
myexample.com/aaa/
myexample.com/bbb/
并添加重写目标以删除路径的第一部分。这只是重写目标用途的一个示例,它只是让您能够在应用程序本身预期的不同路径下为应用程序提供服务。
入口示例:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: example-ingress
namespace: example-namespace
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /$2
spec:
rules:
- host: myexample.com
http:
paths:
- path: /aaa(/|$)(.*)
pathType: Prefix
backend:
service:
name: app-a
port:
number: 80
- path: /bbb(/|$)(.*)
pathType: Prefix
backend:
service:
name: app-b
port:
number: 80
注意,虽然这在 Rest API 和类似的东西上工作得很好,但在网页上可能不太好用,因为网页可能会尝试在不同的路径加载资源(例如,如果它不使用相对路径) )。这就是为什么(通常)前端应用程序需要知道它们在域下的哪条路径上提供服务。
关于重写目标的语法,我将以上面写的 Ingress 为例。有几件事需要考虑:
让我们从
path
和 pathType
交互开始。通过路径,我可以定义在哪里提供服务。根据 pathType
,它可能只是整个路径的 Prefix
,即 Exact
路径,或者它可以取决于入口控制器(又名 ImplementationSpecific
)。文档中通过一长串示例很好地解释了一切(https://kubernetes.io/docs/concepts/services-networking/ingress/#examples)
我几乎可以用 path 和 pathType 做所有事情,除非我想要服务的应用程序期望在与 Ingress 中指定的路径不同的路径上提供服务;这就是
rewrite-target
发挥作用的时候。
就像上面的示例一样,我可以使用
rewrite-target
在与预期不同的路径下为应用程序提供服务,并根据需要编写 url。我还可以使用正则表达式和捕获组(这就是 $1
、$2
等等)
例如,如果我写
path: /bbb(/|$)(.*)
,我的意思是该路径将匹配 /bbb 下的所有内容,无论 bbb 后面有或没有 /。如果我然后写 rewrite-target: /$2
我的意思是请求将被重写以用 /bbb
替换 /
,然后采用第二个捕获组(这意味着第二个正则表达式 (.*)
)
文档解释得很好,即使它仍然使用旧的 Ingress 资源(https://kubernetes.github.io/ingress-nginx/examples/rewrite/)
@AndD提供了很好的解释!
有几件事我想补充:
(/|$)(.*)
有时至关重要,因为您想在https://example.com和https://example.com/$1
和$2
变量捕获未更改的路径元素,docs所以这是我的做法(
/
路径类型(前缀)下的主服务和所有子路径,不包括/test
路径类型(精确)指向测试服务):
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ingress-nginx-dev
namespace: develop
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /$1
spec:
rules:
- host: example.com
http:
paths:
- backend:
service:
name: nginx-test-svc
port:
number: 80
path: /test(.*)
pathType: Exact
- host: example.com
http:
paths:
- backend:
service:
name: nginx-main-svc
port:
number: 80
path: /(.*)
pathType: Prefix