設定

設定

我使用 python 建立單頁應用程式燒瓶框架。我在用著古尼康作為網頁伺服器,我使用它進行了容器化泊塢窗。它部署在Azure Kubernetes 服務阿克斯) 和Nginx 入口控制器

設定

我的 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.comexample.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 的活性和就緒性檢查失敗,因為它們也在雙前綴路徑下。

代理修復

我嘗試按照建議使用 ProxyFix在這個SO答案中並在初始化應用程式後新增以下行:

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 基礎設施一起)是根據模板構建的,因此我想要一個可以添加到此類模板中或可以單獨添加到程式碼中的解決方案。

答案1

您的代理配置缺少必要的X-Forwarded-Prefix標頭配置。

文件

X-Forwarded-Prefix 標頭

若要將非標準X-Forwarded-Prefix標頭新增至帶有字串值的上游請求中,可以使用下列註解:

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

這需要與 Proxyfix Flask 配置一起使用,x_prefix=1當然包括參數。

相關內容