适合人群:Kubernetes / k3s / OrbStack 部署 DolphinScheduler 3.2.x,Master 或 Worker 一直 CrashLoop / OOMKilled / 不 Ready
环境:OrbStack Ubuntu + k3s、DolphinScheduler 3.2.2
关键词:DolphinScheduler、OOMKilled、JAVA_OPTS、-Xmx、容器内存
一、现象:节点「活着」,调度却不稳
常见表现有几种,看起来不像同一类问题,根因往往是同一个:
|
表象 |
你会怎么猜 |
真正可能是 |
|---|---|---|
|
Master / Worker Pod |
机器内存不够 |
JVM 堆大于 Pod limit |
|
Pod 反复重启,Ready 一直红 |
镜像坏了 / 探针太严 |
启动即被 kubelet 杀 |
|
UI「节点不存在」或任务派发不稳 |
注册中心挂了 |
进程根本没稳下来 |
|
|
下发逻辑 bug |
节点半死不活,派发失败 |
在本地 k3s / OrbStack 上,很多人会给 Master / Worker 配:
resources:
limits:
memory: "2Gi"
而 DolphinScheduler 官方镜像默认 JVM 堆往往偏大(常见接近 4G)。
容器说只能用 2Gi,JVM 一上来就要 4G——这仗必输。

二、根因:容器内存 ≠ JVM 默认堆
2.1 Kubernetes 怎么杀进程?
当容器内存使用超过 limits.memory,kubelet 会:
-
记录事件:
OOMKilled -
杀掉容器
-
按重启策略拉起 → 再撞墙 → CrashLoop
你在 kubectl describe pod 里常会看到:
Last State: Terminated
Reason: OOMKilled
Exit Code: 137
2.2 为什么官方默认堆这么大?
物理机 / 大内存虚拟机上,4G 堆很常见;
一进「本地 K8s 最小清单」,大家习惯把 limit 压到 1~2Gi,配置没一起改,就炸了。
一句话:
Pod limit 是硬顶;
-Xmx必须明显小于这个硬顶,还要给元空间、直接内存、线程栈留余量。
经验公式(单进程容器):
-Xmx ≈ limits.memory × 0.6 ~ 0.75
例如 limit=2Gi → -Xmx1536m 通常比较稳妥。
三、怎么确认是堆撞墙?
3.1 看事件与退出码
kubectl -n dolphinscheduler describe pod -l component=master | tail -40
kubectl -n dolphinscheduler get pod -l 'component in (master,worker)' -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.status.containerStatuses[0].lastState.terminated.reason}{"\n"}{end}'
出现 OOMKilled / 137,优先怀疑内存。
3.2 看当前 JAVA_OPTS
kubectl -n dolphinscheduler exec deploy/dolphinscheduler-master -- printenv JAVA_OPTS
kubectl -n dolphinscheduler exec deploy/dolphinscheduler-worker -- printenv JAVA_OPTS
如果没有显式 -Xmx,或仍是很大的默认值,就对上了。
3.3 对照 resources
kubectl -n dolphinscheduler get deploy dolphinscheduler-master dolphinscheduler-worker -o jsonpath='{range .items[*]}{.metadata.name}{" limit="}{.spec.template.spec.containers[0].resources.limits.memory}{"\n"}{end}'
四、修复:显式 JAVA_OPTS + UseContainerSupport
4.1 推荐配置(2Gi limit)
env:
- name: JAVA_OPTS
value: >-
-server
-Xms512m
-Xmx1536m
-XX:+UseContainerSupport
-Duser.timezone=Asia/Shanghai
要点:
-
-Xms512m:避免启动瞬时申请过大 -
-Xmx1536m:给 2Gi limit 留出余量 -
-XX:+UseContainerSupport:让 JVM 感知 cgroup 限制(JDK 8u191+ / 11+ 常见)
4.2 调参清单(可直接收藏)

-
先定 Pod limit(本地开发 2Gi 够用)
-
再写 JAVA_OPTS(堆 < limit)
-
重启后验证 Ready、无 OOMKilled
4.3 落地到清单
Master / Worker Deployment 都要改(只改一边会出现「半边集群活着」)。
改完后:
kubectl apply -f k8s/dolphinscheduler.yaml
kubectl -n dolphinscheduler rollout restart deploy/dolphinscheduler-master deploy/dolphinscheduler-worker
kubectl -n dolphinscheduler rollout status deploy/dolphinscheduler-master deploy/dolphinscheduler-worker
五、验证:怎样算修好了?
# 1. Pod Ready
kubectl -n dolphinscheduler get pods
# 2. 近期没有 OOMKilled
kubectl -n dolphinscheduler get events --field-selector reason=OOMKilling --sort-by='.lastTimestamp' | tail
# 3. 进程内堆配置生效
kubectl -n dolphinscheduler exec deploy/dolphinscheduler-master -- printenv JAVA_OPTS
期望:
-
Master / Worker
1/1 Running -
监控中心节点在线
-
重新跑工作流可正常下发(若之前还有 DNS 注册问题,需一并修好)
六、和「任务不下发」的关系
堆内存问题经常和另一个坑连环出现:
-
默认大堆 → OOM / 不 Ready
-
节点半死 → 任务派不出去
-
UI 报
TaskInstanceLogPath is empty
所以排查「不下发」时,请同时问两句:
-
ZK 注册地址能不能解析?(见同系列第一篇)
-
JVM 堆有没有超过 Pod limit?(就是本篇)
两篇合起来,本地 k3s 上大半「节点假活 / 任务不跑」都能覆盖。
七、写在最后
本地 K8s 部署 DolphinScheduler,最容易复制「生产大堆配置」到「玩具级 limit」。
记住:
先看
limits.memory,再写-Xmx;永远给容器留余量。
如果你的 limit 是 1Gi,就把 -Xmx 降到 512m~768m,并同步下调 readiness 的启动等待预期——小堆冷启动往往更快,但不代表业务并发能力够用。

410

被折叠的 条评论
为什么被折叠?



