生产环境必须用deployment+service yaml,而非kubectl run;node.js镜像需alpine多阶段构建、非root用户、精确暴露端口、合理配置replicas/resources/probes/selector及语义化镜像标签。

直接用 kubectl run 能跑起来,但生产环境必须写 Deployment + Service YAML,否则无法扩缩容、健康检查或暴露端口。
Node.js 镜像必须用多阶段构建且非 root 用户
很多人用 FROM node:18 直接 COPY + CMD,结果镜像超 1GB、权限过高、启动慢。Alpine 基础镜像 + 多阶段构建才是实际做法:
-
RUN npm ci --only=production比npm install更快更确定,跳过 devDependencies - 最终镜像里只保留
/app/node_modules和代码,不带node_modules/.bin或构建工具 - 必须加
USER node,否则容器默认以 root 运行,Kubernetes PodSecurityPolicy 或 PodSecurityAdmission 会拒绝调度 - 暴露端口要和代码监听端口一致:比如
app.listen(3000)就得EXPOSE 3000,否则livenessProbe会失败
Deployment YAML 里 replicas 和 imagePullPolicy 容易写错
常见错误是本地测试时用 image: my-node-app:latest,但没设 imagePullPolicy: Always,导致 Kubernetes 复用旧缓存镜像;或者在 CI/CD 中硬编码 replicas: 1,上线后扛不住流量。
-
imagePullPolicy在私有仓库或本地 Minikube 环境下建议显式写成Always,避免拉取 stale 镜像 -
replicas别写死,用 Helm value 或 Kustomize patch 替代,方便不同环境差异化配置 -
containerPort必须和EXPOSE及应用实际监听端口一致,Kubernetes 不校验这个值,但 Service 的targetPort依赖它 - 务必加
resources.requests,哪怕只是memory: "64Mi",否则在资源紧张的集群中可能被 OOMKilled
Service 类型选错会导致服务根本访问不到
ClusterIP 是默认类型,只能集群内访问;想从外部访问,不能只改 type: LoadBalancer 就完事——Minikube 需要 minikube tunnel,裸金属集群得配 MetalLB,云厂商才真正支持自动创建 LB。
- 开发调试优先用
kubectl port-forward service/your-service 3000:3000,绕过 Service 类型限制 - 若用
NodePort,注意端口范围默认是30000–32767,别写port: 80或port: 3000 -
service.spec.selector必须和 Deployment 的spec.template.metadata.labels完全匹配,一个字段不一致就找不到 Pod - HTTP 应用建议加
readinessProbe,比如httpGet.path: /healthz,避免流量打到还没 ready 的实例上
最常被忽略的是镜像 tag —— 本地 docker build -t myapp:v1 . && docker push 后,YAML 里写的却是 image: myapp:latest,而集群拉的其实是 registry 里早已过期的 latest。每次更新必须用语义化版本(如 v1.2.3)并同步更新 YAML 中的 image 字段。











