nginx - FastAPI文档不适用于Nginx Ingress Controller

标签 nginx kubernetes kubernetes-ingress nginx-ingress fastapi

我编写了一个在Kubernetes容器中运行FastAPI服务器的应用程序。与Pod的外部通信通过单独Pod中的Nginx入口 Controller 进行。我正在运行nginx:1.17.0。

一切就绪后,我可以使用curl调用通过入口地址与应用服务器进行交互,并在浏览器中访问所有简单的GET路径以及address / openapi.json。如果我在Kubernetes中使用应用程序服务的内部ip,我也可以访问交互式文档页面。
但是,尝试访问交互式文档页面(address / docs#/ default /)给我一个关于/openapi.json的错误。

enter image description here

由于curl调用按预期工作,因此我认为问题不一定在入口定义中,但由于使用应用程序的内部ip也可以正常工作,因此问题不应在应用程序内部。
我已经在下面包含了入口定义文件。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app-nginx-deployment
  labels:
    app: nginx
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
        - name: nginx
          image: nginx:1.17.0
          imagePullPolicy: IfNotPresent
          ports:
            - containerPort: 80

---
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: my-app-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /$2
spec:
  rules:
  - host: my-host.info
    http:
      paths:
      - path: /server(/|$)(.*)
        backend:
          serviceName: my-app-service # This is the service that runs my fastAPI server pod
          servicePort: 80

编辑
这是service.yaml文件
apiVersion: v1
kind: Service
metadata:
  name: my-app-service
spec:
  type: ClusterIP
  selector:
    app: server
  ports:
    - protocol: "TCP"
      port: 80
      targetPort: 80

由于该服务是我本地群集中的ClusterIP,因此我可能可以直接使用它,但是我没有尝试过。当我 curl 时,我使用诸如
curl -X GET "http://my-host.info/server/subpath/" -H "accept: application/json"
curl -X POST "http://my-host.info/server/subpath/update/" -H "accept: application/json"

从本地群集外部。

这些是所有正在运行的服务:
NAMESPACE              NAME                        TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)                  AGE
default                kubernetes                  ClusterIP   10.96.0.1       <none>        443/TCP                  11d
default                my-app-service              ClusterIP   10.96.68.29     <none>        80/TCP                   18h
kube-system            kube-dns                    ClusterIP   10.96.0.10      <none>        53/UDP,53/TCP,9153/TCP   28d
kubernetes-dashboard   dashboard-metrics-scraper   ClusterIP   10.96.114.1     <none>        8000/TCP                 28d
kubernetes-dashboard   kubernetes-dashboard        ClusterIP   10.96.249.255   <none>        80/TCP                   28d

在我的/etc/hosts文件中,我已将10.0.0.1(群集“外部” IP)连接到my-host.info。

为什么会这样?

最佳答案

我认为您绝对应该研究FastApi的官方文档:https://fastapi.tiangolo.com/advanced/behind-a-proxy/
如您所述,在内部访问Swagger自动文档时,工作正常,但从群集外部访问时,会出现有关/openapi.json的错误。
service.yaml中,您有:

      - path: /server(/|$)(.*)
        backend:
          serviceName: my-app-service # This is the service that runs my fastAPI server pod
          servicePort: 80
当使用uvicorn启动应用程序时,您应该传递root_pathuvicorn main:app --root-path /server注意:在这里您将能够访问路由器端点,但不能访问Swagger文档。为了获取Swagger文档,您必须编辑您的主要main.py文件:

from fastapi import FastAPI, Request

app = FastAPI(openapi_prefix="/server")

@app.get("/")
def read_root(request: Request):
    return {"message": "Hello World", "root_path": request.scope.get("root_path")}

我搜索了为什么我们需要显式传递OpenApi前缀,但是我发现只有解决方法,例如:https://github.com/iwpnd/fastapi-aws-lambda-example/issues/2
因此,我建议将root_path存储在系统上的环境变量$ROOT_PATH=/server中,并将其传递给uvicorn main:app --root-path $ROOT_PATHmain.py中:
import os
from fastapi import FastAPI, Request

app = FastAPI(openapi_prefix=os.getenv('ROOT_PATH', ''))

@app.get("/")
def read_root(request: Request):
    return {"message": "Hello World", "root_path": request.scope.get("root_path")}

更新07.07.2020
如果使用fastapi版本,当前tiangolo准备使用docker镜像https://github.com/tiangolo/uvicorn-gunicorn-fastapi-docker已“过时”,当前版本为:0.55.1-在此处报告:link
从0.56.0开始支持“root_path”

关于nginx - FastAPI文档不适用于Nginx Ingress Controller ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60397218/

相关文章:

ruby-on-rails - Nginx 上的 SSL 导致重定向循环

docker - 如何查看kubernetes的入口端点?

kubernetes - 为什么 Kubernetes 使用 yaml 文件为 "resource"

kubernetes - 与服务背后的所有Kubernetes Pod通信

php - Laravel Forge (Nginx) Gzip 和浏览器缓存 + SSL

ruby-on-rails - ActionController::InvalidAuthenticityToken 在登录时使用 NGINX 和 Rails

nginx - 使用 nginx ingress 时是否有 pod 级 nginx 的意义?

web-services - Kubernetes: "persistent"端口转发

kubernetes - K8S 入口 : How to limit requests in flight per pod

kubernetes - Istio路由端口规范