ripclawbr
ripclawbr

Reputation: 11

How to write an ingress-controller target-rewrite rule in my example?

I am not very familiar with ingress but I am playing around with it.

My goal is to write a target-rewrite policy that redirects all traffic for the /application path to the correct / path were the service is listening.

I came up with the following ingress definition

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: application-ingress
  namespace: myapp
  annotations:
    kubernetes.io/ingress.class: "nginx"
    nginx.ingress.kubernetes.io/app-root: /application
spec:
  rules:
 - host: myhost.foo.com
    http:
      paths:
      - path: /
        backend:
          serviceName: myapp-service
          servicePort: 8080
  tls:
 - secretName: myapp-cert

But when applied, browsing to myhost.foo.com/application doesn't redirect the traffic to the root path where the service is listening. It simply times out.

But, if I remove the traffic-rewrite statement and simply browse to myhost.foo.com, then it works, so it's not a problem with the service being incorrectly configured.

Any guidance is appreciated.

Upvotes: 1

Views: 2927

Answers (1)

mario
mario

Reputation: 11098

In fact it works in exactly the opposite way. Your exzmple would make sense if your application was listening on /application, in other words if it had its root path at /application rather than at /, all requests sent to / would be redirected to /application. Check the example here.

As you can see here:

nginx.ingress.kubernetes.io/app-root annotation defines the Application Root that the Controller must redirect if it's in '/' context.

In your example you've defined only access path at /, in other words it works only when you're accessing your app at myhost.foo.com. You didn't mention anywhere in your ingress definition that it might be accesst at other paths like /application so myhost.foo.com/application have no chances to work.

If you rather want to be able to access your app at myhost.foo.com/application you need something like below:

spec:
  rules:
 - host: myhost.foo.com
    http:
      paths:
      - path: /application
        backend:
          serviceName: myapp-service
          servicePort: 8080

but without a rewrite it will send any request to your backend Pod, exposed by your myapp-service Service not to its / but to /application as you're accessing your ingress backend via this particular path.

To solve that you need a rewrite. As you can read in the documentation:

In some scenarios the exposed URL in the backend service differs from the specified path in the Ingress rule. Without a rewrite any request will return 404. Set the annotation nginx.ingress.kubernetes.io/rewrite-target to the path expected by the service.

Following this example your ingress definition may look as follows:

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /$2
  name: rewrite
  namespace: default
spec:
  rules:
  - host: myhost.foo.com
    http:
      paths:
      - backend:
          serviceName: myapp-service
          servicePort: 8080
        path: /application(/|$)(.*)

In this ingress definition, any characters captured by (.*) will be assigned to the placeholder $2, which is then used as a parameter in the rewrite-target annotation.

The ingress definition above will result in the following rewrites:

myhost.foo.com/application rewrites to myhost.foo.com/

myhost.foo.com/application/ rewrites to myhost.foo.com/

myhost.foo.com/application/new rewrites to myhost.foo.com/new

You can also try:

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /$1
  name: rewrite
  namespace: default
spec:
  rules:
  - host: rewrite.bar.com
    http:
      paths:
      - backend:
          serviceName: http-svc
          servicePort: 80
        path: /(.*)

Upvotes: 2

Related Questions