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:
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.
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`) && 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:
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`) && PathPrefix(`/foo`)
middlewares:
- name: strip-foo-path
services:
- kind: Service
name: nexus
port: 8081
- kind: Rule
match: Host(`nexus.qikqiak.com`) && 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:
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`) && PathPrefix(`/foo`)
middlewares:
- name: replace-path
services:
- kind: Service
name: nexus
port: 8081
- kind: Rule
match: Host(`nexus.qikqiak.com`) && (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:
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