Flink集群部署实战:从Standalone到高可用配置

发布时间:2026/10/14 7:20:21
Flink集群部署实战:从Standalone到高可用配置
这个系列写到了第 6 篇前面几篇把 Flink 里的流处理概念、DataStream API、运行架构一层层拆开讲完了今天轮到最实际的一环Flink 集群安装部署。单机模式跑通 Demo 的时候很多人觉得 Flink 也就那么回事但真正把 JobManager 和 TaskManager 拆到多台机器上才发现分布式环境里的“能不能跑起来”和“跑得稳不稳”完全是两码事。这篇内容会把部署模式选型、环境准备、配置文件、启动验证、高可用配置这一整条链路过一遍最后附上一份常见问题速查表适合已经会写简单 Flink 程序、想自己搭一套集群练手的人也适合准备给团队搭测试环境但不想对着官方文档翻半天的朋友。先说解决什么问题。集群部署的最终目标只有一个让 Flink 任务在多台机器上并行执行同时具备一定的容错和恢复能力。单机模式下所有进程挤在一起内存、CPU、网络都是瓶颈而且只要进程挂掉任务就没了。把 JobManager 和 TaskManager 分布到不同节点之后计算能力可以横向扩展再配合 ZooKeeper 或 YARN 这类外部依赖才算是一个真正能用于生产的运行环境。下面从选型开始一步一步说。1. 部署前先想清楚选哪种集群模式很多人拿到安装包直接开装结果装完发现模式不对又要推倒重来。Flink 的部署模式决定了你要不要装 Hadoop、要不要装 ZooKeeper、要不要懂容器先花十分钟想清楚这一步比后面省三天时间都值。1.1 三种部署模式一句话说清Flink 主流的部署模式就三种Standalone、YARN、Kubernetes。可以快速理解成Standalone 是“自己拉队伍”Flink 自己管理所有进程、资源和故障恢复不依赖外部调度器装起来最简单适合学习和测试。YARN 是“借别人的地盘干活”把资源申请、节点分配、失败重启交给 YARNFlink 只负责运行任务适合公司已有 Hadoop 集群的场景。Kubernetes 是“把容器编排交给 K8s”Flink 进程以 Pod 方式运行由 Kubernetes 负责调度、扩缩容和重启适合已经容器化的平台。光看概念可能没感觉直接上一个表格对照更清晰对比项StandaloneYARNKubernetes额外依赖可选 ZooKeeperHA 必需Hadoop YARNKubernetes 集群部署难度低中高资源管理方式Flink 自己管YARN 管K8s 管自动扩缩容能力无有限好生产适用场景小团队或测试已有 Hadoop 生态推荐容器化成熟团队1.2 我的选型思路与集群规划我给学习场景的建议是先用 Standalone 模式而且把高可用一起配上。原因很简单Standalone 把 Flink 最核心的进程模型暴露得最彻底——JobManager 负责调度TaskManager 负责干活两个角色的通信全部摆在眼前。把这种模式吃透之后再看 YARN 和 K8s无非是换了一个资源提供方很多概念是相通的。这次规划一个三节点集群角色分配如下节点角色主要工作建议配置node-1JobManager TaskManager调度 执行任务4 核 8Gnode-2JobManager TaskManager高可用备选 执行任务4 核 8Gnode-3TaskManager执行任务4 核 8G这里有个很多人会问的点JobManager 能不能和 TaskManager 放同一台机器学习环境完全没问题生产环境不建议。JobManager 是调度核心虽然进程本身不重但承担着所有任务的分配和检查点协调工作一旦和 TaskManager 争抢内存与 CPU很容易出现“调度节点卡住导致整个集群假死”的情况。后面讲 YARN 模式的时候你会发现YARN 默认尽量避免让管理进程和计算进程挤在同一台机器也是出于同样的考虑。生产环境即便不换模式也至少单独留一台机器做 JobManager再留一台做备选。这个习惯我吃过亏之后就一直坚持后面没再犯过类似的错。2. 环境准备这些坑提前踩掉能省一半时间环境准备是最枯燥但最容易出问题的地方。很多人觉得不就是装个 JDK 嘛结果集群起不来查了半天发现是 hosts 文件没配好、防火墙没放行、或者 SSH 免密不通。先把基础工作做扎实比后面抱着日志猜半天强得多。2.1 JDK 与操作系统版本怎么选Flink 依赖 JVM 运行JDK 版本直接决定你能不能顺利启动。Flink 1.17 和 1.18 这几代版本对 Java 8 和 Java 11 都支持生产环境我更推荐 JDK 11原因有两个一是以后升级 Flink 版本时不用重新折腾 JDK二是 JDK 11 对内存较大的堆场景更友好。当然如果公司内部统一用 JDK 8也没必要专门换版本匹配以官方兼容性表为准。操作系统这边主流 Linux 发行版都能跑CentOS 系、Ubuntu、Debian 系都行。有个容易忽略的点防火墙和 SELinux。集群节点之间要通信如果防火墙开着至少要放行 8081Web UI、6123JobManager RPC、6121/6122TaskManager 数据端口和 2181ZooKeeper。端口不提前规划好后面排查起来非常痛苦。还有一个比防火墙更容易坑人的点时间同步。分布式下的 Leader 选举、检查点恢复、日志排查都对时间比较敏感节点间时间差超过几百毫秒就可能出现“莫名其妙”的故障。我见过一个最典型的案例两台机器差了快两分钟JobManager 高可用切换死活不成功最后发现是 NTP 服务根本没装。2.2 SSH 免密与主机名映射Standalone 集群的启动脚本是通过 SSH 到各个节点上启动 TaskManager 的所以节点之间的免密登录必须提前配好。具体操作三步走# 1. 在每个节点上生成密钥 ssh-keygen -t rsa -P -f ~/.ssh/id_rsa # 2. 把公钥发给其他所有节点包括自己 ssh-copy-id node-1 ssh-copy-id node-2 ssh-copy-id node-3 # 3. 逐个验证免密 ssh node-2 hostname这里有两点容易出错。第一公钥必须互相发不是只从一台机器发出去就完事因为集群启动脚本可能从任意一个节点发起 SSH 连接。第二/etc/hosts 要统一配置把 IP 和主机名映射写进去避免脚本走 DNS 解析出问题。有个坑我至今记得有次在 node-2 上误把本机 IP 写成了 127.0.0.1结果 Flink 启动后 JobManager 之间互相找不到对方日志全是 Connection refused这种问题不静下心来查根本想不到是 hosts 的问题。2.3 目录规划与运行用户千万别用 root 账号跑 Flink。一是安全问题二是 Flink 的脚本和任务以 root 运行后后续做权限控制会很别扭。我习惯创建一个专门的用户useradd -m flink mkdir -p /data/flink/{log,checkpoint,savepoint} chown -R flink:flink /opt/flink /data/flink目录规划的意义在于后续升级、迁移、备份都方便。软件安装目录单独放数据目录检查点、日志单独放不要全堆在安装目录里。检查点目录是 Flink 做故障恢复的关键生产环境一般挂到独立存储或 HDFS 上这里先建好本地目录结构后面配置里会用到。多节点集群里确认每个 JobManager 节点上都有同样的目录、并且运行用户能写这个细节很基础但特别容易被忽略。3. 安装配置三个文件搞定核心环境准备好了接下来是真正动手的部分。Flink 安装包本身不需要编译解压就能用难点全在配置。Standalone 集群最核心的文件就是 flink-conf.yaml、masters、workers这三个文件理解透了整个集群的骨架也就清楚了。3.1 下载与解压版本选择也是门学问下载 Flink 之前先想一下版本。我见过不少人在官网直接下载最新版结果发现跟公司已有的 Hadoop 版本对不上又回退。建议优先选择“已发布一段时间、社区维护稳定”的版本。学习场景可以跟教程保持一致生产环境一定要先确认兼容性。下载解压的流程很简单wget https://archive.apache.org/dist/flink/flink-1.18.0/flink-1.18.0-bin-scala-2.12.tgz tar -zxvf flink-1.18.0-bin-scala-2.12.tgz -C /opt/flink mv /opt/flink/flink-1.18.0 /opt/flink/current注意 Scala 版本的选择如果你用 Scala 开发 Flink 任务这个版本要和代码里的 Scala 版本一致如果只用 Java API选默认版本即可。接着配置环境变量echo export FLINK_HOME/opt/flink/current /etc/profile echo export PATH$PATH:$FLINK_HOME/bin /etc/profile source /etc/profile三个节点都要做同样的操作。实际部署时我会把配置好的整个目录 rsync 到其他节点这样安装目录、配置文件全部一致能少很多低级错误。3.2 flink-conf.yaml先理解内存模型再改参数flink-conf.yaml 是整个集群最重要的配置文件真正需要手动改的参数其实不多。很多人一打开文件就懵几百个配置项不知道哪些是必改。Standalone 模式必须先理解两个角色各自的内存模型。JobManager 进程默认分配一个固定的 JVM 内存主要管理任务调度、检查点协调内存需求不大。TaskManager 是真正干活的进程每个 TaskManager 内部要分成 JVM 堆、托管内存Managed Memory和网络缓冲三块。默认情况下比例大概是 50%、40%、10%。托管内存给算子状态、排序、聚合这些操作用网络缓冲给数据在 TaskManager 之间流转用。给你一份可以直接起步的配置示例# 每个 JobManager 进程总内存 jobmanager.memory.process.size: 1024m # 每个 TaskManager 进程总内存 taskmanager.memory.process.size: 4096m # 每个 TaskManager 提供的 slot 数 taskmanager.numberOfTaskSlots: 4 # 默认并行度 parallelism.default: 2 # Web UI 地址 rest.address: node-1 rest.port: 8081参数怎么定是有计算逻辑的不是拍脑袋。比如一台 8G 物理内存的节点操作系统本身要占一部分假设留给 Flink 进程 6GTaskManager 的 process.size 配 4G 比较稳妥。每个 TaskManager 的 slot 数最好不要超过物理核数4 核机器配 4 个 slot 已经足够再多只会增加线程切换开销。有个坑必须提醒网上很多老教程里写 taskmanager.heap.memory.size 这种参数Flink 1.11 之后就废弃了现在统一用 taskmanager.memory.process.size 这种总内存模型。如果你抄了一段老配置任务还没跑内存就被扣了一块日志里全是各种 OutOfMemory排查起来特别费劲。3.3 masters 与 workers 文件集群角色绑定在哪个文件里masters 文件决定 JobManager 跑在哪台机器workers 文件决定 TaskManager 跑在哪台机器都在 Flink 的 conf 目录下。masters 文件格式很简单每行一个节点后面跟端口node-1:8081 node-2:8081workers 文件同理每行一个节点node-1 node-2 node-3注意masters 里写多个节点前提是 flink-conf.yaml 里开了高可用。如果开了 HAnode-1 和 node-2 就是互为热备的关系如果没开 HA写了多个也只会用第一个。workers 文件简单所有要跑 TaskManager 的节点都写进去。三个节点的 conf 目录必须完全一致。我实际操作时会在主节点改好然后一条命令同步过去rsync -av /opt/flink/current/conf/ flinknode-2:/opt/flink/current/conf/ rsync -av /opt/flink/current/conf/ flinknode-3:/opt/flink/current/conf/配置同步特别容易被忽略结果就是主节点配好了高可用从节点还是旧配置一启动就报错。养成“改完文件先同步”的习惯能省很多时间。4. 启动集群从命令到验证一条龙配置改完激动人心的时刻到了。但启动集群不是敲一条命令就完事还得学会观察状态、查日志、确认集群真的就绪。这一节把从启动到验证的完整过程拆开讲。4.1 启动与停止命令Flink 的 Standalone 集群启动只需要在主节点上执行一条命令bin/start-cluster.sh这个脚本会读取 masters 和 workers 文件在主节点启动 JobManager然后通过 SSH 到所有 workers 节点启动 TaskManager。启动时能看到类似 “Starting JobManager” “Starting TaskManager” 的输出。如果某台机器失败脚本不会自动中止但日志会有提示。停止集群是对称操作bin/stop-cluster.sh这里有几点经验。第一启动前确认 ZooKeeper如果配了 HA已经跑起来否则 JobManager 找不到外部协调服务启动会失败。第二修改 flink-conf.yaml 后必须重启集群才生效没有热加载一说。第三node-1 和 node-2 都是 JobManager 角色时不要在两台机器上分别执行 start-cluster.sh只需要在其中一台执行即可脚本会自动把全部节点拉起来。4.2 怎么判断集群真的起来了启动完先别急着提交任务花五分钟确认状态。最常用的是 jps 命令直接看 Java 进程jps -l在 JobManager 节点上应该看到类似输出12680 org.apache.flink.runtime.entrypoint.StandaloneSessionClusterEntrypoint 12711 org.apache.flink.runtime.taskexecutor.TaskManagerRunnerStandaloneSessionClusterEntrypoint 就是 JobManager 进程TaskManagerRunner 是 TaskManager。有的节点上只有 TaskManagerRunner没有 StandaloneSessionClusterEntrypoint这很正常因为角色不同。进程有了再看 Web UI。浏览器访问http://node-1:8081进入 Dashboard 后重点看左侧的 Task Managers 列表确认里面有 3 个 TaskManagerSlot 数量显示为总数比如每台 4 个 slot三台就是 12 个。如果数量不对说明某台机器没起来去对应节点看日志。日志文件在 log 目录下命名规则类似 flink-flink-standalonesession-0-node-1.log。JobManager 和 TaskManager 的日志分开存排查问题时先分清是哪个角色出了问题再去看对应日志不然很容易在错误的日志里浪费时间。最后还可以用命令行做一次验证bin/flink list集群正常的话这条命令能连上 JobManager 并列出当前运行的任务。如果命令报错“Could not connect to the cluster”十有八九是 JobManager 地址或网络问题。5. 高可用配置别让单点故障拖垮你的任务很多人搭集群时觉得高可用是“以后再说”的事真等 JobManager 所在机器宕机、任务全部挂掉时才知道后悔。Standalone 集群默认只有一个 JobManager这是典型的单点故障。这一节专门讲怎么把高可用配上。5.1 为什么 Standalone 必须搭配 ZooKeeperFlink 的高可用实现依赖外部协调服务 ZooKeeper。这个概念可以类比生活一个班里不能只有一个班长万一班长请假了整个班没人管所以要选一个副班长随时顶上。ZooKeeper 就是负责“选副班长”和“记录谁在管事”的角色。具体到机制上多个 JobManager 节点启动后会在 ZooKeeper 上注册ZooKeeper 通过分布式锁决定哪一个是 Leader主 JobManager其余节点进入 Standby 状态。如果 Leader 挂了ZooKeeper 会通知其他节点抢锁一个 Standby 节点自动提升为 Leader接管任务调度。Flink 早期版本做过不需要 ZooKeeper 的高可用尝试后来都移除了。现在做 Standalone 高可用ZooKeeper 是硬性依赖没有它就没有 Leader 选举不存在“简易 HA”的选项。5.2 配置 HA 的完整步骤假设已经装好一个 ZooKeeper 集群学习环境用单节点 ZooKeeper 也行先跑通机制配置步骤如下。第一步在 flink-conf.yaml 里打开 HA指定 ZooKeeper 地址high-availability: zookeeper high-availability.zookeeper.quorum: node-1:2181,node-2:2181,node-3:2181 high-availability.zookeeper.path.root: /flink high-availability.storageDir: file:///data/flink/hahigh-availability.storageDir 是 HA 元数据的存储位置JobManager 的检查点、作业图等恢复信息都存在这里。生产环境建议用 HDFS 这类分布式文件系统测试环境用本地路径也够。注意这个目录在多个 JobManager 节点上都要存在并且运行用户可写。第二步masters 文件写入两个 JobManagernode-1:8081 node-2:8081第三步重启集群。顺序是先启动 ZooKeeper再执行 start-cluster.sh。没有打开 HA 时masters 文件写多个节点没有意义只会用第一个。5.3 HA 实测kill 掉主 JobManager 后会发生什么配置好之后最好实测一次别等真出事才发现配错了。操作很简单在主节点上用 jps 找到 StandaloneSessionClusterEntrypoint 的进程号直接 killkill -9 12680等一两分钟去 node-2 上看 Web UI。正常情况下 node-2 会顶上成为新的 LeaderDashboard 依然可以正常访问正在运行的任务由新的 JobManager 接管。注意这个过程不是瞬间完成的ZooKeeper 需要先发现 Leader 失联再触发重新选举期间任务会进入短暂的中断或恢复流程。这里有个常见误区HA 不等于“任务永远不中断”。Standalone 的 HA 保证的是 JobManager 不成为单点但任务本身的恢复还依赖检查点配置。如果任务没开检查点JobManager 挂了之后重启任务状态无法顺畅衔接。所以高可用和检查点是配套的只看一个等于白配。6. 从 Standalone 到生产YARN 与 Kubernetes 模式怎么衔接学完 Standalone 之后一定会面临一个问题生产环境到底用哪种模式这一节聊聊两种主流生产模式的思路以及和 Standalone 的关系。6.1 生产环境为什么不推荐裸 StandaloneStandalone 模式下所有资源都是静态分配的TaskManager 起多少个就是多少个JobManager 跑在固定节点上资源无法动态伸缩。新任务要跑但 slot 不够不会自动帮你加机器任务少的时候机器闲置资源照样占着。这对生产环境来说很难接受。另外Standalone 没有应用级隔离。多个任务共享同一个 TaskManager一个任务的异常内存占用可能拖累同进程里的其他任务出问题时定位也比较头疼。这不是说 Standalone 一无是处它的定位就是学习、测试以及对运维要求不高的边缘场景。生产环境的选择基本两种有 Hadoop 生态上 YARN容器化成熟上 Kubernetes。6.2 YARN 模式的核心Session 与 Per-JobYARN 模式的核心思想是把 Flink 当成 YARN 的一个应用程序提交。在 YARN 模式下你不需要手动管理 TaskManagerYARN 会根据资源申请自动在集群节点上启动容器来运行 TaskManager任务结束后资源自动释放。YARN 模式有两种提交方式Session 和 Per-Job。Session 模式是先在 YARN 上申请一个常驻的 Flink 集群然后向这个集群提交多个任务适合任务多但单个任务体量小的场景。Per-Job 是每个任务单独申请一个 Flink 集群任务结束集群销毁适合重量级任务、需要资源隔离的生产场景。需要配置好 Hadoop 相关环境变量后才能提交export HADOOP_CLASSPATH$(hadoop classpath) flink run -m yarn-cluster -yjm 1024m -ytm 4096m ./my-job.jar我建议学习路径上先跑通 Standalone再接触 YARN。YARN 模式下很多“资源从哪来、TaskManager 怎么起”的问题被 YARN 屏蔽了如果连 Standalone 的进程模型都没概念出了问题根本不知道往哪个方向查。6.3 Kubernetes 模式一句话点评Kubernetes 模式是容器化团队的首选。Flink 可以原生方式跑在 K8s 上也可以配合 Flink Kubernetes Operator 做声明式管理。优势在于扩容、缩容、故障重启都能交给 K8s和公司已有的监控体系、发布流程容易打通。K8s 模式的学习曲线最陡需要懂容器、镜像、Pod 调度等一整套概念。如果团队没有容器化基础设施不用一上来就折腾 K8s先跑通 YARN 往往更稳妥。7. 常见问题速查表集群部署过程中遇到的问题大部分是重复出现的。这个章节整理部署阶段最高频的故障现象和排查方向再分享一个我比较依赖的日志排查习惯相当于整套流程的收尾部分。7.1 高频故障速查表按“现象 → 原因 → 处理”的结构把这些典型问题列成表可以直接对照排查现象常见原因排查与处理start-cluster.sh 启动后 TaskManager 数量不对SSH 免密不通过、workers 配置不全检查 SSH 免密、查看 TaskManager 节点日志Web UI 打不开8081 端口未监听、防火墙未放行确认 JobManager 进程存在、检查端口和防火墙TaskManager 启动失败日志提示内存不足物理内存小于 taskmanager.memory.process.size调小进程内存或减少节点上的进程数JobManager 启动后立刻退出ZooKeeper 未启动、HA 配置错误检查 ZooKeeper 状态、查看日志中的异常堆栈提交任务报 Could not connect to the clusterJobManager 地址配置错误、网络不通检查配置、确认 JobManager 存活、ping 目标节点HA 切换不成功节点间时钟不同步、ZooKeeper 地址配置错误校准时间、核对 ZooKeeper quorum 配置节点上出现 Permission denied目录属主不对、运行用户不可写统一运行用户chown 数据目录和日志目录修改配置后行为没变化忘记重启集群修改 flink-conf.yaml 后必须重启生效7.2 一个高效的日志排查习惯看日志是最花时间的事。我的经验是别从头翻到尾第一步先用 grep 定位关键词比如 JobManager 起不来先 grep “Exception” 或 “ERROR”再从定位到的那几行往外扩展看上下文效率比顺序翻高很多。另外日志文件增长特别快。生产环境一定要把日志滚动和监控接上否则排查问题全靠肉眼翻日志既慢又容易漏。学习环境的话至少养成每次修改配置后清空一次 log 目录的习惯这样日志里只有最新一次启动的记录排查起来干净很多。部署这件事我第一次搭三节点集群的时候也折腾了大半天。最尴尬的是启动失败后反复查配置最后发现是两个节点上的 flink-conf.yaml 不一致一个开了 HA 一个没开JobManager 之间行为完全对不上。后来我养成了一个习惯每次动手之前先写一份部署清单节点角色、端口、目录、依赖服务都列出来部署完逐项打勾出问题直接对照清单往回查效率高非常多。Flink 集群部署本身不难难的是把每一步背后的原理搞清楚以及养成规范的操作习惯。下一篇文章我打算写任务提交和检查点配置到时会重点讲怎么让任务在故障之后真正“活过来”。