ELK Stack — Metricbeat and Heartbeat
Metricbeat Overview
Metricbeat is a lightweight shipper that collects system-level and service-level metrics from your servers and ships them to Elasticsearch or Logstash. It provides out-of-the-box modules for operating system metrics, Docker, Kubernetes, databases, web servers, and more.
┌─────────────────────────────────────────────────────────┐
│ Your Server │
│ │
│ ┌────────────────────────────────────────────────────┐ │
│ │ Metricbeat │ │
│ │ │ │
│ │ ┌────────────┐ ┌────────────┐ ┌──────────────┐ │ │
│ │ │ System │ │ Docker │ │ Kubernetes │ │ │
│ │ │ Module │ │ Module │ │ Module │ │ │
│ │ │ │ │ │ │ │ │ │
│ │ │ ● CPU │ │ ● container│ │ ● pod │ │ │
│ │ │ ● Memory │ │ ● cpu │ │ ● node │ │ │
│ │ │ ● Disk │ │ ● memory │ │ ● container │ │ │
│ │ │ ● Network │ │ ● diskio │ │ ● volume │ │ │
│ │ │ ● Process │ │ ● network │ │ ● event │ │ │
│ │ │ ● Filesystem│ │ ● info │ │ ● deployment │ │ │
│ │ └─────┬───────┘ └─────┬─────┘ └──────┬───────┘ │ │
│ │ │ │ │ │ │
│ │ └────────────────┼────────────────┘ │ │
│ │ │ │ │
│ │ ▼ │ │
│ │ ┌──────────────────┐ │ │
│ │ │ Elasticsearch / │ │ │
│ │ │ Logstash Output │ │ │
│ │ └──────────────────┘ │ │
│ └────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────┘
Metricbeat Installation
# Debian/Ubuntu
curl -L -O https://artifacts.elastic.co/downloads/beats/metricbeat/metricbeat-8.17.0-amd64.deb
sudo dpkg -i metricbeat-8.17.0-amd64.deb
# RHEL/CentOS
curl -L -O https://artifacts.elastic.co/downloads/beats/metricbeat/metricbeat-8.17.0-x86_64.rpm
sudo rpm -vi metricbeat-8.17.0-x86_64.rpm
# macOS
brew install elastic/tap/metricbeat-full
# Docker
docker pull docker.elastic.co/beats/metricbeat:8.17.0
Complete metricbeat.yml Configuration
# ========================= Metricbeat Modules ============================
metricbeat.config.modules:
path: ${path.config}/modules.d/*.yml
reload.enabled: true
reload.period: 10s
# ========================= System Module =================================
metricbeat.modules:
- module: system
metricsets:
- cpu
- memory
- network
- process
- process_summary
- filesystem
- diskio
- load
- socket_summary
- uptime
enabled: true
period: 10s
# Monitor top N processes by CPU and memory
processes: ['.*']
process.include_top_n:
by_cpu: 10
by_memory: 10
cpu.metrics: ["percentages", "normalized_percentages"]
core.metrics: ["percentages"]
# ========================= Elasticsearch Output ==========================
output.elasticsearch:
hosts: ["https://es-node-1:9200"]
username: "metricbeat_writer"
password: "${ES_PASSWORD}"
ssl:
enabled: true
certificate_authorities: ["/etc/metricbeat/certs/ca.crt"]
# ============================== Kibana ===================================
setup.kibana:
host: "https://kibana-host:5601"
# ============================= Dashboards ================================
setup.dashboards.enabled: true
# ============================== Processors ===============================
processors:
- add_host_metadata:
when.not.contains.tags: forwarded
- add_cloud_metadata: ~
# ============================== Logging ==================================
logging.level: info
logging.to_files: true
logging.files:
path: /var/log/metricbeat
name: metricbeat
keepfiles: 7
permissions: 0644
System Module Metricsets
The system module provides granular control over which metrics to collect:
| Metricset | Metrics collected |
|---|---|
cpu |
CPU usage (user, system, idle, iowait, IRQ, steal) per core |
memory |
Total, used, free, cached, swap, hugepages |
load |
1-min, 5-min, 15-min load averages |
network |
Bytes in/out, packets in/out, errors, drops per interface |
diskio |
Read/write bytes, IOPS, queue length per device |
filesystem |
Total, used, free, usage percentage per mount point |
process |
CPU, memory, file descriptors, state per process |
process_summary |
Count of processes by state (running, sleeping, zombie) |
socket_summary |
Open TCP/UDP sockets count |
uptime |
System uptime duration |
Docker Module
# /etc/metricbeat/modules.d/docker.yml
- module: docker
metricsets:
- container
- cpu
- diskio
- healthcheck
- info
- memory
- network
hosts: ["unix:///var/run/docker.sock"]
period: 10s
enabled: true
# Filter by container labels
# labels.dedot: true
Kubernetes Module
# /etc/metricbeat/modules.d/kubernetes.yml
- module: kubernetes
metricsets:
- node
- system
- pod
- container
- volume
- event
period: 10s
host: ${NODE_NAME}
hosts: ["https://${NODE_NAME}:10250"]
bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token
ssl.verification_mode: none
add_metadata: true
Heartbeat Overview
Heartbeat is a lightweight daemon that periodically checks whether your services are reachable. It supports HTTP, TCP, and ICMP monitors. Think of it as your uptime monitoring agent — deployed externally to your services to verify they are healthy.
Unlike Metricbeat (which runs on the server), Heartbeat is typically deployed outside the monitored services to simulate real user access patterns.
Heartbeat Installation
# Debian/Ubuntu
curl -L -O https://artifacts.elastic.co/downloads/beats/heartbeat/heartbeat-8.17.0-amd64.deb
sudo dpkg -i heartbeat-8.17.0-amd64.deb
# RHEL/CentOS
curl -L -O https://artifacts.elastic.co/downloads/beats/heartbeat/heartbeat-8.17.0-x86_64.rpm
sudo rpm -vi heartbeat-8.17.0-x86_64.rpm
Complete heartbeat.yml Configuration
# =========================== Heartbeat Monitors ==========================
heartbeat.monitors:
# --- HTTP Monitor: check web applications ---
- type: http
id: web-app-monitor
name: "Production Web App"
enabled: true
urls:
- "https://myapp.example.com"
- "https://api.example.com/health"
schedule: '@every 30s'
timeout: 10s
# Check response body
check.response:
status: [200]
body:
- "healthy"
- "ok"
# Check response headers
check.response.headers:
Content-Type: "application/json"
# TLS settings
ssl:
verification_mode: full
tags: ["web", "production"]
# --- HTTP Monitor: check Elasticsearch cluster ---
- type: http
id: es-cluster-health
name: "Elasticsearch Cluster"
enabled: true
urls:
- "https://es-node-1:9200/_cluster/health"
schedule: '@every 60s'
timeout: 10s
username: "heartbeat_reader"
password: "${ES_MONITOR_PASSWORD}"
check.response:
status: [200]
json:
- description: "Cluster status is green or yellow"
condition:
contains:
status: "green"
ssl:
certificate_authorities: ["/etc/heartbeat/certs/ca.crt"]
# --- TCP Monitor: check database ports ---
- type: tcp
id: postgres-monitor
name: "PostgreSQL"
enabled: true
hosts: ["db-primary.internal:5432", "db-replica.internal:5432"]
schedule: '@every 30s'
timeout: 5s
tags: ["database", "postgresql"]
- type: tcp
id: redis-monitor
name: "Redis Cache"
enabled: true
hosts: ["redis.internal:6379"]
schedule: '@every 15s'
timeout: 3s
tags: ["cache", "redis"]
# --- ICMP Monitor: check host reachability ---
- type: icmp
id: host-ping
name: "Server Ping Check"
enabled: true
hosts: ["10.0.1.10", "10.0.1.11", "10.0.1.12"]
schedule: '@every 60s'
timeout: 5s
wait: 1s
tags: ["infrastructure", "ping"]
# ========================= Elasticsearch Output ==========================
output.elasticsearch:
hosts: ["https://es-node-1:9200"]
username: "heartbeat_writer"
password: "${ES_PASSWORD}"
ssl:
enabled: true
certificate_authorities: ["/etc/heartbeat/certs/ca.crt"]
# ============================== Kibana ===================================
setup.kibana:
host: "https://kibana-host:5601"
# ============================= Dashboards ================================
setup.dashboards.enabled: true
# ============================== Processors ===============================
processors:
- add_host_metadata: ~
- add_cloud_metadata: ~
# ============================== Logging ==================================
logging.level: info
logging.to_files: true
logging.files:
path: /var/log/heartbeat
name: heartbeat
keepfiles: 7
Monitor Types Comparison
| Monitor | Protocol | Use Case | Example |
|---|---|---|---|
http |
HTTP/HTTPS | Web apps, APIs, health endpoints | Check https://api.example.com/health returns 200 |
tcp |
TCP | Databases, message brokers, any TCP service | Verify PostgreSQL port 5432 is open |
icmp |
ICMP (ping) | Host reachability, network connectivity | Ping servers on the internal network |
Uptime Dashboard
After loading dashboards (heartbeat setup --dashboards), open Kibana and navigate to Uptime (or Observability → Uptime) to see:
- Monitor status — up/down for each configured monitor
- Availability percentage — over configurable time windows
- Response time trends — latency graphs for HTTP and TCP monitors
- Certificate expiration — TLS certificate monitoring for HTTPS endpoints
- Alerts — configure alerts when monitors go down
Starting and Managing Metricbeat and Heartbeat
# --- Metricbeat ---
# Test config
metricbeat test config -e
metricbeat test output
# Start
sudo systemctl start metricbeat
sudo systemctl enable metricbeat
# --- Heartbeat ---
# Test config
heartbeat test config -e
heartbeat test output
# Start
sudo systemctl start heartbeat-elastic
sudo systemctl enable heartbeat-elastic
# --- Load dashboards ---
metricbeat setup --dashboards
heartbeat setup --dashboards
Quick Reference
| Task | Metricbeat | Heartbeat |
|---|---|---|
| Config file | /etc/metricbeat/metricbeat.yml |
/etc/heartbeat/heartbeat.yml |
| Modules dir | /etc/metricbeat/modules.d/ |
— |
| Enable module | metricbeat modules enable docker |
— |
| Test config | metricbeat test config -e |
heartbeat test config -e |
| Test output | metricbeat test output |
heartbeat test output |
| Start service | systemctl start metricbeat |
systemctl start heartbeat-elastic |
| Load dashboards | metricbeat setup --dashboards |
heartbeat setup --dashboards |
| Default period | 10s |
@every 30s |
| Typical memory | ~30-50 MB | ~20-30 MB |
Next: Processors — enrich, filter, and transform data at the edge before shipping.