简体   繁体   English

Kubernetes Nginx-ingress如何在Express中处理路由

[英]Kubernetes nginx-ingress how to deal with routing in Express

I have an Azure Kubernetes Cluster on which a couple of NodesJS Express Applications runs. 我有一个运行两个NodesJS Express应用程序的Azure Kubernetes群集。 I handle the incoming request by nginx-ingress 我通过nginx-ingress处理传入的请求

nginx-ingress Nginx入口

controller: https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/static/mandatory.yaml 控制器: https : //raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/static/mandatory.yaml

service: https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/static/provider/cloud-generic.yaml 服务: https : //raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/static/provider/cloud-generic.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

example app1-service 示例app1-service

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. 就像您可以看到kubernetesurl.com/app1上的所有流量都转发到了app1-service。 And until there everything works. 直到一切正常。

example app1 示例app1

Dockerfile: FROM node:8 WORKDIR /opt Dockerfile:FROM节点:8 WORKDIR / opt

COPY package.json /opt
RUN npm install

COPY . /opt

CMD ["npm", "start"]

server.js: 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: 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>

Question

  1. If I submit my form, I get redirected to kubernetesurl.com/auth . 如果提交表单,我将被重定向到kubernetesurl.com/auth

    But I need kubernetesurl.com/app1/auth. 但是我需要kubernetesurl.com/app1/auth。

  2. If I use a response.redirect('/home') inside '/', I get redirected to kubernetesurl.com/home . 如果我在'/'内使用response.redirect('/ home')则会重定向到kubernetesurl.com/home

    But I need kubernetesurl.com/app1/home. 但是我需要kubernetesurl.com/app1/home。

  3. If I add a link with relative url to index.html like home, I get redirected to kubernetesurl.com/home . 如果我将带有相对URL的链接添加到home之类的index.html, 则会重定向到kubernetesurl.com/home

    But I need kubernetesurl.com/app1/home. 但是我需要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). 当我开始在VM上将Express表示为服务时,一切正常(当然,因为该应用程序在不带代理的情况下在“ /”上运行)。

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. 由于您有两个不同的位置,指向两个不同的服务,因此可以尝试对相对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. 因此,基本上,您只使用第一个组( location1location2 )路由到Ingress级别的正确服务。

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. 然后,可以通过重写规则来消除该组,该规则将仅保留第二组来重写正确的应用程序编号,而第三组则将您传递给URL的其他所有内容进行野匹配。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM