I have an Azure Kubernetes Cluster on which a couple of NodesJS Express Applications runs. I handle the incoming request by nginx-ingress
controller: https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/static/mandatory.yaml
ingress:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: myingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /$2
#nginx.ingress.kubernetes.io/use-regex: "true"
spec:
rules:
- http:
paths:
- path: /app1(/|$)(.*)
backend:
serviceName: app1-service
servicePort: 80
- path: /app2(/|$)(.*)
backend:
serviceName: app2-service
servicePort: 80
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: app1
spec:
replicas: 2
template:
metadata:
labels:
app: app1
spec:
nodeSelector:
"beta.kubernetes.io/os": linux
containers:
- name: nodejs
image: xxx.azurecr.io/app1:v1.0
imagePullPolicy: Always
ports:
- containerPort: 80
protocol: TCP
---
kind: Service
apiVersion: v1
metadata:
name: app1-service
spec:
selector:
app: app1
ports:
- port: 80
protocol: TCP
type: NodePort
Like you can see all traffic on kubernetesurl.com/app1 gets forwarded to app1-service. And until there everything works.
Dockerfile: FROM node:8 WORKDIR /opt
COPY package.json /opt
RUN npm install
COPY . /opt
CMD ["npm", "start"]
server.js:
app.get('/', function(request, response) {
response.sendFile(path.join(__dirname + '/login.html'));
});
app.post('/auth', function(request, response) {
... some auth stuff
response.redirect('/home');
});
app.get('/home', function(request, response) {
response.sendFile(path.join(__dirname + '/home.html'));
})
login.html:
<form action="auth" method="POST">
<input type="text" name="username" placeholder="Username" required>
<input type="password" name="password" placeholder="Password" required>
<input type="submit">
</form>
If I submit my form, I get redirected to kubernetesurl.com/auth.
But I need kubernetesurl.com/app1/auth.
If I use a response.redirect('/home') inside '/', I get redirected to kubernetesurl.com/home.
But I need kubernetesurl.com/app1/home.
If I add a link with relative url to index.html like home, I get redirected to kubernetesurl.com/home.
But I need kubernetesurl.com/app1/home.
When I start express as a service on my VM, everything works (of course, because the app runs on '/' without proxying).
How I get it running with proxying?
Since you have two different locations, pointed to two different services, you can try grouping and rewriting the relative URL.
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /app$2/$3
kubernetes.io/ingress.class: "nginx"
spec:
rules:
- host: example.com
http:
paths:
- path: /(location)(1)/(.*)
backend:
serviceName: service1
servicePort: 80
- path: /(location)(2)/(.*)
backend:
serviceName: service2
servicePort: 80
So basically you're only using the first group (location1
and location2
) to route to the correct service at Ingress level.
Then, this group can be dismissed by the rewrite rule which will only keep the second group for rewriting the correct application number and the third to wild-match everything else that you need to pass in your URL.