Prometheus 监控实战 04:Flink 指标接入 Prometheus


前面已经把 Prometheus、Node Exporter、Pushgateway 和 PromQL 的基础用法整理了一遍。到这里,Prometheus 已经能采集主机指标和短任务指标,但还没有接入真正的大数据计算组件。

这篇开始把 Flink 接进来。

Flink 本身有一套 Metrics System,可以把 JobManager、TaskManager、作业、算子、JVM、网络 Shuffle 等指标暴露出去。Prometheus 要采集 Flink 指标,比较直接的方式是启用 Flink 自带的 Prometheus Reporter,让 JobManager 和 TaskManager 进程各自启动一个 /metrics 端口,然后 Prometheus 去拉取这些端口。

本篇先在单机 Standalone 模式下完成接入,后面再接 Grafana 面板。

这里用 Standalone 只是为了把 Flink 指标接入 Prometheus 的最小链路跑通。生产环境如果运行在 YARN 或 Kubernetes 上,通常还要结合服务发现、动态 target 配置或平台侧的监控方案。

1. 环境说明

当前仍然使用前几篇的同一台服务器:

hostname
date '+%Y-%m-%d %H:%M:%S'
java -version

输出如下:

lavm-bzoq5mwl1h
2025-05-09 22:29:45

openjdk version "11.0.13" 2021-10-19 LTS

本次新增 Flink:

/opt/module/flink-1.20.1/bin/flink --version

输出如下:

Version: 1.20.1, Commit ID: cb1e7b5

当前几个端口规划如下:

端口 组件 说明
8081 Flink Web Dashboard Flink Standalone Web UI
9249 Flink JobManager Prometheus Reporter JobManager 指标
9250 Flink TaskManager Prometheus Reporter TaskManager 指标
9090 Prometheus Web UI 和 HTTP API
9100 Node Exporter 主机指标
9091 Pushgateway 短任务指标

这些端口在实验环境里可以临时开放访问,但生产环境不要直接把 Flink Web UI、Flink Reporter、Prometheus、Node Exporter、Pushgateway 暴露到公网。对外访问更建议通过 VPN、内网、安全组、防火墙、Nginx Basic Auth 或统一网关做访问控制。

这里先让 Flink 使用 Standalone 模式启动一个 JobManager 和一个 TaskManager。对于 Prometheus 来说,不管 Flink 是 Standalone、YARN 还是 Kubernetes,最终要解决的问题都是一样的:让 Prometheus 能发现并抓取 Flink Reporter 暴露出来的 /metrics。区别在于 target 发现方式不同:Standalone 固定进程适合先用 static_configs,YARN/Kubernetes 这类动态环境更适合服务发现或自动化生成 targets。

先准备安装目录:

mkdir -p /opt/software /opt/module
cd /opt/software

下载 Flink 1.20.1:

curl -L -o flink-1.20.1-bin-scala_2.12.tgz \
  https://archive.apache.org/dist/flink/flink-1.20.1/flink-1.20.1-bin-scala_2.12.tgz

本文以 Flink 1.20.1 为例,为了固定实验版本使用 Apache Archive 地址。阅读时可以到 Flink 官方下载页选择最新稳定版本。这里选择的是 Scala 2.12 构建版本,如果使用其他 Flink 发行包,需要保持 JobManager、TaskManager、客户端和依赖版本一致。Flink 1.20 可以使用 Java 11,本实验环境使用 OpenJDK 11。

解压并移动到 /opt/module:

tar -zxf flink-1.20.1-bin-scala_2.12.tgz -C /opt/software
mv /opt/software/flink-1.20.1 /opt/module/flink-1.20.1

如果 /opt/module/flink-1.20.1 已经存在,先备份旧目录,确认不需要后再删除,避免直接覆盖已有配置。

检查版本:

/opt/module/flink-1.20.1/bin/flink --version

输出:

Version: 1.20.1, Commit ID: cb1e7b5

本文使用的 Flink 1.20.1 发行包中已经包含 Prometheus Reporter 相关 jar,不需要额外单独下载插件。如果使用精简包、自定义发行包或特殊部署方式,需要确认 Prometheus Reporter 依赖是否存在。重点是后面的 config.yaml 配置。

3. 配置 Prometheus Reporter

Flink 1.20 使用的主配置文件是:

/opt/module/flink-1.20.1/conf/config.yaml

修改前先备份一份,并检查是否已经存在同名配置项,避免重复配置导致实际生效结果不清楚:

cp /opt/module/flink-1.20.1/conf/config.yaml \
   /opt/module/flink-1.20.1/conf/config.yaml.bak

grep -n 'metrics.reporter.prom\|bind-address\|bind-host' \
  /opt/module/flink-1.20.1/conf/config.yaml

在文件末尾追加下面配置:

rest.bind-address: 0.0.0.0
jobmanager.bind-host: 0.0.0.0
taskmanager.bind-host: 0.0.0.0

metrics.reporter.prom.factory.class: org.apache.flink.metrics.prometheus.PrometheusReporterFactory
metrics.reporter.prom.port: 9249-9250
metrics.scope.jm: flink_jobmanager
metrics.scope.tm: flink_taskmanager

这几项配置分两类。

第一类是监听地址:

配置 说明
rest.bind-address 让 Flink REST 服务 / Web Dashboard 绑定到指定地址,便于外部访问
jobmanager.bind-host JobManager 绑定地址
taskmanager.bind-host TaskManager 绑定地址

第二类是指标:

配置 说明
metrics.reporter.prom.factory.class 启用 Prometheus Reporter
metrics.reporter.prom.port Reporter 端口范围
metrics.scope.jm JobManager 指标前缀
metrics.scope.tm TaskManager 指标前缀

这里把 rest.bind-address、jobmanager.bind-host、taskmanager.bind-host 都配置成 0.0.0.0,只是为了实验环境访问方便。生产环境建议绑定内网地址,或者通过更严格的访问控制限制访问范围。

metrics.reporter.prom.factory.class 是通过 factory class 启用 Prometheus Reporter。Flink 启动后,JobManager 和 TaskManager 会根据端口范围分别启动 Reporter HTTP 服务。metrics.scope.jm 和 metrics.scope.tm 是为了让指标前缀更清晰,后面会看到指标名类似 flink_jobmanager_… 和 flink_taskmanager_…。

这里把端口写成 9249-9250,因为 JobManager 和 TaskManager 在同一台机器上启动,它们都需要占用一个 Reporter 端口。在当前单机环境中,JobManager 实际占用了 9249,TaskManager 实际占用了 9250;不同启动顺序或已有端口占用时,实际端口可能不同,需要以 ss -lntp 或 Flink 日志为准。如果后面实际 Reporter 端口不是 9249/9250,Prometheus 的 targets 也要同步修改。

如果是多台机器,每台机器上都有自己的 TaskManager,端口规划可以保持一致;如果同一台机器上有多个 JobManager/TaskManager 进程,端口范围至少要覆盖同机 Flink 进程数量,否则 Reporter 可能因为端口不足启动失败。如果是在已有 Flink 集群上修改 config.yaml,需要重启 JobManager/TaskManager 后 Reporter 配置才会生效。

启动 Flink 集群:

cd /opt/module/flink-1.20.1
bin/stop-cluster.sh
bin/start-cluster.sh

如果之前已经启动过 Flink,先停止旧进程再重新启动,可以减少端口冲突和旧配置未生效的问题。

查看进程:

jps

输出中可以看到两个 Flink 进程:

874008 StandaloneSessionClusterEntrypoint
874577 TaskManagerRunner

如果环境里没有 jps,也可以用 ps -ef | grep flink 查看 Flink 进程。

检查端口:

ss -lntp | egrep ':8081|:9249|:9250'

输出如下:

LISTEN 0 128 *:8081 *:* users:(("java",pid=874008,fd=145))
LISTEN 0   3 *:9249 *:* users:(("java",pid=874008,fd=74))
LISTEN 0   3 *:9250 *:* users:(("java",pid=874577,fd=74))

这里的 :8081、:9249、*:9250 表示服务监听在所有网卡上。如果云服务器安全组放开这些端口,外部也可能访问。

打开 Flink Web Dashboard,地址是 http://服务器IP:8081;如果在服务器本机访问,也可以用 http://localhost:8081。页面里可以看到当前有 1 个 TaskManager、1 个可用 slot,没有正在运行的作业:

对应的 REST API 也能拿到同样的信息:

curl -s http://localhost:8081/overview

返回结果如下:

{
  "taskmanagers": 1,
  "slots-total": 1,
  "slots-available": 1,
  "jobs-running": 0,
  "jobs-finished": 0,
  "jobs-cancelled": 0,
  "jobs-failed": 0,
  "flink-version": "1.20.1",
  "flink-commit": "cb1e7b5"
}

这里的 slots-total、slots-available 都是 1,是因为当前单机 Standalone 环境只启动了 1 个 TaskManager 和 1 个 slot。实际生产环境会根据 TaskManager 数量和 slot 配置变化。这一步确认 Flink 本身已经正常启动。

Prometheus Reporter 启用后,可以直接访问 Reporter 端口。

先看 JobManager:

curl -s http://localhost:9249/metrics | head

页面效果如下:

可以看到指标已经是 Prometheus 文本格式,比如:

# HELP flink_jobmanager_numRunningJobs numRunningJobs (scope: jobmanager)
# TYPE flink_jobmanager_numRunningJobs gauge
flink_jobmanager_numRunningJobs{host="localhost",} 0.0

这里 label 后面的逗号是 Flink Reporter 输出格式中的表现,不影响 Prometheus 解析。

再看 TaskManager:

curl -s http://localhost:9250/metrics \
  | grep '^flink_taskmanager_Status_Shuffle_Netty_AvailableMemorySegments'

输出如下:

flink_taskmanager_Status_Shuffle_Netty_AvailableMemorySegments{host="localhost",tm_id="localhost:40899_9f74ef",} 4096.0

这个指标名比较具体,不同 Flink 版本、配置或运行状态下可能略有差异。如果 grep 不到,可以先用下面的方式看当前实际暴露的 TaskManager 指标:

curl -s http://localhost:9250/metrics | grep '^flink_taskmanager_' | head

这说明 JobManager 和 TaskManager 都已经把自身指标暴露出来了。此时只是 Flink Reporter 暴露成功,还不代表 Prometheus 已经采集成功;Prometheus 侧还需要配置 scrape_configs 并确认 target 为 UP。如果 /metrics 没有输出 Flink 指标,需要检查 Flink 是否已经重启、Reporter 配置是否写对、Reporter 端口是否监听、Flink 日志中是否有 PrometheusReporter 启动或报错信息。

修改 Prometheus 配置:

cp /opt/module/prometheus-3.2.1/prometheus.yml \
   /opt/module/prometheus-3.2.1/prometheus.yml.bak

vim /opt/module/prometheus-3.2.1/prometheus.yml

在原来的 scrape_configs 中追加两个 job:

- job_name: "flink_jobmanager"
  static_configs:
    - targets: ["localhost:9249"]

- job_name: "flink_taskmanager"
  static_configs:
    - targets: ["localhost:9250"]

这里的 localhost:9249 和 localhost:9250 只适用于 Prometheus 和 Flink 在同一台机器上的实验环境。如果 Prometheus 和 Flink 不在同一台机器上,需要把 localhost 换成 Flink 所在服务器的内网 IP 或 DNS 名称。这种 static_configs 写法适合单机或固定 IP 环境;如果 TaskManager 数量动态变化,不建议长期手动维护 targets,应考虑服务发现或自动生成 targets。

此时完整采集对象变成:

job target 说明
prometheus localhost:9090 Prometheus 自身
node_exporter localhost:9100 主机指标
pushgateway localhost:9091 短任务指标
flink_jobmanager localhost:9249 Flink JobManager 指标
flink_taskmanager localhost:9250 Flink TaskManager 指标

重启前先检查配置:

/opt/module/prometheus-3.2.1/promtool check config \
  /opt/module/prometheus-3.2.1/prometheus.yml

确认配置无误后再重启 Prometheus。实验环境可以直接重启,生产环境需要谨慎操作,避免短暂影响监控采集;更推荐使用 systemd 管理进程。

pkill -f '/opt/module/prometheus-3.2.1/prometheus'

nohup /opt/module/prometheus-3.2.1/prometheus \
  --config.file=/opt/module/prometheus-3.2.1/prometheus.yml \
  --storage.tsdb.path=/opt/module/prometheus-3.2.1/data \
  --web.listen-address=0.0.0.0:9090 \
  > /opt/module/prometheus-3.2.1/prometheus.log 2>&1 &

Prometheus 默认没有登录认证,这里监听 0.0.0.0:9090 仍然只是实验环境做法,不建议直接暴露到公网。

等待一个采集周期后,查询 Flink target 的 up。这个采集周期来自 prometheus.yml 中的 scrape_interval,一般等待十几秒到几十秒即可:

up{job=~"flink_.*"}

结果如下:

两个 target 都是 1。下面是 Prometheus UI 中整理后的 instant query 展示结果,不是 HTTP API 原始 JSON:

up{instance="localhost:9249", job="flink_jobmanager"} 1
up{instance="localhost:9250", job="flink_taskmanager"} 1

这说明 Prometheus 已经能正常抓取 Flink 的两个 Reporter 端口。但 up=1 只能证明 Reporter 端口可抓取,不代表 Flink 作业一定正常。比如当前没有提交作业,up 仍然可以是 1。

7. 查询 JobManager 指标

先查一个最直观的 JobManager 指标:

flink_jobmanager_numRunningJobs

页面结果如下:

当前没有提交 Flink 作业,所以值是 0:

flink_jobmanager_numRunningJobs{host="localhost", instance="localhost:9249", job="flink_jobmanager"} 0

这个指标适合用来观察当前 JobManager 上有多少个正在运行的作业。当前只是启动了 Standalone 集群,没有提交 Flink 作业,所以值为 0 是正常现象。如果要观察 Flink 集群资源状态,通常还会继续关注:

flink_jobmanager_numRegisteredTaskManagers
flink_jobmanager_taskSlotsTotal

这两个指标分别表示已注册 TaskManager 数量和总 slot 数。

在当前环境里,直接查询可以看到:

curl -s http://localhost:9249/metrics \
  | egrep 'flink_jobmanager_(numRegisteredTaskManagers|taskSlotsTotal)'

输出如下:

flink_jobmanager_numRegisteredTaskManagers{host="localhost",} 1.0
flink_jobmanager_taskSlotsTotal{host="localhost",} 1.0

这和 Flink Web Dashboard 上看到的 1 个 TaskManager、1 个 slot 是一致的。如果这里和 Dashboard 不一致,需要检查 Prometheus 是否已经完成最新采集,或者 Flink 指标是否存在延迟。

8. 查询 TaskManager 指标

TaskManager 指标数量会明显多于 JobManager,通常包括 JVM、网络、Shuffle、内存、线程、GC、task/operator 等维度。不同作业运行后还会出现更多作业级指标。这里先查一个 Shuffle 网络内存段指标:

flink_taskmanager_Status_Shuffle_Netty_AvailableMemorySegments

页面结果如下:

结果中包含 tm_id:

flink_taskmanager_Status_Shuffle_Netty_AvailableMemorySegments{
  host="localhost",
  instance="localhost:9250",
  job="flink_taskmanager",
  tm_id="localhost:40899_9f74ef"
} 4096

tm_id 是 TaskManager 维度的标识。后面如果一个集群里有多个 TaskManager,这个 label 就很重要,可以用它区分是哪一个 TaskManager 的指标。

TaskManager 的 JVM 内存也可以查:

flink_taskmanager_Status_JVM_Memory_Heap_Used

不同 Flink 版本或 scope 配置下,指标名可能略有差异。如果查不到,可以先在 /metrics 中 grep JVM_Memory_Heap 确认实际指标名。

如果要换算成 MB:

flink_taskmanager_Status_JVM_Memory_Heap_Used / 1024 / 1024

如果要按 TaskManager 聚合:

sum by(instance, tm_id)(flink_taskmanager_Status_JVM_Memory_Heap_Used)

如果要看 JVM 堆内存使用率,可以写成:

flink_taskmanager_Status_JVM_Memory_Heap_Used
  / flink_taskmanager_Status_JVM_Memory_Heap_Max * 100

这里的思路和前面 Node Exporter 一样:原始指标只负责表达状态,真正用于排查和告警时,还需要通过 PromQL 做过滤、聚合和单位换算。对于 Counter 类型指标,还需要结合 rate()、increase() 等函数;Gauge 类型指标通常可以直接做当前值、聚合或单位换算。

接入 Flink 后,最明显的感觉是指标名会比较长,这主要和 Flink scope、metric group、模块层级有关。比如:

flink_taskmanager_Status_Shuffle_Netty_AvailableMemorySegments

可以拆成几层看:

片段 含义
flink_taskmanager 指标作用域,来自 metrics.scope.tm
Status Flink 内部状态指标
Shuffle_Netty Shuffle Netty 模块
AvailableMemorySegments 可用内存段数量

JobManager 指标也类似:

flink_jobmanager_numRunningJobs
flink_jobmanager_numRegisteredTaskManagers
flink_jobmanager_taskSlotsTotal

所以实际排查时,可以先按前缀找一批指标:

curl -s http://localhost:9249/metrics | grep '^flink_jobmanager_' | head
curl -s http://localhost:9250/metrics | grep '^flink_taskmanager_' | head

也可以在 Prometheus Web UI 的查询框中输入 flink_jobmanager 或 flink_taskmanager 前缀,查看自动补全出来的指标。再把确认有用的指标拿到 Prometheus 页面里写 PromQL。

如果想确认当前 Prometheus 中已经有哪些 job 和 instance,可以用 API 快速看一下:

curl -s 'http://localhost:9090/api/v1/label/job/values'
curl -s 'http://localhost:9090/api/v1/label/instance/values'

10. 常见问题排查

Flink Reporter 是否真正生效,可以按下面顺序检查:

  1. 看 Flink 日志中是否有 PrometheusReporter 启动或报错信息。
  2. 用 ss -lntp 确认 9249/9250 或实际 Reporter 端口是否监听。
  3. 用 curl -s http://localhost:9249/metrics | head 查看原始指标。
  4. 修改 Prometheus 配置后,查询 up{job=~”flink_.*”}。

几个常见问题可以这样定位:

现象 排查方向
9249/9250 没有监听 检查 config.yaml 配置是否写对,Flink 是否已经重启
Prometheus target down 检查 targets 地址和端口是否写错
本机 curl 可以,Prometheus 抓不到 确认 Prometheus 和 Flink 是否在同一台机器,localhost 是否用错
指标名查不到 确认 Flink 版本、scope 配置、Reporter 是否启用
Reporter 端口冲突 扩大 metrics.reporter.prom.port 端口范围
修改配置不生效 确认 JobManager 和 TaskManager 都已经重启

11. 小结

这篇完成了 Flink 指标接入 Prometheus 的最小闭环:

  1. 部署并启动 Flink Standalone。
  2. 在 config.yaml 中启用 Prometheus Reporter。
  3. 当前实验环境中 JobManager 暴露 9249/metrics,TaskManager 暴露 9250/metrics。
  4. Prometheus 新增 flink_jobmanager 和 flink_taskmanager 两个采集任务。
  5. 使用 up{job=~”flink_.*”}、flink_jobmanager_numRunningJobs 和 TaskManager Shuffle 指标验证链路。

到这里,Prometheus 已经能拿到 Flink 运行时指标。在做 Grafana 面板前,建议先确认 Prometheus 中 Flink target 为 UP,并能查到 JobManager、TaskManager 的核心指标。下一篇继续接 Grafana,把这些指标做成可视化面板,先把 Flink 集群状态、TaskManager 状态和 JVM 指标展示出来。


文章作者: hnbian
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 hnbian !
评论
  目录