AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / server / 问题 / 1142373
Accepted
gigio
gigio
Asked: 2023-08-25 17:38:18 +0800 CST2023-08-25 17:38:18 +0800 CST 2023-08-25 17:38:18 +0800 CST

部署在 URL 前缀后面时处理 Flask 路由路径

  • 772

我使用 python Flask框架构建单页应用程序。我使用Gunicorn作为 Web 服务器,并使用docker将其容器化。它通过Nginx Ingress Controller部署在Azure Kubernetes Services ( aks )上。

设置

我的 Flask 应用程序如下所示:

src/main.py

from flask import Flask
from src.routes import main_bp


app = Flask(__name__)
app.register_blueprint(main_bp)


@app.route('/health/live')
def healthLiveMsg():
    return 'Healthy'


@app.route('/health/ready')
def healthReadyMsg():
    return 'Healthy'


if __name__ == '__main__':
    app.run(host='0.0.0.0', port=80)

src/main_bp.py

from flask import Blueprint, render_template


main_bp = Blueprint('main', __name__)

# home page
@main_bp.route('/')
def home():
    return render_template('index.html')

# some other page
@main_bp.route('/import')
def import_page():
    # some code...
    return renter_template('import.html')


# some backend job trigger
@main_bp.route('/run_job', methods=['POST'])
def run_job():
    # some code...    


def register_blueprints(app):
    app.register_blueprint(main_bp)

有base.html一个导航栏,我使用 Flask 的url_for功能分别获取主页和导入页面的链接href="{{ url_for('main.home') }},href="{{ url_for('main.import_page') }}

aks 入口在以下 yaml 模板中定义:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: __AksIngress__-ingress
  namespace: __AksNamespace__
  annotations:
    nginx.ingress.kubernetes.io/proxy-buffer-size: 16k
    nginx.ingress.kubernetes.io/proxy-body-size: "0"
    nginx.ingress.kubernetes.io/server-alias: __AksNamespace__.__AksDnsZone__.__AksDomainName__
    nginx.ingress.kubernetes.io/rewrite-target: /$1
    nginx.ingress.kubernetes.io/proxy-connect-timeout: "3600"
    nginx.ingress.kubernetes.io/proxy-read-timeout: "3600"
    nginx.ingress.kubernetes.io/proxy-send-timeout: "3600"
    nginx.ingress.kubernetes.io/server-snippet: keepalive_timeout 3600s;client_body_timeout 3600s;client_header_timeout 3600s;
spec:
  tls:
  - hosts:
    - __AksNamespace__.__AksDnsZone__.__AksDomainName__
    secretName: __AksIngress__-tls
  ingressClassName: nginx
  rules:
  - host: __AksNamespace__.__AksDnsZone__.__AksDomainName__
    http:
      paths:
      - path: /myapp/?(.*)
        pathType: Prefix
        backend:
          service:
            name: myapp-service
            port:
              number: 80

问题

当部署在 aks 上时,可以通过以下地址访问该应用程序example.com/myapp。所提供的页面显示导航栏的 html,其中包含hrefs as"/"和"/import"。当点击其中任何一个时,浏览器会导航到example.com并example.com/import删除myapp前缀,当然会出现 404 错误。我们期望在页面导航时正确构建 URL,并带有前缀,例如example.com/myapp/import。活性和就绪性检查(可在example.com/myapp/health/live和获取example.com/myapp/health/ready)由 Kubernetes 找到。

我的尝试

我尝试了多种解决方案,但没有一个有效。

SCRIPT_NAME

经过几次搜索后,我发现这篇博客文章提到了正确的解决方案。我在 dockerfile 中设置了环境变量并在本地计算机上运行容器,是的,它正在工作:

  • 主页位于localhost/myapp
  • 单击导航栏将我带到localhost/myapp/import
  • 单击导入页面中发布的按钮以localhost/myapp/run_job触发后端作业。

然而,部署到 aks 后,一切都只是多了一个额外的前缀:

  • 主页现在位于example.com/myapp/myapp
  • 导航到其他页面example.com/myapp/import时,我会看到该页面现在位于example.com/myapp/myapp/import
  • 类似的事情与run_job
  • 此外,kubernetes 的活性和就绪性检查失败,因为它们也在双前缀路径下。

代理修复

我尝试按照此 SO 答案中的建议使用 ProxyFix ,并在初始化应用程序后添加以下行:

app.wsgi_app = ProxyFix(app.wsgi_app, x_for=1, x_host=1)

然而,这似乎并没有产生任何效果。我也尝试过传递x_prefix=1参数,但没有成功。

问题

我读了很多东西,现在我已经很困惑了。我开始使用“flaskrouting with aks”作为关键词来搜索答案,然后转移到“wsgi服务器”,然后“nginx反向代理”“nginx前缀”或“nginx入口”,现在我不确定实际上是什么正在发生。我不确定解决方案是否应该来自ingress.yamlgunicorn,或者是否是需要适应的flask应用程序。

我看到的行为是什么以及如何解决它?

由于此项目结构(与 aks 基础设施一起)是根据模板构建的,因此我想要一个可以添加到此类模板中或者可以单独添加到代码中的解决方案。

gunicorn
  • 1 1 个回答
  • 14 Views

1 个回答

  • Voted
  1. Best Answer
    Gerald Schneider
    2023-08-25T18:25:06+08:002023-08-25T18:25:06+08:00

    您的代理配置缺少必要的X-Forwarded-Prefix标头配置。

    从文档中:

    X-Forwarded-Prefix 标头

    要将非标准X-Forwarded-Prefix标头添加到带有字符串值的上游请求中,可以使用以下注释:

    nginx.ingress.kubernetes.io/x-forwarded-prefix: "/path"
    

    这需要与 Proxyfix Flask 配置一起使用,x_prefix=1当然包括参数。

    • 0

相关问题

  • Nginx 重定向到 http://localhost

  • 主管没有使用 Django 项目正确重新加载 Gunicorn

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    新安装后 postgres 的默认超级用户用户名/密码是什么?

    • 5 个回答
  • Marko Smith

    SFTP 使用什么端口?

    • 6 个回答
  • Marko Smith

    命令行列出 Windows Active Directory 组中的用户?

    • 9 个回答
  • Marko Smith

    什么是 Pem 文件,它与其他 OpenSSL 生成的密钥文件格式有何不同?

    • 3 个回答
  • Marko Smith

    如何确定bash变量是否为空?

    • 15 个回答
  • Martin Hope
    Tom Feiner 如何按大小对 du -h 输出进行排序 2009-02-26 05:42:42 +0800 CST
  • Martin Hope
    Noah Goodrich 什么是 Pem 文件,它与其他 OpenSSL 生成的密钥文件格式有何不同? 2009-05-19 18:24:42 +0800 CST
  • Martin Hope
    Brent 如何确定bash变量是否为空? 2009-05-13 09:54:48 +0800 CST
  • Martin Hope
    cletus 您如何找到在 Windows 中打开文件的进程? 2009-05-01 16:47:16 +0800 CST

热门标签

linux nginx windows networking ubuntu domain-name-system amazon-web-services active-directory apache-2.4 ssh

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve