Previously we introduced the use of URL Rewrite in ingress-nginx, where rewriting paths is mostly similar to the traditional nginx approach, but if we use Traefik as our gateway, what do we do when we encounter URL Rewrite requirements? We introduced the basic features of Traefik2.1 in an article on understanding the use of Traefik2.1, but we did not mention URL Rewrite.

For example, if we deploy a Nexus application in a Kubernetes cluster, we expose the service through IngressRoute, like any other application, with the following list of resources: (nexus.yaml)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
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 deploy Traefik2.1 Ingress Controller in the cluster first, you can refer to the previous article on understanding the use of Traefik2.1 and deploy the above application directly:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
$ 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

Once deployed, we only need to resolve the domain name nexus.qikqiak.com to Traefik’s node according to the configuration in the IngressRoute object to access.

image

Now we have a requirement that we only have one domain name available, but we have many different applications to expose, so we can only distinguish them by PATH paths. when we visit http:/nexus.qikqiak.com/foo, it is our Nexus application, and when the path starts with /bar, it is some other application. At this point we need to do URL Rewrite.

First we use the middleware StripPrefix, which removes the prefix from the path before forwarding the request, and when using the middleware we just We only need to understand that the middleware is operating on our direct requests, not on the real application that receives the request and then modifies it.

image

Now we add a middleware as follows.

1
2
3
4
5
6
7
8
apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
  name: strip-foo-path
spec:
  stripPrefix:
    prefixes:
    - /foo

Now we need to match the /foo request from the http:/nexus.qikqiak.com/foo request and apply the request under this path to the middleware above, because eventually our Nexus application will not receive the request with the /foo path, so we need to remove this We need to remove this prefix before the request reaches the application and update the IngressRoute object with.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
  name: nexus
spec:
  entryPoints:
  - web
  routes:
  - kind: Rule
    match: Host(`nexus.qikqiak.com`) && PathPrefix(`/foo`)  # 匹配 /foo 路径
    middlewares:
    - name: strip-foo-path
    services:
    - kind: Service
      name: nexus
      port: 8081

After creating the middleware to update the IngressRoute object above, this time we go to the browser and visit http:/nexus.qikqiak.com/foo and this time we find that our page is not styled in any way.

image

We can see through the Chrome Network that the request for the /foo path is a 200 status code, but all the other static resource objects are indeed 404, why is this? We look closely at our IngressRoute resource object above, we now only match the /foo request, while our static resources are /static path at the beginning, of course, it does not match, so there is a 404, so we just need to add this /static path match can be, the same update IngressRoute object.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
  name: nexus
spec:
  entryPoints:
  - web
  routes:
  - kind: Rule
    match: Host(`nexus.qikqiak.com`) && PathPrefix(`/foo`)
    middlewares:
    - name: strip-foo-path
    services:
    - kind: Service
      name: nexus
      port: 8081
  - kind: Rule
    match: Host(`nexus.qikqiak.com`) && PathPrefix(`/static`)  # 匹配 /static 的请求
    services:
    - kind: Service
      name: nexus
      port: 8081

Then update the IngressRoute resource object, and when you go to access the application again, you can find that the page style is now normal, and you can access the application normally:

image

However, after entering the application, we found that there are still error messages, and through Network analysis we found that there are some requests starting with /service that are 404, but of course we can add this prefix to the path.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
  name: nexus
spec:
  entryPoints:
  - web
  routes:
  - kind: Rule
    match: Host(`nexus.qikqiak.com`) && PathPrefix(`/foo`)
    middlewares:
    - name: replace-path
    services:
    - kind: Service
      name: nexus
      port: 8081
  - kind: Rule
    match: Host(`nexus.qikqiak.com`) && (PathPrefix(`/static`) || PathPrefix(`/service`))  # 匹配 /static 和 /service 的请求
    services:
    - kind: Service
      name: nexus
      port: 8081

After the update, the application is fully functional when accessed again.

image

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