Admin commands: dfsadmin, fsck and balancer

Servers come and go: disks fail, new machines arrive. This lesson shows the tools that keep HDFS healthy through all of it, on a real 5-node cluster: dfsadmin to see and control the cluster, fsck to prove every block is safe, decommissioning to retire a DataNode without risk, and the balancer to spread data onto a new node.

Module 6 · HDFS operations⏱ 28 minIntermediateReal decommission and balancer runsBalancer simulatorRuns in your browser (Python)8 practice problems
1 The story

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.

dfsadmin -report-refreshNodes-safemode-printTopology see and control fsck -files -blocks-racks-list-corrupt… is my data healthy? decommission exclude file+ refreshNodescopy blocks away retire a node safely balancer full nodes →empty nodes-threshold % spread blocks evenly All four ran on our 5-DataNode lab cluster; the outputs below are real. myphatshala.in
Arjun Sir

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.

Riya

And the new server?

Arjun Sir

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.

2 Definition

HDFS administration tools

Formal definition (write this in exams)

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.

In simple words

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

DecommissionRetire a DataNode after copying its blocks elsewhere.
Exclude fileThe file named by dfs.hosts.exclude: nodes listed there are decommissioned.
refreshNodesTells the NameNode to re-read the include/exclude files, without a restart.
RecommissionRemove a node from the exclude file and refresh: it becomes Normal again.
UtilisationHow full a DataNode is: used space as a % of its capacity.
ThresholdBalancer target: every node within this many % of the average (default 10).
IterationOne round of balancer planning and block moves.
Maintenance modeShort planned downtime for a node without copying all its blocks.

Defaults and limits (Hadoop 3.5.0, from the lab)

Balancer threshold10% by default; allowed range 1.0 to 100.0 (“Expecting a number in the range of [1.0, 100.0]”)
Balancer bandwidthdfs.datanode.balance.bandwidthPerSec = 104857600 (100 MB/s per DataNode)
Concurrent movesdfs.datanode.balance.max.concurrent.moves = 100
Gives up after5 iterations with no block moved (“max idle iteration = 5”)
Decommission checkEvery 30 s (dfs.namenode.decommission.interval)
fsckRead-only by default; -move / -delete change files

Admin tools at three levels

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

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?) and hdfs 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 -setBalancerBandwidth only when jobs are quiet.
  • Recommissioned nodes often lose their replicas as “excess” and come back nearly empty: plan a balancer run.
  • fsck on / 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.

3 Types and ways to use it

The commands you will actually use

ToolCommandWhat it tells or does
dfsadmin-report [-live|-dead|-decommissioning]Capacity, used, remaining; per-DataNode status and block counts
dfsadmin-refreshNodesRe-read include/exclude files: start decommission or recommission
dfsadmin-safemode get|enter|leave|waitSafe mode control (Lesson 5.6)
dfsadmin-printTopologyRacks and nodes, with In Service / Decommissioned
dfsadmin-getDatanodeInfo host:9867Uptime and software version of one DataNode
dfsadmin-setBalancerBandwidth bytesChange balancer speed on all DataNodes, no restart
dfsadmin-saveNamespace, -fetchImage dirForce a checkpoint (needs safe mode); download the latest fsimage
fsckpath -files -blocks -locations -racksEvery file, block and replica location
fsck/ -list-corruptfileblocksOnly the damaged blocks
fsck-move / -deleteMove corrupt files to /lost+found or delete them (last resort)
balancer-threshold N, -exclude, -sourceHow 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, slow

Maintenance mode

For a reboot or short repair: blocks with enough other replicas are not copied; the node comes back with its data.

Planned, short

Just stop it

HDFS treats it as a failure: dead after about 10.5 minutes, then re-replication. Fine for crashes, wrong for planned work.

Unplanned

Stop many at once

Several nodes holding all replicas of a block = missing data. Always one at a time, or decommission together.

Dangerous

Run 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”.

4 Step by step

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

  1. Morning check: dfsadmin -report

    hdfs dfsadmin -report -dead
    Configured 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):
    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.
  2. Health check: fsck

    hdfs fsck / -list-corruptfileblocks
    hdfs fsck /user/hadoop/canteen -files -blocks -racks
    The 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: HEALTHY
    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.
  3. Who is where: topology and node info

    hdfs dfsadmin -printTopology
    hdfs dfsadmin -getDatanodeInfo lab5-datanode-1:9867
    Rack: /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-1
    9867 is the DataNode's IPC port (9866 is its data port). Uptime is in seconds.
  4. Decommission datanode-4

    # 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 seconds
    Refresh 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 : Decommissioned
    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.
  5. Prove it, then bring it back

    hdfs fsck / | grep -E 'Status|Under-replicated|Number of data-nodes'
    > /opt/hadoop/etc/hadoop/dfs.exclude          # empty the exclude file
    hdfs dfsadmin -refreshNodes
    Status: HEALTHY Number of data-nodes: 4 Under-replicated blocks: 0 (0.0 %) Refresh nodes successful Decommission Status : Normal
    “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.
  6. A new, empty node and the balancer

    docker run -d --name lab5-datanode-6 ... --tmpfs /tmp/hadoop-hadoop:size=1536m apache/hadoop:3.5.0 hdfs datanode
    hdfs balancer -threshold 5
    INFO 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)
    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.
  7. When the balancer gives up

    # same run, iterations 1 to 5
    Need 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%
    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.
  8. Speed limits and mistakes

    hdfs dfsadmin -setBalancerBandwidth 52428800
    hdfs balancer -threshold 0.5
    hdfs dfsadmin -saveNamespace
    Balancer 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.
    52428800 bytes = 50 MB/s per DataNode, applied at once. The threshold must be at least 1%. -saveNamespace is 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.

5 See it happen

Decommission, then balance

Block A lives on dn-2, dn-4 and dn-5. We retire dn-4, then add an empty dn-6.

Retire a node and fill a new one 6 steps
What you see hadoop@namenode : ~ $ hdfs dfsadmin -report172.19.0.7 Decommission Status : NormalNum of Blocks: 11 $ echo 172.19.0.7 > dfs.exclude$ hdfs dfsadmin -refreshNodesRefresh nodes successful t=2s Decommission in progresst=8s Decommission in progresst=46s Decommission in progress t=52s Decommissioned$ hdfs fsck /Status: HEALTHY Under-replicated: 0 $ hdfs balancer -threshold 51 underutilized: [172.19.0.9]Need to move 1.32 GB Successfully moved blk_…844 to 172.19.0.9… moved in this iteration 914.72 MB (8)172.19.0.9 used 60.02% myphatshala.in
Behind the screen NameNode dn-2 dn-3 dn-4 dn-5 A A A A dn-6 (new, own disk) B dn-4 marked “decommissioning”: still serves reads copy A from a live replica to dn-3 all blocks have 3 other replicas: safe to switch off dn-6 empty → “underutilized” block B copied to dn-6, then removed from its source myphatshala.in
6 Real-world use

Admin tools at work

old serversone by one

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.

Add new→Balance + decommission→Remove old
balancer01:00 to 06:00

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.

Scheduler→balancer→Even disks by morning
HEALTHYmissing: 0

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.

NameNode metrics→Alert rules→On-call
maintenancereboot, patch

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.

Maintenance→Patch + reboot→In service

Simplified; organisations differ in tools and policies.

7 Run the code

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}%")
average 57.6% moves 15 (1920 MB) dn-1: 60.8% dn-2: 60.8% dn-3: 60.8% dn-6: 48.0%
  • 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.7
before: Decommission Status: Normal, Num of Blocks: 2 Refresh nodes successful t=1s Decommission Status: Decommission in progress, Num of Blocks: 2 t=8s Decommission Status: Decommission in progress, Num of Blocks: 2 t=14s Decommission Status: Decommission in progress, Num of Blocks: 2 t=21s Decommission Status: Decommission in progress, Num of Blocks: 2 t=27s Decommission Status: Decommission in progress, Num of Blocks: 2 t=34s Decommission Status: Decommission in progress, Num of Blocks: 2 t=40s Decommission Status: Decommission in progress, Num of Blocks: 2 t=47s Decommission Status: Decommission in progress, Num of Blocks: 2 t=53s Decommission Status: Decommission in progress, Num of Blocks: 2 t=60s Decommission Status: Decommissioned, Num of Blocks: 2 Status: HEALTHY Number of data-nodes: 5 Under-replicated blocks: 0 (0.0 %) ### recommission Refresh nodes successful after: Decommission Status: Normal, Num of Blocks: 0

Real 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-6
### 1. Start datanode-6 with a 1.5 GB disk of its own (a RAM disk) 172.19.0.3 used 0.32% 172.19.0.4 used 0.37% 172.19.0.6 used 0.37% 172.19.0.7 used 0.05% 172.19.0.8 used 0.00% 172.19.0.9 used 0.00% ### 2. Balancer, threshold 5% Time Stamp Iteration# Bytes Already Moved Bytes Left To Move Bytes Being Moved NameNode 10:03:05 1 underutilized: [172.19.0.9] 10:03:05 Need to move 1.32 GB to make the cluster balanced. 10:03:05 Decided to move 340.33 MB bytes from 172.19.0.7 to 172.19.0.9 10:03:05 Decided to move 250.58 MB bytes from 172.19.0.8 to 172.19.0.9 10:03:05 Decided to move 250.54 MB bytes from 172.19.0.6 to 172.19.0.9 10:03:05 Decided to move 250.58 MB bytes from 172.19.0.3 to 172.19.0.9 10:03:05 Decided to move 340.38 MB bytes from 172.19.0.4 to 172.19.0.9 ... Out of space: The volume with the most available space (=1073725440 B) is less than the block size (=134217728 B)., reportedBlock move is failed 10:03:07 Successfully moved blk_1073741846_1022 with size=19627626 from 172.19.0.4 to 172.19.0.9 through 172.19.0.6:9866 10:03:08 Successfully moved blk_1073741860_1038 with size=134217728 from 172.19.0.7 to 172.19.0.9 through 172.19.0.7:9866 10:03:17 Successfully moved blk_1073741844_1020 with size=134217728 from 172.19.0.4 to 172.19.0.9 through 172.19.0.6:9866 10:03:18 Successfully moved blk_1073741847_1024 with size=134217728 from 172.19.0.3 to 172.19.0.9 through 172.19.0.6:9866 10:03:20 Successfully moved blk_1073741845_1021 with size=134217728 from 172.19.0.4 to 172.19.0.9 through 172.19.0.6:9866 10:03:20 Successfully moved blk_1073741849_1026 with size=134217728 from 172.19.0.4 to 172.19.0.9 through 172.19.0.6:9866 10:03:20 Successfully moved blk_1073741850_1027 with size=134217728 from 172.19.0.6 to 172.19.0.9 through 172.19.0.6:9866 10:03:20 Successfully moved blk_1073741842_1018 with size=134217728 from 172.19.0.6 to 172.19.0.9 through 172.19.0.6:9866 Oct 21, 2026, 10:03:21 AM 0 914.72 MB 1.32 GB 1.40 GB 8 hdfs://namenode:8020 10:03:30 1 underutilized: [172.19.0.9] 10:03:30 Need to move 430.09 MB to make the cluster balanced. 10:03:30 Decided to move 26.85 MB bytes from 172.19.0.7 to 172.19.0.9 10:03:30 Decided to move 195.07 MB bytes from 172.19.0.6 to 172.19.0.9 10:03:30 Decided to move 65.06 MB bytes from 172.19.0.8 to 172.19.0.9 10:03:30 Decided to move 65.06 MB bytes from 172.19.0.3 to 172.19.0.9 10:03:30 Decided to move 154.85 MB bytes from 172.19.0.4 to 172.19.0.9 ... Out of space: The volume with the most available space (=643919872 B) is less than the block size (=134217728 B)., reportedBlock move is failed Oct 21, 2026, 10:03:31 AM 1 914.72 MB 430.09 MB 506.89 MB 8 hdfs://namenode:8020 [... iterations 2, 3 and 4 print the same lines; trimmed here ...] 10:04:10 1 underutilized: [172.19.0.9] 10:04:10 Need to move 429.78 MB to make the cluster balanced. 10:04:10 Decided to move 116.60 MB bytes from 172.19.0.8 to 172.19.0.9 10:04:10 Decided to move 78.39 MB bytes from 172.19.0.7 to 172.19.0.9 10:04:10 Decided to move 116.60 MB bytes from 172.19.0.3 to 172.19.0.9 10:04:10 Decided to move 194.99 MB bytes from 172.19.0.4 to 172.19.0.9 ... Out of space: The volume with the most available space (=643919872 B) is less than the block size (=134217728 B)., reportedBlock move is failed No block has been moved for 5 iterations. Exiting... Oct 21, 2026, 10:04:11 AM 5 914.72 MB 429.78 MB 506.58 MB 8 hdfs://namenode:8020 Oct 21, 2026, 10:04:11 AM Balancing took 1.1124 minutes ### 3. After 172.19.0.3 used 0.27% 172.19.0.4 used 0.22% 172.19.0.6 used 0.27% 172.19.0.7 used 0.00% 172.19.0.8 used 0.00% 172.19.0.9 used 60.02%

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

8 Line by line

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.

Example 1BeginnerDecommission · time

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?

Input
12 TB · 1 GB/s
Expected output
about 3.4 hours

Approach

  1. Time = data ÷ total copy speed.
  2. Convert TB to GB (×1024).
  3. 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.

Example 2IntermediateBalancer · planning

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?

Input
10 × 40 TB at 75% · 5 new × 40 TB · threshold 10%
Expected output
average 50.0%, each new node needs 16.0 TB, total 80 TB

Approach

  1. New average = total used ÷ total capacity.
  2. Each new node needs at least (average − 10%) × 40 TB.
  3. 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.

Example 3AdvancedBalancer · bandwidth

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?

Input
80 TB · 5 receivers · 100 or 300 MB/s
Expected output
100 MB/s: 47 hours (1.9 days)
300 MB/s: 16 hours (0.6 days)

Approach

  1. Each new node receives 16 TB.
  2. Time = 16 TB ÷ per-node bandwidth.
  3. 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.

9 Quiz and revision

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.

P1Easy

Read the report

From the real report lines, how much of the configured capacity is used by HDFS, in %?

Input
Configured Capacity 1352765870080 · DFS Used 3037733930
Expected output
0.22%
Show solution and explanation
print(f"{100 * 3037733930 / 1352765870080:.2f}%")
0.22%

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.

P2Easy

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?

Input
2 8 14 20 28 34 40 46 52
Expected output
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")
in progress: 8 average gap: 6.25 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.

P3Easy

Bandwidth in MB/s

Convert the real -setBalancerBandwidth 52428800 and the default 104857600 to MB/s.

Input
52428800 · 104857600 bytes/s
Expected output
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")
52428800 = 50.0 MB/s 104857600 = 100.0 MB/s

How it works: 50 MB/s and 100 MB/s per DataNode.

P4Medium

Parse balancer moves

From real “Successfully moved” lines, total the bytes moved and count moves per source.

Input
three log lines
Expected output
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))
274.71836280822754 MB {'172.19.0.4': 2, '172.19.0.7': 1}

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.

P5Medium

Over or under?

Classify nodes like the balancer: over-utilised (> avg + t), above average, below average, under-utilised (< avg − t), with t = 10.

Input
utilisations 92, 81, 70, 64, 12 %
Expected output
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)
dn-1 92 over dn-2 81 over dn-3 70 above dn-4 64 above dn-6 12 under average 63.8

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

P6Medium

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?

Input
block → nodes
Expected output
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")
A live replicas left: 1 B live replicas left: 1 C live replicas left: 2

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.

P7Business problem

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?

Input
20 × Rs 4.5 lakh · 5% used
Expected output
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")
Rs 90 lakh of hardware, about Rs 85.5 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.

P8Advanced

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.

Input
4 blocks · 2 racks · free space per node
Expected output
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]}))
A copy to dn-1 racks [1, 2] B copy to dn-2 racks [1, 2] D copy to dn-2 racks [1, 2]

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.

HDFS · operationsFresher

“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, run hdfs dfsadmin -refreshNodes.
  • Watch -report until 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.
Operations · capacityExperienced

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 -setBalancerBandwidth at night, and repeat until balanced.
  • Short term, free space on the full nodes (old temp data, trash) so jobs stop failing.
TroubleshootingExperienced

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.
HDFS · healthFresher

“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 -move or -delete.
  • HDFS repairs under-replicated blocks itself; fsck tells you whether anything is beyond repair.