在 Apache DolphinScheduler 3.4.2 上使用原生 Amazon EMR Serverless 插件

目录

  1. 功能简介
  2. 为什么选择 EMR Serverless + DolphinScheduler
  3. 前置条件
  4. 全新部署 DolphinScheduler 3.4.2(含 EMR Serverless 插件)
  5. 从旧版本升级到 3.4.2 以获得 EMR Serverless 能力
  6. 使用 EMR Serverless Task 提交任务
  7. IAM 权限配置参考
  8. 避坑指南(FAQ & Troubleshooting)

1. 功能简介

Apache DolphinScheduler 从 3.4.2 版本起,原生集成了 Amazon EMR Serverless Task 插件(artifact: dolphinscheduler-task-emr-serverless)。该插件允许用户直接在 DolphinScheduler 的 DAG 工作流中,以可视化方式向 EMR Serverless 提交 Spark / Hive 作业,并实现:

  • 同步等待:提交后自动每 10 秒轮询 Job Run 状态,直到 SUCCESS / FAILED / CANCELLED 才返回结果给调度引擎,确保 DAG 依赖关系正确传递。
  • 日志回显:任务完成后可在 DolphinScheduler UI 中直接查看执行日志,无需跳转到 AWS Console。
  • 自动取消:如果在 DolphinScheduler 中 Kill 任务,插件会自动调用 CancelJobRun API 取消正在运行的作业。
  • Failover 支持:Worker 节点故障时,新 Worker 可通过 jobRunId 恢复对运行中作业的跟踪。
  • 混合调度:同一工作流中可同时编排 EMR on EC2 任务和 EMR Serverless 任务,按需分配不同资源形态。

工作原理:插件在后台使用 aws-java-sdk,将用户填写的 JSON 参数转换为 StartJobRunRequest 对象并通过 StartJobRun API 提交到 AWS,然后通过 GetJobRun API 轮询作业状态直至完成。

注意:EMR (EC2) 和 EMR Serverless 是 两个独立的插件模块dolphinscheduler-task-emr vs dolphinscheduler-task-emr-serverless),安装一个不代表另一个也能用。


2. 为什么选择 EMR Serverless + DolphinScheduler

对比维度EMR on EC2EMR Serverless
集群管理需要运维长驻集群或手动创建/销毁完全免运维,按需启停
成本模型按实例小时计费(含空闲时间)仅按 vCPU-hour + GB-hour 计费,任务间无空闲浪费
弹性扩缩依赖 Managed Scaling / Auto Scaling自动按需分配资源,秒级扩容
本地存储需要预配置 EBS无需关注,自动提供
适合场景需要 SSH/长驻交互式/复杂依赖的场景ETL 批处理、定时 SQL、Spark 脚本

与 DolphinScheduler 结合的价值

  • 利用 DolphinScheduler 的 DAG 编排能力,将分散的 ETL 脚本组织为有序的数据管线
  • EMR Serverless 消除集群运维负担,DolphinScheduler 负责调度与监控
  • 原生插件封装了异步轮询、状态跟踪、日志获取等复杂逻辑,用户只需填写 JSON 参数

3. 前置条件

项目要求
DolphinScheduler 版本≥ 3.4.2
JavaJDK 8 或 JDK 11
元数据库MySQL 8.x 或 PostgreSQL 12+
EC2 实例挂载有 EMR Serverless 相关权限的 IAM Role
EMR Serverless已创建至少一个 Application(Spark 或 Hive 类型),状态为 STARTED 或 CREATED
S3准备好日志桶和脚本文件存储位置
IAMJob Execution Role(EMR Serverless 任务实际执行时使用的角色)

4. 全新部署 DolphinScheduler 3.4.2(含 EMR Serverless 插件)

4.1 下载安装包

VERSION=3.4.2
wget https://dlcdn.apache.org/dolphinscheduler/${VERSION}/apache-dolphinscheduler-${VERSION}-bin.tar.gz
tar -xzf apache-dolphinscheduler-${VERSION}-bin.tar.gz
cd apache-dolphinscheduler-${VERSION}-bin

4.2 安装 EMR Serverless Task 插件

官方二进制包 plugins/ 目录默认为空,必须手动安装所需插件:

# 方式一:一次性安装全部插件(需要能访问 Maven Central)
bash bin/install-plugins.sh

# 方式二(推荐):只安装需要的插件,更快更省空间
export JAVA_HOME=/path/to/jdk

# 安装 EMR Serverless 插件
./mvnw dependency:get \
  -DgroupId=org.apache.dolphinscheduler \
  -DartifactId=dolphinscheduler-task-emr-serverless \
  -Dversion=3.4.2 \
  -Dclassifier=shade \
  -Ddest=plugins/task-plugins/

# 如果同时需要 EMR on EC2 插件
./mvnw dependency:get \
  -DgroupId=org.apache.dolphinscheduler \
  -DartifactId=dolphinscheduler-task-emr \
  -Dversion=3.4.2 \
  -Dclassifier=shade \
  -Ddest=plugins/task-plugins/

⚠️ dolphinscheduler-task-emr-serverless 的 shade 包体积较大(打包了完整的 AWS EMR Serverless SDK)。

4.3 补充 MySQL JDBC 驱动(如使用 MySQL)

官方包因 GPL 许可不内置 MySQL 驱动:

curl -o mysql-connector-j-8.4.0.jar \
  https://repo1.maven.org/maven2/com/mysql/mysql-connector-j/8.4.0/mysql-connector-j-8.4.0.jar

# 复制到每个模块的 libs/ 目录
for dir in api-server master-server worker-server alert-server tools; do
  cp mysql-connector-j-8.4.0.jar $dir/libs/
done

4.4 配置数据源(MySQL 示例)

修改以下模块的 conf/application.yamlapi-server、master-server、alert-server、tools 四处都要改,worker-server 不连数据库无需修改):

spring:
  profiles:
    active: mysql  # 默认是 postgresql,改为 mysql

# 在 mysql profile 块中配置:
  datasource:
    url: jdbc:mysql://your-rds-endpoint:3306/dolphinscheduler?useUnicode=true&characterEncoding=UTF-8
    username: dolphin_user
    password: your-password
    driver-class-name: com.mysql.cj.jdbc.Driver

4.5 配置 AWS 凭证

编辑 conf/aws.yaml(默认内容是占位的 MinIO 测试凭证,必须替换)。

注意aws.emr 段的配置被 EMR on EC2 和 EMR Serverless 两个 Task 插件共享

# 推荐:EC2 实例挂载 IAM Role 时使用 InstanceProfile
aws:
  emr:
    credentials.provider.type: InstanceProfileCredentialsProvider
    region: us-east-1   # 改为您的实际 Region

如果是非 EC2 环境或需要跨账号,可以使用静态 Key(不推荐生产环境):

aws:
  emr:
    credentials.provider.type: AWSStaticCredentialsProvider
    access.key.id: AKIA...
    access.key.secret: your-secret-key
    region: us-east-1

4.6 配置 Tenant

编辑 worker-server/conf/application.yaml

tenant-config:
  auto-create-tenant-enabled: true
  default-tenant-enabled: true   # 默认是 false,建议改为 true

4.7 初始化数据库并启动

# 初始化 schema
bash tools/bin/upgrade-schema.sh

# 启动全部服务
bash bin/start-all.sh
# 或逐个启动:
bash api-server/bin/start.sh
bash master-server/bin/start.sh
bash worker-server/bin/start.sh
bash alert-server/bin/start.sh

4.8 验证插件加载

查看 master-server 和 worker-server 日志:

grep "Success register task plugin" master-server/logs/master-server.log
# 应看到:
# Success register task plugin: EMR_SERVERLESS
# Success register task plugin: EMR  (如果也安装了)


5. 从旧版本升级到 3.4.2 以获得 EMR Serverless 能力

5.1 升级路径

3.1.x / 3.2.x / 3.3.x → 3.4.2

DolphinScheduler 支持跨版本升级,升级工具会逐版本执行 DDL。

5.2 升级步骤

Step 1: 备份

# 备份数据库
mysqldump -h your-rds-endpoint -u root -p dolphinscheduler > dolphinscheduler_backup.sql

# 备份当前安装目录
cp -r /opt/dolphinscheduler /opt/dolphinscheduler-backup

Step 2: 停止旧版本所有服务

bash bin/stop-all.sh

Step 3: 解压新版本

tar -xzf apache-dolphinscheduler-3.4.2-bin.tar.gz -C /opt/

Step 4: 迁移配置

将旧版本中已修改的配置(application.yamlaws.yaml、自定义环境变量)迁移到新目录中的对应位置。

Step 5: 执行 Schema 升级

# 补充 MySQL JDBC 驱动到 tools/libs/
cp mysql-connector-j-8.4.0.jar tools/libs/

# 执行升级
bash tools/bin/upgrade-schema.sh

如果遇到 Duplicate key name 错误,参见下方避坑指南 #6。

Step 6: 安装 EMR Serverless 插件

按照 4.2 节 的方式安装插件。

Step 7: 配置 AWS 凭证

按照 4.5 节 配置 aws.yaml

Step 8: 启动新版本

bash bin/start-all.sh

Step 9: 验证

  1. 检查日志确认插件加载成功
  2. 在 UI 中创建一个 EMR Serverless 类型的任务节点(应能在任务类型列表中看到)
  3. 提交测试任务验证端到端连通性

6. 使用 EMR Serverless Task 提交任务

6.1 创建任务

在 DolphinScheduler UI 中:

  1. 进入 项目管理 → 项目名称 → 工作流定义,点击"创建工作流"进入 DAG 编辑页面
  2. 从左侧工具栏拖拽 AmazonEMRServerless 任务节点到画布

6.2 任务参数说明

参数说明示例
Application IdEMR Serverless Application 的 ID,可在 EMR Serverless 控制台获取00fkht2eodujab09
Execution Role ArnJob 运行时使用的 IAM Role ARN,该角色需要有访问 S3、Glue 等服务的权限arn:aws:iam::123456789012:role/EMRServerlessRole
Job Name作业名称(可选),用于在 EMR Serverless 控制台中标识作业DailyETL-SparkSQL
StartJobRunRequest JSON对应 StartJobRunRequest 中 JobDriverConfigurationOverrides 部分的 JSON 配置(见下方示例)

⚠️ 重要StartJobRunRequest JSON不需要包含 ApplicationIdExecutionRoleArn 字段,它们会自动从上方的表单参数注入。

6.3 示例一:提交 Spark 作业

StartJobRunRequest JSON

{
  "JobDriver": {
    "SparkSubmit": {
      "EntryPoint": "s3://my-bucket/scripts/my-spark-job.py",
      "EntryPointArguments": [
        "s3://my-bucket/input/",
        "s3://my-bucket/output/"
      ],
      "SparkSubmitParameters": "--conf spark.executor.cores=4 --conf spark.executor.memory=8g --conf spark.executor.instances=10 --conf spark.hadoop.hive.metastore.client.factory.class=com.amazonaws.glue.catalog.metastore.AWSGlueDataCatalogHiveClientFactory"
    }
  },
  "ConfigurationOverrides": {
    "MonitoringConfiguration": {
      "S3MonitoringConfiguration": {
        "LogUri": "s3://my-bucket/emr-serverless-logs/"
      }
    }
  }
}

说明

  • EntryPoint:S3 上的 Spark 入口文件(jar 或 Python 脚本)
  • EntryPointArguments:传递给入口程序的参数列表
  • SparkSubmitParameters:等价于 spark-submit 的 --conf--jars--class 等参数
  • MonitoringConfiguration:指定日志输出的 S3 路径

6.4 示例二:提交 Hive 作业

StartJobRunRequest JSON

{
  "JobDriver": {
    "HiveSQL": {
      "Query": "s3://my-bucket/scripts/my-hive-query.sql",
      "Parameters": "--hiveconf hive.exec.dynamic.partition=true --hiveconf hive.exec.dynamic.partition.mode=nonstrict"
    }
  },
  "ConfigurationOverrides": {
    "MonitoringConfiguration": {
      "S3MonitoringConfiguration": {
        "LogUri": "s3://my-bucket/emr-serverless-logs/"
      }
    },
    "ApplicationConfiguration": [
      {
        "Classification": "hive-site",
        "Properties": {
          "hive.metastore.client.factory.class": "com.amazonaws.glue.catalog.metastore.AWSGlueDataCatalogHiveClientFactory"
        }
      }
    ]
  }
}

说明

  • Query:S3 上的 Hive SQL 文件路径
  • Parameters:Hive 运行时参数
  • ApplicationConfiguration:相当于 Hive 的 site 配置,此处配置 Glue Data Catalog 作为 Hive Metastore

6.5 作业状态流转

提交后 DolphinScheduler 每 10 秒轮询作业状态:

SUBMITTED → PENDING → SCHEDULED → RUNNING → SUCCESS
                                          → FAILED
                                          → CANCELLED

  • 作业达到 SUCCESS 状态 → 任务标记为成功
  • 作业达到 FAILEDCANCELLED 状态 → 任务标记为失败
  • 在 DolphinScheduler 中 Kill 任务 → 自动调用 CancelJobRun API 取消运行中的作业

6.6 注意事项

  1. Application 状态:Application Id 对应的 EMR Serverless Application 必须处于 STARTEDCREATED 状态
  2. Execution Role 权限:需要具备 emr-serverless:StartJobRunemr-serverless:GetJobRunemr-serverless:CancelJobRun,以及作业所需的 S3、Glue 等数据访问权限
  3. JSON 不含 ID 字段StartJobRunRequest JSON 中不要重复写 ApplicationIdExecutionRoleArn,它们从表单自动注入
  4. Failover:EMR Serverless Task 支持 Worker 故障恢复,新 Worker 可通过 jobRunId 继续跟踪运行中的作业

7. IAM 权限配置参考

7.1 EC2 实例 IAM Role(DolphinScheduler Worker 所在机器)

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "emr-serverless:StartJobRun",
        "emr-serverless:GetJobRun",
        "emr-serverless:CancelJobRun",
        "emr-serverless:ListJobRuns",
        "emr-serverless:GetApplication",
        "emr-serverless:ListApplications"
      ],
      "Resource": "*"
    },
    {
      "Effect": "Allow",
      "Action": "iam:PassRole",
      "Resource": "arn:aws:iam::*:role/EMRServerlessJobRole",
      "Condition": {
        "StringLike": {
          "iam:PassedToService": "emr-serverless.amazonaws.com"
        }
      }
    }
  ]
}

7.2 EMR Serverless Job Execution Role

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "s3:GetObject",
        "s3:PutObject",
        "s3:ListBucket",
        "s3:DeleteObject"
      ],
      "Resource": [
        "arn:aws:s3:::your-bucket",
        "arn:aws:s3:::your-bucket/*"
      ]
    },
    {
      "Effect": "Allow",
      "Action": [
        "glue:GetDatabase",
        "glue:GetDatabases",
        "glue:GetTable",
        "glue:GetTables",
        "glue:GetPartition",
        "glue:GetPartitions",
        "glue:CreateTable",
        "glue:UpdateTable",
        "glue:BatchCreatePartition"
      ],
      "Resource": "*"
    },
    {
      "Effect": "Allow",
      "Action": [
        "logs:PutLogEvents",
        "logs:CreateLogGroup",
        "logs:CreateLogStream",
        "logs:DescribeLogGroups",
        "logs:DescribeLogStreams"
      ],
      "Resource": "*"
    }
  ]
}

Trust Policy:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Service": "emr-serverless.amazonaws.com"
      },
      "Action": "sts:AssumeRole"
    }
  ]
}


8. 避坑指南(FAQ & Troubleshooting)

以下问题基于实际部署经验总结,按出现频率排列。


问题 1:Cannot find TaskChannel for : EMR_SERVERLESS

现象:任务提交后 master 日志报 TaskExecutionContextCreateException: Cannot find TaskChannel for : EMR_SERVERLESS

原因:EMR Serverless 插件未安装。官方二进制包 plugins/ 目录默认为空。

解决

./mvnw dependency:get \
  -DgroupId=org.apache.dolphinscheduler \
  -DartifactId=dolphinscheduler-task-emr-serverless \
  -Dversion=3.4.2 -Dclassifier=shade \
  -Ddest=plugins/task-plugins/

# 安装后必须重启全部四个服务
bash bin/stop-all.sh && bash bin/start-all.sh

⚠️ 常见误区:安装了 dolphinscheduler-task-emr(EC2 版)后以为 EMR Serverless 也能用——两者是独立的 artifact。


问题 2:装了插件但 api-server 查看日志仍报错

现象:任务执行成功,但在 UI 点击"查看日志"时报 Cannot find TaskChannel for : EMR_SERVERLESS

原因:api-server 也会加载 task 插件(用于日志查询、参数校验等功能),但只重启了 master/worker,忘记重启 api-server。

解决

bash api-server/bin/stop.sh && bash api-server/bin/start.sh

教训:改动 plugins/ 目录后,master-server、worker-server、api-server、alert-server 全部要重启。插件通过 JVM classpath 加载,不支持热加载。


问题 3:Connection refused: localhost:9000UnrecognizedClientException

现象:EMR Serverless 任务报连接 localhost:9000 被拒绝,或 AWS 返回 403 凭证无效。

原因conf/aws.yaml 是官方包自带的占位 MinIO 测试配置,里面写的是 minioadmin / localhost:9000 / cn-north-1 等假值。

解决

# conf/aws.yaml
aws:
  emr:
    credentials.provider.type: InstanceProfileCredentialsProvider
    region: us-east-1   # 改为实际 Region

验证 EC2 实例的 IAM Role 有权限:

aws sts get-caller-identity
aws emr-serverless list-applications --region us-east-1


问题 4:The tenantCode is default, please enable TenantConfig#isDefaultTenantEnabled

现象:任务被 dispatch 到 worker 后立即失败,无日志。

原因:DolphinScheduler 3.4.x 默认 default-tenant-enabled: false(安全隔离),任务租户为 default 时拒绝执行。

解决

# worker-server/conf/application.yaml
tenant-config:
  default-tenant-enabled: true

重启 worker-server 后重试任务。


问题 5:MySQL JDBC 驱动缺失

现象:启动时或执行 upgrade-schema.sh 时报 No suitable driver found for jdbc:mysql://...

原因:GPL 许可问题,官方包不内置 MySQL 驱动。

解决

curl -o mysql-connector-j-8.4.0.jar \
  https://repo1.maven.org/maven2/com/mysql/mysql-connector-j/8.4.0/mysql-connector-j-8.4.0.jar

for dir in api-server master-server worker-server alert-server tools; do
  cp mysql-connector-j-8.4.0.jar $dir/libs/
done


问题 6:升级时报 Duplicate key name 'uniq_workflow_definition_code'

现象:从旧版本升级,运行 upgrade-schema.sh 中途报 MySQL 语法错误。

原因:数据库表结构曾被之前某次未完成的手动升级改过,但 t_ds_version 表版本号停留在旧值,导致工具重复执行已生效的 DDL。

解决

  1. SHOW INDEX FROM <table> / DESCRIBE <table> 核实报错的 DDL 是否已实际生效
  2. 确认是幂等冲突后,注释掉 tools/sql/sql/upgrade/{对应版本}_schema/mysql/dolphinscheduler_ddl.sql 中已生效的 ALTER 语句
  3. 重新运行 upgrade-schema.sh
  4. 最终确认 SELECT * FROM t_ds_version 为目标版本号

⚠️ 不要直接删库重来,历史数据难以恢复。


问题 7:反向代理后 UI 404 或 WebSocket 断连

现象:通过 Nginx 反代后页面加载异常。

原因:DolphinScheduler 有固定的 context-path /dolphinscheduler/,且部分功能依赖 WebSocket。

解决(Nginx 配置参考)

server {
    listen 80;
    
    location /dolphinscheduler/ {
        proxy_pass http://localhost:12345/dolphinscheduler/;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        
        # WebSocket 支持
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
    }
    
    location = / {
        return 302 /dolphinscheduler/ui/;
    }
}


参考资料

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值