flask应用必须监听0.0.0.0而非127.0.0.1,否则k8s探针和service流量无法访问导致就绪失败;需从环境变量读取port、禁用debug=true、确保dockerfile路径匹配、deployment与service端口一致,并验证configmap/secret注入生效。

Flask应用必须监听0.0.0.0,不能只绑127.0.0.1
本地开发时用 app.run(host='127.0.0.1') 没问题,但进Kubernetes后会直接导致Pod就绪失败(CrashLoopBackOff 或持续 NotReady)。因为K8s的健康探针、Service流量、其他Pod访问都依赖容器网络栈暴露在所有接口上。
正确写法是:
if __name__ == "__main__":
app.run(host="0.0.0.0", port=int(os.environ.get("PORT", "5000")))
- 硬编码端口(如
5000)可以,但建议从环境变量读取,方便Deployment里统一控制 - 不要加
debug=True—— 生产环境禁用,且会触发多进程/重载机制,与K8s容器生命周期冲突 - 若用
gunicorn,启动命令中必须显式指定--bind 0.0.0.0:5000,不能只写:5000(部分镜像默认行为仍可能绑定 localhost)
Dockerfile里WORKDIR和COPY路径不匹配会导致启动失败
常见错误是 WORKDIR /app 之后用 COPY . .,但实际项目根目录下没有 app.py,而是放在 src/app.py 或 web/app.py。容器启动时找不到入口文件,报错 ModuleNotFoundError: No module named 'app' 或 exec: "python": executable file not found in $PATH。
验证方式:构建完镜像后,先本地运行测试路径是否通:
docker run --rm -it your-flask-image sh -c "ls -l && python -m flask --version"
- 确保
COPY后能直接python app.py(或对应入口文件) - 推荐显式指定路径,比如
COPY src/ /app/,再WORKDIR /app,比模糊的COPY . .更可控 - Alpine 镜像(如
python:3.9-alpine)默认没装bash,调试时用sh;若需bash,得额外RUN apk add bash
Deployment里containerPort和Service的targetPort必须一致
这是最常被忽略的“隐性断连”点:Deployment中写了 containerPort: 5001,但Service里写成 targetPort: 5000,结果Service始终无法转发流量,kubectl get endpoints 显示为空。
两个端口必须数值相同(或Service里用字符串名,但需在container里声明 name: http),否则K8s不会建立Endpoint映射。
- 检查命令:
kubectl get endpoints flask-web-app-service—— 正常应显示IP+端口列表 - 如果为空,优先核对Deployment的
containers[].ports[].containerPort和Service的spec.ports[].targetPort - NodePort场景下,
nodePort(如32510)是宿主机端口,和容器内端口无关,别混淆
ConfigMap/Secret挂载后,Python代码读不到环境变量?
很多人把配置写进ConfigMap,又在Deployment里用 envFrom: [configMapRef: {name: my-config}],但Flask里仍用 os.environ.get("ENV") 读不到——原因通常是容器启动时ConfigMap还没挂载完,或者挂载路径不是环境变量注入方式。
关键区别:
-
envFrom是把ConfigMap的data字段**直接转为环境变量**,生效快,适合简单键值对 -
volumes + volumeMounts是把ConfigMap内容写成文件(如/config/app.conf),需代码主动读文件,延迟低但逻辑要自己写 - Secret同理,但值必须是base64编码;用
envFrom时K8s自动解码,无需Python处理
验证是否生效:kubectl exec -it <pod-name> -- env | grep ENV</pod-name>,有输出才说明环境变量真进了容器。
真正卡住的地方往往不在YAML语法,而在容器内部路径、端口绑定逻辑、环境变量注入时机这些“看不见”的链路。每次部署前,先 kubectl logs 看启动日志,再 kubectl exec 进容器手动验证路径和端口,比反复改YAML高效得多。











