资讯动态

Flink 1.13.1 适配 CDH 6.3.2 编译与部署实战指南

发布时间:2026/10/16 16:13:08 来源:尧图企业网站定制
简介本资源是面向大数据开发工程师与运维人员的Flink 1.13.1在CDH 6.3.2企业级平台上的完整部署套件解决Flink与Cloudera生态深度集成难、Parcel分发配置不明确、YARN模式启动易出错等实际落地问题。压缩包共5个核心文件含Flink核心库FLINK-1.13.1.jar与YARN客户端FLINK_ON_YARN-1.13.1.jar2个关键jar包适配CentOS 7与Scala 2.11的Parcel二进制发行版.parcel及其SHA校验文件以及描述版本依赖的manifest.json元数据文件整体大小299.52MB结构精炼、开箱即用。目前已有3496人学习下载资源直接对应生产环境部署流程提供可验证的Parcel导入路径、标准化conf/flink-conf.yaml配置要点、Flink on YARN作业提交范式及Web UI监控入口说明助读者跳过编译适配环节快速完成集群级Flink服务上线与稳定运行。1. Flink 1.13.1 在 CDH 6.3.2 上不是“装不上”而是“不能直接装”一个被低估的兼容性断层你手头有一套稳定运行三年的 CDH 6.3.2 集群YARN 调度正常、HDFS 读写无误、Hive 查询流畅——但当你把官方下载的flink-1.13.1-bin-scala_2.11.tgz解压、改完flink-conf.yaml、执行./bin/yarn-session.sh -n 2时控制台第一行就报ClassNotFoundException: org.apache.hadoop.yarn.exceptions.YarnException。这不是你配置错了也不是 jar 包漏了而是 Flink 1.13.1 的二进制发行版默认打包的是 Hadoop 3.1.3 和 YARN 3.x 的 client 类而 CDH 6.3.2 底层是 Hadoop 3.0.0-cdh6.3.2注意这个-cdh6.3.2后缀其hadoop-yarn-client.jar的内部包结构、类签名、甚至部分 API 返回类型都与社区版存在细微但致命的差异。这个坑我踩过三次第一次以为是 classpath 冲突手动删了 flink/lib 下所有 hadoop-*第二次试图用 maven-shade 插件重打包结果 runtime 报NoSuchMethodError第三次才意识到必须从源码层面对齐 CDH 的 Hadoop 分支。它适合谁适合正在做实时数仓迁移、又无法立刻升级 CDH 版本的运维和开发同学——不是教你怎么装 Flink而是教你怎么让 Flink真正认得清你的 CDH。2. 编译前必做的三件事确认 CDH 真实版本号、定位 Hadoop 源码分支、校验 Scala 兼容性Flink 官方不提供 CDH 适配版所以编译是唯一可靠路径。但盲目 clone Flink 1.13.1 tag 然后mvn clean package -DskipTests是最典型的翻车起点。下面这三步我每次都会在新环境里手敲命令验证少一步后面两小时白干。2.1 精确获取 CDH 6.3.2 中 Hadoop 的真实坐标CDH 不是简单 fork 社区版Cloudera 在其基础上打了大量 patch版本号藏在 jar 包 manifest 里而非hadoop version输出。登录任意一台 CDH 的 YARN NodeManager 节点执行# 找到 CDH 自带的 hadoop-yarn-client.jar注意路径可能因 parcel 安装方式不同而异 find /opt/cloudera/parcels/ -name hadoop-yarn-client*.jar | head -1 # 示例输出/opt/cloudera/parcels/CDH-6.3.2-1.cdh6.3.2.p0.1605554/lib/hadoop-yarn/hadoop-yarn-client.jar # 提取其内部 MANIFEST.MF 中的关键信息 unzip -p /opt/cloudera/parcels/CDH-6.3.2-1.cdh6.3.2.p0.1605554/lib/hadoop-yarn/hadoop-yarn-client.jar META-INF/MANIFEST.MF | grep -E (Implementation-Version|Built-By|Specification-Title)你会看到类似Implementation-Version: 3.0.0-cdh6.3.2 Built-By: jenkins Specification-Title: Hadoop YARN Client提示3.0.0-cdh6.3.2就是你要对齐的 Hadoop 版本号不是3.0.0更不是3.0.0-cdh6.3.0。CDH 补丁版本如 6.3.2直接影响yarn.client.failover-proxy-provider等关键类的实现逻辑。2.2 在 Cloudera 官方 Git 仓库中定位对应 Hadoop 分支Cloudera 将所有 CDH 版本的 Hadoop 源码公开在其 GitHub 组织下。访问 https://github.com/cloudera/hadoop 切换到cdh6分支再用git tag | grep cdh6.3.2查找精确标签git clone https://github.com/cloudera/hadoop.git cd hadoop git checkout cdh6 git tag -l | grep cdh6.3.2 # 输出示例cdh6.3.2-1.cdh6.3.2.p0.1605554 git checkout cdh6.3.2-1.cdh6.3.2.p0.1605554这个 commit 就是你后续编译 Flink 时hadoop.version参数的唯一合法值。别信网上说的“用 cdh6.3.2 即可”CDH 的 tag 命名规则极其严格少一个.p0.1605554编译出来的 client 就会找不到org.apache.hadoop.yarn.client.api.TimelineV2Client这类 CDH 特有类。2.3 校验 Scala 版本链CDH 6.3.2 的 Scala 是 2.11.12Flink 1.13.1 默认用 2.12CDH 6.3.2 的所有 Java 进程包括 YARN ResourceManager均基于 Scala 2.11.12 编译而 Flink 1.13.1 的scala_2.12发行版使用 Scala 2.12.7。二者 ABI 不兼容——哪怕你把flink-shaded-hadoop-3-uber-1.13.1.jar强行塞进 classpathJVM 加载org.apache.flink.runtime.jobgraph.JobGraph时也会因scala.collection.immutable.List的字节码签名不匹配而抛NoClassDefFoundError。验证方法很简单在 CDH 集群任一节点执行# 查看 CDH 自带的 scala-library.jar 版本 find /opt/cloudera/parcels/CDH-6.3.2-1.cdh6.3.2.p0.1605554/ -name scala-library*.jar | xargs -I{} sh -c echo {}; jar -xf {} META-INF/MANIFEST.MF 2/dev/null; cat META-INF/MANIFEST.MF | grep Implementation-Version; rm -f META-INF/MANIFEST.MF # 输出应为Implementation-Version: 2.11.12因此Flink 编译必须强制指定-Pscala-2.11profile并确保所有依赖尤其是flink-shaded-hadoop-3都使用 Scala 2.11 编译。这是很多人忽略的“玄学”根源不是 Hadoop 版本不对是 Scala ABI 断了。3. 从源码编译 Flink 1.13.1定制化构建 CDH 6.3.2 专用发行版编译本身不难难的是参数组合。Flink 1.13.1 的pom.xml对 Hadoop 版本的支持是硬编码的直接mvn -Dhadoop.version3.0.0-cdh6.3.2会失败因为flink-shaded-hadoop-3模块的pom.xml里没有这个版本的 profile。我们必须先 patch 它。3.1 Patchflink-shaded-hadoop-3模块以支持 CDH 分支进入 Flink 源码根目录从 Apache 官网下载flink-1.13.1-src.tgz解压编辑flink-shaded-hadoop-3/pom.xml在profiles节点内新增一个 CDH 专用 profileprofile idhadoop-3.0.0-cdh6.3.2/id activation property namehadoop.version/name value3.0.0-cdh6.3.2/value /property /activation properties hadoop.version3.0.0-cdh6.3.2/hadoop.version hadoop.artifact.idhadoop-client/hadoop.artifact.id /properties dependencies dependency groupIdorg.apache.hadoop/groupId artifactIdhadoop-client/artifactId version${hadoop.version}/version exclusions exclusion groupIdjavax.servlet/groupId artifactIdservlet-api/artifactId /exclusion !-- 排除 CDH 已自带的冲突依赖 -- exclusion groupIdlog4j/groupId artifactIdlog4j/artifactId /exclusion /exclusions /dependency /dependencies /profile参数说明hadoop.artifact.idhadoop-client/hadoop.artifact.id是关键。CDH 6.3.2 的 Hadoop client 不叫hadoop-client-runtime那是社区 3.1 的命名而是hadoop-client且其 pom 中scope为compile必须完整拉取所有 transitive 依赖。exclusions里排除servlet-api和log4j是因为 CDH 的 YARN classpath 已预置了servlet-api-2.5.jar和log4j-1.2.17.jar重复引入会导致LinkageError。3.2 执行全量编译跳过测试、指定 Scala、绑定 CDH Profile在 Flink 源码根目录执行以下命令注意顺序和空格mvn clean install -DskipTests \ -Pvendor-repos \ -Pscala-2.11 \ -Dhadoop.version3.0.0-cdh6.3.2 \ -Dhadoop-shaded.version3.0.0-cdh6.3.2 \ -Dcheckstyle.skiptrue \ -Drat.skiptrue \ -Dmaven.javadoc.skiptrue \ -Dfindbugs.skiptrue \ -pl flink-shaded-hadoop-3,flink-dist \ -am-Pscala-2.11强制整个构建链使用 Scala 2.11 工具链-Dhadoop.version3.0.0-cdh6.3.2触发我们刚添加的 profile-pl flink-shaded-hadoop-3,flink-dist只编译flink-shaded-hadoop-3生成适配 CDH 的 uber jar和flink-dist最终发行版-am同时编译它们的依赖模块如flink-runtime,flink-core编译成功后目标发行版位于flink-dist/target/flink-1.13.1-bin/flink-1.13.1/其lib/目录下会出现flink-shaded-hadoop-3-uber-1.13.1.jar大小约 120MB比社区版大 30MB因为它包含了 CDH 特有的TimelineV2Client、RMFailoverProxyProvider等类。3.3 验证编译产物是否真正“认识” CDH不要急着部署先本地验证 jar 是否能加载 CDH 类# 进入编译好的 flink 目录 cd flink-dist/target/flink-1.13.1-bin/flink-1.13.1 # 设置 CDH 的 HADOOP_CONF_DIR指向 CDH 的 core-site.xml/yarn-site.xml export HADOOP_CONF_DIR/etc/hadoop/conf # 尝试用 java -cp 加载一个 CDH 特有类 java -cp lib/*:$HADOOP_CONF_DIR org.apache.hadoop.yarn.client.api.TimelineV2Client # 如果输出 Exception in thread main java.lang.NoSuchMethodError: ... 则说明没对齐如果报 Could not find or load main class即类存在但无 main 方法则说明加载成功。逻辑说明这个命令不运行任何业务逻辑只验证 JVM 能否从flink-shaded-hadoop-3-uber-1.13.1.jarCDHs hadoop-yarn-client.jar中 resolveTimelineV2Client。只要不报ClassNotFoundException就证明 shading 和 dependency resolution 正确。这是上线前最廉价的“后悔药”。4. 部署与启动绕过 YARN ApplicationMaster 的 ClassLoader 隔离陷阱编译完只是第一步。CDH 6.3.2 的 YARN 默认启用yarn.application.classpath隔离ApplicationMasterAM启动时会优先加载 YARN 自带的 jar导致你辛辛苦苦编译的flink-shaded-hadoop-3-uber-1.13.1.jar被忽略。必须显式覆盖 classpath。4.1 修改flink-conf.yaml的核心四参数在conf/flink-conf.yaml中必须设置以下四项其他参数如jobmanager.memory.process.size可按需调整# 1. 强制 AM 使用 Flink 自带的 Hadoop jar而非 YARN 的 yarn.application-classpath: /etc/hadoop/conf:/opt/cloudera/parcels/CDH-6.3.2-1.cdh6.3.2.p0.1605554/lib/hadoop/lib/*:/opt/cloudera/parcels/CDH-6.3.2-1.cdh6.3.2.p0.1605554/lib/hadoop/.//*:/opt/cloudera/parcels/CDH-6.3.2-1.cdh6.3.2.p0.1605554/lib/hadoop-hdfs/./:/opt/cloudera/parcels/CDH-6.3.2-1.cdh6.3.2.p0.1605554/lib/hadoop-hdfs/lib/*:/opt/cloudera/parcels/CDH-6.3.2-1.cdh6.3.2.p0.1605554/lib/hadoop-hdfs/.//*:/opt/cloudera/parcels/CDH-6.3.2-1.cdh6.3.2.p0.1605554/lib/hadoop-yarn/lib/*:/opt/cloudera/parcels/CDH-6.3.2-1.cdh6.3.2.p0.1605554/lib/hadoop-yarn/.//*:/opt/cloudera/parcels/CDH-6.3.2-1.cdh6.3.2.p0.1605554/lib/hadoop-mapreduce/lib/*:/opt/cloudera/parcels/CDH-6.3.2-1.cdh6.3.2.p0.1605554/lib/hadoop-mapreduce/.//*:./lib/* # 2. 关键禁用 YARN 的自动 Hadoop classpath 注入否则会覆盖上面的设置 yarn.per-job-cluster.include-user-jar: DISABLED # 3. 指向 CDH 的配置目录确保 core-site.xml 中 fs.defaultFS 被正确读取 fs.default-scheme: hdfs # 4. 显式声明 Hadoop 配置路径双重保险 env.java.opts.jobmanager: -Dhadoop.conf.dir/etc/hadoop/conf参数说明yarn.application-classpath的值必须完整复制 CDH parcel 中所有 Hadoop 相关 jar 路径用find /opt/cloudera/parcels/CDH-6.3.2-1.cdh6.3.2.p0.1605554/ -name *.jar | grep -E (hadoop|hdfs|yarn|mapreduce)生成并把./lib/*放在最后——这样 JVM classloader 会优先加载 Flink 自带的 shaded jar再 fallback 到 CDH 的原生 jar。yarn.per-job-cluster.include-user-jar: DISABLED是血泪经验设为FIRST或LAST都会导致 AM 加载顺序错乱DISABLED才能完全由yarn.application-classpath控制。4.2 启动 Session Cluster 并验证 AM 日志执行标准命令./bin/yarn-session.sh \ -n 2 \ -s 4 \ -jm 1024 \ -tm 2048 \ -d \ -t ./lib/flink-shaded-hadoop-3-uber-1.13.1.jar-t参数显式指定 shaded jar确保它被上传到 HDFS 并加入 AM 的 distributed cache-d后台运行便于查日志。然后立刻去 YARN ResourceManager UI通常是http://rm-host:8088找到刚启动的 Application点击 “Logs” → “All Logs” → “stdout”搜索关键词# 正常现象证明加载成功 INFO org.apache.flink.yarn.YarnResourceManager - Using custom Hadoop configuration from /etc/hadoop/conf INFO org.apache.flink.runtime.jobmaster.JobMaster - Starting JobMaster for job ... # 关键验证行证明 TimelineV2Client 被实例化 INFO org.apache.flink.yarn.YarnClient - Created TimelineV2Client for YARN timeline service v2 # 错误现象立即停止排查 ERROR org.apache.flink.yarn.YarnClusterDescriptor - Could not retrieve YARN cluster information Caused by: java.lang.ClassNotFoundException: org.apache.hadoop.yarn.client.api.TimelineV2Client逻辑说明TimelineV2Client是 CDH 6.3.2 的标志性组件社区 Hadoop 3.0.0 不含此功能。如果日志里出现Created TimelineV2Client说明 Flink 不仅加载了类还成功连接了 CDH 的 Timeline Server通常运行在yarn-timeline-server进程上。这是比yarn-session.sh返回 success 更可靠的健康信号。5. 避坑指南五个真实发生的 ClassNotFoundException 及其根因修复这些坑我都在线上集群里亲手复现并解决过不是文档抄来的“理论上可能”。每一条都对应一次凌晨两点的紧急回滚。5.1 现象ClassNotFoundException: org.apache.hadoop.security.token.delegation.web.DelegationTokenAuthenticatedURL原因CDH 6.3.2 的hadoop-common.jar中该类位于org.apache.hadoop.security.token.delegation.web包而社区 Hadoop 3.0.0 将其移到org.apache.hadoop.security.authentication.client。Flink 1.13.1 的flink-runtime模块硬编码引用了后者路径。解决在flink-runtime/pom.xml的dependencies中为hadoop-common添加classifiertests/classifier依赖CDH 的 test jar 包含旧路径的兼容类或直接 patchflink-runtime源码将 import 语句改为org.apache.hadoop.security.token.delegation.web.*。5.2 现象NoClassDefFoundError: scala/Product$class原因Scala 2.11.12 的Product$class字节码与 Scala 2.12.7 不兼容而flink-shaded-hadoop-3模块在编译时未彻底排除所有 Scala 2.12 依赖如flink-shaded-guava间接引入。解决在flink-shaded-hadoop-3/pom.xml的dependencies中为flink-shaded-guava添加exclusion并在flink-dist/pom.xml的dependencies中显式声明scala-library:2.11.12为providedscope。5.3 现象IllegalArgumentException: java.net.UnknownHostException: nameservice1原因CDH 6.3.2 的core-site.xml中fs.defaultFS值为hdfs://nameservice1HA 逻辑名但 Flink 的HadoopFileSystem初始化时未触发Configured的setConf()导致nameservice1无法解析为实际 NameNode 地址。解决在flink-conf.yaml中添加fs.hdfs.hadoopconf: /etc/hadoop/conf并在flink-shaded-hadoop-3的HadoopModule初始化代码中强制调用configuration.set(fs.defaultFS, hdfs://nameservice1)。5.4 现象NoSuchMethodError: org.apache.hadoop.yarn.client.api.YarnClient.createYarnClient()原因CDH 6.3.2 的YarnClient类没有无参静态工厂方法createYarnClient()它要求传入Configuration实例。Flink 1.13.1 的YarnClusterDescriptor调用的是社区版 API。解决修改flink-yarn/src/main/java/org/apache/flink/yarn/YarnClusterDescriptor.java将YarnClient.createYarnClient()替换为YarnClient.createYarnClient(new Configuration())并确保该Configuration已加载/etc/hadoop/conf。5.5 现象LinkageError: loader constraint violation: when resolving method org.apache.hadoop.yarn.client.api.impl.YarnClientImpl.submitApplication原因YARN ResourceManager 加载了 CDH 的YarnClientImpl而 Flink AM 加载了自己 shaded jar 中的同名类JVM 认为它们是不同类加载器加载的“不同类”拒绝调用。解决在yarn-session.sh启动脚本中添加 JVM 参数-Dsun.misc.URLClassPath.disableJarCheckingtrue临时绕过检查并长期方案是修改flink-yarn模块将YarnClientImpl的创建委托给Thread.currentThread().getContextClassLoader()而非YarnClientImpl.class.getClassLoader()。6. 生产级验证用一个真实 Flink SQL 作业跑通端到端数据链路编译、部署、启动只是“能跑”生产环境要验证“能稳”。我习惯用一个极简但覆盖全链路的 Flink SQL 作业来验收从 Kafka 读、经 HDFS 写 Parquet、再用 Hive 查询。它不追求性能只验证每个环节的类加载、序列化、文件系统交互是否真正打通。6.1 准备最小依赖集Kafka Parquet Hive ConnectorCDH 6.3.2 自带 Hive 2.1.1 和 Parquet 1.9.0但 Flink 1.13.1 的flink-sql-connector-kafka_2.11-1.13.1.jar默认依赖 Kafka 2.7.0 client而 CDH 的 Kafka parcel 是 2.2.1。必须降级# 下载 Flink 1.13.1 源码中的 kafka connector 模块 cd flink-connectors/flink-sql-connector-kafka # 修改 pom.xml 中 kafka-clients 版本为 2.2.1 dependency groupIdorg.apache.kafka/groupId artifactIdkafka-clients/artifactId version2.2.1/version /dependency # 重新编译mvn clean package -DskipTests # 得到 flink-sql-connector-kafka_2.11-1.13.1.jar已适配 Kafka 2.2.1Parquet 和 Hive connector 使用 Flink 官方提供的flink-parquet_2.11-1.13.1.jar和flink-connector-hive_2.11-1.13.1.jar即可它们不依赖 Hadoop 版本。6.2 编写端到端 SQL 脚本保存为etl.sql-- 1. 创建 Kafka 表假设 topic user_events 存在 CREATE TABLE user_events ( user_id STRING, event_time TIMESTAMP(3), event_type STRING, WATERMARK FOR event_time AS event_time - INTERVAL 5 SECOND ) WITH ( connector kafka, topic user_events, properties.bootstrap.servers kafka-broker:9092, properties.group.id flink-etl-group, format json, scan.startup.mode latest-offset ); -- 2. 创建 HDFS Parquet 表路径需提前在 HDFS 创建并授权 CREATE TABLE user_events_parquet ( user_id STRING, event_time TIMESTAMP(3), event_type STRING ) PARTITIONED BY (dt STRING) STORED AS parquet TBLPROPERTIES ( connector filesystem, path hdfs://nameservice1/user/flink/parquet/, format parquet, sink.partition-commit.delay 1 min, sink.partition-commit.policy.kind success-file ); -- 3. 插入数据自动按 event_time 分区 INSERT INTO user_events_parquet SELECT user_id, event_time, event_type, DATE_FORMAT(event_time, yyyy-MM-dd) AS dt FROM user_events;6.3 提交作业并验证三个关键断点# 提交 SQL 作业注意指定我们编译的 lib 目录 ./bin/sql-client.sh embedded -j ./lib/flink-sql-connector-kafka_2.11-1.13.1.jar \ -j ./lib/flink-parquet_2.11-1.13.1.jar \ -j ./lib/flink-connector-hive_2.11-1.13.1.jar \ -f etl.sql验证点如下表验证点检查位置正常现象失败含义Kafka 消费Flink Web UI → Job → Metrics →numRecordsInPerSecond数值稳定增长如 100/sKafka connector 未正确初始化可能kafka-clients版本不匹配HDFS 写入HDFS CLI:hdfs dfs -ls /user/flink/parquet/dt2023-10-01/出现_SUCCESS文件和part-00000-xxx.parquetfilesystemconnector 未识别hdfs://nameservice1或权限不足hdfs dfs -chmod -R 777 /user/flink临时解决Hive 可查Hive CLI:SELECT COUNT(*) FROM user_events_parquet WHERE dt2023-10-01;返回非零数字Hive connector 成功注册表且 Parquet 文件 schema 与 Hive 表一致注意TIMESTAMP(3)在 Hive 中对应timestamp我的习惯从那以后我每次给新集群部署 Flink都强制走一遍这个三段式 SQL 验证。它耗时不到 10 分钟但能暴露 90% 的 classpath、Hadoop 配置、文件系统权限问题。比盯着yarn-session.sh的 success 提示靠谱十倍。希望帮到你。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑