Kubernetes Ingress path rewrite dosen't work as expected

11/3/2021

I have an ingress, defined as the following:

Name:             online-ingress
Namespace:        default
Address:          
Default backend:  default-http-backend:80 (<error: endpoints "default-http-backend" not found>)
Rules:
  Host          Path  Backends
  ----          ----  --------
  jj.cloud.com  
                /online/(.*)   online:80 (172.16.1.66:5001)
                /userOnline    online:80 (172.16.1.66:5001)
Annotations:    nginx.ingress.kubernetes.io/rewrite-target: /$1
Events:
  Type    Reason          Age                From                      Message
  ----    ------          ----               ----                      -------
  Normal  AddedOrUpdated  29m (x4 over 74m)  nginx-ingress-controller  Configuration for default/online-ingress was added or updated

If I test it with no rewrite, it's ok.

curl -X POST jj.cloud.com:31235/userOnline -H 'Content-Type: application/json' -d '{"url":"baidu.com","users":["ua"]}'
OK

However, if I try to use rewrite, it will fail.

curl -X POST jj.cloud.com:31235/online/userOnline -H 'Content-Type: application/json' -d '{"url":"baidu.com","users":["ua"]}'
<html>
<head><title>404 Not Found</title></head>
<body>
<center><h1>404 Not Found</h1></center>
<hr><center>nginx/1.21.3</center>
</body>
</html>

And it will produce the following error logs:

2021/11/03 10:21:25 [error] 134#134: *63 open() "/etc/nginx/html/online/userOnline" failed (2: No such file or directory), client: 172.16.0.0, server: jj.cloud.com, request: "POST /online/userOnline HTTP/1.1", host: "jj.cloud.com:31235"
172.16.0.0 - - [03/Nov/2021:10:21:25 +0000] "POST /online/userOnline HTTP/1.1" 404 153 "-" "curl/7.29.0" "-"

Why the path /online/userOnline doesn't match /online/(.*) and rewrite it to /userOnline? Or are there some other errors? Here is the yaml:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: online-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /$2
spec:
  rules:
    - host: jj.cloud.com
      http:
        paths:
          - path: /online(/|$)/(.*)
            pathType: Prefix
            backend:
              service: 
                name: online
                port: 
                  number: 80
          - path: /userOnline
            pathType: Prefix
            backend:
              service:
                name: online
                port:
                  number: 80
  ingressClassName: nginx

When I checked the generated nginx config, I found (default-online-ingress.conf):

location /online(/|$)/(.*) {

It seems lost of the modifier for regex match, like this:

location ~* "^/online(/|$)/(.*)" {

If it's true, how to make rewrite take effect and generate correct nginx config?

-- tanxin
kubernetes
nginx
nginx-ingress
url-rewriting

1 Answer

11/4/2021

If I understood your issue correctly, you have a problem with captured groups.

According to Nginx Rewrite targets it seems to me,

  • your patch should be path: /online(/|$)(.*)
  • your rewrite-target: should be rewrite-target: /$2
  • in addition, if you use nginx ingress, I believe you should specify that in annotation section as kubernetes.io/ingress.class: nginx

yaml:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: online-ingress
  annotations:
    kubernetes.io/ingress.class: nginx
    nginx.ingress.kubernetes.io/rewrite-target: /$2
spec:
  rules:
    - host: jj.cloud.com
      http:
        paths:
          - path: /online(/|$)(.*)
            pathType: Prefix
            backend:
              service: 
                name: online
                port: 
                  number: 80
          - path: /userOnline
            pathType: Prefix
            backend:
              service:
                name: online
                port:
                  number: 80
  ingressClassName: inner-nginx
-- Vit
Source: StackOverflow