简体   繁体   English

Kubernetes NGINX 入口 controller - 如果查询字符串存在则不同的路由

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM