Using URL Rewrite in Traefik 2.X

Previously, we introduced the use of URL Rewrite in ingress-nginx, where the path rewriting is mostly similar to the traditional nginx method. However, if we are using the more cloud-native Traefik as our gateway, how do we handle URL Rewrite requirements? In an earlier article, we discussed the basic functionalities of Traefik 2.1, but we did not mention URL Rewrite. In Traefik 2.1, we can still conveniently achieve this functionality using middleware.

For example, we have deployed a Nexus application in a Kubernetes cluster. Like other applications, we expose the service through IngressRoute, and the corresponding resource manifest is as follows: (nexus.yaml)

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nexus
  labels:
    app: nexus
spec:
  selector:
    matchLabels:
      app: nexus
  template:
    metadata:
      labels:
        app: nexus
    spec:
      containers:
      - image: cnych/nexus:3.20.1
        imagePullPolicy: IfNotPresent
        name: nexus
        ports:
        - containerPort: 8081


---
apiVersion: v1
kind: Service
metadata:
  labels:
    app: nexus
  name: nexus
spec:
  ports:
  - name: nexusport
    port: 8081
    targetPort: 8081
  selector:
    app: nexus


---
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
  name: nexus
spec:
  entryPoints:
  - web
  routes:
  - kind: Rule
    match: Host(`nexus.qikqiak.com`)
    services:
    - kind: Service
      name: nexus
      port: 8081

Of course, the prerequisite is to first deploy the Traefik 2.1 Ingress Controller in the cluster. If you haven’t deployed it yet, you can refer to the previous article to understand the use of Traefik 2.1 and directly deploy the above application:

$ kubectl apply -f nexus.yaml
$ kubectl get ingressroute
NAME                AGE
nexus               19h
$ kubectl get pods
NAME                                      READY   STATUS    RESTARTS   AGE
nexus-f9f8c77b5-vvvvw                     1/1     Running   0          20h
$ kubectl get svc
NAME            TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)          AGE
kubernetes      ClusterIP   10.96.0.1        <none>        443/TCP          62d
nexus           NodePort    10.96.175.87     <none>        8081:30776/TCP   20h

After deployment, we just need to resolve the domain name <span>nexus</span><span>.</span><span>qikqiak</span><span>.</span><span>com</span> to the Traefik node to access it:

Using URL Rewrite in Traefik 2.X

At this point, we can easily accomplish this. Now, we have a requirement where we only have one domain name available, but we need to expose many different applications. In this case, we can only distinguish them through the PATH. For example, we want to access our Nexus application when visiting <span>http</span><span>:</span><span>/nexus.qikqiak.com/</span><span>foo</span>, while other applications should be accessed when the path starts with <span>/</span><span>bar</span>. This scenario is quite common, and we will need to perform URL Rewrite.

First, we use the StripPrefix middleware (https://www.qikqiak.com/traefik-book/middlewares/stripprefix/). The function of this middleware is to remove the prefix from the path before forwarding the request. When using middleware, we just need to understand that the operations of the middleware are on our direct requests and not on the actual requests received by the application.

Using URL Rewrite in Traefik 2.X

Now we add a middleware as follows:

apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
  name: strip-foo-path
spec:
  stripPrefix:
    prefixes:
    - /foo

Now we need to match the request from <span>http</span><span>:</span><span>/nexus.qikqiak.com/</span><span>foo</span> with the request for <span>/</span><span>foo</span> and apply this path to the above middleware. The request received by our Nexus application will not have the <span>/</span><span>foo</span> path, so we need to remove this prefix before the request reaches the application and update the IngressRoute object:

apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
  name: nexus
spec:
  entryPoints:
  - web
  routes:
  - kind: Rule
    match: Host(`nexus.qikqiak.com`) &amp;&amp; PathPrefix(`/foo`)  # Match /foo path
    middlewares:
    - name: strip-foo-path
    services:
    - kind: Service
      name: nexus
      port: 8081

After creating the middleware and updating the IngressRoute object, we can now visit <span>http</span><span>:</span><span>/nexus.qikqiak.com/</span><span>foo</span> in the browser, but we find that our page has no styles:

Using URL Rewrite in Traefik 2.X

We can check the request for the <span>/</span><span>foo</span> path in Chrome’s Network tab, and see that it returns a 200 status code, but all other static resource requests return 404. Why is this? Upon careful observation of our IngressRoute resource object, we see that we only matched requests for <span>/</span><span>foo</span>, while our static resources start with <span>/</span><span>static</span>, so they do not match and return 404. We just need to add a match for the <span>/</span><span>static</span> path and update the IngressRoute object:

apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
  name: nexus
spec:
  entryPoints:
  - web
  routes:
  - kind: Rule
    match: Host(`nexus.qikqiak.com`) &amp;&amp; PathPrefix(`/foo`)
    middlewares:
    - name: strip-foo-path
    services:
    - kind: Service
      name: nexus
      port: 8081
  - kind: Rule
    match: Host(`nexus.qikqiak.com`) &amp;&amp; PathPrefix(`/static`)  # Match /static requests
    services:
    - kind: Service
      name: nexus
      port: 8081

After updating the IngressRoute resource object, we can access the application again, and the page styles are now normal, and we can access the application properly:

Using URL Rewrite in Traefik 2.X

However, after entering the application, we find that there are still error messages. Analyzing the Network tab shows that there are still some requests starting with <span>/</span><span>service</span> that return 404. We can simply add a match for this prefix path:

apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
  name: nexus
spec:
  entryPoints:
  - web
  routes:
  - kind: Rule
    match: Host(`nexus.qikqiak.com`) &amp;&amp; PathPrefix(`/foo`)
    middlewares:
    - name: replace-path
    services:
    - kind: Service
      name: nexus
      port: 8081
  - kind: Rule
    match: Host(`nexus.qikqiak.com`) &amp;&amp; (PathPrefix(`/static`) || PathPrefix(`/service`))  # Match /static and /service requests
    services:
    - kind: Service
      name: nexus
      port: 8081

After updating, we can access the application again, and everything is functioning normally:

Using URL Rewrite in Traefik 2.X

The middleware functionality in Traefik 2.X is very powerful, and the series of middleware provided by the official documentation can meet most of our needs. For other middleware usage, you can refer to the documentation: https://www.qikqiak.com/traefik-book/middlewares/overview/.

K8S Advanced Training Camp, click the image below for details

Using URL Rewrite in Traefik 2.X

Using URL Rewrite in Traefik 2.X

Leave a Comment