[英]Kubernetes NGINX Ingress controller - different route if query string exists
Is it possible with the Nginx ingress controller for Kubernetes to have an ingress rule that routes to different services based on if a query string exists?对于 Kubernetes 的 Nginx 入口 controller 是否可以有一个入口规则,该规则根据是否存在查询字符串路由到不同的服务? For example..
例如..
/foo/bar -> route to serviceA /foo/bar -> 到 serviceA 的路由
/foo/bar?x=10 -> route to serviceB /foo/bar?x=10 -> 路由到 serviceB
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: my-ingress
spec:
rules:
- host: xxxx.com
http:
paths:
- path: /foo/bar(/|$)(.*)
pathType: Prefix
backend:
service:
name: serviceA
port:
number: 8001
- path: /foo/bar(/|$)(.*)\?
pathType: Prefix
backend:
service:
name: serviceB
port:
number: 8002
I managed to find a working solution for what you described with two ingress objects.我设法为您用两个入口对象描述的内容找到了一个可行的解决方案。 With the example that you provided ingress won't be able to direct you towards
service-b
since nginx does not match query string at all.在您提供入口的示例中,由于 nginx 根本不匹配查询字符串,因此无法将您引导至
service-b
。 This is very well explained here .这在这里得到了很好的解释。
Ingress selects the proper backed based on path. Ingress 根据路径选择适当的支持。 So I have prepared separate path for the second backend and put a conditional redirect to it to the first path so when request reach the
/tmp
path it uses service-b
backend and trims the tmp part from the request.因此,我为第二个后端准备了单独的路径,并将有条件的重定向到第一个路径,因此当请求到达
/tmp
路径时,它使用service-b
后端并从请求中修剪 tmp 部分。
So here's the ingress that matches /foo/bar
for the backend-a
所以这里是匹配
backend-a
/foo/bar
的入口-a
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: my-ingress
annotations:
nginx.ingress.kubernetes.io/configuration-snippet: |
if ($args ~ .+){
rewrite ^ http://xxxx.com/foo/bar/tmp permanent;
}
spec:
rules:
- host: xxxx.com
http:
paths:
- path: /foo/bar
pathType: Prefix
backend:
serviceName: service-a
servicePort: 80
And here is the ingress that matches /foo/bar?
这是匹配
/foo/bar?
and whatever comes after for the backend-b
以及
backend-b
之后发生的任何事情
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: my-ingress-rewrite
annotations:
nginx.ingress.kubernetes.io/use-regex: "true"
nginx.ingress.kubernetes.io/rewrite-target: /foo/bar$1
spec:
rules:
- host: xxxx.com
http:
paths:
- path: /foo/bar/tmp(.*)
backend:
serviceName: service-b
servicePort: 80
Please note, that previous configuration leftovers can prevent that solution from working well.请注意,以前的配置剩余可能会阻止该解决方案正常运行。 Clean up, redeploy and ingress controller restart should help in that situation.
在这种情况下,清理、重新部署和入口 controller 重启应该会有所帮助。
Here are some tests to prove the case.这里有一些测试来证明这一点。 First I have added the
xxxx.com
to /etc/hosts
:首先,我将
xxxx.com
添加到/etc/hosts
:
➜ ~ cat /etc/hosts
127.0.0.1 localhost
192.168.59.2 xxxx.com
- Here we are testing the firs path /foo/bar
: - 这里我们正在测试第一个路径
/foo/bar
:
➜ ~ curl -L -v http://xxxx.com/foo/bar
* Trying 192.168.59.2...
* TCP_NODELAY set
* Connected to xxxx.com (192.168.59.2) port 80 (#0)
> GET /foo/bar HTTP/1.1 <----- See path here!
> Host: xxxx.com
> User-Agent: curl/7.52.1
> Accept: */*
>
< HTTP/1.1 200 OK
< Date: Tue, 13 Apr 2021 12:30:00 GMT
< Content-Type: application/json; charset=utf-8
< Content-Length: 644
< Connection: keep-alive
< X-Powered-By: Express
< ETag: W/"284-P+J4oZl3lklvyqdp6FEGTPVw/VM"
<
{
"path": "/foo/bar",
"headers": {
"host": "xxxx.com",
"x-request-id": "1f7890a47ca1b27d2dfccff912d5d23d",
"x-real-ip": "192.168.59.1",
"x-forwarded-for": "192.168.59.1",
"x-forwarded-host": "xxxx.com",
"x-forwarded-port": "80",
"x-forwarded-proto": "http",
"x-scheme": "http",
"user-agent": "curl/7.52.1",
"accept": "*/*"
},
"method": "GET",
"body": "",
"fresh": false,
"hostname": "xxxx.com",
"ip": "192.168.59.1",
"ips": [
"192.168.59.1"
],
"protocol": "http",
"query": {},
"subdomains": [],
"xhr": false,
"os": {
"hostname": "service-a" <------ Pod hostname that response came from.
- And here we are testing the firs path /foo/bar
: - 在这里我们正在测试第一条路径
/foo/bar
:
➜ ~ curl -L -v http://xxxx.com/foo/bar\?x\=10
* Trying 192.168.59.2...
* TCP_NODELAY set
* Connected to xxxx.com (192.168.59.2) port 80 (#0)
> GET /foo/bar?x=10 HTTP/1.1 <--------- The requested path!
> Host: xxxx.com
> User-Agent: curl/7.52.1
> Accept: */*
>
< HTTP/1.1 301 Moved Permanently
< Date: Tue, 13 Apr 2021 12:31:58 GMT
< Content-Type: text/html
< Content-Length: 162
< Connection: keep-alive
< Location: http://xxxx.com/foo/bar/tmp?x=10
<
* Ignoring the response-body
* Curl_http_done: called premature == 0
* Connection #0 to host xxxx.com left intact
* Issue another request to this URL: 'http://xxxx.com/foo/bar/tmp?x=10'
* Found bundle for host xxxx.com: 0x55d6673218a0 [can pipeline]
* Re-using existing connection! (#0) with host xxxx.com
* Connected to xxxx.com (192.168.59.2) port 80 (#0)
> GET /foo/bar/tmp?x=10 HTTP/1.1
> Host: xxxx.com
> User-Agent: curl/7.52.1
> Accept: */*
>
{
"path": "/foo/bar",
"headers": {
"host": "xxxx.com",
"x-request-id": "96a949a407dae653f739db01fefce7bf",
"x-real-ip": "192.168.59.1",
"x-forwarded-for": "192.168.59.1",
"x-forwarded-host": "xxxx.com",
"x-forwarded-port": "80",
"x-forwarded-proto": "http",
"x-scheme": "http",
"user-agent": "curl/7.52.1",
"accept": "*/*"
},
"method": "GET",
"body": "",
"fresh": false,
"hostname": "xxxx.com",
"ip": "192.168.59.1",
"ips": [
"192.168.59.1"
],
"protocol": "http",
"query": {
"x": "10"
},
"subdomains": [],
"xhr": false,
"os": {
"hostname": "service-b" <-----Service-b host name!
},
"connection": {}
For the responses I've used the mendhak/http-https-echo
image:对于我使用
mendhak/http-https-echo
图像的响应:
apiVersion: v1
kind: Pod
metadata:
name: service-b
labels:
app: echo2
spec:
containers:
- name: service-b #<-------- service-b host name
image: mendhak/http-https-echo
ports:
- containerPort: 80
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.