CLOUD GIDO
工程笔记
场记2026-09-09GIDO

K8s 上 DolphinScheduler 任务不下发?一篇讲透:TaskInstanceLogPath is empty

适合人群:在 Kubernetes / k3s / OrbStack 上部署 DolphinScheduler 3.2.x,遇到「任务实例日志为空 / 任务未分发」的同学
环境:OrbStack Ubuntu + k3s、DolphinScheduler 3.2.2、PostgreSQL + ZooKeeper
关键词:DolphinScheduler、Kubernetes、任务下发、UnknownHostException、Worker 注册


一、现象:UI 能跑,日志却报「没下发」

工作流实例已经创建了,点开任务实例查日志,直接报错:

查询任务实例日志错误:
TaskInstanceLogPath is empty, maybe the taskInstance doesn't be dispatched

翻译成人话:这个任务实例根本没有成功分发到 Worker,所以:

  • 实例的 host 为空
  • log_path 为空
  • UI 自然查不到任何日志

很多同学第一反应是「Worker 挂了」「分组配错了」。Worker Pod 明明是 Running,分组也是 default,问题往往在更隐蔽的地方——注册地址在 K8s 里不可解析

排查流程图


二、根因:Master 用了「一次性」的 Pod 主机名注册

2.1 Dolphin 在 K8s 里怎么发现彼此?

DolphinScheduler 的 Master / Worker 会把自身地址写进 ZooKeeper。任务下发链路大致是:

API / 调度触发
   → Master 从 ZK 找可用 Worker
   → Master 按 ZK 里登记的地址连 Worker
   → Worker 执行任务,写回 host / log_path

架构示意:

K8s 上 Master / Worker / ZK 通过 Service DNS 通信

2.2 默认行为踩坑点

在 Kubernetes 里,Deployment 的 Pod 主机名通常类似:

dolphinscheduler-master-7df8dd688b-gqxb7

如果 Master 直接用这个名字去注册,会出现:

组件注册结果能否被解析
Masterdolphinscheduler-master-xxx:5678❌ 集群内其他 Pod 解析不了
Worker若已用 Pod IP / Service,相对正常

于是 Master ↔ Worker 通信阶段就会出现:

UnknownHostException: dolphinscheduler-master-xxxx

任务派发失败 → 实例 host 为空 → 日志路径为空。

修复前后对比

一句话总结:不是 Dolphin「不会调度」,而是 注册的主机名在 K8s DNS 里不存在,派发链路在网络层断了。


三、怎么确认就是这个问题?

按下面顺序排查,通常 5 分钟能定位。

3.1 看任务实例

在库表或 API 里看该任务实例:

  • host 是否为空
  • log_path 是否为空
  • 状态是否长期停在「提交成功 / 派发中」一类中间态

3.2 看 Master / Worker 日志

Master 或 Worker 日志里重点搜:

UnknownHostException
Connection refused
dispatch

若出现对 dolphinscheduler-master-<随机后缀> 的解析失败,基本坐实。

3.3 看 ZooKeeper 注册内容

进 ZK 看 Master / Worker 注册节点(路径因版本略有差异),关注:

  • Master 是否注册成 随机 Pod 名
  • Worker 是否注册成 可解析的 IP 或 Service 名

理想状态应类似:

Master : dolphinscheduler-master:5678
Worker : dolphinscheduler-worker:1234
# 或 Worker 使用 Pod IP:1234(需保证 Master 能访问该 IP)

3.4 UI 监控中心

监控中心 → Master / Worker

  • 节点是否在线
  • Worker 分组是否为 default(与配置 WORKER_GROUPS 一致)

节点「看起来在线」但仍派发失败时,更要核对 注册地址是否可解析,不要只看状态灯。


四、修复方案:固定 hostname + ClusterIP Service

思路很简单:让注册名 = 集群内稳定可解析的 DNS 名

4.1 给 Master / Worker 固定 hostname

在 Pod 模板里设置:

# Master Deployment
spec:
  template:
    spec:
      hostname: dolphinscheduler-master
      containers:
        - name: master
          image: apache/dolphinscheduler-master:3.2.2
          ports:
            - containerPort: 5678
            - containerPort: 5679
# Worker Deployment
spec:
  template:
    spec:
      hostname: dolphinscheduler-worker
      containers:
        - name: worker
          image: apache/dolphinscheduler-worker:3.2.2
          ports:
            - containerPort: 1234
            - containerPort: 1235

4.2 配合同名 ClusterIP Service

dolphinscheduler-master / dolphinscheduler-worker 在集群 DNS 里真正存在:

apiVersion: v1
kind: Service
metadata:
  name: dolphinscheduler-master
  namespace: dolphinscheduler
spec:
  type: ClusterIP
  selector:
    app: dolphinscheduler
    component: master
  ports:
    - name: rpc
      port: 5678
      targetPort: 5678
    - name: actuator
      port: 5679
      targetPort: 5679
---
apiVersion: v1
kind: Service
metadata:
  name: dolphinscheduler-worker
  namespace: dolphinscheduler
spec:
  type: ClusterIP
  selector:
    app: dolphinscheduler
    component: worker
  ports:
    - name: rpc
      port: 1234
      targetPort: 1234
    - name: actuator
      port: 1235
      targetPort: 1235

4.3 (可选)Worker 显式声明地址

部分版本在 K8s 里自动推断 worker 地址不稳定,可注入:

env:
  - name: MY_POD_IP
    valueFrom:
      fieldRef:
        fieldPath: status.podIP
  - name: JAVA_TOOL_OPTIONS
    value: "-Dworker.worker-address=$(MY_POD_IP):1234"

4.4 顺手避坑:JVM 内存别超过 Pod limit

Master / Worker 若仍用默认大堆(例如 4G),而 Pod limit 只有 2Gi,会反复 OOM / 不 Ready,表现为「节点不存在 / 派发不稳」。建议显式控制,例如:

-Xmx1536m

并保证 resources.limits.memory 大于堆 + 元空间余量。

展开讲解见同系列第二篇:dolphin-k8s-heap-oom.md
若进程活着却一直 BUSY,见第三篇:dolphin-k8s-master-busy.md


五、修复后如何验证?

  1. 滚动重启 Master / Worker(必要时连带 API)
  2. 再查 ZK:注册地址应为固定 hostname 或稳定 IP
  3. 重新运行工作流(重点!)
  4. 新任务实例应有非空的 host,日志可正常打开

⚠️ 旧实例不会自动恢复
修复前已经失败 / 卡住的任务实例,log_path 仍是空的;请重新触发一次运行再查日志。

验证命令示例:

# Pod 是否 Ready
kubectl get pods -n dolphinscheduler

# Service 是否存在
kubectl get svc -n dolphinscheduler | grep -E 'master|worker'

# Master / Worker 日志是否还有 UnknownHostException
kubectl logs -n dolphinscheduler deploy/dolphinscheduler-master --tail=100
kubectl logs -n dolphinscheduler deploy/dolphinscheduler-worker --tail=100

六、下发通了之后,还可能踩的两个坑

这次排障过程中,任务真正跑起来后又遇到两个「连环雷」,一并记录。

6.1 Doris / MySQL SQL 任务:缺 JDBC 驱动

java.lang.ClassNotFoundException: com.mysql.cj.jdbc.Driver

Doris 数据源插件底层走 MySQL 协议,需要 mysql-connector-j。K8s 官方镜像默认往往不带这个 jar。

处理:把驱动挂到 API 和 Worker 的 libs 目录,例如:

volumeMounts:
  - name: mysql-jdbc
    mountPath: /opt/dolphinscheduler/libs/mysql-connector-j-8.0.33.jar
    subPath: mysql-connector-j-8.0.33.jar

本地 Compose 场景同理:Worker / API 都要挂,否则会出现「UI 测连通性成功、真正跑任务失败」或反过来。

6.2 UI 选了上海时区,日志却是 UTC

Dolphin 有两层时区:

层级作用常见配置
用户时区(右上角)UI 展示偏好Asia/Shanghai
服务端时区调度、入库、日志常默认 UTC

若希望「调度时刻、日志时间戳、页面显示」都是东八区,需要统一服务端:

# ConfigMap
TZ: "Asia/Shanghai"
SPRING_JACKSON_TIME_ZONE: "Asia/Shanghai"

# JVM
-Duser.timezone=Asia/Shanghai

改完后 rollout 重启 API / Master / Worker;历史实例时间不会自动改写


七、可复用的排查清单(建议收藏)

遇到 TaskInstanceLogPath is empty 时,按这个清单走:

  1. Worker / Master Pod 是否 Ready?
  2. 监控中心节点是否在线?Worker 分组是否 default
  3. ZK 注册地址是否为可解析的 Service 名或 Pod IP?
  4. Master / Worker 日志是否有 UnknownHostException
  5. 是否给 Deployment 固定了 hostname,并创建了同名 Service?
  6. JVM 堆是否超过容器内存 limit?
  7. 修复后是否重新运行了工作流(而不是只看旧实例)?
  8. SQL / Doris 任务是否挂了 MySQL JDBC?
  9. 时区是否在服务端与 UI 两侧对齐?

八、写在最后

在物理机或 Docker Compose 单机网上,用主机名互通往往「碰巧能用」;一上 Kubernetes,Pod 名不可跨 Pod 解析就成了高频坑。

对 DolphinScheduler 来说,记住这条就够:

谁注册到 ZK,谁的地址就必须能被对方用集群 DNS(或 IP)访问到。

固定 hostname + 同名 ClusterIP Service,是本地 k3s / OrbStack 最小代价的解法;生产环境也可以换成 Headless Service、StatefulSet 稳定网络标识等更标准的方案,原理相同。

如果你也在 K8s 上踩过「任务不下发 / 日志路径为空」,欢迎在评论区贴一下你的 ZK 注册地址和 Master 日志关键词,一起对照。


发布到 CSDN 时建议

  • 标题:可直接用本文标题,或改成《K8s 部署 DolphinScheduler 3.2:任务不下发与 TaskInstanceLogPath is empty 排查实录》
  • 标签DolphinScheduler Kubernetes k3s 大数据 调度
  • 封面图:可用文中「BEFORE / AFTER」对比图
  • 插图:本文三张图在同目录
    • images/ds-troubleshoot-flow.png
    • images/ds-k8s-architecture.png
    • images/ds-dispatch-before-after.png
      上传 CSDN 后把 Markdown 图片路径换成编辑器生成的图床地址即可