背景说明
大数据实时计算平台Flink引擎以Application模式运作在Yarn集群,在使用租户权限管理的过程中,遇到任务提交失败的异常,详细堆栈如下:
Failed to download resource { { hdfs://felixzh:9001/flink/libs/lib/log4j-core-2.17.1.jar, 1745737698195, FILE, null },pending,[(container_1740966828306_0038_01_000001)],5175757223143519,DOWNLOADING} java.io.IOException: Resource hdfs://felixzh:9001/flink/libs/lib/log4j-core-2.17.1.jar is not publicly accessible and as such cannot be part of the public cache.

排查上述问题,遂有此文。本文以上述异常为入口,结合yarn applciation作业提交流程、yarn资源文件本地化机制,排查相关源码,最后给出Flink Application提交模式与yarn资源文件本地化可见性的适配方案。欢迎关注微信公众号:大数据从业者

问题分析
根据错误日志查找Flink源码,发现flink-table模块ResourceManager类中有类似日志,对应源码如图所示:

需要仔细辨别才能发现,虽然Failed to download resource能对应上,但是后面的异常对应不上。笔者刚开始没注意,浪费时间梳理Flink这块的代码。其实,真正的异常日志是AM container打印的,对应于Hadoop源码hadoop-yarn-server-nodemanager模块的ResourceLocalizationService资源本地化服务。对应源码如图所示:

而后半段日志is not publicly accessible…对应于hadoop-yarn-common模块FSDownload类,对应代码如图所示:

从代码可以看出问题就是:已经设置可见性为PUBLIC的资源实际使用时候发现并不是public的。
这里需要先介绍下什么是资源以及资源本地化?所谓资源就是yarn container运行所需要的文件或者jar包等。而资源本地化就是在container运行前资源文件需要提前从HDFS下载到nodemanager节点的本地目录。
每个Application能够提交运行到yarn集群的流程都要包括:yarn client将资源文件上传到HDFS共享目录、ResourceManager启动ApplicationMaster进程、ApplicationMaster分配任务、nodemanager进程下载资源文件、然后启动container运行任务。大致流程如图所示:

而资源可见性共分为如下三类:
PUBLIC:nodemanager节点所有用户共享;PRIVATE:nodemanager节点相同用户的所有application共享;APPLICATION:nodemanager节点单个应用程序内的Container共享。
所谓共享即同一nodemanager节点内、共享范围内只缓存一份资源文件。相应源码注释如下:

解决方法
经过上述分析,解决方法分为两类:第一类适用于HDFS没有权限管理的环境,可以直接将资源文件放置到HDFS共享目录(即权限至少设置为755)。另一类适用于HDFS需要开启权限管理的环境,这种需要修改Flink源码将默认写死的可见性为PUBLIC改为可配置的PUBLIC/PRIVATE/APPLICATION。相关源码路径为:
flink-yarn/src/main/java/org/apache/flink/yarn/YarnClusterDescriptor.java

完整修改内容见FelixZh笔者的github:
https://github.com/felixzh2020/flink/commit/a3999698effe8914a75cc49e0953e2b055a664c5
效果验证
通过大数据实时计算平台创建普通的测试用户user01,对应的HDFS授权HD路径设置为/user/user01。权限详情如下:
[root@felixzh bin]# ./hdfs dfs -ls /user/Found 1 itemsdrwx------ - user01 supergroup 0 2025-04-28 15:34 user/user01[root@felixzh bin]# ./hdfs dfs -ls /user/user01Found 1 itemsdrwx------ - user01 supergroup 0 2025-04-28 15:34 /user/user01/lib
由于/user/user01目录只有用户user01有读写执行权限,所以资源可见性为APPLICATION和PRIVATE均可。实际验证如下:
./flink run-application -t yarn-application -Dyarn.provided.lib.dirs=/user/user01/lib -Dyarn.provided.lib.local-resource-visibility=APPLICATION ../examples/batch/WordCount.jar

./flink run-application -t yarn-application -Dyarn.provided.lib.dirs=/user/user01/lib -Dyarn.provided.lib.local-resource-visibility=PRIVATE ../examples/batch/WordCount.jar

强调一点:APPLICATION和PRIVATE可见性的本地资源文件会随着applciation执行完成立即清理。而PUBLIC可见性的资源文件在applciation执行完成仍然存在,NodeManager会定期清理过期的缓存文件:定时yarn.nodemanager.localizer.cache.cleanup.interval-ms启动清理确保每个缓存目录容量小于yarn.nodemanager.localizer.cache.target-size-mb,如果超过该值,则采用LRU算法清除不再使用的缓存文件。欢迎关注微信公众号:大数据从业者
题外话
五一假期阅读了朋友赠书《麦肯锡讲全球企业数字化》,在数字化与人工智能时代,学习企业数字化成功转型的六个关键部分:制定以业务为导向的转型路线、打造吸引数字化人才的环境、聚焦数字化产品、构建高效高质量的技术环境、专注于关键数据洞察实际价值、鼓励数字化解决方案的落地推广。受益匪浅,有需要的朋友可以看下:




