3. Flink on YARN实战:环境准备、提交命令、资源参数配置、日志查看与问题排查

好,咱们直接进入正题。Flink on YARN 是生产环境里最常见的部署方式之一。说白了,就是把 Flink 作业交给 YARN 去管理资源和调度。你想想看,YARN 本来就是做资源管理的,Flink 作业跑在上面,资源分配、容错、日志这些事都能交给 YARN 来处理,省心不少。

我个人习惯把这一整套流程分成四个环节:环境准备、提交命令、参数调优、问题排查。咱们一个一个来过。

核心思路: Flink on YARN 的本质是让 YARN 的 ApplicationMaster 来启动 Flink 的 JobManager 和 TaskManager。你提交的 jar 包和配置,决定了作业怎么跑、跑在哪、用多少资源。

Flink on YARN 作业提交流程 Flink on YARN 作业提交流程 Flink 客户端 YARN ResourceManager ApplicationMaster / JobManager TaskManager 容器(多个 YARN Container) 1. 客户端提交 jar + 配置 2. RM 分配 Container 3. AM 启动 JobManager 4. JM 申请 TaskManager 资源 5. TaskManager 启动 Slot 6. 作业开始运行

3.1 环境准备:先把地基打好

环境准备这块,我踩过不少坑。有一次在客户现场,折腾了半天发现是 Hadoop 版本和 Flink 不兼容。所以,咱们先把基础环境理清楚。

你需要准备的东西:

  • Hadoop 集群:YARN 必须跑起来,ResourceManager 和 NodeManager 都正常。建议 Hadoop 2.7+ 或 3.x。
  • Flink 发行包:去官网下载对应 Hadoop 版本的包。比如 flink-1.17.0-bin-scala_2.12.tgz。
  • Java 环境:JDK 8 或 11,这个不用多说。
  • 环境变量:HADOOP_HOME、HADOOP_CONF_DIR 必须配好。Flink 会通过它们找到 YARN 的配置。

我的小习惯: 在 flink-conf.yaml 里显式设置 yarn.application.name,这样在 YARN 界面上能一眼认出你的作业。不然全是 "Flink session",找起来头疼。

验证环境很简单,跑一行命令:

echo $HADOOP_HOME
echo $HADOOP_CONF_DIR
hadoop version

如果都能正常输出,环境就差不多了。

3.2 提交命令:两种模式,两种玩法

Flink on YARN 有两种提交模式:Session 模式 和 Per-Job 模式。我刚开始用的时候也纠结过选哪个,后来发现其实看场景。

模式 特点 适用场景
Session 模式 先启动一个常驻集群,再往里面提交作业。资源复用,启动快。 多个小作业、交互式查询、开发测试。
Per-Job 模式 每个作业单独启动一个 YARN 集群,作业结束集群自动释放。 生产环境的大作业、需要隔离资源的场景。

Session 模式提交示例:

# 先启动一个 YARN Session
./bin/yarn-session.sh -n 4 -s 2 -jm 1024 -tm 2048

# 然后提交作业到该 Session
./bin/flink run -m yarn-cluster -yn 4 ./examples/streaming/WordCount.jar

Per-Job 模式提交示例:

./bin/flink run -m yarn-cluster \
  -yn 4 \
  -yjm 1024 \
  -ytm 2048 \
  -ys 2 \
  -yqu default \
  ./examples/streaming/WordCount.jar

注意: Per-Job 模式在 Flink 1.15 之后被标记为废弃,推荐使用 Application 模式。但很多老项目还在用,所以我还是讲一下。新项目建议直接用 Application 模式。

3.3 资源参数配置:别让作业饿死或撑死

资源参数配置是门学问。配少了作业跑不动,配多了集群资源浪费。我曾经遇到过一个作业,TaskManager 内存配了 8G,结果数据量只有几百兆,白白浪费资源。

核心参数一览:

参数 说明 建议值
-yn / yarn.containers TaskManager 数量 根据并行度来,一般 4-16 个
-yjm / yarn.jobmanager.memory JobManager 内存 (MB) 1024-4096,看作业复杂度
-ytm / yarn.taskmanager.memory 每个 TaskManager 内存 (MB) 2048-8192,看数据量
-ys / yarn.slots 每个 TaskManager 的 Slot 数 一般 2-4,和 CPU 核数对应
-yqu / yarn.queue YARN 队列 根据集群配置,比如 root.production

我的经验公式:

  • 每个 Slot 分配 1-2 GB 内存,看算子复杂度。
  • TaskManager 内存 = Slot 数 × 每个 Slot 内存 + 管理开销(约 10%)。
  • 并行度不要超过集群总 Slot 数,否则作业会排队等资源。

避坑指南: 我曾经把 yarn.taskmanager.memory 设得比 YARN 的 yarn.nodemanager.resource.memory-mb 还大,结果作业一直提交失败。后来才发现是资源超限了。记住,TaskManager 内存不能超过 NodeManager 的可用内存。

3.4 日志查看与问题排查:遇到问题别慌

作业跑起来之后,日志就是你的眼睛。Flink on YARN 的日志分布在好几个地方,我刚开始找日志找得头大。

日志位置一览:

  • YARN 界面:通过 ResourceManager 的 Web UI(默认 8088 端口)找到你的 Application,点击 "Logs" 可以查看 AM 和 Container 的日志。
  • Flink Web UI:JobManager 的 Web 界面(默认 8081 端口),可以看到作业的实时状态、TaskManager 列表、异常信息。
  • 本地日志:如果你用 Session 模式,Flink 客户端会输出日志到 log/ 目录下。

常见问题排查思路:

  1. 作业提交失败:先看 YARN 界面,Application 状态是 FAILED 还是 KILLED。FAILED 一般是资源不足或配置错误,KILLED 可能是内存超限或被管理员杀掉。
  2. 作业运行缓慢:去 Flink Web UI 看背压(Back Pressure)和 Checkpoint 耗时。背压高说明下游处理不过来,Checkpoint 超时说明状态后端有问题。
  3. TaskManager 丢失:检查 YARN 日志,看是不是 NodeManager 把 Container 杀了。通常是内存超限,调大 yarn.taskmanager.memory 或者减小并行度。

我的排查习惯: 遇到问题先看 YARN 的 Application 日志,里面会打印出 Flink 的异常堆栈。如果堆栈信息不全,再去 Flink Web UI 看 TaskManager 的 stdout 和 stderr。这两个地方基本能覆盖 90% 的问题。

一个实用的命令:

# 查看 YARN 日志(需要知道 Application ID)
yarn logs -applicationId application_123456789_0001

这个命令会把所有 Container 的日志拉下来,方便本地分析。我经常用它来排查那些在界面上看不清楚的异常。

注意: YARN 日志默认只保留一段时间,如果作业已经结束很久,日志可能已经被清理了。建议在作业运行时就开启日志持久化,或者把关键日志输出到外部系统(比如 Kafka、Elasticsearch)。