Kubernetes 集群中的 DisallowedHost Django 部署:无效 HTTP_HOST header
DisallowedHost Django deployment in Kubernetes cluster: Invalid HTTP_HOST header
我在我的 Azure Kubernetes 集群中有一个前端服务的 Django 部署,具有一些基本配置。但请注意,同样的问题适用于我的本地 Minikube 集群。我从我的远程容器注册表中获取我的 Django 前端容器映像并公开 port 8010
。我的服务配置也很简单。
frontend.deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: frontend-v1
labels:
app: frontend-v1
spec:
replicas: 1
selector:
matchLabels:
app: frontend-v1
template:
metadata:
labels:
app: frontend-v1
spec:
containers:
- name: frontend-v1
imagePullPolicy: Always
image: yourremotename.azurecr.io/frontend-remote:v1
ports:
- containerPort: 8010
imagePullSecrets:
- name: acr-secret
frontend.service.yaml
kind: Service
apiVersion: v1
metadata:
name: frontend-v1
spec:
selector:
app: frontend-v1
ports:
- NodePort:
protocol: TCP
port: 8010
targetPort: 8010
type: NodePort
现在,当我在浏览器中访问部署的前端服务时 即http://172.17.194.253:31436 使用 Django 的设置 DEBUG = True
,我得到错误:
Traceback (most recent call last):
File "/usr/local/lib/python3.6/dist-packages/django/core/handlers/exception.py", line 34, in inner
response = get_response(request)
File "/usr/local/lib/python3.6/dist-packages/django/utils/deprecation.py", line 93, in __call__
response = self.process_request(request)
File "/usr/local/lib/python3.6/dist-packages/django/middleware/common.py", line 48, in process_request
host = request.get_host()
File "/usr/local/lib/python3.6/dist-packages/django/http/request.py", line 122, in get_host
raise DisallowedHost(msg)
Exception Type: DisallowedHost at /
Exception Value: Invalid HTTP_HOST header: '172.17.194.253:31436'. You may need to add '172.17.194.253' to ALLOWED_HOSTS.
但是如何将动态创建的 pod 的 HostIp 绑定到 Django 的 ALLOWED_HOSTS
?
从 Kubernetes 1.7 开始,可以在您的 kubernetes 部署文件中请求 pod 的 HostIp。(1)
首先调整部署文件,为HostIp设置所需的环境变量。在下面的场景中,我设置了 POD_IP 和 HOST_IP,因为它们是不同的。您可以在 Kubernetes 部署文件中使用环境变量注入各种 Kubernetes 应用程序数据变量,有关此主题的更多信息请查看 here.
frontend.service.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: frontend-v1
labels:
app: frontend-v1
spec:
replicas: 1
selector:
matchLabels:
app: frontend-v1
template:
metadata:
labels:
app: frontend-v1
spec:
containers:
- name: frontend-v1
imagePullPolicy: Always
image: yourremotename.azurecr.io/frontend-remote:v1
ports:
- containerPort: 8010
env:
- name: POD_IP
valueFrom:
fieldRef:
fieldPath: status.podIP
- name: HOST_IP
valueFrom:
fieldRef:
fieldPath: status.hostIP
imagePullSecrets:
- name: acr-secret
现在在 Django 设置中调整 ALLOWED_HOSTS
配置以指向 HOST_IP
环境变量。
settings.py
import os
...
ALLOWED_HOSTS = [os.environ.get('HOST_IP'), '127.0.0.1']
....
请注意,这允许 pod 的 HostIP 以及 localhost 用于本地开发目的。
警告! 一些博客文章或教程建议您设置 ALLOWED_HOSTS = ['*']
以接受所有主机 IP,但这是一个严重的安全漏洞。不要这样做!
现在重新部署您的 pod,您的 Django 应用程序应该再次 运行 顺利。
或者,只需在 readinessProbe header 中添加 Host: yourdomain.com
。您还可以自定义默认路径。
readinessProbe:
httpGet:
path: /
port: 8010 # Must be same as containerPort
httpHeaders:
- name: Host
value: yourdomain.com
我在我的 Azure Kubernetes 集群中有一个前端服务的 Django 部署,具有一些基本配置。但请注意,同样的问题适用于我的本地 Minikube 集群。我从我的远程容器注册表中获取我的 Django 前端容器映像并公开 port 8010
。我的服务配置也很简单。
frontend.deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: frontend-v1
labels:
app: frontend-v1
spec:
replicas: 1
selector:
matchLabels:
app: frontend-v1
template:
metadata:
labels:
app: frontend-v1
spec:
containers:
- name: frontend-v1
imagePullPolicy: Always
image: yourremotename.azurecr.io/frontend-remote:v1
ports:
- containerPort: 8010
imagePullSecrets:
- name: acr-secret
frontend.service.yaml
kind: Service
apiVersion: v1
metadata:
name: frontend-v1
spec:
selector:
app: frontend-v1
ports:
- NodePort:
protocol: TCP
port: 8010
targetPort: 8010
type: NodePort
现在,当我在浏览器中访问部署的前端服务时 即http://172.17.194.253:31436 使用 Django 的设置 DEBUG = True
,我得到错误:
Traceback (most recent call last):
File "/usr/local/lib/python3.6/dist-packages/django/core/handlers/exception.py", line 34, in inner
response = get_response(request)
File "/usr/local/lib/python3.6/dist-packages/django/utils/deprecation.py", line 93, in __call__
response = self.process_request(request)
File "/usr/local/lib/python3.6/dist-packages/django/middleware/common.py", line 48, in process_request
host = request.get_host()
File "/usr/local/lib/python3.6/dist-packages/django/http/request.py", line 122, in get_host
raise DisallowedHost(msg)
Exception Type: DisallowedHost at /
Exception Value: Invalid HTTP_HOST header: '172.17.194.253:31436'. You may need to add '172.17.194.253' to ALLOWED_HOSTS.
但是如何将动态创建的 pod 的 HostIp 绑定到 Django 的 ALLOWED_HOSTS
?
从 Kubernetes 1.7 开始,可以在您的 kubernetes 部署文件中请求 pod 的 HostIp。(1)
首先调整部署文件,为HostIp设置所需的环境变量。在下面的场景中,我设置了 POD_IP 和 HOST_IP,因为它们是不同的。您可以在 Kubernetes 部署文件中使用环境变量注入各种 Kubernetes 应用程序数据变量,有关此主题的更多信息请查看 here.
frontend.service.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: frontend-v1
labels:
app: frontend-v1
spec:
replicas: 1
selector:
matchLabels:
app: frontend-v1
template:
metadata:
labels:
app: frontend-v1
spec:
containers:
- name: frontend-v1
imagePullPolicy: Always
image: yourremotename.azurecr.io/frontend-remote:v1
ports:
- containerPort: 8010
env:
- name: POD_IP
valueFrom:
fieldRef:
fieldPath: status.podIP
- name: HOST_IP
valueFrom:
fieldRef:
fieldPath: status.hostIP
imagePullSecrets:
- name: acr-secret
现在在 Django 设置中调整 ALLOWED_HOSTS
配置以指向 HOST_IP
环境变量。
settings.py
import os
...
ALLOWED_HOSTS = [os.environ.get('HOST_IP'), '127.0.0.1']
....
请注意,这允许 pod 的 HostIP 以及 localhost 用于本地开发目的。
警告! 一些博客文章或教程建议您设置 ALLOWED_HOSTS = ['*']
以接受所有主机 IP,但这是一个严重的安全漏洞。不要这样做!
现在重新部署您的 pod,您的 Django 应用程序应该再次 运行 顺利。
或者,只需在 readinessProbe header 中添加 Host: yourdomain.com
。您还可以自定义默认路径。
readinessProbe:
httpGet:
path: /
port: 8010 # Must be same as containerPort
httpHeaders:
- name: Host
value: yourdomain.com