docker - Kubernetes uvicorn fastapi 基于路径的路由 Ingress 不起作用

标签 docker fastapi kubernetes-ingress azure-aks uvicorn

我使用用 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 文档,其中提到了几种可能与这种情况相关的方法,但是太胖了,我无法理解问题的根本原因。欢迎任何帮助或建议。

enter image description here

当前的 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/

相关文章:

storage - Docker 镜像占用了大量空间?

mongodb - 从 docker-compose 导入 mongodb 数据

python - FastAPI Hello World 示例 : Internal Server Error

fastapi - 是否可以将 Path 参数传递给 FastAPI 依赖函数?

kubernetes - 排查 Google kubernetes 负载均衡器不健康节点的问题

Terraform AWS EKS ALB Kubernetes Ingress 不会创建监听器或目标组

kubernetes - 如何让 Kubernetes Ingress 端口 80 在裸机单节点集群上工作

docker - 使用 AWS CodeBuild 构建 Windows 容器

docker - 设置traefik.docker.network的默认值

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