nginx 入口控制器和基本 django 应用程序的路由问题
Routing issues with nginx ingress controller and basic django app
编辑:我用一个完全可重现的例子重写了这个问题。
我有一个示例 Django 应用程序,基础入门 https://docs.djangoproject.com/en/3.2/intro/tutorial01/,即有两个路径 /admin
和 /polls
。
如果我使用 NodePort 部署应用程序,我可以毫无问题地访问这两个路径。但是,我还没有设法对 Nginx 入口控制器做同样的事情。我尝试了几种注释和路径的组合都无济于事。
所以,假设这个 yaml:
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: django
name: django
spec:
selector:
matchLabels:
app: django
template:
metadata:
labels:
app: django
spec:
containers:
- image: "ay0o/django-ingress:latest"
name: django
# ---
# apiVersion: v1
# kind: Service
# metadata:
# name: django
# spec:
# ports:
# - nodePort: 31000
# port: 8000
# targetPort: 8000
# selector:
# app: django
# type: NodePort
---
apiVersion: v1
kind: Service
metadata:
name: django
spec:
ports:
- port: 8000
selector:
app: django
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: django
spec:
rules:
- http:
paths:
- path: /django
pathType: Prefix
backend:
service:
name: django
port:
number: 8000
当我使用 NodePort 时,http://localhost:31000/admin
和 http://localhost:31000/polls
工作正常。
当我使用 Ingress 时,http://localhost/django
returns 来自 django 的 404(因为路径既不是 admin 也不是 polls),但是 http://localhost/django/admin
和 http://localhost/django/polls
return 来自 nginx 的 404,表示入口没有正确路由。
所以,我应该更改什么才能使 http://localhost/django/admin
和 http://localhost/django/polls
不会 return 404?
我得出的结论是,不可能为 Django 应用程序使用基于路径的 Ingress,这可能与 Django 的内部机制有关。
那里的每个示例都使用基于主机的规则,而且确实有效。比如上面的Ingress可以改成下面这样就可以了
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: django
spec:
rules:
- host: localhost
http:
paths:
- pathType: Prefix
path: "/"
backend:
service:
name: django
port:
number: 8000
如果有人想出使用基于路径的路由的解决方案,请随时回答问题。
我认为你不应该让他们都管理路由路径。你必须选择其中之一。这是因为 Ingress 是为微服务集群路由流量而构建的。如果你想真正使用它,你必须将你的应用程序拆分为两个单独的服务,这些服务仅在 / 处接受请求。并让路由跟Ingress。查看此页面:
https://kubernetes.io/docs/concepts/services-networking/ingress/#simple-fanout
如果您不想更改您的应用程序或者它只是为了测试目的。它使用两条规则部署 Ingress 的方式:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: django
namespace: default
spec:
ingressClassName: nginx
rules:
- host: localhost
http:
paths:
- path: /admin
pathType: Prefix
backend:
service:
name: django
port:
number: 80
- path: /polls
pathType: Prefix
backend:
service:
name: django
port:
number: 80
这将接受两个路径上的请求。
编辑:我用一个完全可重现的例子重写了这个问题。
我有一个示例 Django 应用程序,基础入门 https://docs.djangoproject.com/en/3.2/intro/tutorial01/,即有两个路径 /admin
和 /polls
。
如果我使用 NodePort 部署应用程序,我可以毫无问题地访问这两个路径。但是,我还没有设法对 Nginx 入口控制器做同样的事情。我尝试了几种注释和路径的组合都无济于事。
所以,假设这个 yaml:
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: django
name: django
spec:
selector:
matchLabels:
app: django
template:
metadata:
labels:
app: django
spec:
containers:
- image: "ay0o/django-ingress:latest"
name: django
# ---
# apiVersion: v1
# kind: Service
# metadata:
# name: django
# spec:
# ports:
# - nodePort: 31000
# port: 8000
# targetPort: 8000
# selector:
# app: django
# type: NodePort
---
apiVersion: v1
kind: Service
metadata:
name: django
spec:
ports:
- port: 8000
selector:
app: django
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: django
spec:
rules:
- http:
paths:
- path: /django
pathType: Prefix
backend:
service:
name: django
port:
number: 8000
当我使用 NodePort 时,http://localhost:31000/admin
和 http://localhost:31000/polls
工作正常。
当我使用 Ingress 时,http://localhost/django
returns 来自 django 的 404(因为路径既不是 admin 也不是 polls),但是 http://localhost/django/admin
和 http://localhost/django/polls
return 来自 nginx 的 404,表示入口没有正确路由。
所以,我应该更改什么才能使 http://localhost/django/admin
和 http://localhost/django/polls
不会 return 404?
我得出的结论是,不可能为 Django 应用程序使用基于路径的 Ingress,这可能与 Django 的内部机制有关。
那里的每个示例都使用基于主机的规则,而且确实有效。比如上面的Ingress可以改成下面这样就可以了
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: django
spec:
rules:
- host: localhost
http:
paths:
- pathType: Prefix
path: "/"
backend:
service:
name: django
port:
number: 8000
如果有人想出使用基于路径的路由的解决方案,请随时回答问题。
我认为你不应该让他们都管理路由路径。你必须选择其中之一。这是因为 Ingress 是为微服务集群路由流量而构建的。如果你想真正使用它,你必须将你的应用程序拆分为两个单独的服务,这些服务仅在 / 处接受请求。并让路由跟Ingress。查看此页面:
https://kubernetes.io/docs/concepts/services-networking/ingress/#simple-fanout
如果您不想更改您的应用程序或者它只是为了测试目的。它使用两条规则部署 Ingress 的方式:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: django
namespace: default
spec:
ingressClassName: nginx
rules:
- host: localhost
http:
paths:
- path: /admin
pathType: Prefix
backend:
service:
name: django
port:
number: 80
- path: /polls
pathType: Prefix
backend:
service:
name: django
port:
number: 80
这将接受两个路径上的请求。