我使用用 Python 和 Uvicorn (FastAPI) 编写的多个 API 来管理 Azure AKS 群集。我们使用 ingress-nginx 入口 Controller 。
目前,API 是通过类似于以下内容的唯一 URL 访问的:servicename.departmentname.companyname.com。我正在尝试将唯一的 url 路由转换为公共(public)根 url + 路径路由。例如,上面的内容将变为departmentname.companyname.com/servicename。
但是,这始终会导致错误,要么是 404 未找到错误,要么是“无法加载 API 定义”错误(参见屏幕截图),具体取决于我正在测试的具体设置。
我查看了 FastApi 文档,其中提到了几种可能与这种情况相关的方法,但是太胖了,我无法理解问题的根本原因。欢迎任何帮助或建议。
当前的 k8s 唯一 url 路由 Ingress 资源如下所示:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: servicename-api-ingress
namespace: servicename-api-prod
annotations:
cert-manager.io/cluster-issuer: letsencrypt-clusterissuer
spec:
ingressClassName: nginx
rules:
- host: servicename.departmentname.companyname.com
http:
paths:
- path: /
pathType: ImplementationSpecific
backend:
service:
name: servicename-api-service
port:
number: 80
tls:
- hosts:
- servicename.departmentname.companyname.com
secretName: servicename-api-tls
相应的 Dockerfile 如下所示:
# build stage
FROM python:3.10
# install PDM
RUN pip install -U pip setuptools wheel
RUN pip install pdm
# copy files
COPY pyproject.toml pdm.lock README.md /project/
COPY src/ /project/src
# install dependencies and project
WORKDIR /project
RUN pdm install
# set command/entrypoint, adapt to fit your needs
CMD ["pdm", "run", "uvicorn", "companyname.servicename.api.main:app", "--host", "0.0.0.0", "--port", "8080"]
当转换到 root url + path 路由时,上面的 Ingress 资源必须如下所示,但这个定义不起作用。
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: servicename-api-ingress
namespace: servicename-api-prod
annotations:
cert-manager.io/cluster-issuer: letsencrypt-clusterissuer
spec:
ingressClassName: nginx
rules:
- host: departmentname.companyname.com
http:
paths:
- path: /servicename/
pathType: Prefix
backend:
service:
name: servicename-api-service
port:
number: 80
tls:
- hosts:
- departmentname.companyname.com
secretName: servicename-api-tls
最佳答案
我们是这样解决的:
在 Dockerfile 中,我们向运行命令添加一个 --root-path 参数,如下所示:
CMD ["pdm", "run", "uvicorn", "our.uvicorn.service.main:app", "--root-path", "/service/api/v1", "--host", "0.0.0.0", "--port", "8080"]
在 kubernetes 入口资源中,我们使用正则表达式来捕获正确的路径:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: our-cool-ingress
namespace: our-cool-namespace
annotations:
cert-manager.io/cluster-issuer: letsencrypt-clusterissuer
nginx.ingress.kubernetes.io/use-regex: "true"
nginx.ingress.kubernetes.io/rewrite-target: /$2
spec:
ingressClassName: nginx
rules:
- host: our.cool.url.com
http:
paths:
- path: /service/api/v1(/|$)(.*)
pathType: Prefix
backend:
service:
name: our-cool-service
port:
number: 80
tls:
- hosts:
- our.cool.url.com
secretName: our-cool-url-com-tls
路径可以是您喜欢的任何内容,只要 DOckerfile 和入口路径中的值相同即可,在本例中为“/service/api/v1”。
干杯,迈克
关于docker - Kubernetes uvicorn fastapi 基于路径的路由 Ingress 不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/76414203/