Retire one server, welcome another
Monday at the canteen-analytics team. Datanode-4's disk is throwing errors and must go back to the vendor, and a new server has arrived. Riya's first idea: switch datanode-4 off and plug the new one in. Her lead, Arjun, stops her. Switching a node off makes HDFS panic-copy its blocks only after 10 minutes, and until then some blocks have one copy fewer. The new server would sit almost empty while the old ones stay full. There are proper tools for both jobs, and a third one to prove that nothing was lost.
Just switching datanode-4 off would be a small disaster on purpose. The NameNode can't tell “retired” from “crashed”, so it waits until the node is declared dead and only then copies its blocks. Decommissioning tells it first: “copy everything this node holds to others, and tell me when it's safe”. On our lab that took one minute.
And the new server?
HDFS never moves existing blocks by itself. New files will use the new node, but the old data stays where it is. The balancer moves blocks from fuller nodes to emptier ones. And after all that, fsck confirms every file still has all its replicas. Today we run all of it.
HDFS administration tools
hdfs dfsadmin is the administration client for the NameNode: it reports cluster capacity and DataNode status (-report), controls safe mode (-safemode), reloads the include/exclude host lists (-refreshNodes), shows the rack topology (-printTopology), and manages checkpoints, quotas and balancer bandwidth. hdfs fsck checks the health of the namespace: for each file it compares the expected replication with the live replicas and reports missing, corrupt, under- and over-replicated blocks, without repairing anything unless asked (-move, -delete). Decommissioning retires a DataNode by listing it in the file named by dfs.hosts.exclude and running -refreshNodes; the NameNode re-replicates all its blocks to other nodes before marking it Decommissioned. The balancer (hdfs balancer) moves block replicas from over-utilised to under-utilised DataNodes until every node's utilisation is within -threshold percent of the cluster average, never reducing a block's replication or breaking rack placement.
dfsadmin is the dashboard and control panel, fsck is the health check-up, decommission is a proper farewell for a server, and the balancer is the shelf-arranger who moves boxes from crowded shelves to empty ones.
Words you'll meet in this lesson
dfs.hosts.exclude: nodes listed there are decommissioned.Defaults and limits (Hadoop 3.5.0, from the lab)
| Balancer threshold | 10% by default; allowed range 1.0 to 100.0 (“Expecting a number in the range of [1.0, 100.0]”) |
|---|---|
| Balancer bandwidth | dfs.datanode.balance.bandwidthPerSec = 104857600 (100 MB/s per DataNode) |
| Concurrent moves | dfs.datanode.balance.max.concurrent.moves = 100 |
| Gives up after | 5 iterations with no block moved (“max idle iteration = 5”) |
| Decommission check | Every 30 s (dfs.namenode.decommission.interval) |
| fsck | Read-only by default; -move / -delete change files |
Admin tools at three levels
Beginner Like moving house
- Decommission: before you leave a flat, you pack and move everything out. Only then do you hand back the keys.
- Balancer: a new cupboard arrives empty; you move some things into it so no cupboard overflows.
- fsck: walking through the house with the inventory list to check nothing is missing.
Intermediate The admin routine
- Daily:
hdfs dfsadmin -report(dead nodes? capacity?) andhdfs fsck /(HEALTHY?). - Retire a node: add it to the exclude file →
-refreshNodes→ wait for Decommissioned → stop it. - Add a node: start the DataNode (it registers itself) → run
hdfs balancer, ideally at night. - Investigate a file:
hdfs fsck path -files -blocks -locations -racks.
Advanced What experienced admins watch for
- Decommission needs somewhere to put the copies: with 3 racks and replication 3, retiring a whole rack can stall placement.
- A decommission stuck at “still has 1 blocks to replicate” usually means a block whose copies can't be placed (bad target, full disks, open files).
- The balancer is safe to stop at any time (Ctrl+C); moved blocks stay moved. Raise
-setBalancerBandwidthonly when jobs are quiet. - Recommissioned nodes often lose their replicas as “excess” and come back nearly empty: plan a balancer run.
fsckon/of a huge cluster is heavy for the NameNode; run it on sub-trees or off-peak.
Exam tip: “What is decommissioning? How do you add and remove DataNodes?” Removing: add the host to dfs.hosts.exclude, run hdfs dfsadmin -refreshNodes, wait for status Decommissioned (blocks re-replicated), then stop the node. Adding: install Hadoop with the same configuration, start the DataNode (add it to dfs.hosts if an include list is used, then refreshNodes), and run the balancer.
The commands you will actually use
| Tool | Command | What it tells or does |
|---|---|---|
| dfsadmin | -report [-live|-dead|-decommissioning] | Capacity, used, remaining; per-DataNode status and block counts |
| dfsadmin | -refreshNodes | Re-read include/exclude files: start decommission or recommission |
| dfsadmin | -safemode get|enter|leave|wait | Safe mode control (Lesson 5.6) |
| dfsadmin | -printTopology | Racks and nodes, with In Service / Decommissioned |
| dfsadmin | -getDatanodeInfo host:9867 | Uptime and software version of one DataNode |
| dfsadmin | -setBalancerBandwidth bytes | Change balancer speed on all DataNodes, no restart |
| dfsadmin | -saveNamespace, -fetchImage dir | Force a checkpoint (needs safe mode); download the latest fsimage |
| fsck | path -files -blocks -locations -racks | Every file, block and replica location |
| fsck | / -list-corruptfileblocks | Only the damaged blocks |
| fsck | -move / -delete | Move corrupt files to /lost+found or delete them (last resort) |
| balancer | -threshold N, -exclude, -source | How even, and which nodes may be involved |
Ways to take a DataNode out
Decommission
Copies every block away first. For permanent removal. Took 48 to 60 s in our lab.
Safe, slowMaintenance mode
For a reboot or short repair: blocks with enough other replicas are not copied; the node comes back with its data.
Planned, shortJust stop it
HDFS treats it as a failure: dead after about 10.5 minutes, then re-replication. Fine for crashes, wrong for planned work.
UnplannedStop many at once
Several nodes holding all replicas of a block = missing data. Always one at a time, or decommission together.
DangerousRun hdfs dfsadmin and hdfs balancer -help with no other arguments for the exact usage of your version. The balancer's own help describes the threshold as “Percentage of disk capacity”.
A morning of real admin work
All commands ran in the namenode container of the lab: 5 DataNodes, two racks (/rack1: datanode-1, -2; /rack2: datanode-3, -4, -5).
Morning check: dfsadmin -report
The three numbers to read first: dead datanodes, missing blocks, under-replicated blocks. Capacity looks odd here (1.23 TB configured, 86 GB present) because all five lab DataNodes sit on one shared laptop disk; on real servers each node has its own disks.hdfs dfsadmin -report -deadConfigured Capacity: 1352765870080 (1.23 TB) Present Capacity: 92735646762 (86.37 GB) DFS Remaining: 89697912832 (83.54 GB) DFS Used: 3037733930 (2.83 GB) DFS Used%: 3.28% Replicated Blocks: Under replicated blocks: 0 Blocks with corrupt replicas: 0 Missing blocks: 0 Missing blocks (with replication factor 1): 0 ... ------------------------------------------------- Dead datanodes (0):Health check: fsck
fsck asks the NameNode only; it reads no data. It shows each block's live replicas with their racks: two in one rack and one in the other, exactly the placement rule from Lesson 5.3.hdfs fsck / -list-corruptfileblocks hdfs fsck /user/hadoop/canteen -files -blocks -racksThe filesystem under path '/' has 0 CORRUPT blocks /user/hadoop/canteen/raw/day1.csv 47 bytes, replicated: replication=3, 1 block(s): OK 0. BP-1507681208-172.19.0.3-1792565333483:blk_1073741852_1029 len=47 Live_repl=3 [/rack1/172.19.0.3:9866, /rack1/172.19.0.4:9866, /rack2/172.19.0.6:9866] /user/hadoop/canteen/raw/day2.csv 34 bytes, replicated: replication=3, 1 block(s): OK 0. BP-1507681208-172.19.0.3-1792565333483:blk_1073741855_1033 len=34 Live_repl=3 [/rack2/172.19.0.6:9866, /rack1/172.19.0.4:9866, /rack1/172.19.0.3:9866] Status: HEALTHYWho is where: topology and node info
9867 is the DataNode's IPC port (9866 is its data port). Uptime is in seconds.hdfs dfsadmin -printTopology hdfs dfsadmin -getDatanodeInfo lab5-datanode-1:9867Rack: /rack1 172.19.0.4:9866 (lab5-datanode-1.lab5_default) In Service 172.19.0.3:9866 (lab5-datanode-2.lab5_default) In Service Rack: /rack2 172.19.0.8:9866 (lab5-datanode-5.lab5_default) In Service 172.19.0.7:9866 (lab5-datanode-4.lab5_default) In Service 172.19.0.6:9866 (lab5-datanode-3.lab5_default) In Service Uptime: 945, Software version: 3.5.0, Config version: core-3.0.0,hdfs-1Decommission datanode-4
During decommission the node still serves reads, so nothing breaks. The NameNode copies each of its blocks from any live replica to another node, checking progress every 30 seconds. Then it is safe to switch it off.# once: hdfs-site.xml of the NameNode has # dfs.hosts.exclude = /opt/hadoop/etc/hadoop/dfs.exclude echo 172.19.0.7 > /opt/hadoop/etc/hadoop/dfs.exclude hdfs dfsadmin -refreshNodes hdfs dfsadmin -report | grep -A3 'Name: 172.19.0.7' # repeated every few secondsRefresh nodes successful t=2s Decommission Status : Decommission in progress t=8s Decommission Status : Decommission in progress ... t=46s Decommission Status : Decommission in progress t=52s Decommission Status : DecommissionedProve it, then bring it back
“4 data-nodes” and 0 under-replicated: every block had 3 replicas without datanode-4. After recommissioning, its replicas became extra copies (4 instead of 3), and the NameNode deleted excess ones. Datanode-4 had 11 blocks before; a minute after coming back it had 0. A recommissioned node often returns nearly empty.hdfs fsck / | grep -E 'Status|Under-replicated|Number of data-nodes' > /opt/hadoop/etc/hadoop/dfs.exclude # empty the exclude file hdfs dfsadmin -refreshNodesStatus: HEALTHY Number of data-nodes: 4 Under-replicated blocks: 0 (0.0 %) Refresh nodes successful Decommission Status : NormalA new, empty node and the balancer
Datanode-6 got its own 1.5 GB disk, so it was the only empty one (the other five share one disk and look equally full). The balancer planned moves, then copied 8 blocks in 16 seconds. “through 172.19.0.6”: the bytes came from a replica in the target's own rack, not necessarily from the node being emptied. Afterwards the source replica is deleted, so replication stays 3.docker run -d --name lab5-datanode-6 ... --tmpfs /tmp/hadoop-hadoop:size=1536m apache/hadoop:3.5.0 hdfs datanode hdfs balancer -threshold 5INFO Balancer:568 - 1 underutilized: [172.19.0.9:9866:DISK] INFO Balancer:810 - Need to move 1.32 GB to make the cluster balanced. INFO Balancer:663 - Decided to move 340.33 MB bytes from 172.19.0.7:9866:DISK to 172.19.0.9:9866:DISK INFO Balancer:663 - Decided to move 340.38 MB bytes from 172.19.0.4:9866:DISK to 172.19.0.9:9866:DISK ... INFO Dispatcher:407 - Successfully moved blk_1073741844_1020 with size=134217728 from 172.19.0.4:9866:DISK to 172.19.0.9:9866:DISK through 172.19.0.6:9866 ... INFO Dispatcher:1289 - Total bytes (blocks) moved in this iteration 914.72 MB (8)When the balancer gives up
The tiny lab disk started refusing blocks with “Out of space”. A failed move is just skipped: the block stays where it was, with all its replicas. After 5 rounds without progress, the balancer stops. On a real cluster, check the target's disks and rerun.# same run, iterations 1 to 5Need to move 430.09 MB to make the cluster balanced. ... Out of space: The volume with the most available space (=643919872 B) is less than the block size (=134217728 B). ... (the same in iterations 2, 3, 4 and 5) No block has been moved for 5 iterations. Exiting... Oct 21, 2026, 10:04:11 AM Balancing took 1.1124 minutes $ hdfs dfsadmin -report (DFS Used%) 172.19.0.3 0.27% 172.19.0.4 0.22% 172.19.0.6 0.27% 172.19.0.7 0.00% 172.19.0.8 0.00% 172.19.0.9 60.02%Speed limits and mistakes
52428800 bytes = 50 MB/s per DataNode, applied at once. The threshold must be at least 1%.hdfs dfsadmin -setBalancerBandwidth 52428800 hdfs balancer -threshold 0.5 hdfs dfsadmin -saveNamespaceBalancer bandwidth is set to 52428800 Expecting a number in the range of [1.0, 100.0]: 0.5 saveNamespace: Safe mode should be turned ON in order to create namespace image.-saveNamespaceis only allowed in safe mode, so the namespace doesn't change while it is written.
Never decommission (or stop) more nodes at once than your replication can survive, and never put every node of a rack in the exclude file unless the other racks have room for all those blocks. Watch -report -decommissioning until it is empty.
Decommission, then balance
Block A lives on dn-2, dn-4 and dn-5. We retire dn-4, then add an empty dn-6.
- Datanode-4 is Normal and holds 11 blocks.
- We list it in the exclude file and refresh: no restart needed.
- Status changes to “Decommission in progress”.
- 52 seconds later: Decommissioned, and fsck shows nothing under-replicated.
- A new, empty node appears; the balancer calls it underutilised.
- 8 blocks (914.72 MB) move to it in the first iteration.
- Block A has 3 replicas: dn-2, dn-4, dn-5.
- dn-4 is marked decommissioning. Its replicas no longer count towards the 3, but it still serves reads.
- The NameNode asks dn-2 to copy A to dn-3, respecting rack placement.
- Every block of dn-4 now has 3 replicas elsewhere: Decommissioned.
- dn-6 joins with an empty disk. The average utilisation is far above its 0%, so it is underutilised.
- The balancer copies block B to dn-6 and deletes one source replica: still 3 copies, just better spread.
Admin tools at work
1. Hardware refresh
A bank replaces 200 five-year-old DataNodes. New nodes are added and balanced first; old ones are decommissioned a few at a time, each batch confirmed with fsck before the next. Users notice nothing.
2. Night-time balancing
Teams schedule hdfs balancer -threshold 10 at night and raise the bandwidth for those hours with -setBalancerBandwidth, then lower it before office jobs start.
3. Monitoring and alerts
Monitoring reads the same numbers as -report (dead nodes, missing and under-replicated blocks) from the NameNode's metrics and pages the on-call engineer when missing blocks are above zero.
4. Patching without copying terabytes
For a 20-minute OS patch, admins put a node into maintenance mode instead of decommissioning it, so HDFS doesn't copy its many terabytes away and back.
Simplified; organisations differ in tools and policies.
A balancer in 30 lines
This program does what hdfs balancer does, simplified: compute each node's utilisation (used ÷ capacity) and the cluster average, then move 128 MB blocks from the fullest node to the emptiest until every node is within the threshold of the average.
cap = {"dn-1": 4000, "dn-2": 4000, "dn-3": 4000, "dn-6": 4000} # MB
used = {"dn-1": 3200, "dn-2": 3072, "dn-3": 2944, "dn-6": 0}
threshold = 10 # percent
block = 128 # MB
def util(n):
return 100 * used[n] / cap[n]
def average():
return 100 * sum(used.values()) / sum(cap.values())
moves = 0
while True:
avg = average()
src = max(used, key=util)
dst = min(used, key=util)
if util(src) - avg <= threshold and avg - util(dst) <= threshold:
break
used[src] -= block
used[dst] += block
moves += 1
print(f"average {average():.1f}% moves {moves} ({moves * block} MB)")
for n in cap:
print(f" {n}: {util(n):5.1f}%")return 100 * used[n] / cap[n]Utilisation is a percentage of capacity, not a block count. That is why a big new disk with 0 blocks is “underutilised”.if util(src) - avg <= threshold and avg - util(dst) <= threshold:Balanced = every node within ±threshold of the average. Here 10%, the default; the real tool accepts 1 to 100.used[src] -= blockA real move copies the block to the target and then deletes the source replica, so replication never drops.
Run it on your PC: retire a node, fill a new one
Two scripts for the hdfs-lab folder. The first decommissions a DataNode and prints its status every few seconds until it is Decommissioned, checks fsck and recommissions it. The second starts a sixth DataNode with its own small disk and runs the balancer. First add HDFS-SITE.XML_dfs.hosts.exclude=/opt/hadoop/etc/hadoop/dfs.exclude to the config file and recreate the namenode (docker compose up -d).
Decommission and recommission one DataNode
#!/usr/bin/env bash
# decommission_watch.sh: retire one DataNode safely and watch HDFS copy its blocks away.
# Needs dfs.hosts.exclude=/opt/hadoop/etc/hadoop/dfs.exclude in the NameNode's hdfs-site.xml.
# Run from the hdfs-lab folder: bash decommission_watch.sh 172.19.0.4
IP=${1:?give the DataNode IP}
NN="docker exec lab5-namenode-1"
status() { $NN hdfs dfsadmin -report 2>/dev/null | grep -m1 -A20 "^Name: $IP:" |
grep -E "Decommission Status|Num of Blocks" | sed 's/ : /: /' | paste -sd'|' | sed 's/|/, /'; }
echo "before: $(status)"
$NN bash -c "echo $IP > /opt/hadoop/etc/hadoop/dfs.exclude"
$NN hdfs dfsadmin -refreshNodes
start=$(date +%s)
while true; do
s=$(status); echo "t=$(( $(date +%s) - start ))s $s"
[[ $s == *"Status: Decommissioned"* ]] && break
sleep 5
done
$NN bash -c "hdfs fsck / 2>/dev/null | grep -E 'Status:|Under-replicated|Number of data-nodes'"
echo "### recommission"
$NN bash -c "> /opt/hadoop/etc/hadoop/dfs.exclude"
$NN hdfs dfsadmin -refreshNodes
sleep 10; echo "after: $(status)"
# In the hdfs-lab folder (find the IP with: hdfs dfsadmin -printTopology):
# bash decommission_watch.sh 172.19.0.7Real output. Only 2 blocks, yet 60 s: the NameNode checks decommission progress every 30 s. After recommissioning, its replicas were extra copies and were removed: 0 blocks.
Add a node, run the balancer
#!/usr/bin/env bash
# add_node_and_balance.sh: add a new, empty DataNode with its own small disk, then run the balancer.
# Run from the hdfs-lab folder (compose project "lab5", network lab5_default).
NN="docker exec lab5-namenode-1"
show() {
$NN hdfs dfsadmin -report 2>/dev/null |
awk '/^Name:/{ip=$2; sub(":9866","",ip)} /^DFS Used%/{if(ip) printf " %-12s used %6s\n", ip, $3; ip=""}'
}
echo "### 1. Start datanode-6 with a 1.5 GB disk of its own (a RAM disk)"
docker run -d --name lab5-datanode-6 --hostname datanode-6 --network lab5_default \
--env-file config --tmpfs /tmp/hadoop-hadoop:size=1536m,mode=1777 \
apache/hadoop:3.5.0 hdfs datanode > /dev/null
sleep 25; show
echo "### 2. Balancer, threshold 5%"
$NN hdfs balancer -threshold 5 2>&1 |
grep -E "underutilized|Need to move|Decided to move|Successfully moved|Out of space|^[A-Z][a-z]{2} [0-9]+, |No block|Iteration#" |
sed -E 's/^2026-[0-9-]+ ([0-9:]+) (INFO|WARN) [A-Za-z]+:[0-9]+ - /\1 /; s/java.io.IOException: Got error.*(Out of space)/ ... \1/; s/:9866:DISK//g' | cut -c1-150
echo "### 3. After"
show
# In the hdfs-lab folder:
# bash add_node_and_balance.sh
# Remove the extra node afterwards: docker rm -f lab5-datanode-6Real output, with iterations 2 to 4 trimmed. 8 blocks moved in 16 s, then the 1.5 GB RAM disk refused more blocks (“Out of space”) and the balancer stopped after 5 idle iterations. No data was at risk: a failed move leaves the block where it was.
Deciding what a decommission must copy
For each block on the retiring node, count the replicas on other live nodes and decide whether a new copy is needed.
Worked examples: real problems, solved and traced in memory
Three admin calculations: how long a decommission takes, how much data a balancer must move, and how much faster it runs with more bandwidth. Each runs live and is traced in memory.
How long to retire a 12 TB node?
Problem statement
A DataNode holds 12 TB. Re-replication across the cluster reaches about 1 GB/s in total. Roughly how long does decommissioning take, and why does it hardly matter how many blocks there are?
12 TB · 1 GB/s
about 3.4 hours
Approach
- Time = data ÷ total copy speed.
- Convert TB to GB (×1024).
- Convert seconds to hours.
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 must the balancer move?
Problem statement
Ten DataNodes of 40 TB each are 75% full. We add five empty 40 TB nodes. With threshold 10%, how much data must move at least, so that each new node is within 10% of the new average?
10 × 40 TB at 75% · 5 new × 40 TB · threshold 10%
average 50.0%, each new node needs 16.0 TB, total 80 TB
Approach
- New average = total used ÷ total capacity.
- Each new node needs at least (average − 10%) × 40 TB.
- Multiply by 5.
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 long will that take at 100 MB/s per node?
Problem statement
Moving those 80 TB: each of the 5 new nodes receives at most at the balancer bandwidth (default 100 MB/s per DataNode). How long does it take at 100 MB/s, and at 300 MB/s set with -setBalancerBandwidth at night?
80 TB · 5 receivers · 100 or 300 MB/s
100 MB/s: 47 hours (1.9 days) 300 MB/s: 16 hours (0.6 days)
Approach
- Each new node receives 16 TB.
- Time = 16 TB ÷ per-node bandwidth.
- Compare the two settings.
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 6.4 in one screen
hdfs dfsadmin -report: capacity, dead nodes, missing / under-replicated blocks, per-node status.hdfs fsck path -files -blocks -locations -racks: health from metadata; read-only by default.- Decommission: host in
dfs.hosts.exclude→-refreshNodes→ Decommission in progress → Decommissioned → stop. Lab: 52 s and 60 s. - Recommission: remove from the exclude file + refresh; excess replicas are deleted, so the node may come back empty.
- New nodes are not filled automatically: run
hdfs balancer [-threshold 10]. - Balanced = every node within threshold % (of capacity) of the average; range 1 to 100.
- Lab balancer: 8 blocks, 914.72 MB in 16 s; then “Out of space” and exit after 5 idle iterations.
- Bandwidth: 100 MB/s per node by default; change live with
-setBalancerBandwidth.
Interview and viva questions
What is DataNode decommissioning in HDFS?
The safe way to remove a DataNode. You list it in the exclude file (dfs.hosts.exclude) and run hdfs dfsadmin -refreshNodes. The NameNode copies all its block replicas to other nodes while it keeps serving reads. When every block has enough replicas elsewhere, its status becomes Decommissioned and it can be shut down.
How do you add a new DataNode to a running cluster?
Install Hadoop with the cluster's configuration on the new machine and start the DataNode; it registers with the NameNode on its own. If an include file (dfs.hosts) is used, add it there and run -refreshNodes. Then run the balancer so existing data spreads onto it.
What does the HDFS balancer do?
It moves block replicas from DataNodes whose utilisation is above the cluster average to those below it, until every node is within the threshold (default 10%) of the average. Each move copies the block to the target and then removes one source replica, respecting rack placement, so replication is unchanged.
Is it safe to stop the balancer in the middle?
Yes. Each block move is complete or not done at all; stopping the balancer leaves the cluster partly balanced but fully consistent. You can rerun it later.
What is the difference between fsck in Linux and hdfs fsck?
Linux fsck checks and repairs a local file system's structures. hdfs fsck reports HDFS health from the NameNode: missing, corrupt and under-replicated blocks per file. It does not repair; HDFS repairs replicas itself, and -move or -delete only deal with files that have lost all good replicas.
Why is a decommission stuck in progress?
Usually some blocks cannot get new replicas: not enough nodes or racks for the placement policy, full disks, a failing target node, or files still open for writing. The NameNode log shows lines like “still has 1 blocks to replicate”, and hdfs fsck or -report -decommissioning help find them.
Practice problems
Admin exercises using real reports, logs and timings from the lab.
Read the report
From the real report lines, how much of the configured capacity is used by HDFS, in %?
Configured Capacity 1352765870080 · DFS Used 3037733930
0.22%
Show solution and explanation
print(f"{100 * 3037733930 / 1352765870080:.2f}%")How it works: 0.22% of configured capacity. The report printed 3.28% because DFS Used% is relative to Present Capacity (86.37 GB), not the 1.23 TB configured.
Decommission duration
The real watcher printed status at t = 2, 8, 14, 20, 28, 34, 40, 46 s (in progress) and 52 s (Decommissioned). How many checks were in progress, and what was the average gap between checks?
2 8 14 20 28 34 40 46 52
in progress: 8 average gap: 6.25 s
Show solution and explanation
t = [2, 8, 14, 20, 28, 34, 40, 46, 52]
gaps = [b - a for a, b in zip(t, t[1:])]
print("in progress:", len(t) - 1, " average gap:", sum(gaps) / len(gaps), "s")How it works: 8 checks in progress, one every 6.25 s on average (sleep plus the time each -report takes), then Decommissioned at 52 s.
Bandwidth in MB/s
Convert the real -setBalancerBandwidth 52428800 and the default 104857600 to MB/s.
52428800 · 104857600 bytes/s
52428800 = 50.0 MB/s 104857600 = 100.0 MB/s
Show solution and explanation
for b in [52428800, 104857600]:
print(b, "=", b / 1024 / 1024, "MB/s")How it works: 50 MB/s and 100 MB/s per DataNode.
Parse balancer moves
From real “Successfully moved” lines, total the bytes moved and count moves per source.
three log lines
274.71836280822754 MB {'172.19.0.4': 2, '172.19.0.7': 1}Show solution and explanation
from collections import Counter
lines = ["Successfully moved blk_1073741846_1022 with size=19627626 from 172.19.0.4 to 172.19.0.9",
"Successfully moved blk_1073741860_1038 with size=134217728 from 172.19.0.7 to 172.19.0.9",
"Successfully moved blk_1073741844_1020 with size=134217728 from 172.19.0.4 to 172.19.0.9"]
total, src = 0, Counter()
for l in lines:
w = l.split()
total += int(w[4].split("=")[1]); src[w[6]] += 1
print(total / 1024 / 1024, "MB", dict(src))How it works: About 274.7 MB from 3 moves; 172.19.0.4 was the source twice. On all 8 lines this gives the 914.72 MB the balancer printed.
Over or under?
Classify nodes like the balancer: over-utilised (> avg + t), above average, below average, under-utilised (< avg − t), with t = 10.
utilisations 92, 81, 70, 64, 12 %
dn-1 92 over dn-2 81 over dn-3 70 above dn-4 64 above dn-6 12 under average 63.8
Show solution and explanation
util = {"dn-1": 92, "dn-2": 81, "dn-3": 70, "dn-4": 64, "dn-6": 12}
avg, t = sum(util.values()) / len(util), 10
for n, u in util.items():
kind = "over" if u > avg + t else "above" if u > avg else "under" if u < avg - t else "below"
print(n, u, kind)
print("average", avg)How it works: Average 63.8%: dn-1 and dn-2 over-utilised, dn-3 and dn-4 above average, dn-6 under-utilised. The balancer pairs over with under first, as the real log shows (“overUtilized => underUtilized”).
Safe to stop two nodes?
Given replica locations, can dn-2 and dn-5 be stopped at the same time without making any block unavailable?
block → nodes
A live replicas left: 1 B live replicas left: 1 C live replicas left: 2
Show solution and explanation
blocks = {"A": {"dn-2", "dn-4", "dn-5"}, "B": {"dn-2", "dn-5", "dn-3"}, "C": {"dn-1", "dn-2", "dn-3"}}
stop = {"dn-2", "dn-5"}
for b, nodes in blocks.items():
left = nodes - stop
print(b, "live replicas left:", len(left), "" if left else "<- UNAVAILABLE")How it works: All keep at least 1 replica, but A and B drop to 1: one more failure loses them. Decommission instead, or stop one at a time.
Cost of an empty new rack
A new rack of 20 nodes (Rs 4.5 lakh each) is added but the balancer is never run; for 6 months it holds only 5% of data while old nodes run near full and jobs slow down. What is the investment sitting mostly idle?
20 × Rs 4.5 lakh · 5% used
Rs 90 lakh of hardware, about Rs 85.5 lakh of it unused
Show solution and explanation
cost = 20 * 4.5
print(f"Rs {cost:.0f} lakh of hardware, about Rs {cost * 0.95:.1f} lakh of it unused")How it works: Rs 90 lakh of servers, about Rs 85.5 lakh worth idle (illustrative). A balancer run on day one puts it to work.
Decommission planner
Simulate decommissioning dn-4: for each of its blocks choose a target node that does not already hold the block, prefers keeping replicas on 2 racks, and has the most free space. Print the plan.
4 blocks · 2 racks · free space per node
A copy to dn-1 racks [1, 2] B copy to dn-2 racks [1, 2] D copy to dn-2 racks [1, 2]
Show solution and explanation
rack = {"dn-1": 1, "dn-2": 1, "dn-3": 2, "dn-4": 2, "dn-5": 2}
free = {"dn-1": 50, "dn-2": 80, "dn-3": 30, "dn-5": 60}
blocks = {"A": ["dn-2", "dn-4", "dn-5"], "B": ["dn-4", "dn-1", "dn-3"], "D": ["dn-4", "dn-3", "dn-5"]}
for b, nodes in blocks.items():
if "dn-4" not in nodes:
continue
keep = [n for n in nodes if n != "dn-4"]
racks = {rack[n] for n in keep}
cands = [n for n in free if n not in keep]
if len(racks) == 1: # all others on one rack: need the other rack
cands = [n for n in cands if rack[n] not in racks]
target = max(cands, key=free.get)
free[target] -= 1
print(b, "copy to", target, "racks", sorted(racks | {rack[target]}))How it works: A goes to dn-1 (dn-2 and dn-5 already span both racks, so the most free space wins after dn-2 is excluded). B goes to dn-2. D (left only on rack 2) must go to rack 1: dn-2. Real NameNodes apply the same ideas with more rules.
Real-world scenario questions (asked in company interviews)
Admin questions separate people who have run a cluster from people who have only read about one.
“How do you remove a DataNode from a cluster?”
The classic commissioning and decommissioning question.
The interviewer is checking: exclude file, refreshNodes, waiting for completion.
Show a strong answer
- Add the host to the file named by
dfs.hosts.exclude, runhdfs dfsadmin -refreshNodes. - Watch
-reportuntil the status is Decommissioned; the NameNode copies all its blocks meanwhile. Then stop the DataNode and remove it. - Confirm with
hdfs fsck /: HEALTHY, 0 under-replicated. Never just switch it off.
New nodes added last month are almost empty
Old DataNodes are at 92% and jobs fail with disk-full errors, while 10 new nodes are at 8%.
The interviewer is checking: that HDFS never rebalances existing data on its own.
Show a strong answer
- Only new writes land on new nodes; existing blocks stay put. Run
hdfs balancer -threshold 10(or lower). - Run it off-peak, raise
-setBalancerBandwidthat night, and repeat until balanced. - Short term, free space on the full nodes (old temp data, trash) so jobs stop failing.
Decommission has been “in progress” for a day
The NameNode log repeats “still has 1 blocks to replicate”.
The interviewer is checking: placement constraints and stuck blocks.
Show a strong answer
- Find the block in the log (BlockStateChange lines show its replicas) and its file with
hdfs fsck. - Typical causes: no node/rack where a replica may go (small cluster, whole rack being retired), full or failing target disks, a file still open for writing, or replication higher than the node count.
- Fix the cause: add capacity, close or recover the file, lower its replication; in our lab a broken target node kept failing until its pending copy timed out (5 minutes) and another node was chosen.
“What does hdfs fsck tell you?”
A quick check of whether you know what fsck reads and changes.
The interviewer is checking: read-only report vs repair.
Show a strong answer
- For a path: files, blocks, replicas (with
-files -blocks -locations -racks), and totals of missing, corrupt, under- and over-replicated blocks; status HEALTHY or CORRUPT. - It reads NameNode metadata only and changes nothing unless you pass
-moveor-delete. - HDFS repairs under-replicated blocks itself; fsck tells you whether anything is beyond repair.