简体   繁体   English

使用 Kubernetes 入口资源 (nginx) 在不同路径上的两个 Flask 应用程序

[英]Two Flask apps on different paths with Kubernetes Ingress resource (nginx)

My goal is the following: I have two Flask apps in two separate Docker containers and I want to access them via different paths on the same IP address, like this: 127.0.0.1/app1, 127.0.0.1/app2 (but with a real IP address). My goal is the following: I have two Flask apps in two separate Docker containers and I want to access them via different paths on the same IP address, like this: 127.0.0.1/app1, 127.0.0.1/app2 (but with a real IP 地址)。

I want to do this with Kubernetes.我想用 Kubernetes 做到这一点。

I have a Kubernetes cluster running (Azure Kubernetes Service), with a Deployment and Service for each of the two Docker containers.我有一个 Kubernetes 集群正在运行(Azure Kubernetes 服务),两个 Docker 容器中的每一个都有一个部署和服务。 The pod for each app is running fine.每个应用程序的 pod 运行良好。 I also installed an ingress controller (Nginx) in my cluster and now I am trying to make it work with a single Ingress resource.我还在集群中安装了一个入口 controller (Nginx),现在我正试图让它与单个入口资源一起工作。

If I do it as follows, it works perfectly for 1 single app (either one of them works on IP-address/):如果我按以下方式执行此操作,则它适用于 1 个单个应用程序(其中任何一个都适用于 IP 地址/):

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: ingress-name
  namespace: my-namespace
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  rules:
  - http:
      paths:
      - path: /
        backend:
          serviceName: service1 (or service2)
          servicePort: 5000

But when I try the following it doesn't work:但是当我尝试以下它不起作用时:

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: ingress-name
  namespace: my-namespace
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  rules:
  - http:
      paths:
      - path: /app1
        backend:
          serviceName: service1 
          servicePort: 5000
      - path: /app2
        backend:
          serviceName: service2 
          servicePort: 5000

I am able to see the html page that gets rendered by the Flask app, for both applications on their respective paths, but none of the functionalities work.我能够看到由 Flask 应用程序呈现的 html 页面,这两个应用程序都在各自的路径上,但这些功能都不起作用。

Other than the fact that the paths don't always seem to work (I sometimes get redirected to IP-address/ when I try to connect to IP-address/app1 or IP-address/app1/), the problem is the following (I think):除了路径似乎并不总是有效(当我尝试连接到 IP-address/app1 或 IP-address/app1/ 时,我有时会被重定向到 IP-address/)之外,问题如下(我认为):

Each of the Flask applications have a "/predict" route, that only accepts POST requests, where the respective calls for the apps are made (Each application is an AI application that makes a prediction for a given input).每个 Flask 应用程序都有一个“/predict”路由,它只接受 POST 请求,其中对应用程序进行了相应的调用(每个应用程序都是一个 AI 应用程序,对给定的输入进行预测)。

The calls for both apps are made to IP-address/predict, instead of IP-address/app1/predict or IP-address/app2/predict.两个应用程序的调用均针对 IP-address/predict,而不是 IP-address/app1/predict 或 IP-address/app2/predict。 Also the static files cannot be accessed because of this path problem.此外,由于此路径问题,无法访问 static 文件。

I don't know if this is the right way to do it?我不知道这是否是正确的做法? I tried playing around with the 'rewrite-target' as well, but haven't figured out a solution.我也尝试过使用“重写目标”,但还没有找到解决方案。

I hope someone can explain me what I'm doing wrong.我希望有人能解释我做错了什么。

Check your rewrite annotation in the ingress resource.检查入口资源中的重写注释。 Any request that you make will be rewritten to / .您提出的任何请求都将被重写为/ This means that if you call IP:80/app1 your container will receive IP:80/这意味着如果您调用IP:80/app1您的容器将收到IP:80/

nginx.ingress.kubernetes.io/rewrite-target: /

If you don't want that to happen, then remove that rewrite annotation.如果您不希望发生这种情况,请删除该重写注释。 Your ingress would end up like this:你的入口最终会是这样的:

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: ingress-name
  namespace: my-namespace
spec:
  rules:
  - http:
      paths:
      - path: /app1
        backend:
          serviceName: service1 
          servicePort: 5000
      - path: /app2
        backend:
          serviceName: service2 
          servicePort: 5000

Your containers will receive the full path based on /app1 and /app2 .您的容器将收到基于/app1/app2的完整路径。

UPDATE Check this example.更新检查这个例子。 I have two backends that listen on / and respond an html with a number that you configure via an environment variable.我有两个后端监听/并使用您通过环境变量配置的数字响应 html。

---
apiVersion: v1
kind: Service
metadata:
  name: backend1
  namespace: default
  labels:
    mojix.service: backend1
spec:
  ports:
  - name: "8000"
    port: 8000
    targetPort: 8000
  selector:
    mojix.service: backend1
status:
  loadBalancer: {}

---
apiVersion: apps/v1
kind: Deployment
metadata:
  namespace: default
  labels:
    mojix.service: backend1
  name: backend1
spec:
  replicas: 1
  selector:
    matchLabels:
      mojix.service: backend1
  template:
    metadata:
      creationTimestamp: null
      labels:
        mojix.service: backend1
    spec:
      containers:
      - name: backend1
        image: lozuwa/number_backend:latest
        env:
          - name: BACKEND_NUMBER
            value: "1"
      hostname: backend1
      restartPolicy: Always
---
apiVersion: v1
kind: Service
metadata:
  name: backend2
  namespace: default
  labels:
    mojix.service: backend2
spec:
  ports:
  - name: "8000"
    port: 8000
    targetPort: 8000
  selector:
    mojix.service: backend2
status:
  loadBalancer: {}

---
apiVersion: apps/v1
kind: Deployment
metadata:
  namespace: default
  labels:
    mojix.service: backend2
  name: backend2
spec:
  replicas: 1
  selector:
    matchLabels:
      mojix.service: backend2
  template:
    metadata:
      creationTimestamp: null
      labels:
        mojix.service: backend2
    spec:
      containers:
      - name: backend2
        image: lozuwa/number_backend:latest
        env:
          - name: BACKEND_NUMBER
            value: "2"
      hostname: backend2
      restartPolicy: Always

I have the following ingress.我有以下入口。

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: vizix-ingress
  namespace: default
  annotations:
    kubernetes.io/ingress.class: nginx
    nginx.ingress.kubernetes.io/ssl-redirect: "false"
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  rules:
  - http:
      paths:
      - path: /app1
        backend:
          serviceName: backend1
          servicePort: 8000
      - path: /app2
        backend:
          serviceName: backend2
          servicePort: 8000

If you hit IP/app1 you get Response from 1 and if you hit IP/app2 you get Response from 2 .如果你点击IP/app1你会Response from 1 ,如果你点击IP/app2你会Response from 2 My containers listen on / that is why I need the rewrite.我的容器监听/这就是我需要重写的原因。 What path does your application expect?您的应用程序期望什么路径?

You may consider to supply capture groups entirely within Ingress manifest and specify particular regular expression that will define the source Nginx rewrite rule.您可以考虑完全在 Ingress 清单中提供捕获组,并指定将定义源 Nginx 重写规则的特定正则表达式。

I would expect to get it working as desired, after some adjustments in the genuine Ingress manifest:在对真正的Ingress清单进行一些调整后,我希望它能够按预期工作:

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: ingress-name
  namespace: my-namespace
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /$2
spec:
  rules:
  - http:
      paths:
      - path: /app1(/|$)(.*)
        backend:
          serviceName: service1 
          servicePort: 5000
      - path: /app2(/|$)(.*)
        backend:
          serviceName: service2 
          servicePort: 5000

Probably, you would also need to add Trailing slash in the target URL, instructing Nginx engine to properly serve some static content.可能,您还需要在目标 URL 中添加斜杠,指示 Nginx 引擎正确提供一些 static 内容。

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

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