[INFRA] EMR集群CWagent组件功能和运行原理分析

请注意本文部分内容经过AI辅助生成,虽然经过笔者检查但是并不保证内容的正确性,请自行判断准确性,本文对相关后果不承担责任

本文主要讲述 EMR 集群中的 CloudWatch Agent组件。CWAgent 是负责采集操作系统级别指标(CPU、内存、磁盘、网络等)并发送到 CloudWatch Metrics 的守护进程。它和 MetricsCollector 的职责完全不同:MC 采集的是 YARN/HDFS 应用指标用于 Managed Scaling 决策,而 CWAgent 采集的是 OS 系统指标用于监控告警。

这是理解 EMR 指标体系最关键的一点:

复制代码
路径 1: cloudwatch-sink → MC → EMR 控制面 (Managed Scaling 决策用)
        HDFS/YARN 应用指标,不出现在 CloudWatch 控制台

路径 2: CWAgent → CloudWatch Metrics (监控告警用)
        OS 系统指标 (CPU/内存/磁盘/网络),出现在 CloudWatch 控制台
        namespace=CWAgent

本文的测试环境是emr7.12版本,在创建集群时启用了cloudwatch agent组件,细节如下

CWAgent 的版本号是 CWAgent/1.300032.2-EMR.0,RPM 包是 emr-amazon-cloudwatch-agent-1.300032.2.amzn.0-1.amzn2023.x86_64。它是一个 Go 原生进程(不是 Java),内存占用约 45MB,比 Java 组件轻量得多。

它运行在 EMR 集群的每个节点上(Master 和 Worker 都运行),EMR 版本在标准 CWAgent 基础上增加了:

  • EMR 专用配置(自动注入 cluster.idinstance.id、node.type 维度)
  • OTLP gRPC 接收器(接收 Hadoop 组件通过 cloudwatch-sink 推送的指标)
  • TLS 加密的跨节点指标传输

关键特性:

特性 说明
所有节点运行 Master(node.type=master)和 Worker(node.type=core/task)
60 秒采集 系统指标每 60 秒采集一次
Go 原生进程 非 Java,内存占用约 45MB
双管道架构 Telegraf 采集器 + OpenTelemetry Collector 管道
OTLP 接收 监听 4317(本地) / 4318(TLS) 端口接收 Hadoop 组件指标
CloudWatch 输出 指标发送到 CloudWatch Metrics,namespace=CWAgent

进程信息

bash 复制代码
/opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent \
  -config /opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.toml \
  -envconfig /opt/aws/amazon-cloudwatch-agent/etc/env-config.json \
  -otelconfig /opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.yaml \
  -pidfile /opt/aws/amazon-cloudwatch-agent/var/amazon-cloudwatch-agent.pid

systemd 服务配置

ini 复制代码
[Unit]
Description=Amazon CloudWatch Agent
After=network.target

[Service]
Type=simple
ExecStart=/opt/aws/amazon-cloudwatch-agent/bin/start-amazon-cloudwatch-agent
KillMode=process
Restart=on-failure
RestartSec=60s

[Install]
WantedBy=multi-user.target

注意:与 MetricsCollector 不同,CWAgent 没有 MemoryMax/CPUQuota 限制。

采集的系统指标(34 个)

CPU 指标(11 个)

指标 说明
cpu_usage_active CPU 活跃使用率
cpu_usage_idle CPU 空闲率
cpu_usage_user 用户态 CPU
cpu_usage_system 内核态 CPU
cpu_usage_iowait I/O 等待
cpu_usage_steal 被虚拟化偷取的 CPU
cpu_usage_irq 硬中断
cpu_usage_softirq 软中断
cpu_usage_nice nice 进程
cpu_usage_guest 虚拟机 guest
cpu_usage_guest_nice 虚拟机 guest nice

采集粒度:percpu=true(每个 CPU 核心)+ totalcpu=true(汇总)

内存指标(10 个)

指标 说明
mem_active 活跃内存
mem_available 可用内存
mem_available_percent 可用内存百分比
mem_free 空闲内存
mem_inactive 非活跃内存
mem_total 总内存
mem_used 已用内存
mem_used_percent 已用内存百分比
mem_buffered 缓冲区内存
mem_cached 缓存内存

磁盘指标(4 个)

指标 说明
disk_free 磁盘可用空间
disk_total 磁盘总空间
disk_used 磁盘已用空间
disk_used_percent 磁盘使用率

采集粒度:resources=["*"](所有挂载点)

网络指标(4 个)

指标 说明
net_bytes_recv 接收字节数
net_bytes_sent 发送字节数
net_packets_recv 接收包数
net_packets_sent 发送包数

网络指标经过 cumulativetodelta 处理器转换为增量值。

Swap 指标(3 个)

指标 说明
swap_free Swap 可用
swap_used Swap 已用
swap_used_percent Swap 使用率

进程指标(2 个)

指标 说明
processes_running 运行中进程数
processes_total 总进程数

CloudWatch 维度

每个指标都附带以下维度,用于在 CloudWatch 中过滤和聚合:

维度 Master 值 Worker 值
cluster.id j-2Y8SIX4Q4K5ZJ j-2Y8SIX4Q4K5ZJ
instance.id i-07a7bdb3b2bd9b410 (各节点实例 ID)
node.type master core / task
service.name system system

聚合维度配置:[cluster.id, instance.id, node.type, service.name]

双管道(Pipeline)架构

CWAgent 内部有两条 OTel Pipeline:

metrics/host(直接输出)

复制代码
receivers: telegraf_disk, telegraf_mem, telegraf_processes, telegraf_swap, telegraf_cpu
processors: (无)
exporters: awscloudwatch

适用于绝对值指标(内存使用量、磁盘空间等),不需要任何转换,直接发送到 CloudWatch。

metrics/hostDeltaMetrics(增量转换)

复制代码
receivers: telegraf_net, otlp/metrics0, otlp/metrics1
processors: cumulativetodelta/hostDeltaMetrics
exporters: awscloudwatch

适用于累积值指标(网络字节数等),通过 cumulativetodelta 处理器转换为增量值后再发送。网络指标是累积值(从启动以来的总字节数),需要转换为每个采集周期的增量才有意义。

OTLP 接收器

CWAgent 同时作为 OpenTelemetry Collector 运行,监听两个 gRPC 端口:

端口 绑定地址 TLS 用途
4317 127.0.0.1 本地组件推送指标
4318 0.0.0.0 有 (mTLS) 跨节点指标接收

TLS 证书位置:

复制代码
/etc/emr-cluster-metrics/amazon-cloudwatch-agent/tls-artifacts/
├── ca-cert.pem    ← CA 证书
├── cert.pem       ← 服务端证书
├── key.pem        ← 私钥
└── extract-artifacts.sh

Master vs Worker 的端口差异:

  • Master:4317 (127.0.0.1) + 4318 (0.0.0.0 TLS)
  • Worker:仅 4317 (127.0.0.1),4318 未监听

cloudwatch-sink 组件

注意:cloudwatch-sink-2.22.0` 是一个 Hadoop Metrics2 Sink 插件,名字叫 "cloudwatch-sink" 但不推送到 CloudWatch ,而是推送到 MetricsCollector(端口 9501),由 MC 通过 WebSocket 上报到 EMR 控制面,用于 Managed Scaling 决策。这些指标不会出现在 CloudWatch 控制台

hadoop-metrics2.properties 配置

properties 复制代码
# 全局采样周期:300 秒(5 分钟)
*.period=300

# 指标白名单(仅这 11 个会被推送)
*.sink.cloudwatch.metricsList = TotalLoad,CapacityTotalGB,UnderReplicatedBlocks,
  CapacityRemainingGB,PendingDeletionBlocks,PendingReplicationBlocks,
  CorruptBlocks,CapacityUsedGB,NumLiveDataNodes,NumDeadDataNodes,MissingBlocks

# 8 个 Hadoop 组件启用 CloudWatchSink
namenode.sink.cloudwatch.class    = com.amazon.ws.emr.hadoop.metrics2.sink.cloudwatch.CloudWatchSink
datanode.sink.cloudwatch.class    = com.amazon.ws.emr.hadoop.metrics2.sink.cloudwatch.CloudWatchSink
resourcemanager.sink.cloudwatch.class = com.amazon.ws.emr.hadoop.metrics2.sink.cloudwatch.CloudWatchSink
nodemanager.sink.cloudwatch.class = com.amazon.ws.emr.hadoop.metrics2.sink.cloudwatch.CloudWatchSink
mrappmaster.sink.cloudwatch.class = com.amazon.ws.emr.hadoop.metrics2.sink.cloudwatch.CloudWatchSink
jobhistoryserver.sink.cloudwatch.class = com.amazon.ws.emr.hadoop.metrics2.sink.cloudwatch.CloudWatchSink
maptask.sink.cloudwatch.class     = com.amazon.ws.emr.hadoop.metrics2.sink.cloudwatch.CloudWatchSink
reducetask.sink.cloudwatch.class  = com.amazon.ws.emr.hadoop.metrics2.sink.cloudwatch.CloudWatchSink

白名单指标(11 个)

指标 说明 示例值
TotalLoad HDFS 总连接数 0
CapacityTotalGB HDFS 总容量 (GB) 116.0
CapacityUsedGB HDFS 已用容量 (GB) 0.0
CapacityRemainingGB HDFS 剩余容量 (GB) 116.0
NumLiveDataNodes 存活 DataNode 数 2
NumDeadDataNodes 死亡 DataNode 数 0
UnderReplicatedBlocks 副本不足的块数 0
PendingReplicationBlocks 待复制块数 0
PendingDeletionBlocks 待删除块数 0
CorruptBlocks 损坏块数 0
MissingBlocks 丢失块数 0

NameNode JMX 实际暴露了约66 个 FSNamesystem 指标,但只有以上 11 个在白名单中会被推送。

配置文件层次

CWAgent 的配置经过多层转换:

复制代码
emr-amazon-cloudwatch-agent.json          ← EMR 生成的源配置(JSON)
    │
    │ config-translator(启动时自动转换)
    │
    ├──► amazon-cloudwatch-agent.toml      ← Telegraf 格式(inputs/outputs)
    └──► amazon-cloudwatch-agent.yaml      ← OTel Collector 格式(receivers/exporters/pipelines)

修改配置时应编辑 emr-amazon-cloudwatch-agent.json,然后重启服务让 config-translator 重新生成 toml/yaml。

CloudWatch 输出配置

yaml 复制代码
exporters:
  awscloudwatch:
    namespace: CWAgent
    region: cn-north-1
    mode: EC2
    force_flush_interval: 1m0s
    max_datums_per_call: 1000
    max_values_per_datum: 150
    resource_to_telemetry_conversion:
      enabled: true
    rollup_dimensions:
      - [cluster.id, instance.id, node.type, service.name]

八、Master vs Worker 对比

项目 Master Worker (Core)
服务状态 active (running) active (running)
node.type master core
系统指标采集 ✅ 相同 ✅ 相同
OTLP 4317 (本地)
OTLP 4318 (TLS) --- (未监听)
cloudwatch-sink NameNode/RM/JHS DataNode/NM

目录结构

复制代码
/opt/aws/amazon-cloudwatch-agent/
├── bin/
│   ├── amazon-cloudwatch-agent              ← 主二进制(Go)
│   ├── amazon-cloudwatch-agent-ctl          ← 管理工具
│   ├── config-translator                    ← JSON→TOML/YAML 转换器
│   ├── start-amazon-cloudwatch-agent        ← 启动脚本
│   └── CWAGENT_VERSION                      ← 版本文件
├── etc/
│   ├── emr-amazon-cloudwatch-agent.json     ← EMR 专用 JSON 配置(源)
│   ├── amazon-cloudwatch-agent.d/
│   │   └── file_emr-amazon-cloudwatch-agent.json
│   ├── amazon-cloudwatch-agent.toml         ← 转换后的 Telegraf 配置
│   ├── amazon-cloudwatch-agent.yaml         ← OTel Collector 配置
│   ├── env-config.json                      ← 环境变量配置
│   └── common-config.toml                   ← 通用配置
├── var/
│   └── amazon-cloudwatch-agent.pid          ← PID 文件
└── logs/
    ├── amazon-cloudwatch-agent.log          ← 启动日志
    └── configuration-validation.log         ← 配置验证日志

/var/log/emr-cluster-metrics/amazon-cloudwatch-agent/
└── amazon-cloudwatch-agent.log              ← 运行时日志

/etc/emr-cluster-metrics/amazon-cloudwatch-agent/tls-artifacts/
├── ca-cert.pem, cert.pem, key.pem           ← OTLP TLS 证书

/usr/share/aws/emr/cloudwatch-sink/lib/
└── cloudwatch-sink-2.22.0.jar               ← Hadoop Metrics2 Sink 插件

运维指南

常用命令

bash 复制代码
# 服务管理
systemctl status amazon-cloudwatch-agent
sudo systemctl restart amazon-cloudwatch-agent

# 使用官方管理工具
sudo /opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-ctl -a status

# 版本查看
cat /opt/aws/amazon-cloudwatch-agent/bin/CWAGENT_VERSION

# 日志查看
sudo tail -f /var/log/emr-cluster-metrics/amazon-cloudwatch-agent/amazon-cloudwatch-agent.log

# 配置查看
sudo cat /opt/aws/amazon-cloudwatch-agent/etc/emr-amazon-cloudwatch-agent.json | python3 -m json.tool

# 端口检查
sudo ss -tlnp | grep -E "4317|4318"

# Hadoop Metrics2 cloudwatch-sink 配置
grep cloudwatch /etc/hadoop/conf/hadoop-metrics2.properties
相关推荐
A小辣椒8 天前
AWS Clould Support Engineer就职面试题
aws
亚林瓜子11 天前
AWS WAF中如何放行某个触发了托管规则的接口
aws·waf
悠悠1213813 天前
AWS DevOps Agent 体验一周后,我决定把 oncall 手机调成静音了
云计算·aws·devops
yyuuuzz13 天前
独立站运营的几个技术层面常见问题
大数据·运维·服务器·网络·数据库·aws
yyuuuzz13 天前
游戏云服务器推荐的技术选择思路
大数据·运维·服务器·游戏·云计算·aws
kernelcraft14 天前
Boto3:Python 操作 AWS 的官方 SDK
开发语言·python·其他·aws
陆水A19 天前
【实时数仓·3】Flink多表JOIN状态爆炸——Event Time Temporal JOIN + TTL分层治理
大数据·数据仓库·数据分析·flink·数据库开发·bigdata
普通网友21 天前
Serverless 框架:多云函数部署(AWS + 阿里云 + 腾讯云)
阿里云·serverless·aws
TG_yunshuguoji22 天前
亚马逊云代理商:如何用 CloudWatch+Lambda 打造自动化告警系统
大数据·运维·自动化·云计算·aws
yyuuuzz22 天前
独立站搭建的几个核心技术问题
运维·服务器·网络·数据库·aws