EMR Core 节点 Flink Client 部署方案:从 Master 打包到 Bootstrap Action 自动分发的完整技术路径

问题背景

Amazon EMR 上跑 Apache Flink 时,Flink Client 工具链(flinkflink-sql-clientyarn-session.sh)默认只装在 Master 节点。Core 节点的职责是运行 YARN NodeManager 和 HDFS DataNode,负责计算和存储。

随着企业数据平台的演进,越来越多团队在 Core 节点上部署 DolphinScheduler、Airflow 等工作流调度系统的 Worker 组件。这些 Worker 需要直接调用 Flink 命令提交作业,但 Core 节点上没有 Flink Client。

SSH 回 Master 执行是一种绕路方案,但增加了架构复杂度、维护成本和故障点。本文介绍一种通过 Bootstrap Action 自动分发的方案,实现一次打包、多次复用。

技术方案

架构概览

Master 节点打包 → S3 存储 → Bootstrap Action → Core/Task 节点安装

环境:EMR 7.10.0 / Flink 1.20.0-amzn-4(AWS 定制构建,与 EMR 发行版绑定)。

打包流程

连接 Master 节点后执行:

# 验证环境
sudo -u hadoop /usr/lib/flink/bin/yarn-session.sh -d -jm 1024 -tm 2048
yarn application -list

# 打包
tar -czf flink-client-1.20.0-amzn-4.tar.gz -C /usr/lib flink
tar -czf flink-conf.tar.gz -C /etc flink

# 上传 S3
aws s3 cp flink-client-1.20.0-amzn-4.tar.gz s3://<bucket>/emr/bootstrap/
aws s3 cp flink-conf.tar.gz s3://<bucket>/emr/bootstrap/

注意:必须用 hadoop 用户或完整路径,否则 $bin 路径解析报错。EMR 中 Flink 版本号 1.20.0-amzn-4 是 AWS 基于开源版本的定制构建。

Bootstrap Action 脚本

#!/bin/bash
set -e
S3_PREFIX="s3://<bucket>/emr/bootstrap"
IS_MASTER=$(cat /emr/instance-controller/lib/info/instance.json | jq -r '.isMaster')

if [ "$IS_MASTER" = "false" ]; then
    # 下载解压
    aws s3 cp "${S3_PREFIX}/flink-client-1.20.0-amzn-4.tar.gz" /tmp/
    sudo tar -xzf /tmp/flink-client-1.20.0-amzn-4.tar.gz -C /usr/lib/
    aws s3 cp "${S3_PREFIX}/flink-conf.tar.gz" /tmp/
    sudo tar -xzf /tmp/flink-conf.tar.gz -C /etc/

    # 修复 broken symlink
    if [ -L "/etc/flink/conf" ] && [ ! -e "/etc/flink/conf" ]; then
        sudo rm -f /etc/flink/conf
        [ -d "/etc/flink/conf.dist" ] && sudo cp -r /etc/flink/conf.dist /etc/flink/conf || sudo mkdir -p /etc/flink/conf
    fi
    [ -L "/usr/lib/flink/conf" ] && [ ! -e "/usr/lib/flink/conf" ] && sudo rm -f /usr/lib/flink/conf && sudo ln -sf /etc/flink/conf /usr/lib/flink/conf

    # wrapper scripts(避免 symlink 的 $bin 路径问题)
    sudo tee /usr/bin/flink > /dev/null << 'W'
#!/bin/bash
exec /usr/lib/flink/bin/flink "$@"
W
    sudo chmod +x /usr/bin/flink
    sudo tee /usr/bin/flink-sql-client > /dev/null << 'W'
#!/bin/bash
exec /usr/lib/flink/bin/sql-client.sh "$@"
W
    sudo chmod +x /usr/bin/flink-sql-client
    sudo tee /usr/bin/yarn-session.sh > /dev/null << 'W'
#!/bin/bash
exec /usr/lib/flink/bin/yarn-session.sh "$@"
W
    sudo chmod +x /usr/bin/yarn-session.sh

    cat << 'EOF' | sudo tee /etc/profile.d/flink.sh
export FLINK_HOME=/usr/lib/flink
export PATH=$FLINK_HOME/bin:$PATH
EOF
    rm -f /tmp/flink-*.tar.gz
fi

Flink 的 bin 脚本内部用 . "$bin"/config.sh 做相对路径引用。symlink 会把 $bin 解析为 symlink 所在的 /usr/bin/ 而不是实际的 /usr/lib/flink/bin/,导致 config.sh 加载失败。

wrapper scripts 用 exec 直接调用原始路径的脚本,$bin 自然解析为正确路径。

EMR Master 节点上 /etc/flink/conf 是指向 /etc/alternatives/flink-conf 的 symlink,但 Core 节点上这个 alternatives 目标不存在。从 Master 打包后解压到 Core,symlink 就是 broken 的。脚本会检测并用 conf.dist 目录替代。

创建集群

aws emr create-cluster \
  --release-label emr-7.10.0 \
  --applications Name=Flink Name=Hadoop \
  --bootstrap-actions Path=s3://<bucket>/emr/bootstrap/install_flink_client.sh,Name="Install Flink Client on Core" \
  --instance-type m5.xlarge --instance-count 3 \
  --service-role EMR_DefaultRole \
  --ec2-attributes InstanceProfile=EMR_EC2_DefaultRole \
  --name "Flink-Cluster"

验证

从 Master SSH 到 Core 节点,执行 flink --versionflink-sql-client --help。排查看 /var/log/bootstrap-actions/1/stdout

方案评估

维度 说明
复用性 同版本 EMR 直接复用,EMR 升级时重新打包
执行时机 集群启动时自动,无人工干预
范围 仅 Core/Task 节点
耗时 S3 下载 + 解压约 30 秒
依赖 jq(EMR 默认自带)

生产建议:上线前通过 Bootstrap 日志验证安装结果,避免调度系统因环境缺失静默失败。

本文参考亚马逊云科技官方博客:在 AWS EMR Core 节点部署 Flink Client 的实战指南

posted @ 2026-04-27 05:33  亚马逊云开发者  阅读(5)  评论(0)    收藏  举报