Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Kubernetes uvicorn fastapi path based routing Ingress not working

I manage an Azure AKS cluster with several API's written in Python and Uvicorn (FastAPI). We use the ingress-nginx ingress controller.

Currently API's are reached through a unique url similar to: servicename.departmentname.companyname.com. I am attempting to transition unique url routes to a common root url + path routes. For instance, the above would then become departmentname.companyname.com/servicename.

However, this is consistently causing errors, either 404 not found error or "Failed to load API definition" error (see screenshot), depending on the exact setup I am testing.

I have looked into the FastApi documentation which mentions several approaches that might be relevant in this case, but so fat I haven't been able to understand the root cause of the problem. Any help or suggestions are welcome.

enter image description here

The current k8s uniqure url rout Ingress resource looks like this:

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

The corresponding Dockerfile looks like this:

# 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"]

When transitioning to the root url + path route, the above Ingress resource would have to look something like the below, but this definition is not working.

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
like image 693
h4tt3n Avatar asked Dec 21 '25 09:12

h4tt3n


1 Answers

We have solved it like this:

In the Dockerfile we add a --root-path parameter to the run command, like this:

CMD ["pdm", "run", "uvicorn", "our.uvicorn.service.main:app", "--root-path", "/service/api/v1", "--host", "0.0.0.0", "--port", "8080"]

In the kubernetes ingress resource, we use regex to catch the right path:

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

Path can be anything you like, as long as the value is the same in both DOckerfile and ingress path, in this example "/service/api/v1".

Cheers, Mike

like image 51
h4tt3n Avatar answered Dec 23 '25 22:12

h4tt3n



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!