MetricBeat 核心功能与日志/指标对比
MetricBeat 是 Elastic Stack 的轻量级指标采集器,定期收集操作系统、软件或服务的指标数据(Metrics)指标数据存储于 Elasticsearch 实现实时分析
指标(Metric)与日志(Log)的本质区别:
1 ) 日志(Logs):
- 记录离散的随机事件(如应用程序调试信息、错误报告或 Web Server 请求记录)。其特点是无规律性,仅在事件发生时捕获瞬时状态
- 示例:Web Server 日志包含 IP、时间戳、请求路径、返回状态码(如
192.168.1.1 [10/May/2023:14:23:45] "GET /index.html HTTP/1.1" 200 1024)
2 ) 指标(Metrics):
- Metrics 为可聚合的度量数据,采集具有计划性(如每分钟采集CPU负载)。数据通常为数值型,辅以少量文本描述,记录可聚合的数值型数据,且采集行为具有强计划性。例如:
- 每 1 分钟收集一次 Web Server 的响应时长
- 每 1 分钟收集主机的 CPU 负载(如
CPU Load: 1.2, 1.5, 2.0 @ 10:00, 10:10, 10:20)
- 关键差异:日志时间戳无规律,而指标采集间隔严格固定(如每 10 分钟)
- 示例
// CPU 负载指标示例 { "timestamp": "2023-10-10T14:35:00Z", "cpu.load.1m": 0.75, "cpu.load.5m": 0.68 }
关键差异:Logs时间戳无规律,Metrics采集间隔固定(如每10分钟一次)
MetricBeat 架构:Module 与 Metricset 设计
Module 封装监控对象(如操作系统、数据库),Metricset 定义指标集合,划分依据为减少采集调用次数。以 Redis Module 为例:
redis/infoMetricset:通过单次INFO命令获取全部数据redis/keyspaceMetricset:独立采集键空间数据,支持自定义采集频率(如1秒/次)
MetricBeat 配置示例
metricbeat.modules:
- module: redis
metricsets: ["info", "keyspace"]
period: 60s # info 采集间隔
hosts: ["localhost:6379"]
keyspace.period: 1s # keyspace 独立间隔
事件数据结构:
{
"@timestamp": "2023-05-10T08:00:00Z",
"beat": {"name": "server01"},
"metricset": {
"name": "redis.info",
"rtt": 150
},
"redis": {
"info": {
"clients": 12,
"cpu": {"user": 45.2, "sys": 3.1}
}
}
}
模块化生态与配置实战
内置 Module 覆盖场景:
| Module | Metricset 示例 | 监控对象 |
|---|---|---|
| system | cpu, diskio, memory | 操作系统 |
| redis | info, keyspace | Redis 数据库 |
| docker | container, cpu, diskio | Docker 容器 |
| elasticsearch | node_stats, index | ES 集群 |
| kafka | consumer, partition | Kafka 消息队列 |
配置流程:
- 下载对应操作系统的 MetricBeat 安装包
- 编辑
metricbeat.yml启用模块:
output.elasticsearch:
hosts: ["http://localhost:9200"]
metricbeat.modules:
- module: system
metricsets: ["cpu", "memory", "network"]
period: 10s
processes: [".*"] # 监控所有进程
- module: redis
metricsets: ["info"]
period: 30s
hosts: ["redis-host:6379"]
- 启用模块(需 root 权限):
./metricbeat modules enable system redis # 启用模块
./metricbeat modules list # 验证启用状态
chown root metricbeat.yml # 解决权限错误
Metricbeat 通过两级结构组织监控任务:
1 ) Module(模块):预封装的监控对象模板,开箱即用
- 示例:
system:监控操作系统(CPU、内存、磁盘)redis:监控 Redis 服务mysql/zookeeper/docker:监控数据库、中间件及容器
2 ) Metricset(指标集):Module 中的子单元,代表一组关联指标的集合,划分依据是最小化数据采集请求次数。
-
以
redisModule 为例: -
infoMetricset:通过单条INFO命令获取 Redis 全局状态 -
keyspaceMetricset:单独监控数据库键空间统计 -
Metricset 独立存在的必要性:
- 支持为不同指标集设置独立采集频率(如
info每分钟采集,keyspace每秒采集) - 避免高频采集干扰低频任务,优化资源消耗
- 支持为不同指标集设置独立采集频率(如
3 ) Metricbeat 数据流与存储结构
采集的数据以 Event 形式发送至 Elasticsearch,其通用结构如下:
{
"@timestamp": "2023-05-10T10:00:00Z", // 采集时间戳
"beat": {
"name": "monitor-host-01", // 采集主机标识
"version": "8.10.0"
},
"metricset": {
"name": "redis_info", // 指标集名称
"module": "redis", // 所属模块
"rtt": 150 // 请求往返耗时(微秒)
},
"event": { // 实际指标数据
"dataset": "redis.info",
"cpu": {
"used": 1200,
"sys": 350,
"user": 850
}
}
}
- 注:
event.cpu字段与 RedisINFO命令的输出直接对应(如used_cpu_sys: 350)
4 )配置实战:System 模块监控操作系统
Metricbeat 配置核心位于 metricbeat.yml 的 modules 节段:
metricbeat.modules:
- module: system # 启用 system 模块
metricsets: # 指定指标集
- cpu
- load
- network
period: 10s # 基础采集频率
processes: [".*"] # 监控所有进程
# 为特定 Metricset 设置独立频率
- module: system
metricsets: ["filesystem"]
period: 1m # 每分钟采集文件系统
- module: system
metricsets: ["uptime"]
period: 15m # 每 15 分钟采集运行时长
权限与部署要点:
- Root 权限需求:
system模块需 root 权限访问系统指标 - 配置文件所有权:必须由运行用户持有,否则报错
config file must be owned by the beat userchown metricbeat_user:metricbeat_group /etc/metricbeat/metricbeat.yml
5 )Kibana 数据可视化与诊断
数据入库后,通过 Kibana 进行聚合分析:
- 索引模板自动加载:
./metricbeat setup --template # 导入预定义字段映射 - Discover 界面诊断:
- 按
metricset.name过滤(如system.network) - 关键字段:
host.name(主机名)、system.network.in.bytes(入站流量)
- 按
- Dashboard 示例:
- CPU 负载趋势:聚合多主机
system.cpu.user.pct - 内存消耗 Top 进程:按
system.process.memory.rss.bytes排序
- CPU 负载趋势:聚合多主机
MetricBeat 数据流架构
1 ) 数据结构标准化
采集的 Event 数据遵循统一格式:
{
"@timestamp": "2023-10-10T14:35:00Z",
"beat": {
"name": "server-01",
"version": "8.9.0"
},
"metricset": {
"name": "cpu",
"module": "system",
"rtt": 153 // 采集耗时(微秒)
},
"system": {
"cpu": {
"user": 45.2,
"system": 12.1
}
}
}
2 ) 配置核心要素
metricbeat.yml 关键配置项:
output.elasticsearch:
hosts: ["http://localhost:9200"]
metricbeat.modules:
- module: system
metricsets: ["cpu", "memory", "network"]
period: 10s
processes: [".*"] # 监控所有进程
- module: redis
metricsets: ["info"]
hosts: ["redis://localhost:6379"]
数据可视化与 Kibana 集成
MetricBeat 自动推送索引模板至 Elasticsearch:
./metricbeat setup --index-management # 手动初始化模板
Kibana 数据分析操作:
- 进入
Discover视图,索引模式选择metricbeat-* - 筛选字段:
metricset.name: system.cpu→ CPU 使用率趋势system.network.name: eth0→ 网卡流量统计
- 关键指标可视化:
- CPU Load:折线图展示 user/sys 占比
- Memory Usage:堆叠面积图显示 used/cached
- Disk IO:柱状图对比读写吞吐量
注:开箱即用仪表盘需导入 metricbeat 预置模板
System 模块监控操作系统
1 ) 权限与配置文件处理
MetricBeat 需 root 权限采集系统指标,必须修正配置归属权:
修改配置文件所有者
chown root:root metricbeat.yml
chmod 600 metricbeat.yml
启动服务(需root)
./metricbeat -e
2 ) Kibana 数据验证流程
-
导入预置仪表盘
./metricbeat setup --dashboards -
Kibana Discover 过滤数据
metricset.name: network # 查看网卡流量 host.name: "web-server-01" -
核心监控字段
字段路径 含义 system.cpu.user.pct用户空间CPU使用率 system.memory.used.pct内存使用率 system.network.in.bytes网卡入流量
工程示例:1
1 ) 方案 1:基础数据写入服务
// src/elastic/elastic.service.ts
import { Injectable } from '@nestjs/common';
import { Client } from '@elastic/elasticsearch';
@Injectable()
export class ElasticService {
private readonly client: Client;
constructor() {
this.client = new Client({
node: 'http://localhost:9200',
auth: { username: 'elastic', password: 'changeme' }
});
}
async indexMetricData(index: string, body: any) {
return this.client.index({
index,
body,
refresh: true // 实时可见性
});
}
}
// src/metrics/metrics.controller.ts
import { Controller, Post } from '@nestjs/common';
import { ElasticService } from '../elastic/elastic.service';
@Controller('metrics')
export class MetricsController {
constructor(private readonly elasticService: ElasticService) {}
@Post('system')
async receiveSystemMetrics() {
const metricData = {
timestamp: new Date().toISOString(),
cpu_load: 1.8,
memory_used: 75.2
};
await this.elasticService.indexMetricData('system-metrics', metricData);
return { status: 'Metric stored' };
}
}
2 ) 方案 2:安全增强与性能优化
Elasticsearch 配置:
elasticsearch.yml
xpack.security.enabled: true
cluster.name: prod-monitoring
thread_pool.write.queue_size: 1000 # 高吞吐场景
NestJS 连接池管理:
// 扩展 ElasticService
import { ConnectionPool } from '@elastic/elasticsearch';
async bulkIndex(metrics: any[]) {
const body = metrics.flatMap(metric => [
{ index: { _index: 'system-metrics' } },
metric
]);
return this.client.bulk({
body,
filter_path: 'items.*.error' // 仅返回错误信息
});
}
3 ) 方案 3:生产环境高可用架构
组件拓扑:
MetricBeat Agents → Kafka → NestJS Ingestion Service → Elasticsearch Cluster
↘ Dead Letter Queue (RabbitMQ)
NestJS 消费者服务:
// src/kafka/kafka.consumer.ts
import { Kafka, Consumer } from 'kafkajs';
@Injectable()
export class KafkaConsumer {
private consumer: Consumer;
constructor(private elasticService: ElasticService) {
const kafka = new Kafka({ brokers: ['kafka1:9092'] });
this.consumer = kafka.consumer({ groupId: 'metric-group' });
}
async start() {
await this.consumer.connect();
await this.consumer.subscribe({ topic: 'metricbeat-data' });
this.consumer.run({
eachMessage: async ({ message }) => {
try {
const metric = JSON.parse(message.value.toString());
await this.elasticService.indexMetricData(metric);
} catch (error) {
// 投递至死信队列
this.sendToDLQ(message);
}
}
});
}
}
关键配置参数:
| 组件 | 配置项 | 推荐值 | 作用 |
|---|---|---|---|
| Elasticsearch | indices.query.bool.max_clause_count | 8192 | 提升复杂查询能力 |
| MetricBeat | queue.mem.events | 4096 | 内存队列缓冲 |
| NestJS | httpAdapter.setTimeout | 30000 | 防止ES超时阻断 |
工程示例:2
以下提供三种完整工程方案,覆盖 NestJS 集成、Elasticsearch 配置优化及自定义监控开发
1 ) 方案 1:NestJS 服务集成 Metricbeat 数据消费
场景:在 NestJS 后端服务中查询 Elasticsearch 存储的指标数据,生成监控报告
// src/metrics/metrics.service.ts
import { Injectable } from '@nestjs/common';
import { ElasticsearchService } from '@nestjs/elasticsearch';
@Injectable()
export class MetricsService {
constructor(private readonly esService: ElasticsearchService) {}
async getCpuUsage(host: string): Promise<any> {
const response = await this.esService.search({
index: 'metricbeat-*', // 动态匹配索引
body: {
query: {
bool: {
filter: [
{ term: { 'metricset.name': 'cpu' } },
{ term: { 'host.name': host } }
],
must: { range: { '@timestamp': { gte: 'now-1h' } } }
}
},
aggs: {
avg_cpu: { avg: { field: 'system.cpu.user.pct' } }
}
}
});
return response.aggregations.avg_cpu.value;
}
}
// 调用示例:返回主机 "web-server-01" 的 CPU 平均使用率
// this.metricsService.getCpuUsage('web-server-01');
2 ) 方案 2:Elasticsearch 索引生命周期管理(ILM)
场景:自动滚动删除旧监控数据,避免存储爆炸。
metricbeat.yml 追加配置
setup.ilm:
policy_name: metricbeat_policy
rollover_alias: metricbeat
创建 ILM 策略(通过 Kibana Dev Tools)
PUT _ilm/policy/metricbeat_policy
{
"policy": {
"phases": {
"hot": {
"actions": {
"rollover": { "max_size": "50GB", "max_age": "30d" }
}
},
"delete": {
"min_age": "90d",
"actions": { "delete": {} }
}
}
}
}
3 ) 方案 3:自定义 Metricset 开发(Redis 键空间监控)
场景:扩展 Redis 模块,增加高频键空间扫描。
// metricbeat/module/redis/keyspace/keyspace.go
package keyspace
import (
"github.com/elastic/beats/v7/metricbeat/mb"
"github.com/go-redis/redis/v8"
)
func init() {
mb.Registry.MustAddMetricSet("redis", "keyspace", New,
mb.DefaultMetricSet(),
mb.WithHostParser(parseHost),
)
}
type MetricSet struct {
mb.BaseMetricSet
client *redis.Client
}
func New(base mb.BaseMetricSet) (mb.MetricSet, error) {
cfg := struct{ Hosts []string `config:"hosts"` }{}
base.Module().UnpackConfig(&cfg)
client := redis.NewClient(&redis.Options{Addr: cfg.Hosts[0]})
return &MetricSet{BaseMetricSet: base, client: client}, nil
}
func (m *MetricSet) Fetch(reporter mb.ReporterV2) {
// 执行自定义命令:扫描键空间统计
cmd := m.client.Info(ctx, "keyspace")
result, err := cmd.Result()
if err != nil {
reporter.Error(err)
return
}
// 解析并发送事件
reporter.Event(mb.Event{
MetricSetFields: common.MapStr{
"keys": parseKeyspaceStats(result), // 自定义解析函数
},
})
}
配置启用自定义 Metricset:
- module: redis
metricsets: ["info", "keyspace"] # 添加自定义 keyspace
hosts: ["redis://localhost:6379"]
period: 1s # 高频采集
工程示例:3
1 )基础监控告警服务
// monitoring.service.ts
import { Injectable } from '@nestjs/common';
import { ElasticsearchService } from '@nestjs/elasticsearch';
@Injectable()
export class MonitoringService {
constructor(private readonly esService: ElasticsearchService) {}
async fetchCpuMetrics(hostname: string): Promise<any> {
const { body } = await this.esService.search({
index: 'metricbeat-*',
body: {
query: {
bool: {
filter: [
{ term: { 'metricset.name': 'cpu' } },
{ term: { 'host.name': hostname } },
{ range: { '@timestamp': { gte: 'now-1h' } } }
]
}
},
aggs: {
avg_cpu: { avg: { field: 'system.cpu.user.pct' } }
}
}
});
return body.aggregations.avg_cpu.value;
}
}
2 ) 动态阈值告警引擎
// alert.engine.ts
import { ElasticsearchService } from '@nestjs/elasticsearch';
export class AlertEngine {
constructor(private es: ElasticsearchService) {}
async checkMemoryThreshold(threshold: number): Promise<string[]> {
const query = {
index: 'metricbeat-*',
size: 0,
body: {
query: {
bool: {
filter: [
{ term: { 'metricset.name': 'memory' } },
{ range: { '@timestamp': { gte: 'now-5m' } } }
]
}
},
aggs: {
high_mem_hosts: {
terms: { field: 'host.name', size: 10 },
aggs: { max_mem: { max: { field: 'system.memory.used.pct' } } }
}
}
}
};
const { body } = await this.es.search(query);
return body.aggregations.high_mem_hosts.buckets
.filter(b => b.max_mem.value > threshold)
.map(b => b.key);
}
}
3 ) 集群状态看板(ES原生API)
获取集群节点CPU负载TOP5
GET metricbeat-*/_search
{
"size": 0,
"query": { "term": { "metricset.name": "cpu" } },
"aggs": {
"nodes": {
"terms": { "field": "beat.name", "size": 5 },
"aggs": { "avg_load": { "avg": { "field": "system.cpu.load.5" } } }
}
}
}
高级配置技巧
1 ) MetricSet 定制策略
- module: system
metricsets:
- name: cpu
period: 5s # 高频采集CPU
- name: filesystem
period: 5m # 低频采集磁盘
filters: # 只监控根分区
- drop_event:
when:
not:
equals:
system.filesystem.mount_point: "/"
2 ) 容器化部署要点
Dockerfile 示例
FROM docker.elastic.co/beats/metricbeat:8.9.0
COPY metricbeat.docker.yml /usr/share/metricbeat/metricbeat.yml
USER root # 容器内需root权限
CMD ["--strict.perms=false"] # 关闭严格权限检查
常见问题解决方案
| 问题现象 | 原因 | 解决方案 |
|---|---|---|
config file must be owned by beat user | 配置文件权限错误 | chown root metricbeat.yml |
Exiting: data path already locked | 多实例共享数据目录 | 设置 path.data: /unique-path |
Connection to ES failed | 网络/证书问题 | 检查 output.elasticsearch.ssl 配置 |
最佳实践:生产环境务必启用 ILM(索引生命周期管理)
setup.ilm.enabled: true
setup.ilm.rollover_alias: "metricbeat"
权限错误处理:
ERROR: metricbeat.yml must be owned by the beat user
解决方案:
sudo chown root:root metricbeat.yml # 所有权变更
sudo setcap cap_net_raw=ep ./metricbeat # 网络采集权限
数据未入库检查:
- 验证 ES 连接:
curl http://localhost:9200/_cat/health - 查看 MetricBeat 日志:
journalctl -u metricbeat -n 50 - 测试模板加载:
./metricbeat test output
性能调优参数:
metricbeat.yml 优化
queue.spool:
file:
path: "/var/spool/metricbeat"
max_size: 1GB
processors:
- drop_event:
when:
less_than:
cpu.system.pct: 0.1 # 过滤低负载事件
关键优化与补充知识点
1 ) 性能调优:
- 调整
queue.mem.events避免内存溢出 - 使用
loadbalance: true在多个 Elasticsearch 节点间分流写入
2 ) 安全加固:
- Elasticsearch 启用 TLS:在
output.elasticsearch中配置protocol: "https" - Metricbeat 启用内置认证:
xpack.security.enabled: true
3 ) Kubernetes 集成:
metricbeat.autodiscover:
providers:
- type: kubernetes
templates:
- condition: contains("redis", "${data.container.image}")
config:
- module: redis
hosts: "${data.host}:6379"
metricsets: ["info"]
4 ) 与 Zabbix 对比优势:
- 轻量级部署:无需独立 Server/Agent 分层架构
- 一体化生态:数据直接入 Elasticsearch,无缝衔接 Kibana 可视化
- 扩展便捷:支持自定义 Module 开发(Go 语言)
进阶:自定义 Module 开发
步骤分解:
- 创建 Python 模块(需 Golang 基础):
mymodule.yml - module: custom_app metricsets: ["health"] period: 5s - 实现数据采集逻辑:
// module/customapp/health.go func (m *MetricSet) Fetch() ([]common.MapStr, error) { resp, _ := http.Get("http://app:8080/health") data := map[string]interface{}{} json.NewDecoder(resp.Body).Decode(&data) return []common.MapStr{"status": data["status"]}, nil } - 编译并部署:
make # 生成 metricbeat 二进制 ./metricbeat -e -d "customapp" # 调试模式
扩展应用场景
1 ) Kubernetes 监控
metricbeat.modules:
- module: kubernetes
metricsets: ["node", "pod", "system"]
period: 30s
2 ) 自定义 MetricSet 开发
// 示例:采集 Nginx 活跃连接数
func (m *NginxMetricSet) Fetch() ([]common.MapStr, error) {
conn, _ := net.Dial("tcp", m.host)
conn.Write([]byte("GET /status HTTP/1.1\r\n\r\n"))
data, _ := io.ReadAll(conn)
return eventMapping(data), nil
}
与传统方案对比与选型建议
MetricBeat vs Zabbix:
| 维度 | MetricBeat | Zabbix |
|---|---|---|
| 部署复杂度 | ⭐(单二进制文件) | ⭐⭐⭐(需Server/Agent) |
| 扩展性 | ⭐⭐⭐(Go模块化开发) | ⭐⭐(自定义脚本) |
| 数据粒度 | 秒级采集 | 分钟级 |
| 资源占用 | <50MB 内存 | >200MB 内存 |
| 云原生支持 | 原生K8s DaemonSet集成 | 需Operator辅助 |
选型指南:
- 选择 MetricBeat 当需:
- 快速监控云主机/容器(开箱即用Docker/Kubernetes模块)
- 与Elastic Stack深度集成(Kibana预置仪表盘)
- 低资源环境部署(ARM设备支持)
- 选择 Zabbix 当需:
- 传统网络设备SNMP监控
- 无Elasticsearch基础设施的场景
关键概念说明:
- Elasticsearch:分布式搜索分析引擎,用于存储和查询指标数据
- NestJS:基于TypeScript的Node.js框架,提供依赖注入和模块化架构
- DaemonSet:Kubernetes中在每节点运行Pod副本的控制器
- 死信队列(DLQ):存储处理失败消息的备份队列,防止数据丢失
总结
Metricbeat 通过 Module/Metricset 两级抽象,实现了监控任务的模块化与精细化控制。其核心价值在于:
- 开箱即用:覆盖操作系统、数据库、容器等 50+ 官方 Module
- 灵活扩展:支持自定义 Metricset 开发与独立频率配置
- 生态集成:与 Elastic Stack 深度协同,替代传统监控工具(如 Zabbix)的复杂架构
通过本文的NestJS 消费示例、ES 索引管理及自定义监控开发三方案,可快速构建企业级监控体系。初学者建议从system模块入手,逐步扩展至业务中间件监控。
646

被折叠的 条评论
为什么被折叠?



