Django应用怎么部署到Kubernetes

wen python案例 2

Django应用部署到Kubernetes:从零到生产的完整实战指南

目录导读

  1. 为什么选择Kubernetes部署Django?
  2. 部署前的环境准备
  3. Django应用容器化(Dockerfile编写)
  4. 构建生产级Kubernetes清单文件
  5. 数据库与静态文件处理方案
  6. Ingress配置与域名绑定
  7. 自动扩缩容与健康检查
  8. 常见问题与问答集锦

为什么选择Kubernetes部署Django?

传统将Django部署在单一服务器的方式,在面对流量激增时容易崩溃,Kubernetes作为容器编排平台,提供了自动伸缩、服务发现、滚动更新等能力,举个真实场景:某电商平台Django应用在双11期间,通过K8s的HPA(水平自动伸缩)将实例从3个自动扩展到30个,而运维人员仅需配置阈值。

Django应用怎么部署到Kubernetes

问答:
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方案:

  1. 创建PVC(持久卷声明)挂载静态文件目录
  2. 使用collectstatic命令将文件收集到PVC
  3. 通过Nginx Ingress直接暴露静态文件路径
  4. 更优方案: 上传至对象存储(如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依赖,解决方案有两种:

  1. 在Dockerfile中添加apt-get install libsqlite3-dev
  2. 生产环境切换至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应用的标配架构。

抱歉,评论功能暂时关闭!