The cluster can't call you. Monitoring can.
Riya stops one DataNode on the lab cluster on purpose and starts a tiny monitor that reads the NameNode's metrics. She expects an alert within a minute. It arrives after 296 seconds. Later she raises the replication of one file, puts the DR NameNode into safe mode and starts two big jobs: each time the monitor says something. At the end everything is fixed, yet one alert keeps firing: 7 under-replicated blocks that nobody broke on purpose.
Five minutes for a dead DataNode? The heartbeat is every 3 seconds!
The DataNode becomes stale after 30 seconds without a heartbeat. But the NameNode recounts stale nodes in a background check that runs every 5 minutes by default, so the metric we read lagged. Knowing how late your numbers are is part of monitoring.
And the 7 blocks at the end? We cleaned up everything.
Job staging files. Every job writes its jar and split list with replication 10, and our cluster has only 3 DataNodes. Jobs we killed left those files behind. A real alert, a useless one, and it will page someone at 3 AM until we fix the cause. Today we build the monitor, break the cluster on purpose, and learn which alerts deserve to wake a human.
Monitoring and alerting for Hadoop
Monitoring is the continuous collection of metrics, logs and health checks from every daemon and host of a cluster, stored as time series and shown on dashboards. Alerting evaluates rules over those metrics (a condition, a threshold and a duration) and notifies people or systems when a rule fires, with a severity and a runbook. Hadoop daemons expose metrics through the metrics2 framework, readable over HTTP as JSON at /jmx (NameNode, DataNode, ResourceManager, NodeManager, JobHistory Server) and through the YARN REST API; they can also push to sinks. Collectors such as Prometheus (with the JMX exporter), Ambari Metrics or Cloudera Manager scrape these endpoints, and alert managers route notifications to on-call tools. Good alerting targets symptoms that threaten data or service-level objectives (SLOs), uses durations to suppress noise, and accounts for the delay with which each metric is updated.
Every Hadoop daemon publishes numbers about itself on a web page. A collector reads them every few seconds, a rule says “if this number is bad for this long, tell someone”, and the message goes to the person on call with a note on what to do.
Words you'll meet in this lesson
UnderReplicatedBlocks=1.http://namenode:9870/jmx: every metric of a daemon as JSON.From our lab (two clusters, one monitor)
| Healthy baseline | prod: live=3 stale=0 used=0.6% under=0 files=1658, 3 NodeManagers; dr: live=3, safemode=False |
|---|---|
| DataNode stopped | stale alert after 296 s; live stayed 3 and dead 0 (dead needs 10 min 30 s) |
| Replication 4 on 3 DNs | “WARN prod: 1 under-replicated blocks” at the next check |
| Safe mode on DR | “CRIT dr: NameNode in safe mode (read-only)” immediately |
| Two big jobs | pending=1 with memory only 50% used: the queue's ApplicationMaster limit blocked it (Lesson 12.6) |
| After the fixes | stale cleared 246 s after restart; 7 under-replicated blocks left: staging files with replication 10 |
Monitoring at three levels
Beginner A hospital ward
- Every patient is connected to a monitor that shows heart rate and oxygen: those are metrics.
- The machine beeps when oxygen stays below 90% for a while, not for one bad reading: that is an alert rule with a duration.
- A nurse at the desk sees all beds on one screen: the dashboard. The doctor on call is phoned only for serious beeps: severity.
- A beeping machine with a loose sensor is a false positive. Too many of those and nurses stop listening.
Intermediate What to watch on a Hadoop cluster
- HDFS: capacity used %, live/dead/stale DataNodes, missing and corrupt blocks (data at risk), under-replicated blocks (safety margin shrinking), safe mode, NameNode heap and GC pauses, RPC queue time, time since last checkpoint.
- YARN: active/unhealthy/lost NodeManagers, pending applications, queue usage vs capacity, ApplicationMaster failures, containers killed for memory.
- Jobs: did the nightly job finish before its deadline? Job duration trends, failed attempts.
- Hosts: disk full or failing, memory, swap, network errors, clock drift (Kerberos breaks above 5 minutes).
Advanced Designing alerts people trust
- Alert on symptoms that threaten data or an SLO (missing blocks, job late, safe mode), not on every cause; causes go on dashboards.
- Use durations (“for 5 minutes”) and severities; every CRIT has a runbook and an owner.
- Know each metric's lag: stale nodes were recounted every 5 minutes in our lab, and JMX counters such as FilesTotal update with a delay (Lesson 7.5).
- Fix the source of noise: our 7 staging-file blocks need
mapreduce.client.submit.file.replication≤ number of DataNodes, or regular cleanup, not a muted alert. - Add black-box checks: a canary job that writes, reads and runs a tiny MapReduce job proves the whole path works, which no single metric can.
Exam tip: For “How do you monitor a Hadoop cluster?”, name the source (JMX/metrics2 over HTTP, YARN REST), a collector (Prometheus/Ambari/Cloudera Manager), five key metrics (missing blocks, dead DataNodes, capacity %, safe mode, unhealthy NodeManagers) and two alert-design rules (duration, severity + runbook).
Signals, sources and severities
| Signal | Where it comes from | Typical rule | Severity |
|---|---|---|---|
| MissingBlocks, CorruptBlocks | NameNode JMX (FSNamesystem) | > 0 | CRIT: data at risk |
| NumDeadDataNodes | NameNode JMX | > 0 for 5 min | CRIT if several, WARN if one |
| NumStaleDataNodes | NameNode JMX | > 0 for 5 min | WARN (early sign) |
| UnderReplicatedBlocks | NameNode JMX | growing for 30 min | WARN |
| Capacity used % | NameNode JMX | > 80% WARN, > 90% CRIT | WARN / CRIT |
| Safe mode | NameNode JMX (Safemode) | on, outside maintenance | CRIT: writes fail |
| Unhealthy / lost NodeManagers | RM REST /ws/v1/cluster/metrics | > 0 | WARN |
| Pending apps | RM REST | > 0 for 10 min | WARN |
| Job SLA | scheduler / canary | not done by 05:30 | CRIT |
Architecture at a glance
Daemons publish, a collector scrapes, rules decide, people get told. The dashboard and the canary job sit beside the main path.
Where metrics come from
JMX over HTTP
Every daemon serves /jmx as JSON. Filter with ?qry=Hadoop:service=NameNode,name=FSNamesystemState. Our monitor.py reads only this.
YARN REST
/ws/v1/cluster/metrics, /apps, /nodes, /scheduler on the ResourceManager (Module 11).
metrics2 sinks
Daemons can push metrics to files, Ganglia or other systems via hadoop-metrics2.properties.
Prometheus + Grafana
The JMX exporter (a Java agent) turns JMX into Prometheus metrics; Alertmanager routes alerts. Common in self-managed clusters.
open sourceAmbari / Cloudera Manager
Cluster managers that collect metrics, show dashboards and ship ready-made alert rules.
vendorLogs
Log-based alerts: a pattern such as “java.lang.OutOfMemoryError” in a NameNode log (Lesson 11.5).
textAnimated example: Diwali sale night
- 20:00: the sale opens and traffic jumps sixfold. All dashboards are green and the runbook is ready.
- 21:40: a WARN fires at 81% disk use. The runbook says to clear expired temporary data; usage drops to 74%.
- 23:10: three DataNodes in one rack go stale. The rule waits five minutes to be sure, then pages the network team.
- 23:40: under-replicated blocks jump, which is expected after a rack problem. Missing blocks stay at zero, so it is a WARN.
- 03:00: no metric is red, but the canary job takes four times longer than normal: a full queue. Ad-hoc jobs are paused.
- 06:00: the sale report is on time. The morning review adds a disk-growth forecast alert. (Illustrative scenario.)
The best first alert for any cluster is MissingBlocks > 0. It almost never fires falsely, and when it fires, data is unreadable right now.
Build a monitor, then break the cluster
Our monitor is about 60 lines of Python (monitor.py, in “Run it on your PC”). It runs on a lab8 worker that can reach both clusters: prod (the Module 8 lab) and dr (the federation lab from Lesson 7.2).
Read the metrics
The baseline. Everything a rule needs is in two JSON documents per cluster: no agents, no extra software.curl -s 'http://namenode:9870/jmx?qry=Hadoop:service=NameNode,name=FSNamesystemState' curl -s http://resourcemanager:8088/ws/v1/cluster/metrics10:21:11 prod live=3 dead=0 stale=0 used=0.6 under=0 missing=0 files=1658 safemode=False nodes=3 unhealthy=0 lost=0 pending=0 running=0 mem=0 10:21:11 dr live=3 dead=0 stale=0 used=0.1 under=0 missing=0 files=15 safemode=FalseStop a DataNode and wait for the alert
Stale after 30 s, but the stale count is refreshed on the NameNode's heartbeat check (every 5 minutes by default), so our alert came almost 5 minutes late. Note thatdocker exec lab8-worker2-1 hdfs --daemon stop datanode(the alert appeared 296 s after the DataNode stopped) 10:26:08 prod live=3 dead=0 stale=1 used=0.6 under=0 ... 10:26:08 ALERT WARN prod: 1 stale DataNode(s) (no heartbeat for 30 s)livestill says 3: the node is declared dead only after 10 min 30 s.Ask for more replicas than the cluster can give
This one shows up at the next check: the block's target is 4 copies and only 3 DataNodes exist (2 alive).hdfs dfs -setrep 4 /user/hadoop/data/menu.csvReplication 4 set: /user/hadoop/data/menu.csv 10:26:16 ALERT WARN prod: 1 under-replicated blocksSafe mode on the DR cluster
CRIT, because every write to that cluster now fails (Lesson 5.6). The same rule covers both clusters.docker exec lab72-nn-canteen-1 hdfs dfsadmin -safemode enterSafe mode is ON 10:26:17 dr live=3 ... safemode=True 10:26:17 ALERT CRIT dr: NameNode in safe mode (read-only)Fill YARN with two big jobs
10:26:52 prod live=3 dead=0 stale=1 used=0.6 under=8 missing=0 files=1675 ... pending=1 running=1 mem=50 10:26:52 ALERT WARN prod: 8 under-replicated blocks 10:26:52 ALERT WARN prod: 1 app(s) waiting to start (cluster memory 50% used)Two surprises. The second job waited while half the memory was free: the queue's ApplicationMaster limit stopped it (Lesson 12.6). And under-replicated blocks jumped from 1 to 8: each job writes itsjob.jarandjob.splitwith replication 10.Fix everything and look again
(stale cleared 246 s after the restart) 10:31:08 prod live=3 dead=0 stale=0 used=0.6 under=7 missing=0 files=1680 ... 10:31:08 ALERT WARN prod: 7 under-replicated blocksThe jobs were killed, safe mode left, replication reset and the DataNode restarted. Seven blocks still alert: staging files left by the killed jobs, wanting 10 copies forever. Before we cleaned up at the start, the same cause showed 38. Fix the cause (mapreduce.client.submit.file.replication=3, clean old staging folders), don't mute the alert.
Never silence an alert you don't understand. Our “7 under-replicated blocks” was harmless, but the same alert on a real cluster can mean a disk is slowly failing.
Six checks of our monitor
The real monitor output on the left, what happened inside the cluster on the right.
- The healthy baseline: no alerts on either cluster.
- A DataNode is stopped; the stale alert arrives 296 s later.
- Replication 4 on a 3-DataNode cluster: one under-replicated block.
- The DR NameNode enters safe mode: a critical alert.
- Two big jobs: one waits with half the memory free; staging files add under-replicated blocks.
- After every fix, 7 under-replicated blocks still alert.
- The monitor sends two HTTP requests per cluster and applies its rules.
- DataNode 2's process is gone. Its heartbeats stop, but the stale count updates only on the NameNode's periodic check.
- menu.csv now wants 4 replicas; the cluster cannot place a fourth.
- The DR NameNode is read-only in safe mode, so writes there fail.
- The queue's AM limit holds job 2 in ACCEPTED; job staging files ask for 10 replicas.
- DataNode 2 is back, but the killed jobs' staging files keep 7 blocks under-replicated.
Monitoring at work
1. Bank data lake: data-loss alerts first
A bank's platform team pages only for missing or corrupt blocks, safe mode and the regulatory report SLA; everything else goes to a daytime queue so the on-call engineer trusts every page.
2. Telecom: capacity forecasting
Call-detail records grow every month. A forecast alert (“disk full in 45 days at this rate”) gives procurement time to buy nodes, instead of a 90% alert at midnight.
3. E-commerce: canary jobs
A tiny job writes a file, reads it back and runs a word count every 10 minutes. If it fails or slows down, the team knows users are affected even when every metric is green.
4. Government data platform: one view of many clusters
Departments run separate clusters (Lesson 12.1); a central team scrapes all of them into one Prometheus with a cluster label, like our monitor watching prod and dr together.
5. Hospital analytics: log-based alerts
Some problems show up only in logs: a NameNode “JvmPauseMonitor: Detected pause” line, or OutOfMemoryError in a nightly job. A log shipper counts such patterns and alerts on them.
Simplified; organisations differ in tools and policies.
An alert rule engine over real snapshots
These snapshots are the prod numbers our monitor printed during the lab, one per check. The engine applies the same rules as monitor.py, plus one improvement: a rule can require its condition to hold for several checks in a row before it fires.
snapshots = [ # prod, from tx124 (time, stale DataNodes, under-replicated blocks, pending apps)
("10:21:11", 0, 0, 0), ("10:26:08", 1, 0, 0), ("10:26:16", 1, 1, 0),
("10:26:17", 1, 1, 0), ("10:26:52", 1, 8, 1), ("10:31:08", 0, 7, 0),
]
rules = [ # (name, test, checks in a row needed, severity)
("stale DataNode", lambda s: s[1] > 0, 1, "WARN"),
("under-replicated", lambda s: s[2] > 0, 1, "WARN"),
("app waiting", lambda s: s[3] > 0, 1, "WARN"),
]
streak = {name: 0 for name, _, _, _ in rules}
for snap in snapshots:
fired = []
for name, test, need, sev in rules:
streak[name] = streak[name] + 1 if test(snap) else 0
if streak[name] >= need:
fired.append(f"{sev} {name}")
print(snap[0], fired or "ok")("stale DataNode", lambda s: s[1] > 0, 1, "WARN"),Each rule is a test on one snapshot plus how many checks in a row it must hold. 1 = fire at once.streak[name] = streak[name] + 1 if test(snap) else 0A streak counter per rule: the basis of “for 5 minutes” rules in Prometheus and other tools.("10:21:11", 0, 0, 0), ("10:26:08", 1, 0, 0), ("10:26:16", 1, 1, 0),Real values from our run. The stale DataNode appeared at 10:26:08, 296 s after the stop.
Run it on your PC: a monitor for two clusters, and four incidents
You need the Module 8 lab (prod) and the Lesson 7.2 federation lab (dr) running, with the lab8 workers joined to the dr network as in Lesson 12.2 (join_clusters.sh). monitor.py runs on lab8-worker1-1 because that machine can reach both clusters. The lab script stops a DataNode, changes replication, enters safe mode, starts two big jobs, then undoes everything. It takes about 15 minutes, mostly waiting for the stale count to refresh.
The monitor
# monitor.py: a tiny fleet monitor. Reads the JMX/REST endpoints of every NameNode and ResourceManager,
# applies alert rules, prints one line per check. Usage: python3 monitor.py [rounds] [seconds_between]
import json, sys, time, urllib.request
CLUSTERS = { # name: (NameNode web, ResourceManager web or None)
"prod": ("http://namenode:9870", "http://resourcemanager:8088"),
"dr": ("http://nn-canteen:9870", None),
}
def get(url):
with urllib.request.urlopen(url, timeout=5) as r:
return json.load(r)
def nn_metrics(base):
beans = get(base + "/jmx?qry=Hadoop:service=NameNode,name=*")["beans"]
m = {}
for b in beans:
m.update(b)
return m
def check(cluster, nn, rm):
alerts, info = [], {}
try:
m = nn_metrics(nn)
except Exception as e:
return [f"CRIT {cluster}: NameNode not answering ({type(e).__name__})"], info
used = 100.0 * m["CapacityUsed"] / max(m["CapacityTotal"], 1)
info.update(live=m["NumLiveDataNodes"], dead=m["NumDeadDataNodes"], stale=m["NumStaleDataNodes"],
used=round(used, 1), under=m["UnderReplicatedBlocks"], missing=m["MissingBlocks"],
files=m["FilesTotal"], safemode=bool(m.get("Safemode")))
if info["missing"] > 0: alerts.append(f"CRIT {cluster}: {info['missing']} missing blocks")
if info["dead"] > 0: alerts.append(f"CRIT {cluster}: {info['dead']} dead DataNode(s)")
if info["stale"] > 0: alerts.append(f"WARN {cluster}: {info['stale']} stale DataNode(s) (no heartbeat for 30 s)")
if info["under"] > 0: alerts.append(f"WARN {cluster}: {info['under']} under-replicated blocks")
if info["safemode"]: alerts.append(f"CRIT {cluster}: NameNode in safe mode (read-only)")
if used > 80: alerts.append(f"WARN {cluster}: HDFS {used:.0f}% full")
if rm:
c = get(rm + "/ws/v1/cluster/metrics")["clusterMetrics"]
mem = 100.0 * c["allocatedMB"] / max(c["totalMB"], 1)
info.update(nodes=c["activeNodes"], unhealthy=c["unhealthyNodes"], lost=c["lostNodes"],
pending=c["appsPending"], running=c["appsRunning"], mem=round(mem))
if c["unhealthyNodes"] or c["lostNodes"]:
alerts.append(f"CRIT {cluster}: {c['unhealthyNodes']} unhealthy / {c['lostNodes']} lost NodeManagers")
if c["appsPending"] > 0:
alerts.append(f"WARN {cluster}: {c['appsPending']} app(s) waiting to start (cluster memory {mem:.0f}% used)")
return alerts, info
rounds = int(sys.argv[1]) if len(sys.argv) > 1 else 1
pause = int(sys.argv[2]) if len(sys.argv) > 2 else 10
for r in range(rounds):
stamp = time.strftime("%H:%M:%S")
for name, (nn, rm) in CLUSTERS.items():
alerts, info = check(name, nn, rm)
print(f"{stamp} {name:4} " + " ".join(f"{k}={v}" for k, v in info.items()))
for a in alerts:
print(f"{stamp} ALERT {a}")
if r < rounds - 1:
time.sleep(pause)
# Copy it to the worker and run one check:
# docker cp monitor.py lab8-worker1-1:/tmp/monitor.py
# docker exec lab8-worker1-1 python3 /tmp/monitor.py 1Real output of one check on a healthy fleet. Each line is one cluster; ALERT lines appear only when a rule fires.
Break the clusters and watch
# monitor_lab.sh: break things on purpose and watch monitor.py notice. Run on your PC.
M="docker exec lab8-worker1-1 python3 /tmp/monitor.py"
docker cp monitor.py lab8-worker1-1:/tmp/monitor.py
echo "== 0. healthy fleet"; $M 1
echo "== 1. a DataNode process dies on prod's worker2"
docker exec lab8-worker2-1 hdfs --daemon stop datanode; s=$(date +%s)
# a DataNode is "stale" after 30 s without a heartbeat, but the NameNode recounts stale nodes only
# on its heartbeat check (every 5 min by default), so the metric can lag: wait until it shows
until $M 1 | grep -q "prod.*stale=[1-9]"; do sleep 10; done
echo " (the alert appeared $(( $(date +%s) - s )) s after the DataNode stopped)"; $M 1
echo "== 2. someone sets replication 4 on a file (the cluster has only 3 DataNodes, 2 alive)"
docker exec lab8-namenode-1 hdfs dfs -setrep 4 /user/hadoop/data/menu.csv 2>/dev/null | grep -v INFO
sleep 5; $M 1
echo "== 3. an admin puts the DR NameNode into safe mode"
docker exec lab72-nn-canteen-1 hdfs dfsadmin -safemode enter 2>/dev/null
$M 1
echo "== 4. a huge job fills prod's YARN and a second job has to wait"
T=/opt/hadoop/share/hadoop/mapreduce/hadoop-mapreduce-client-jobclient-3.5.0-tests.jar
for n in 1 2; do docker exec -d lab8-namenode-1 bash -c "export HADOOP_CLASSPATH=$T; yarn org.apache.hadoop.mapreduce.SleepJob -libjars $T -m 30 -r 1 -mt 30000 -rt 1000 > /tmp/mon$n.log 2>&1"; sleep 2; done
sleep 30; $M 1
echo "== 5. fix everything and check again"
for n in 1 2; do app=$(docker exec lab8-namenode-1 grep -o "application_[0-9_]*" /tmp/mon$n.log | head -1); docker exec lab8-resourcemanager-1 yarn application -kill $app > /dev/null 2>&1; done
docker exec lab72-nn-canteen-1 hdfs dfsadmin -safemode leave 2>/dev/null
docker exec lab8-namenode-1 hdfs dfs -setrep 3 /user/hadoop/data/menu.csv > /dev/null 2>&1
docker exec lab8-worker2-1 hdfs --daemon start datanode; s=$(date +%s)
until $M 1 | grep -q "prod.*stale=0"; do sleep 10; done
echo " (stale cleared $(( $(date +%s) - s )) s after the restart)"; $M 1
# Run on your PC, in the folder that has monitor.py:
# bash monitor_lab.shReal output. Your delays will differ: the stale count depends on where the NameNode is in its 5-minute heartbeat check when the DataNode stops. The 7 under-replicated blocks at the end are staging files of the killed jobs; delete /tmp/hadoop-yarn/staging/hadoop/.staging/* (when no job is running) to clear them.
A “for 3 checks” rule step by step
Watch the streak counter grow and reset. The rule fires only when the condition held for 3 checks in a row, so one bad reading is ignored.
Worked examples: real problems, solved and traced in memory
Four monitoring problems from different domains: designing thresholds, measuring alert noise, forecasting capacity and checking an SLA with a canary.
WARN and CRIT for disk use at a hospital
Problem statement
A hospital records cluster has 600 TB of HDFS. Data grows 2 TB a day. The team wants a WARN with at least 2 weeks to react and a CRIT with at least 3 days. What usage percentages should the thresholds be?
600 TB · +2 TB/day · WARN 14 days · CRIT 3 days
WARN at 95.3% used (14 days of growth left) CRIT at 99.0% used (3 days of growth left)
Approach
- Space needed for N days = growth × N.
- Threshold = (capacity − that space) / capacity.
- Round down to a simple number.
Solution: run it live
What happens in memory, step by step
Recorded from a real Python run: press Next to execute one line at a time. Watch variables change in each frame, and lists and dictionaries (numbered #1, #2 …) fill up as objects.
How much does a noisy alert cost a payments team?
Problem statement
An “under-replicated blocks > 0” rule fires about 30 times a week because of job staging files (like our 7 blocks). Each page wakes someone for 15 minutes. A duration rule (“for 2 hours”) would cut it to 1 per week. How many hours of sleep per month does the fix save?
30 pages/week → 1 · 15 min each
about 31 hours of interrupted sleep saved per month
Approach
- Pages saved per week × minutes each.
- Convert to hours per month (about 4.3 weeks).
- Compare with the cost of fixing the cause.
Solution: run it live
What happens in memory, step by step
Recorded from a real Python run: press Next to execute one line at a time. Watch variables change in each frame, and lists and dictionaries (numbered #1, #2 …) fill up as objects.
When will the call-records cluster be full?
Problem statement
A telecom cluster used 412, 431, 449 and 470 TB on four Mondays in a row. Total capacity is 700 TB. Fit a straight line and estimate in how many weeks it reaches 85%.
4 weekly readings · 700 TB · target 85%
growing 19.3 TB/week; 85% reached in about 6 weeks
Approach
- Weekly growth = average difference between readings.
- Space left to 85% = 0.85 × 700 − latest.
- Weeks = space left / growth.
Solution: run it live
What happens in memory, step by step
Recorded from a real Python run: press Next to execute one line at a time. Watch variables change in each frame, and lists and dictionaries (numbered #1, #2 …) fill up as objects.
Is the canary telling us something?
Problem statement
An e-commerce canary job normally takes 60–75 s. Tonight its last six runs took 70, 68, 140, 150, 160 and 72 s. The rule is: CRIT if the median of the last 3 runs is at least twice the normal maximum. When does it fire, and does a single slow run fire it?
6 canary durations · normal max 75 s
run 3: median 70 s ok run 4: median 140 s ok run 5: median 150 s CRIT run 6: median 150 s CRIT
Approach
- Slide a window of 3 runs.
- Take the median (robust to one outlier).
- Compare with 2 × 75 = 150 s.
Solution: run it live
What happens in memory, step by step
Recorded from a real Python run: press Next to execute one line at a time. Watch variables change in each frame, and lists and dictionaries (numbered #1, #2 …) fill up as objects.
Check yourself
Quick revision
Lesson 12.4 in one screen
- Every daemon exposes metrics at
/jmx(JSON); YARN also at/ws/v1/cluster/metrics. Collectors: Prometheus + JMX exporter, Ambari, Cloudera Manager; dashboards in Grafana. - HDFS signals: missing/corrupt blocks, dead/stale DataNodes, under-replicated blocks, capacity %, safe mode, NameNode heap/GC, RPC queue time, checkpoint age.
- YARN signals: unhealthy/lost NodeManagers, pending apps, queue usage, AM failures; plus job SLAs and host health.
- Lab: stale alert after 296 s (30 s + 5-minute recount); replication 4 → 1 under-replicated; safe mode → CRIT; job waiting at 50% memory (AM limit).
- False alert: staging files with replication 10 left 7 under-replicated blocks forever. Fix the cause, not the alert.
- Good alerts: symptom-based, WARN vs CRIT, durations, runbook and owner; know each metric's lag.
- Add black-box canary jobs and forecast alerts for capacity.
Interview and viva questions
How do you monitor a Hadoop cluster?
Collect the metrics every daemon publishes (JMX over HTTP at /jmx, the YARN REST API, metrics2 sinks) with a collector such as Prometheus with the JMX exporter, Ambari Metrics or Cloudera Manager, plus host metrics and logs. Show them on dashboards, and alert on rules such as missing blocks, dead DataNodes, capacity above a threshold, safe mode, unhealthy NodeManagers and late jobs, each with a severity, a duration and a runbook.
What is the difference between a stale and a dead DataNode?
A DataNode is stale when the NameNode has not received a heartbeat for 30 seconds (dfs.namenode.stale.datanode.interval); clients avoid it for reads and writes. It is dead after about 10 minutes 30 seconds without heartbeats, and only then does the NameNode start re-replicating its blocks. In our lab the stale count metric itself was refreshed every 5 minutes, so the alert came after 296 seconds.
What is the difference between under-replicated and missing blocks?
An under-replicated block has fewer copies than its target but at least one, so data is still readable and HDFS will copy it again. A missing block has no live copy at all; reads fail until a DataNode holding it comes back. Missing blocks should page someone immediately; under-replicated blocks are usually a warning.
How do you avoid alert fatigue?
Alert only on symptoms that need a human, use durations so short blips do not fire, separate WARN (daytime ticket) from CRIT (page), attach a runbook to every alert, review noisy alerts weekly and fix their cause, and send everything else to dashboards. Our staging-file alert is an example: fix mapreduce.client.submit.file.replication instead of muting it.
What is a canary job?
A small synthetic job run on a schedule, for example every 10 minutes, that writes a file, reads it back and runs a tiny MapReduce or Spark job. Its success and duration are monitored. It detects problems users would feel, such as a full queue or slow storage, even when every individual metric looks healthy.
Practice problems
Monitoring exercises using the real numbers from our lab.
How full is HDFS?
The JMX bean shows CapacityUsed and CapacityTotal. Compute the percentage used and print a WARN above 80%.
used 4,769 MB of 800,000 MB
0.6% used ok
Show solution and explanation
used, total = 4769, 800000
pct = 100 * used / total
print(f"{pct:.1f}% used", "WARN" if pct > 80 else "ok")How it works: 0.6% used, like our lab: no warning.
Under or missing?
Classify each block by its live replicas: 0 = missing, below target = under-replicated, else ok.
target 3; live 3, 2, 0, 1
3 ok 2 under-replicated 0 missing 1 under-replicated
Show solution and explanation
target = 3
for live in [3, 2, 0, 1]:
print(live, "missing" if live == 0 else "under-replicated" if live < target else "ok")How it works: Only the block with 0 live copies is unreadable.
Staging files
Each job leaves 2 staging files (job.jar, job.split), one block each, wanting 10 replicas on a 3-DataNode cluster. How many under-replicated blocks after 4 killed jobs?
4 jobs × 2 blocks
8 under-replicated blocks
Show solution and explanation
print(4 * 2, "under-replicated blocks")How it works: 8 in this model. Our lab showed 8 while two jobs ran and 7 after the fixes; the exact count depends on which staging files each job writes (job.jar, job.split, extra jars), but the cause is the same.
Parse a JMX reply
Read the JSON of a NameNode bean and print live, stale and missing values.
a JSON string
live 3 stale 1 missing 0
Show solution and explanation
import json
reply = '{"beans": [{"NumLiveDataNodes": 3, "NumStaleDataNodes": 1, "MissingBlocks": 0}]}'
b = json.loads(reply)["beans"][0]
print("live", b["NumLiveDataNodes"], "stale", b["NumStaleDataNodes"], "missing", b["MissingBlocks"])How it works: The same parsing monitor.py does, one bean at a time.
Alert delay
Our alert appeared 296 s after the stop; stale is defined at 30 s. How much of the delay came from the metric refresh and scraping?
296 s, 30 s
266 s of lag beyond the 30 s definition
Show solution and explanation
print(296 - 30, "s of lag beyond the 30 s definition")How it works: 266 s: most of the delay was metric lag, not the definition.
Dedupe alerts
The same alert fired at every check. Print it only when it starts and when it clears.
a list of states
check 1: FIRING check 4: RESOLVED check 5: FIRING
Show solution and explanation
states = [False, True, True, True, False, True]
prev = False
for i, s in enumerate(states):
if s != prev:
print(f"check {i}:", "FIRING" if s else "RESOLVED")
prev = sHow it works: Alert managers send “firing” and “resolved” notifications, not one per check.
Is a monitoring tool worth it?
A paid tool costs ₹6 lakh a year. Last year the team had 3 outages of 4 hours each that earlier alerts would have cut to 1 hour. One hour of outage costs ₹2 lakh. Worth it?
₹6 lakh · 3 × 3 hours saved · ₹2 lakh/hour
saves Rs 18 lakh vs costs Rs 6 lakh
Show solution and explanation
saved = 3 * (4 - 1) * 2
print(f"saves Rs {saved} lakh vs costs Rs 6 lakh")How it works: ₹18 lakh saved against ₹6 lakh (illustrative), before counting staff time.
Multi-cluster rules
Apply the same rules to every cluster in a dict and print alerts with the cluster name, like monitor.py.
prod and dr snapshots
WARN prod 1 stale DataNode(s) CRIT dr safe mode
Show solution and explanation
fleet = {"prod": {"missing": 0, "safemode": False, "stale": 1},
"dr": {"missing": 0, "safemode": True, "stale": 0}}
for name, m in fleet.items():
if m["missing"]: print("CRIT", name, "missing blocks")
if m["safemode"]: print("CRIT", name, "safe mode")
if m["stale"]: print("WARN", name, m["stale"], "stale DataNode(s)")How it works: One rule set, many clusters: label every metric with its cluster (Lesson 12.1).
Real-world scenario questions (asked in company interviews)
Monitoring questions are about judgement: what deserves a page, and what you do when one arrives.
“Name five metrics you would alert on for HDFS”
A standard question for Hadoop admin and data engineer roles.
The interviewer is checking: that you know which metrics mean data risk.
Show a strong answer
- Missing and corrupt blocks (page immediately), dead DataNodes, capacity used %, safe mode, under-replicated blocks trend.
- NameNode heap and GC pauses, RPC queue time, time since the last checkpoint.
- Read them from the NameNode /jmx endpoint with a collector such as Prometheus.
The under-replicated-blocks alert fires every night and nobody looks any more
You join a team where on-call engineers mute this alert.
The interviewer is checking: root-cause thinking over muting.
Show a strong answer
- Find which files are under-replicated with
hdfs fsck / | grep -i "under replicated"; often they are job staging files with replication 10 on a small cluster. - Fix the cause: mapreduce.client.submit.file.replication ≤ DataNodes, clean old staging folders.
- Change the rule to “growing for 30 minutes” and keep missing blocks as the page.
All metrics are green but analysts say jobs are slow
Dashboards show healthy nodes and 60% disk use.
The interviewer is checking: black-box monitoring and queue awareness.
Show a strong answer
- Check pending applications and queue usage: a full queue or AM limit keeps jobs in ACCEPTED while memory looks free.
- Check NameNode RPC queue time and GC pauses, which slow every client.
- Add a canary job with a duration alert so this is caught before users report it.
Design monitoring for 12 clusters in three regions
Each business unit ran its own scripts until now.
The interviewer is checking: standardisation and ownership.
Show a strong answer
- One Prometheus per region scraping all daemons via the JMX exporter, every metric labelled with cluster and role, central Grafana and Alertmanager.
- One shared rule set with severities and runbooks; routing by cluster owner; SLOs for key pipelines with canaries.
- Capacity forecasts and a weekly noise review; test alerts with planned drills like the ones in this lesson.