Ingress-nginx: use-regex doesn't seem to work as documented ("must be an absolute path" error)

Created on 18 Oct 2019  路  4Comments  路  Source: kubernetes/ingress-nginx

Is this a request for help? (If yes, you should use our troubleshooting guide and community support channels, see https://kubernetes.io/docs/tasks/debug-application-cluster/troubleshooting/.): no

What keywords did you search in NGINX Ingress controller issues before filing this one? (If you have found any duplicates, you should instead reply there.): use-regex, regex


Is this a BUG REPORT or FEATURE REQUEST? (choose one):
Bug Report

NGINX Ingress controller version:
using helm chart version 1.24.3
I'm not sure how to tell exactly what the ingress controller version is from that though...

Kubernetes version (use kubectl version):
Client Version: version.Info{Major:"1", Minor:"14", GitVersion:"v1.14.3", GitCommit:"5e53fd6bc17c0dec8434817e69b04a25d8ae0ff0", GitTreeState:"clean", BuildDate:"2019-06-06T01:44:30Z", GoVersion:"go1.12.5", Compiler:"gc", Platform:"darwin/amd64"}
Server Version: version.Info{Major:"1", Minor:"13+", GitVersion:"v1.13.11-eks-5876d6", GitCommit:"5876d6b7429820450950ade17fe7b4bf5ccada7f", GitTreeState:"clean", BuildDate:"2019-09-24T20:54:25Z", GoVersion:"go1.11.13", Compiler:"gc", Platform:"linux/amd64"}

(AWS EKS)

Environment:

  • Cloud provider or hardware configuration: AWS EKS & Docker for Mac's Kubernetes
  • OS (e.g. from /etc/os-release): OSX
  • Kernel (e.g. uname -a):
  • Install tools: Helm
  • Others:

What happened:

2 issues...

First, the documentation here: https://github.com/kubernetes/ingress-nginx/blob/master/docs/user-guide/ingress-path-matching.md states

!!! important Regular expressions and wild cards are not supported in the spec.rules.host field. Full hostnames must be used.

This appears to be a false statement. (related to #3534 and #4478 ?)
This ingress configuration works and regexes are used correctly (note that there is also no use-regex annotation)

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: {{ .Release.Name }}-ingress
  labels:
    release: {{ .Release.Name }}
  annotations:
    kubernetes.io/ingress.class: "nginx"
    nginx.ingress.kubernetes.io/rewrite-target: /$2
spec:
  rules:
    - host: "*.mydomain.net"
      http:
        paths:
          - path: /api(/|$)(.*)
            backend:
              serviceName: "{{ .Release.Name }}-api"
              servicePort: 80
          - path: /grafana(/|$)(.*)
            backend:
              serviceName: "{{ .Release.Name }}-grafana"
              servicePort: 3000
          - path: (/|$)(.*)
            backend:
              serviceName: "{{ .Release.Name }}-ui"
              servicePort: 80

The above all works correctly and contradicts that line in the documentation.
The regexes in the paths also seem to work despite the lack of the use-regex annotation.


Second: If a full host name is used instead of *. then the regex handling of the paths no longer works, even with the use-regex annotation.

This yaml:

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: {{ .Release.Name }}-ingress
  labels:
    release: {{ .Release.Name }}
  annotations:
    kubernetes.io/ingress.class: "nginx"
    nginx.ingress.kubernetes.io/rewrite-target: /$2
    nginx.ingress.kubernetes.io/use-regex: "true"
spec:
  rules:
    - host: "qa.mydomain.com"
      http:
        paths:
          - path: /api(/|$)(.*)
            backend:
              serviceName: "{{ .Release.Name }}-api"
              servicePort: 80
          - path: /grafana(/|$)(.*)
            backend:
              serviceName: "{{ .Release.Name }}-grafana"
              servicePort: 3000
          - path: (/|$)(.*)
            backend:
              serviceName: "{{ .Release.Name }}-ui"
              servicePort: 80

now fails with the error:

$ helm install qa .

Error: release qa failed: Ingress.extensions "qa-ingress" is invalid: spec.rules[0].http.paths[2].path: Invalid value: "(/|$)(.*)": must be an absolute path

What you expected to happen:

I would have expected the lack of the use-regex annotation to cause a problem (in the first example)

I would have expected the use-regex annotation to allow the use of regexes in the paths. (in the second example)

The odd part is that changing between a host of *.mydomain.com and qa.mydomain.com seems to change the handling of the regexes in the paths. Regexes _only_ seem to work when a wildcard host is used.

How to reproduce it (as minimally and precisely as possible):

See above yaml.

Locally, you can use Docker for Mac or Minikube and just set host: localhost which will cause the same error.

Anything else we need to know:

My example yaml here also matches what is shown in the helm example here: https://kubernetes.github.io/ingress-nginx/examples/rewrite/

They both:

  • contains a nginx.ingress.kubernetes.io/rewrite-target annotation
  • does not contain a nginx.ingress.kubernetes.io/use-regex annotation
  • is using a static host name (not a wildcard)
  • is using paths that contain regex capture groups

but that causes the "... must be an absolute path" error shown above.

Most helpful comment

I figured out part of this issue.

For whatever reason, when the host is not a wildcard, it hits this logic in k8s:
https://gitlab.cncf.ci/kubernetes/kubernetes/blob/60f4fbf4f25764dbd94b7f8146d927ddc684514d/pkg/apis/extensions/validation/validation.go#L417-418
which is what causes the "must be an absolute path" error for the path

          - path: (/|$)(.*)

To workaround this issue, I changed my path to

          - path: /()(.*)

(the empty capture group is there because my rewrite rule needs the 2 capture groups)

All 4 comments

I figured out part of this issue.

For whatever reason, when the host is not a wildcard, it hits this logic in k8s:
https://gitlab.cncf.ci/kubernetes/kubernetes/blob/60f4fbf4f25764dbd94b7f8146d927ddc684514d/pkg/apis/extensions/validation/validation.go#L417-418
which is what causes the "must be an absolute path" error for the path

          - path: (/|$)(.*)

To workaround this issue, I changed my path to

          - path: /()(.*)

(the empty capture group is there because my rewrite rule needs the 2 capture groups)

facing same issue, on custom helm chart with default ingress template basic configuration with statis host getting:

Invalid value: "map[backend:map[serviceName:lab servicePort:8080] path:/]": must be an absolute path

update: found the right way to do that in Values.yaml:

paths: [/]

Closing. The error you see is not from ingress-nginx but Kubernetes itself when the ingress is validated.

The Ingress "www-example-com" is invalid: spec.rules[0].http.paths[0].path: Invalid value: "(/|$)(.*)": must be an absolute path

The ingress spec requires an absolute path.

Was this page helpful?
0 / 5 - 0 ratings