真正拖慢django pod就绪的是数据库连接、迁移检查、缓存预热等初始化逻辑,须改用gunicorn/uwsgi并禁用自动迁移检查,延迟耗时操作,精简settings,合理配置探针与资源。

直接改 python manage.py runserver 是没用的,K8s 里它根本不是启动瓶颈;真正拖慢 Django Pod 就绪(Ready)的是数据库连接、迁移检查、缓存预热、第三方服务探测这些初始化逻辑 —— 它们卡在主进程里,导致 readiness probe 失败、Pod 反复重启。
避免 manage.py runserver 在生产 K8s 中启动
Django 默认开发模式的 runserver 不仅不支持多线程/多进程,还会主动检查迁移(--check-migrations)、扫描静态文件、加载所有 apps 的 models —— 这些在容器冷启时全量执行,极易超时。K8s 的 readinessProbe 通常设为 10–30 秒,而 runserver 启动常卡在 django.setup() 阶段。
- 必须改用生产级 WSGI 服务器:如
gunicorn或uWSGI,并禁用自动迁移检查 - 在
gunicorn启动命令中显式关闭迁移验证:gunicorn --check-config --skip-check-migrations myproject.wsgi:application - 如果使用
uWSGI,确保配置中不含--check-migrations或类似钩子 -
manage.py runserver仅限本地调试,K8s YAML 中的command和args字段必须替换掉
延迟执行耗时初始化(DB 连接、Cache 预热等)
Django 的 ready() 信号或 AppConfig 的 ready 方法会在所有 apps 加载完成后触发,但默认同步阻塞主进程。一旦里面调用了 cache.get()、connection.cursor() 或第三方 SDK 初始化(比如 OpenTelemetry),就会让整个 Pod 卡住。
- 把非必需的初始化逻辑移到异步任务或单独 initContainer 中,例如用
redis-cli ping检查 Redis 是否就绪,而不是在 Django 启动时连 Redis - 数据库连接池(如
django-db-geventpool)要配置MAX_CONNS=0或延迟创建连接,避免启动时抢连 - 如果必须做缓存预热,改用后台线程 +
threading.Timer延后 5 秒再执行,不要阻塞 WSGI 主循环 - OpenTelemetry-Python 自动注入后,会默认扫描所有已安装包,可加环境变量
OTEL_PYTHON_DISABLED_INSTRUMENTATIONS="requests,sqlalchemy"关闭不需要的插件
精简 Django settings 加载路径
K8s 环境下 DJANGO_SETTINGS_MODULE 若指向一个包含大量条件判断、远程配置拉取(如从 ConfigMap/Secret 动态生成 settings)、或 import 了未使用的模块的文件,会导致启动变慢。
- settings 文件应只做声明,不做运行:避免在 settings.py 顶层执行
requests.get()、open()、或复杂计算 - 拆分 settings:基础配置放
base.py,环境相关部分通过os.environ注入,比如DEBUG = os.getenv("DEBUG", "False") == "True" - 删掉未使用的中间件和 INSTALLED_APPS 条目,特别是那些带
ready()实现但当前场景不需要的包(如django-debug-toolbar在生产必须移除) - 确认
STATICFILES_STORAGE不是本地文件系统类(如StaticFilesStorage),否则 collectstatic 会尝试扫描整个项目目录
调整 K8s 探针与资源限制
很多团队把启动慢归咎于代码,其实 probe 设置不合理才是压垮 Pod 的最后一根稻草。K8s 默认的 initialDelaySeconds: 5 对 Django 来说太激进。
-
livenessProbe和readinessProbe必须分开:liveness 用于崩溃恢复,readiness 控制流量接入;前者可宽松(如 60s 初始延迟),后者需更早反馈(建议 20s 起步,超时设为 3s) - probe 使用轻量端点:不要用
/healthz调用完整 Django 请求栈,改用httpGet直接访问/health/ready/,该 endpoint 只检查 DB 连通性(connection.ensure_connection())和 cache.ping(),不走 middleware - CPU limit 设得太低(如
100m)会触发 CFS throttling,让 Python GIL 竞争加剧,反而拖慢初始化;建议起步设为250m,观察kubectl top pods再下调 - Python 进程启动时需要足够内存解压 bytecode、加载模块,
memoryRequest至少设为256Mi,否则 OOMKilled 频发
最常被忽略的一点:Django 的 __init__.py 和 apps.py 里写的任何顶层代码,都会在每次 WSGI worker fork 时重复执行 —— 包括日志配置、全局变量初始化、甚至 HTTP 客户端实例化。这些看似无害的操作,在 4 个 gunicorn worker 下会变成 4 倍开销。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











