Django应用部署到Kubernetes:从零到生产的完整实战指南
目录导读
- 为什么选择Kubernetes部署Django?
- 部署前的环境准备
- Django应用容器化(Dockerfile编写)
- 构建生产级Kubernetes清单文件
- 数据库与静态文件处理方案
- Ingress配置与域名绑定
- 自动扩缩容与健康检查
- 常见问题与问答集锦
为什么选择Kubernetes部署Django?
传统将Django部署在单一服务器的方式,在面对流量激增时容易崩溃,Kubernetes作为容器编排平台,提供了自动伸缩、服务发现、滚动更新等能力,举个真实场景:某电商平台Django应用在双11期间,通过K8s的HPA(水平自动伸缩)将实例从3个自动扩展到30个,而运维人员仅需配置阈值。

问答:
Q:是否必须使用Kubernetes?小型Django项目能否直接部署?
A:如果日均PV低于1万,推荐直接部署在VPS(如使用Gunicorn+Nginx),但当服务需要多副本、零停机更新或混合云部署时,K8s是更优解。
部署前的环境准备
1 基础设施要求
- 一个运行中的Kubernetes集群(推荐版本≥1.23)
- kubectl命令行工具配置正确
- 容器镜像仓库(如Docker Hub或私有Harbor)
- 域名及SSL证书(生产环境必备)
2 本地开发环境
# 检测环境 kubectl version --client docker --version python --version # 建议3.9+
清单工具准备: 推荐使用Helm简化部署,或直接写YAML文件,本文将采用原生YAML方式,方便理解底层逻辑。
Django应用容器化(Dockerfile编写)
这是部署的核心步骤,以下是一个生产级Dockerfile:
FROM python:3.11-slim AS builder
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
FROM python:3.11-slim
WORKDIR /app
COPY --from=builder /usr/local/lib/python3.11/site-packages /usr/local/lib/python3.11/site-packages
COPY . .
ENV PYTHONUNBUFFERED=1 \
DJANGO_SETTINGS_MODULE=project.settings.production
EXPOSE 8000
CMD ["gunicorn", "project.wsgi:application", "--bind", "0.0.0.0:8000", "--workers", "4"]
关键点解析:
- 使用多阶段构建,减小镜像体积(约从1.2GB降至400MB)
- 不再使用
python manage.py runserver,而是通过Gunicorn启动 - 环境变量
DJANGO_SETTINGS_MODULE指向生产配置
问答:
Q:为什么不用CMD python manage.py runserver?
A:开发服务器是单线程且不安全的,必须使用Gunicorn或uWSGI这类WSGI服务器处理并发请求。
构建生产级Kubernetes清单文件
1 Deployment配置
apiVersion: apps/v1
kind: Deployment
metadata:
name: django-app
namespace: production
spec:
replicas: 3
selector:
matchLabels:
app: django
template:
metadata:
labels:
app: django
spec:
containers:
- name: django
image: your-registry.com/django-app:v1.3
ports:
- containerPort: 8000
env:
- name: DATABASE_URL
valueFrom:
secretKeyRef:
name: db-secret
key: url
- name: SECRET_KEY
valueFrom:
secretKeyRef:
name: django-secret
key: key
resources:
requests:
memory: "512Mi"
cpu: "250m"
limits:
memory: "1Gi"
cpu: "500m"
livenessProbe:
httpGet:
path: /health/
port: 8000
initialDelaySeconds: 30
periodSeconds: 10
2 Service配置
apiVersion: v1
kind: Service
metadata:
name: django-svc
namespace: production
spec:
selector:
app: django
ports:
- port: 80
targetPort: 8000
type: ClusterIP
注意: Service类型设为ClusterIP,对外暴露通过Ingress实现。
数据库与静态文件处理方案
1 数据库管理
有两种选择:
方案A(推荐): 使用托管的云数据库(如RDS for PostgreSQL),通过环境变量注入连接信息
方案B: 在K8s内运行StatefulSet(不推荐生产环境,因为数据持久化复杂)
# 数据库迁移Job示例
apiVersion: batch/v1
kind: Job
metadata:
name: django-migrate
namespace: production
spec:
template:
spec:
containers:
- name: migrate
image: your-registry.com/django-app:v1.3
command: ["python", "manage.py", "migrate"]
envFrom:
- secretRef:
name: db-secret
restartPolicy: Never
2 静态文件与媒体文件
Django的静态文件需要使用持久化存储+CDN方案:
- 创建PVC(持久卷声明)挂载静态文件目录
- 使用
collectstatic命令将文件收集到PVC - 通过Nginx Ingress直接暴露静态文件路径
- 更优方案: 上传至对象存储(如AWS S3、阿里云OSS),配合
django-storages库
配置示例:
# settings.py STATIC_URL = 'https://cdn.example.com/static/' STATIC_ROOT = '/data/static' # 仅用于collectstatic
Ingress配置与域名绑定
使用Ingress Controller(如nginx-ingress)将域名映射到Service:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: django-ingress
namespace: production
annotations:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/ssl-redirect: "true"
spec:
tls:
- hosts:
- app.yourdomain.com
secretName: tls-secret
rules:
- host: app.yourdomain.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: django-svc
port:
number: 80
重要配置:
- 开启SSL重定向,确保HTTPS访问
- 使用独立的
tls-secret存储证书(可通过cert-manager自动管理)
自动扩缩容与健康检查
1 HPA配置
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: django-hpa
namespace: production
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: django-app
minReplicas: 2
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
2 健康检查机制
我们在Deployment中已配置了两种探针:
- 存活探针: 检查
/health/端点,如果连续失败重启容器 - 就绪探针: 只在健康时接受流量(需在Django中实现该路由)
Django健康检查视图示例:
from django.http import JsonResponse
def health_check(request):
# 可增加数据库连接检测
return JsonResponse({"status": "ok"})
常见问题与问答集锦
Q1:Django的SECRET_KEY如何安全存储在K8s中?
A: 使用Secrets资源而非ConfigMap,通过Base64编码后注入环境变量,且永不提交到Git,建议配合外部密钥管理服务(如Vault或AWS Secrets Manager)。
Q2:如何优雅处理数据库迁移?
A: 创建独立的Job资源,在Deployment更新前手动运行migrate,也可使用Init容器,但存在迁移失败导致Pod无法启动的风险,推荐使用ArgoCD或Jenkins流水线控制顺序。
Q3:跨命名空间访问其他服务(如Redis)要如何配置?
A: 如果Redis也在同一集群中,可以使用svc-name.namespace-name.svc.cluster.local格式访问。django-cache.redis.svc.cluster.local:6379
Q4:部署后遇到ModuleNotFoundError: No module named '_sqlite3'怎么办?
A: 基础镜像可能缺少SQLite依赖,解决方案有两种:
- 在Dockerfile中添加
apt-get install libsqlite3-dev - 生产环境切换至PostgreSQL(推荐,可避免此类问题)
Q5:如何在不中断服务的情况下更新Django代码?
A: 通过K8s的滚动更新策略,修改镜像标签并执行:
kubectl set image deployment/django-app django=your-registry.com/django-app:v1.4
K8s会逐一替换Pod,期间服务始终可用,若更新失败,自动回滚到上个版本。
将Django部署到Kubernetes需要关注容器化质量、配置分离、数据持久化三大要点,本文提供了从Dockerfile编写到生产级Ingress配置的完整路径,实际部署时,建议先搭建完整的Staging环境,并配合监控工具(如Prometheus+Grafana)观察应用表现,随着微服务化需求增加,Django+K8s的组合已成为现代Web应用的标配架构。