Kubernetes rewrite-target paths for appending path to match

11/5/2020

I'm using the OSS ingress-nginx Ingress controller and trying to create a rewrite-target rule such that I can append a path string before my string match.

If I wanted to create a rewrite rule with regex that matches /matched/path and rewrites that to /prefix/matched/path, how might I be able to do that?

I've tried something like the following but it's no good, and I'm just confused about the syntax of this ingress definition:

metadata:
  annotations:
    kubernetes.io/ingress.class: nginx
    nginx.ingress.kubernetes.io/rewrite-target: /$2
spec:
  rules:
    - path: /(/prefix/)(/|$)(/matched/path)(.*)
      backend:
        serviceName: webapp1
-- Xenyal
kubernetes
kubernetes-helm
kubernetes-ingress
nginx-ingress

1 Answer

11/6/2020

If I wanted to create a rewrite rule with regex that matches /matched/path and rewrites that to /prefix/matched/path, how might I be able to do that?

In order to achieve this you have add /prefix into your rewrite-target. Here's a working example with ingress syntax from k8s v1.18:

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: example-ingress-v118
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /prefix/$1
spec:
  rules:
    http:
       paths:
       - path: /(matched/path/?.*)
        backend:
          serviceName: test
          servicePort: 80   

Since the syntax for the new ingress changed in 1.19 (see release notes and some small info at the end) I`m placing also an example with it:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: example-ingress-v119
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /prefix/$1
spec:
  rules:
  - http:
      paths:
      - path: /(matched/path/?.*)
        pathType: Prefix
        backend:
          service:
            name: test
            port:
              number: 80

Here is a test with http echo server:

➜  ~ curl 172.17.0.4/matched/path 
{
  "path": "/prefix/matched/path",
  "headers": {
    "host": "172.17.0.4",
    "x-request-id": "011585443ebc6adcf913db1c506abbe6",
    "x-real-ip": "172.17.0.1",
    "x-forwarded-for": "172.17.0.1",
    "x-forwarded-host": "172.17.0.4",
    "x-forwarded-port": "80",
    "x-forwarded-proto": "http",
    "x-scheme": "http",
    "user-agent": "curl/7.52.1",
    "accept": "*/*"
  },

This rule will also ignore the / at the end of the request:

➜  ~ curl 172.17.0.4/matched/path/
{
  "path": "/prefix/matched/path/",
  "headers": {
    "host": "172.17.0.4",
    "x-request-id": "0575e9022d814ba07457395f78dbe0fb",
    "x-real-ip": "172.17.0.1",
    "x-forwarded-for": "172.17.0.1",
    "x-forwarded-host": "172.17.0.4",
    "x-forwarded-port": "80",
    "x-forwarded-proto": "http",
    "x-scheme": "http",
    "user-agent": "curl/7.52.1",
    "accept": "*/*"
  },

Worth to mention some notable differences/changes in the new ingress syntax:

  • spec.backend -> spec.defaultBackend
  • serviceName -> service.name
  • servicePort -> service.port.name (for string values)
  • servicePort -> service.port.number (for numeric values) pathType no longer has a default value in v1; "Exact", "Prefix", or "ImplementationSpecific" must be specified Other Ingress API updates
  • backends can now be resource or service backends
  • path is no longer required to be a valid regular expression (#89778, @cmluciano) SIG API Machinery, Apps, CLI, Network and Testing

    1: https://kubernetes.io/docs/setup/release/notes/

-- acid_fuji
Source: StackOverflow