Monitoring and alerts

A cluster fails quietly unless something is watching. This lesson builds a small monitor over the metrics every Hadoop daemon already publishes, breaks a real cluster in four ways, and uses what we saw, including a late alert and a false one, to design alerts that people trust.

Module 12 · Multiple clusters and operations⏱ 28 minIntermediateReal monitor on 2 clustersLate and false alerts caught liveRuns in your browser (Python)8 practice problems
1 The story

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.

DataNode stops 0 s nobody knows yet: 296 s of silence WARN stale DataNode 296 s under-replicated, safe mode, waiting app: seconds all fixed… still 7 under-replicated 10:26:08 ALERT WARN prod: 1 stale DataNode(s) real output of our monitor.py Two lessons in one run: metrics arrive late, and some alerts are false. myphatshala.in
Riya

Five minutes for a dead DataNode? The heartbeat is every 3 seconds!

Arjun Sir

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.

Kabir

And the 7 blocks at the end? We cleaned up everything.

Arjun Sir

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.

2 Definition

Monitoring and alerting for Hadoop

Formal definition (write this in exams)

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.

In simple words

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

MetricA number with a name and time, e.g. UnderReplicatedBlocks=1.
JMX endpointhttp://namenode:9870/jmx: every metric of a daemon as JSON.
Stale DataNodeNo heartbeat for 30 s. Dead only after 10 min 30 s.
Alert ruleCondition + threshold + duration + severity + runbook link.
WARN / CRITLook at it today / wake someone up now.
Metric lagTime between the event and the metric showing it (296 s in our lab).
False positiveAn alert that fires when nothing needs doing.
Canary jobA tiny job run every few minutes to prove the cluster works end to end.

From our lab (two clusters, one monitor)

Healthy baselineprod: live=3 stale=0 used=0.6% under=0 files=1658, 3 NodeManagers; dr: live=3, safemode=False
DataNode stoppedstale 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 jobspending=1 with memory only 50% used: the queue's ApplicationMaster limit blocked it (Lesson 12.6)
After the fixesstale cleared 246 s after restart; 7 under-replicated blocks left: staging files with replication 10

Monitoring at three levels

Pick your level. New to this? Start at Beginner and climb.

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).

3 Types and ways to use it

Signals, sources and severities

SignalWhere it comes fromTypical ruleSeverity
MissingBlocks, CorruptBlocksNameNode JMX (FSNamesystem)> 0CRIT: data at risk
NumDeadDataNodesNameNode JMX> 0 for 5 minCRIT if several, WARN if one
NumStaleDataNodesNameNode JMX> 0 for 5 minWARN (early sign)
UnderReplicatedBlocksNameNode JMXgrowing for 30 minWARN
Capacity used %NameNode JMX> 80% WARN, > 90% CRITWARN / CRIT
Safe modeNameNode JMX (Safemode)on, outside maintenanceCRIT: writes fail
Unhealthy / lost NodeManagersRM REST /ws/v1/cluster/metrics> 0WARN
Pending appsRM REST> 0 for 10 minWARN
Job SLAscheduler / canarynot done by 05:30CRIT

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.

clusters (prod, dr) NameNode:9870/jmx DataNodes:9864/jmx ResourceManager:8088/ws/v1/cluster/metrics NodeManagers:8042/jmx + host metrics (disk, RAM, network) scrape every 15 s collector Prometheus + JMX exporter (our lab: monitor.py) alert rules MissingBlocks > 0 → CRIT stale > 0 for 5m → WARN + runbook link on-call PagerDuty · Slack · SMS dashboards (Grafana) canary job write · read · tiny MR, every 10 min White-box metrics tell you why; the black-box canary tells you whether users are affected. myphatshala.in

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.

built in

YARN REST

/ws/v1/cluster/metrics, /apps, /nodes, /scheduler on the ResourceManager (Module 11).

built in

metrics2 sinks

Daemons can push metrics to files, Ganglia or other systems via hadoop-metrics2.properties.

push

Prometheus + Grafana

The JMX exporter (a Java agent) turns JMX into Prometheus metrics; Alertmanager routes alerts. Common in self-managed clusters.

open source

Ambari / Cloudera Manager

Cluster managers that collect metrics, show dashboards and ship ready-made alert rules.

vendor

Logs

Log-based alerts: a pattern such as “java.lang.OutOfMemoryError” in a NameNode log (Lesson 11.5).

text

Animated example: Diwali sale night

On call during a sale 6 steps
Animated example sale night · clickstream cluster · 400 nodes 20:00 · sale opens, traffic ×6 dashboard: HDFS 71% · pending apps 0 Neha is on call; everything is green. the runbook for tonight is already open 21:40 · WARN HDFS 81% full raw clicks arrive 6× faster than usual runbook: delete expired temp data, check trash 22:05 · back to 74% 23:10 · 3 stale DataNodes, rack 7 rule waits 5 minutes: still stale at 23:15 one rack switch is dropping packets network team paged; replicas elsewhere keep data safe 23:40 · UnderReplicatedBlocks 2.1 lakh expected after a rack problem: WARN, not CRIT MissingBlocks stays 0, the one that matters re-replication drains it by 01:30 03:00 · canary job: 4 min (normal 1) no metric is red, but users would feel it cause: sales-report queue at 100% ad-hoc jobs paused until 06:00 06:00 · sale report delivered on time 4 alerts, 1 page, 0 data lost morning review: add a disk-growth forecast alert before the next sale Alerts tonight WARN disk 81% CRIT stale rack WARN under-repl. canary slow → SLA met, review done myphatshala.in

The best first alert for any cluster is MissingBlocks > 0. It almost never fires falsely, and when it fires, data is unreadable right now.

4 Step by step

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).

  1. Read the metrics

    curl -s 'http://namenode:9870/jmx?qry=Hadoop:service=NameNode,name=FSNamesystemState'
    curl -s http://resourcemanager:8088/ws/v1/cluster/metrics
    10: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=False
    The baseline. Everything a rule needs is in two JSON documents per cluster: no agents, no extra software.
  2. Stop a DataNode and wait for the alert

    docker 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)
    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 that live still says 3: the node is declared dead only after 10 min 30 s.
  3. Ask for more replicas than the cluster can give

    hdfs dfs -setrep 4 /user/hadoop/data/menu.csv
    Replication 4 set: /user/hadoop/data/menu.csv 10:26:16 ALERT WARN prod: 1 under-replicated blocks
    This one shows up at the next check: the block's target is 4 copies and only 3 DataNodes exist (2 alive).
  4. Safe mode on the DR cluster

    docker exec lab72-nn-canteen-1 hdfs dfsadmin -safemode enter
    Safe mode is ON 10:26:17 dr live=3 ... safemode=True 10:26:17 ALERT CRIT dr: NameNode in safe mode (read-only)
    CRIT, because every write to that cluster now fails (Lesson 5.6). The same rule covers both clusters.
  5. 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 its job.jar and job.split with replication 10.
  6. 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 blocks
    The 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.

5 See it happen

Six checks of our monitor

The real monitor output on the left, what happened inside the cluster on the right.

Breaking things on purpose 6 steps
What you see python3 monitor.py prod live=3 stale=0 under=0 pending=0 mem=0dr live=3 safemode=False(no alerts) $ hdfs --daemon stop datanode... 296 s ...prod live=3 dead=0 stale=1ALERT WARN 1 stale DataNode $ hdfs dfs -setrep 4 menu.csvprod under=1ALERT WARN 1 under-replicated $ dfsadmin -safemode enter (dr)dr safemode=TrueALERT CRIT dr: safe mode 2 big SleepJobspending=1 running=1 mem=50ALERT WARN 1 app waitingALERT WARN 8 under-replicated all fixed, stale cleared after 246 sprod stale=0 pending=0ALERT WARN 7 under-replicated(staging files, replication 10) myphatshala.in
Behind the screen prod NameNode/jmx dr NameNode/jmx DN1 DN2 DN3 3 DataNodes every check: 2 HTTP requests per cluster,compared with the rules DN2 ✕stale after 30 s, but the stale count isrecounted only on the 5-minute heartbeat checkdead only after 10 min 30 s DN2 ✕menu.csv: want 44 copies wanted, only 3 DataNodes exist DN2 ✕dr NameNodeSAFE MODE · read-onlyevery write to DR now fails: CRIT DN2 ✕YARN: job 1 runningjob 2 ACCEPTED: AM limitmemory 50% used.staging/job_…/job.jar, job.splitreplication 10 on 3 DNs killed jobs' staging files7 blocks wanting 10 copiesfix the cause, don't muteDN2 back ✓ myphatshala.in
6 Real-world use

Monitoring at work

MissingBlocks> 0 → page

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.

NameNode JMX→CRIT rules→Pager
disk % trend

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.

Capacity history→Linear forecast→Ticket, not page
canaryevery 10 min

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.

Scheduler→Canary job→Duration alert
10 clusters1 view

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.

Many clusters→One collector→Fleet dashboard
log patternOutOfMemoryError

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.

Daemon logs→Pattern counter→Alert

Simplified; organisations differ in tools and policies.

7 Run the code

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")
10:21:11 ok 10:26:08 ['WARN stale DataNode'] 10:26:16 ['WARN stale DataNode', 'WARN under-replicated'] 10:26:17 ['WARN stale DataNode', 'WARN under-replicated'] 10:26:52 ['WARN stale DataNode', 'WARN under-replicated', 'WARN app waiting'] 10:31:08 ['WARN under-replicated']
  • ("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 1
== 0. healthy fleet 10: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=False

Real 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.sh
== 0. healthy fleet 10: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=False == 1. a DataNode process dies on prod's worker2 (the alert appeared 296 s after the DataNode stopped) 10:26:08 prod live=3 dead=0 stale=1 used=0.6 under=0 missing=0 files=1658 safemode=False nodes=3 unhealthy=0 lost=0 pending=0 running=0 mem=0 10:26:08 ALERT WARN prod: 1 stale DataNode(s) (no heartbeat for 30 s) 10:26:08 dr live=3 dead=0 stale=0 used=0.1 under=0 missing=0 files=15 safemode=False == 2. someone sets replication 4 on a file (the cluster has only 3 DataNodes, 2 alive) Replication 4 set: /user/hadoop/data/menu.csv 10:26:16 prod live=3 dead=0 stale=1 used=0.6 under=1 missing=0 files=1658 safemode=False nodes=3 unhealthy=0 lost=0 pending=0 running=0 mem=0 10:26:16 ALERT WARN prod: 1 stale DataNode(s) (no heartbeat for 30 s) 10:26:16 ALERT WARN prod: 1 under-replicated blocks 10:26:16 dr live=3 dead=0 stale=0 used=0.1 under=0 missing=0 files=15 safemode=False == 3. an admin puts the DR NameNode into safe mode Safe mode is ON 10:26:17 prod live=3 dead=0 stale=1 used=0.6 under=1 missing=0 files=1658 safemode=False nodes=3 unhealthy=0 lost=0 pending=0 running=0 mem=0 10:26:17 ALERT WARN prod: 1 stale DataNode(s) (no heartbeat for 30 s) 10:26:17 ALERT WARN prod: 1 under-replicated blocks 10:26:17 dr live=3 dead=0 stale=0 used=0.1 under=0 missing=0 files=15 safemode=True 10:26:17 ALERT CRIT dr: NameNode in safe mode (read-only) == 4. a huge job fills prod's YARN and a second job has to wait 10:26:52 prod live=3 dead=0 stale=1 used=0.6 under=8 missing=0 files=1675 safemode=False nodes=3 unhealthy=0 lost=0 pending=1 running=1 mem=50 10:26:52 ALERT WARN prod: 1 stale DataNode(s) (no heartbeat for 30 s) 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) 10:26:52 dr live=3 dead=0 stale=0 used=0.1 under=0 missing=0 files=15 safemode=True 10:26:52 ALERT CRIT dr: NameNode in safe mode (read-only) == 5. fix everything and check again Safe mode is OFF (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 safemode=False nodes=3 unhealthy=0 lost=0 pending=0 running=0 mem=0 10:31:08 ALERT WARN prod: 7 under-replicated blocks 10:31:08 dr live=3 dead=0 stale=0 used=0.1 under=0 missing=0 files=15 safemode=False

Real 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.

8 Line by line

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.

Example 1BeginnerThresholds · HDFS

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?

Input
600 TB · +2 TB/day · WARN 14 days · CRIT 3 days
Expected output
WARN at 95.3% used (14 days of growth left)
CRIT at 99.0% used (3 days of growth left)

Approach

  1. Space needed for N days = growth × N.
  2. Threshold = (capacity − that space) / capacity.
  3. 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.

Example 2IntermediateNoise · on-call

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?

Input
30 pages/week → 1 · 15 min each
Expected output
about 31 hours of interrupted sleep saved per month

Approach

  1. Pages saved per week × minutes each.
  2. Convert to hours per month (about 4.3 weeks).
  3. 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.

Example 3IntermediateForecast · telecom

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%.

Input
4 weekly readings · 700 TB · target 85%
Expected output
growing 19.3 TB/week; 85% reached in about 6 weeks

Approach

  1. Weekly growth = average difference between readings.
  2. Space left to 85% = 0.85 × 700 − latest.
  3. 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.

Example 4AdvancedSLA · canary

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?

Input
6 canary durations · normal max 75 s
Expected output
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

  1. Slide a window of 3 runs.
  2. Take the median (robust to one outlier).
  3. 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.

9 Quiz and revision

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.

P1Easy

How full is HDFS?

The JMX bean shows CapacityUsed and CapacityTotal. Compute the percentage used and print a WARN above 80%.

Input
used 4,769 MB of 800,000 MB
Expected output
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")
0.6% used ok

How it works: 0.6% used, like our lab: no warning.

P2Easy

Under or missing?

Classify each block by its live replicas: 0 = missing, below target = under-replicated, else ok.

Input
target 3; live 3, 2, 0, 1
Expected output
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")
3 ok 2 under-replicated 0 missing 1 under-replicated

How it works: Only the block with 0 live copies is unreadable.

P3Easy

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?

Input
4 jobs × 2 blocks
Expected output
8 under-replicated blocks
Show solution and explanation
print(4 * 2, "under-replicated blocks")
8 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.

P4Medium

Parse a JMX reply

Read the JSON of a NameNode bean and print live, stale and missing values.

Input
a JSON string
Expected output
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"])
live 3 stale 1 missing 0

How it works: The same parsing monitor.py does, one bean at a time.

P5Medium

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?

Input
296 s, 30 s
Expected output
266 s of lag beyond the 30 s definition
Show solution and explanation
print(296 - 30, "s of lag beyond the 30 s definition")
266 s of lag beyond the 30 s definition

How it works: 266 s: most of the delay was metric lag, not the definition.

P6Medium

Dedupe alerts

The same alert fired at every check. Print it only when it starts and when it clears.

Input
a list of states
Expected output
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 = s
check 1: FIRING check 4: RESOLVED check 5: FIRING

How it works: Alert managers send “firing” and “resolved” notifications, not one per check.

P7Business problem

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?

Input
₹6 lakh · 3 × 3 hours saved · ₹2 lakh/hour
Expected output
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")
saves Rs 18 lakh vs costs Rs 6 lakh

How it works: ₹18 lakh saved against ₹6 lakh (illustrative), before counting staff time.

P8Advanced

Multi-cluster rules

Apply the same rules to every cluster in a dict and print alerts with the cluster name, like monitor.py.

Input
prod and dr snapshots
Expected output
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)")
WARN prod 1 stale DataNode(s) CRIT dr safe mode

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.

Basics · metricsFresher

“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.
Operations · noiseExperienced

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.
Incident · latencyExperienced

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 · fleetArchitect

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.