<p>I'm trying to have a rule listening to a specific path containing a dollar sign like this:</p>
<pre><code>apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: metadata-ingress
  annotations:
    nginx.ingress.kubernetes.io/enable-cors: &quot;true&quot;
    nginx.ingress.kubernetes.io/ssl-redirect: &quot;true&quot;
    nginx.ingress.kubernetes.io/use-regex: &quot;false&quot;
spec:
  ingressClassName: public
  tls:
  - hosts:
    - mydomain.com
  rules:
  - host: mydomain.com
    http:
      paths:
      - path: /api/v2/$metadata
        pathType: Prefix
        backend:
          service:
            name: busybox
            port:
              number: 8280
</code></pre>
<p>I don't want any url rewrite or anything fancy, just want this specific path to be caught and forwarded to this service.</p>
<p>Without the &quot;$&quot; it works.</p>
<p>I thought disabling regex with <code>use-regex: &quot;false&quot;</code> would fix it, but no.</p>
<p>I also tried using the url encoded value for $ : %24metadata but it doesn't help either.</p>
<p>I also tried to use &quot;exact&quot; instead of &quot;prefix&quot; as the pathType but no.</p>

Dunge
<p>I can't reproduce your problem, but I thought I walk through my test setup and you can tell me if anything is different. For the purpose of testing different paths, I have two deployments using the <a href="https://hub.docker.com/r/traefik/whoami" rel="nofollow noreferrer"><code>traefik/whoami</code></a> image (this just provides a useful endpoint that shows us -- among other things -- the hostname and path involved in the request).</p>
<p>That looks like:</p>
<pre><code>apiVersion: v1
kind: Service
metadata:
  labels:
    app: example
    component: app1
  name: example-app1
spec:
  ports:
  - name: http
    port: 80
    targetPort: http
  selector:
    app: example
    component: app1

---
apiVersion: v1
kind: Service
metadata:
  labels:
    app: example
    component: app2
  name: example-app2
spec:
  ports:
  - name: http
    port: 80
    targetPort: http
  selector:
    app: example
    component: app2

---
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: example
    component: app1
  name: example-app1
spec:
  selector:
    matchLabels:
      app: example
      component: app1
  template:
    metadata:
      labels:
        app: example
        component: app1
    spec:
      containers:
      - image: docker.io/traefik/whoami:latest
        name: whoami
        ports:
        - containerPort: 80
          name: http

---
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: example
    component: app2
  name: example-app2
spec:
  selector:
    matchLabels:
      app: example
      component: app2
  template:
    metadata:
      labels:
        app: example
        component: app2
    spec:
      containers:
      - image: docker.io/traefik/whoami:latest
        name: whoami
        ports:
        - containerPort: 80
          name: http

</code></pre>
<p>I've also deployed the following Ingress resource, which looks mostly like yours, except I've added a second <code>paths</code> config so that we can compare requests that match <code>/api/v2/$metadata</code> vs those that do not:</p>
<pre><code>apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  annotations:
    cert-manager.io/cluster-issuer: house
    nginx.ingress.kubernetes.io/enable-cors: &quot;true&quot;
    nginx.ingress.kubernetes.io/ssl-redirect: &quot;true&quot;
  name: example
spec:
  ingressClassName: nginx
  rules:
  - host: example.apps.infra.house
    http:
      paths:
      - backend:
          service:
            name: example-app1
            port:
              name: http
        path: /
        pathType: Prefix
      - backend:
          service:
            name: example-app2
            port:
              name: http
        path: /api/v2/$metadata
        pathType: Prefix
  tls:
  - hosts:
    - example.apps.infra.house
    secretName: example-cert
</code></pre>
<p>With these resources in place, a request to <code>https://example.apps.infra.house/</code> goes to <code>app1</code>:</p>
<pre><code>$ curl -s https://example.apps.infra.house/ | grep Hostname
Hostname: example-app1-596fcf48bd-dqhvc
</code></pre>
<p>Whereas a request to <code>https://example.apps.infra.house/api/v2/$metadata</code> goes to <code>app2</code>:</p>
<pre><code>$ curl -s https://example.apps.infra.house/api/v2/\$metadata | grep Hostname
Hostname: example-app2-8675dc9b45-6hg7l
</code></pre>
<p>So that all seems to work.</p>
<hr />
<p>We can, if we are so inclined, examine the nginx configuration that results from that Ingress. On my system, the nginx ingress controller runs in the <code>nginx-ingress</code> namespace:</p>
<pre><code>$ kubectl -n nginx-ingress get deploy
NAME                       READY   UP-TO-DATE   AVAILABLE   AGE
ingress-nginx-controller   1/1     1            1           8d
</code></pre>
<p>The configuration lives in <code>/etc/nginx/nginx.conf</code> in the container. We can <code>cat</code> the file to stdout and look for the relevant directives:</p>
<pre><code>$ kubectl -n nginx-ingress exec deploy/ingress-nginx-controller cat /etc/nginx/nginx.conf
...
                location /api/v2/$metadata/ {
                ...
                }
...
</code></pre>
<hr />
<p>Based on your comment, the following seems to work:</p>
<pre><code>apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: example
  annotations:
    nginx.ingress.kubernetes.io/ssl-redirect: &quot;true&quot;
    nginx.ingress.kubernetes.io/rewrite-target: &quot;/$2&quot;
    cert-manager.io/cluster-issuer: house
spec:
  ingressClassName: nginx
  tls:
    - hosts:
      - example.apps.infra.house
      secretName: example-cert
  rules:
  - host: example.apps.infra.house
    http:
      paths:
      - path: /app1(/|$)(.*)
        pathType: Prefix
        backend:
          service:
            name: example-app1
            port:
              name: http

      # Note the use of single quotes (') here; this is
      # important; using double quotes we would need to
      # write `\\$` instead of `\$`.
      - path: '/api/v2/\$metadata'
        pathType: Prefix
        backend:
          service:
            name: example-app2
            port:
              name: http
</code></pre>
<p>The resulting <code>location</code> directives look like:</p>
<pre><code>location ~* &quot;^/api/v2/\$metadata&quot; {
...
}
location ~* &quot;^/app1(/|$)(.*)&quot; {
...
}
</code></pre>
<p>And a request for the <code>$metadata</code> path succeeds.</p>
