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:
uname -a):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:
nginx.ingress.kubernetes.io/rewrite-target annotationnginx.ingress.kubernetes.io/use-regex annotationhost name (not a wildcard)paths that contain regex capture groupsbut that causes the "... must be an absolute path" error shown above.
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.
Most helpful comment
I figured out part of this issue.
For whatever reason, when the
hostis 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
To workaround this issue, I changed my path to
(the empty capture group is there because my rewrite rule needs the 2 capture groups)