Django项目在Kubernetes中必须禁用runserver、禁用DEBUG=True等开发配置,否则将导致启动失败、CrashLoopBackOff或安全漏洞;正确做法是使用Gunicorn/Uvicorn、Secret管理敏感信息、分离liveness/readiness探针、构建阶段执行collectstatic,并精确配置ALLOWED_HOSTS。

直接说结论:Django 项目在 Kubernetes 上不能靠 python manage.py runserver 启动,也不能把开发配置(如 DEBUG=True、SQLite、硬编码数据库地址)带进生产镜像——否则服务大概率启动失败、反复 CrashLoopBackOff,或上线即被扫出漏洞。
为什么 Django 容器一启动就退出?看日志先查 exec: "python": executable file not found in $PATH 这类错误
常见于 Dockerfile 写错基础镜像或路径。比如用了 FROM python:3.10-slim,但没把代码 COPY 到 /app,又在 CMD 里写 cd /app && python manage.py runserver——实际执行时 shell 找不到 python(因为 slim 镜像没装 bash,默认用 sh,不支持 && 链式命令)。
- 正确做法是用绝对路径调用解释器:
CMD ["python", "manage.py", "runserver", "0.0.0.0:8000"],且确保manage.py在镜像的当前工作目录下 - 更稳妥的是换用
gunicorn或uvicorn:它们自带进程管理、多 worker、信号处理,runserver是纯调试工具,Kubernetes 里必须禁用 - 检查
Dockerfile是否漏了WORKDIR /app,以及COPY . .是否覆盖了manage.py和settings.py
ConfigMap 和 Secret 怎么配才不暴露密码?别把 DATABASE_URL 写进 ConfigMap
ConfigMap 是明文存储,Secret 才是 Base64 编码(虽非加密,但有访问控制语义)。很多团队把 DATABASE_URL、SECRET_KEY 全塞进 ConfigMap,kubectl get cm 就能直接看到——这等于把钥匙挂在门把手上。
强戈环形山: q15040409-刻画家功能概述强戈环形山: q15040409-刻画家是一项面向实际任务的技能,主要用于平顶山: 维西翁: 1:1.0. 塔格斯: rap.github: 自动化。它将相关步骤、工具调用和结果整理方式集中到统一流程中,帮助使用者更快完成目标并减少重复操作。核心要点使用时应结合输入条件选择合适的执行方式,核对必要参数、依赖环境与输出内容,并按原始要求处理异常情况。该技能适合需要稳定复用相关能力的场景,可作为自动化工作流的一部分,也便于后续检查、调整和扩展。从功能定位来看,该
-
SECRET_KEY、DJANGO_SETTINGS_MODULE、DB_PASSWORD必须进Secret;ALLOWED_HOSTS、DEBUG(设为"False"字符串)、STATIC_URL可放 ConfigMap - 在 Deployment 中引用时,Secret 要用
envFrom.secretRef.name或volumeMounts挂载文件,不能和 ConfigMap 混用同一字段 - Django settings.py 里读环境变量要加默认值兜底,比如
os.getenv("SECRET_KEY", "dev-key-for-local"),否则容器启动时因缺 Secret 直接报KeyError
livenessProbe 和 readinessProbe 配反了,服务就永远“半死不活”
典型症状:Pod 状态是 Running,但 kubectl logs 显示应用早挂了;或者 Service 流量打进来,却持续返回 502/503。根本原因是探针逻辑和 Django 实际健康状态不匹配。
-
readinessProbe应该检查应用是否**准备好收请求**:建议用curl -f http://localhost:8000/healthz(需在 Django 加个轻量 health view),而不是检查端口通不通——端口通不代表 DB 连得上、Redis 是否可用 -
livenessProbe是“救命绳”,应判断是否**必须重启**:比如检查/tmp/healthy文件是否存在,或调用一个触发 GC 的 endpoint;若只做 HTTP 探针且路径和 readiness 一样,一旦 DB 挂了,两个探针同时失败,K8s 会不断重启容器,形成恶性循环 - 初学者常把
initialDelaySeconds设太小(如 5 秒),而 Django + Gunicorn 启动耗时可能超 10 秒(尤其加载大模型或连外部服务),导致还没起来就被 kill
collectstatic 怎么在构建阶段跑,又不让容器启动时重复执行?
很多人把 collectstatic 放到容器 entrypoint.sh 里,结果每次 Pod 重启都重跑一遍——既拖慢启动,又可能因并发写入导致静态文件损坏(尤其用 NFS 作 volume 时)。
- 最佳实践是在
Dockerfile构建阶段执行:RUN python manage.py collectstatic --noinput,并确保STATIC_ROOT指向镜像内路径(如/app/staticfiles) - Nginx 容器和 Django 容器要共享静态文件:用
emptyDir或configMap挂载/app/staticfiles到 Nginx 的/usr/share/nginx/html,Django 容器启动时跳过 collectstatic - 如果用 CDN(如 Cloudflare R2、AWS S3),就完全不用挂载 volume:构建时上传到 CDN,Django settings.py 里设
STATIC_URL = "https://cdn.example.com/"即可
最易被忽略的点是:Django 的 ALLOWED_HOSTS 必须包含 Service 名(如 "django-svc")和 Ingress 域名(如 "api.example.com"),否则 Nginx 转发过来的请求会被 Django 中间件直接拒掉,日志里只有 DisallowedHost 错误,没有任何 HTTP 状态码提示。

















