HDFS federation

HA protects the NameNode from failure, but not from its own limits: every file and block lives in one NameNode's memory. Federation runs several independent NameNodes, each owning part of the folder tree, on the same DataNodes. This lesson builds a two-NameNode cluster, looks at the block pools on a DataNode's disk, and shows what works and what doesn't across namespaces.

Module 7 · HDFS advanced⏱ 26 minAdvancedReal two-NameNode clusterBlock pools on diskRuns in your browser (Python)8 practice problems
1 The story

When one NameNode's memory is not enough

The university cluster is a success. The canteen project, the hostel system, exam results and research labs all store data in it. Now there are hundreds of millions of files. The NameNode keeps every file and block in RAM, its heap is already huge, garbage-collection pauses are getting longer, and every team's jobs queue up behind the same NameNode. Adding DataNodes adds disk, but not a single extra byte of NameNode memory. HA (Lesson 7.1) gave the NameNode a spare, but the spare has exactly the same limits.

Client view (ViewFS / Router)/canteen → NN-1 · /hostel → NN-2 NameNode 1: canteennamespace /canteen · block pool BP-1 NameNode 2: hostelnamespace /hostel · block pool BP-2 DataNode 1DataNode 2DataNode 3 Every DataNode stores blocks for both NameNodes, in separate block pools (blue = canteen, orange = hostel). myphatshala.in
Arjun Sir

The answer is HDFS federation. Instead of one NameNode for everything, we run several independent NameNodes, each owning part of the namespace: one for /canteen, one for /hostel. They don't talk to each other at all.

Riya

Then each one needs its own DataNodes?

Arjun Sir

No, that's the clever part. The same DataNodes serve all of them. Each NameNode gets its own block pool on every DataNode, so storage is shared and grows for everyone. Clients see one tree through a mount table. Today we start two NameNodes on the same three DataNodes, look inside a DataNode's disk, try to move a file between them, and switch one NameNode off.

2 Definition

HDFS federation

Formal definition (write this in exams)

HDFS federation scales the namespace layer horizontally by running multiple independent NameNodes, each managing its own namespace volume: a namespace (directory tree and file metadata) plus a block pool (the set of blocks belonging to that namespace). NameNodes do not coordinate with each other. All NameNodes share one cluster ID and the same set of DataNodes; each DataNode registers with every NameNode, stores blocks of each pool in a separate directory (current/BP-…), and sends heartbeats and block reports per pool. Clients obtain a unified view through a client-side mount table (ViewFS, viewfs://) or through Router-Based Federation (RBF), where stateless routers forward requests according to a shared mount table. Each nameservice may itself be highly available.

In simple words

Several NameNodes split the folder tree between them, like several librarians each responsible for different sections, while all the bookshelves (DataNodes) are shared. A map tells clients which librarian to ask for which folder.

Words you'll meet in this lesson

Namespace volumeOne NameNode's namespace plus its block pool.
Block pool (BP)The blocks of one namespace; a BP-… folder on every DataNode.
Cluster IDShared by all federated NameNodes; set with -clusterId at format.
NameserviceThe ID of one namespace (and its HA NameNodes), e.g. nsc, nsh.
ViewFSClient-side mount table: viewfs://campus/canteen → hdfs://nn-canteen/canteen.
RBFRouter-Based Federation: routers hold the mount table centrally.
Mount pointA path in the unified view that maps to a folder in one namespace.
Namespace limitOne NameNode's heap and RPC capacity: what federation spreads out.

What we saw in the lab (Hadoop 3.5.0)

Block pools on a DataNodeTwo folders: BP-1200013783-… (canteen, 2.5 M) and BP-343349822-… (hostel, 572 K)
Cluster IDcampus-cluster on both NameNodes; different block pool IDs
Live DataNodesBoth NameNodes report 3: the same machines
Move across mountsmv: Renames across Mount points not supported
One NameNode down/hostel still listed; /canteen fails

Federation at three levels

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

Beginner A library with several librarians

  • One librarian can only remember so many books. So the library hires a second: one for science, one for arts.
  • Both use the same shelves. Each shelf has a science corner and an arts corner (block pools).
  • A signboard at the entrance says which librarian to ask for which section (mount table). If the arts librarian is on leave, science books can still be borrowed.

Intermediate How it is set up and used

  • Format each NameNode with the same cluster ID (hdfs namenode -format -clusterId campus-cluster); list all nameservices in dfs.nameservices so DataNodes register with every NameNode.
  • Each NameNode only knows its own files: hdfs dfs -ls -R hdfs://nn-canteen:8020/ showed only /canteen.
  • With a ViewFS mount table, hdfs dfs -ls / shows /canteen, /hostel, /tmp as one tree.
  • Moving a file between namespaces is a copy (distcp or cp) plus delete, not a rename.

Advanced What architects weigh

  • Why: NameNode heap grows with objects (files, folders, blocks); a common rule of thumb is roughly 150 bytes per object, so hundreds of millions of objects need very large heaps. RPC load also concentrates on one process. Federation splits both.
  • ViewFS vs RBF: ViewFS puts the mount table in every client's configuration (changes must reach every client); RBF keeps it in a shared state store behind routers, so clients use one address and admins can move mount points centrally.
  • Federation + HA: independent. A large cluster may have 4 nameservices, each with an active and standby NameNode.
  • Costs: more NameNodes to run and monitor, uneven growth between namespaces, and no atomic rename across them. Choosing the split (by team, by data domain) matters.

Exam tip: For “Explain HDFS federation”, draw two NameNodes with separate namespaces and block pools, shared DataNodes with one folder per block pool, and a mount table on top. Contrast with HA: HA = availability of one namespace; federation = scalability of the namespace.

3 Types and ways to use it

HA vs federation, and two ways to unify the view

HAFederation
SolvesNameNode failure (availability)NameNode limits (scalability, isolation)
NameNodesActive + standby with the SAME namespaceIndependent, DIFFERENT namespaces
SharedEdit log (JournalNodes)DataNodes and cluster ID
Block poolsOneOne per namespace
Client addresshdfs://nameserviceviewfs://… or router address
Combine?Yes: each federated nameservice can be an HA pair.

Unifying the namespaces

ViewFS

Mount table in the client's core-site.xml (fs.viewfs.mounttable.*). Simple, no extra servers; every client needs the same config.

client-side

Router-Based Federation

hdfs dfsrouter processes with a shared state store; hdfs dfsrouteradmin -add /canteen nsc /canteen. Clients talk to routers.

server-side

Direct URIs

hdfs://nn-hostel:8020/hostel: works, but hard-codes which namespace holds the data.

avoid

Split by

Team, business domain or data type (e.g. /user vs /warehouse vs /tmp), so each namespace grows predictably.

design

Putting /tmp and other small-file-heavy, high-churn folders on their own namespace is a classic use of federation: their constant creates and deletes no longer slow down the NameNode that serves production data.

4 Step by step

Two NameNodes, three shared DataNodes

Our lab: NameNodes nn-canteen (nameservice nsc) and nn-hostel (nsh), and 3 DataNodes, all apache/hadoop:3.5.0. Commands run on datanode-1; full script in “Run it on your PC”.

  1. Configure two nameservices, format with one cluster ID

    HDFS-SITE.XML_dfs.nameservices=nsc,nsh
    HDFS-SITE.XML_dfs.namenode.rpc-address.nsc=nn-canteen:8020
    HDFS-SITE.XML_dfs.namenode.rpc-address.nsh=nn-hostel:8020
    # on each NameNode, once:
    hdfs namenode -format -nonInteractive -clusterId campus-cluster
    nn-canteen: blockpoolID=BP-1200013783-172.21.0.3-1792598083981 clusterID=campus-cluster nn-hostel: blockpoolID=BP-343349822-172.21.0.2-1792598083339 clusterID=campus-cluster
    Same cluster ID, different block pool IDs. A DataNode accepts NameNodes only from its own cluster ID, so getting this right at format time is essential.
  2. One tree for the client

    <name>fs.defaultFS</name><value>viewfs://campus</value>
    <name>fs.viewfs.mounttable.campus.link./canteen</name><value>hdfs://nn-canteen:8020/canteen</value>
    <name>fs.viewfs.mounttable.campus.link./hostel</name><value>hdfs://nn-hostel:8020/hostel</value>
    $ hdfs dfs -ls / Found 3 items -r-xr-xr-x - hadoop users 0 2026-10-21 15:58 /canteen -r-xr-xr-x - hadoop users 0 2026-10-21 15:58 /hostel -r-xr-xr-x - hadoop users 0 2026-10-21 15:58 /tmp $ hdfs dfs -ls /canteen /hostel -rw-r--r-- 3 hadoop supergroup 2488895 2026-10-21 15:58 /canteen/orders.csv -rw-r--r-- 3 hadoop supergroup 538894 2026-10-21 15:58 /hostel/rooms.csv
    The root / is not stored anywhere: ViewFS builds it from the mount table (hence the read-only r-x entries). Each mount point leads to a different NameNode.
  3. Each NameNode knows only its own files

    hdfs dfs -ls -R hdfs://nn-canteen:8020/ ; echo ---; hdfs dfs -ls -R hdfs://nn-hostel:8020/
    drwxr-xr-x - hadoop supergroup 0 2026-10-21 15:58 hdfs://nn-canteen:8020/canteen -rw-r--r-- 3 hadoop supergroup 2488895 2026-10-21 15:58 hdfs://nn-canteen:8020/canteen/orders.csv --- drwxr-xr-x - hadoop supergroup 0 2026-10-21 15:58 hdfs://nn-hostel:8020/hostel -rw-r--r-- 3 hadoop supergroup 538894 2026-10-21 15:58 hdfs://nn-hostel:8020/hostel/rooms.csv drwxr-xr-x - hadoop supergroup 0 2026-10-21 15:55 hdfs://nn-hostel:8020/tmp
    Two completely separate directory trees, each in its own NameNode's memory.
  4. Inside a DataNode: one folder per block pool

    ls /tmp/hadoop-hadoop/dfs/data/current/ ; du -sh /tmp/hadoop-hadoop/dfs/data/current/BP-*
    for nn in nn-canteen nn-hostel; do hdfs dfsadmin -fs hdfs://$nn:8020 -report | grep -m1 'Live datanodes'; done
    BP-1200013783-172.21.0.3-1792598083981 BP-343349822-172.21.0.2-1792598083339 VERSION 2.5M /tmp/hadoop-hadoop/dfs/data/current/BP-1200013783-172.21.0.3-1792598083981 572K /tmp/hadoop-hadoop/dfs/data/current/BP-343349822-172.21.0.2-1792598083339 nn-canteen: Live datanodes (3): nn-hostel: Live datanodes (3):
    The same disk holds both pools: 2.5 MB of canteen orders, 572 KB of hostel rooms. Both NameNodes see all three DataNodes, which heartbeat to each separately.
  5. No rename across namespaces

    hdfs dfs -mv /canteen/orders.csv /hostel/orders.csv
    mv: Renames across Mount points not supported
    A rename is a metadata change inside one NameNode. Two NameNodes can't do it atomically together, so you must copy and delete. Plan the namespace split so that jobs don't need to move data across it.
  6. Switch one NameNode off

    docker stop lab72-nn-canteen-1
    hdfs dfs -ls /hostel
    hdfs dfs -ls /canteen
    -rw-r--r-- 3 hadoop supergroup 538894 2026-10-21 15:58 /hostel/rooms.csv -ls: java.net.UnknownHostException: nn-canteen
    Failure isolation: the hostel namespace keeps working. The canteen namespace is unavailable (in our Docker lab the stopped container's name no longer resolves). In production, each nameservice would also be HA.

Federation does not make one namespace bigger or faster: a single folder tree still lives in one NameNode. If one team's namespace outgrows its NameNode, you must split that tree further (or reduce small files, Lesson 7.5).

5 See it happen

One client, two NameNodes, shared DataNodes

Six steps from our lab: writing to two mount points, looking at the DataNode, and losing one NameNode.

Federation in action 6 steps
What you see hadoop@datanode-1 : ~ $ hdfs dfs -put orders.csv /canteen/(done) $ hdfs dfs -put rooms.csv /hostel/(done) $ hdfs dfs -ls //canteen/hostel/tmp $ ls …/dfs/data/current/BP-1200013783-… 2.5MBP-343349822-… 572K $ hdfs dfs -mv /canteen/orders.csv /hostel/mv: Renames across Mount pointsnot supported (nn-canteen stopped)$ hdfs dfs -ls /hostel/hostel/rooms.csv$ hdfs dfs -ls /canteen-ls: UnknownHostException: nn-canteen myphatshala.in
Behind the screen client mount table/canteen→nsc /hostel→nsh nn-canteennsc · BP-1200013783 nn-hostelnsh · BP-343349822 datanode-1datanode-2datanode-3 /canteen → nn-canteen; blocks into pool BP-1200013783 /hostel → nn-hostel; same DataNodes, other pool “/” exists only in the mount table each DataNode: one folder per block pool, reports to both NNs ✗no shared metadata: rename across NameNodes impossible canteen down; hostel unaffected myphatshala.in
6 Real-world use

Federation at work

NN-1NN-2

1. Very large clusters

Organisations whose HDFS holds hundreds of millions to billions of files have publicly described running many NameNodes with federation, often behind routers, because no single NameNode heap could hold their namespace.

Billions of files→Many nameservices→One view via routers
/tmpown NameNode

2. Isolating noisy workloads

Scratch and staging folders with millions of short-lived files get their own namespace, so their churn doesn't slow the NameNode that serves production tables.

/tmp, /staging→Separate NameNode→Stable prod latency
router

3. Moving data without changing paths

With Router-Based Federation, admins can copy a folder to a less loaded namespace and then repoint its mount entry. Users keep using the same path.

distcp→Update mount table→Same path, new NameNode
team Ateam B

4. Multi-tenant platforms

Shared enterprise clusters give big business units their own namespace for isolation and capacity planning, while sharing DataNodes, YARN and operations.

Business units→One namespace each→Shared storage

Simplified; organisations differ in tools and policies.

7 Run the code

A mount table that routes paths to NameNodes

ViewFS is essentially a longest-prefix lookup: the path's mount point decides which NameNode answers. This program routes a few paths and refuses a rename across mount points, like our real cluster did.

mounts = {"/canteen": "hdfs://nn-canteen:8020/canteen",
          "/hostel":  "hdfs://nn-hostel:8020/hostel",
          "/tmp":     "hdfs://nn-hostel:8020/tmp"}

def resolve(path):
    best = max((m for m in mounts if path == m or path.startswith(m + "/")), key=len, default=None)
    if best is None:
        raise FileNotFoundError(path + " is not under any mount point")
    return mounts[best] + path[len(best):]

def rename(src, dst):
    s, d = resolve(src), resolve(dst)
    if s.split("/")[2] != d.split("/")[2]:
        return "mv: Renames across Mount points not supported"
    return f"renamed inside {s.split('/')[2]}"

for p in ["/canteen/orders.csv", "/hostel/rooms.csv", "/tmp/x"]:
    print(f"{p:22} -> {resolve(p)}")
print(rename("/canteen/orders.csv", "/hostel/orders.csv"))
print(rename("/hostel/rooms.csv", "/tmp/rooms.csv"))
/canteen/orders.csv -> hdfs://nn-canteen:8020/canteen/orders.csv /hostel/rooms.csv -> hdfs://nn-hostel:8020/hostel/rooms.csv /tmp/x -> hdfs://nn-hostel:8020/tmp/x mv: Renames across Mount points not supported renamed inside nn-hostel:8020
  • best = max((m for m in mounts if path == m or path.startswith(m + "/")), key=len, default=None)The longest matching mount point wins, so nested mounts (e.g. /data and /data/logs) work.
  • if s.split("/")[2] != d.split("/")[2]:Different NameNodes behind source and target: no single NameNode can rename atomically. Our cluster printed exactly this message.
  • print(rename("/hostel/rooms.csv", "/tmp/rooms.csv"))Interesting: /hostel and /tmp are on the same NameNode here, so the logic allows it. Real ViewFS is stricter by default and refuses renames between any two different mount points.

Run it on your PC: two NameNodes, three DataNodes

Create a folder hdfs-fed-lab with config, docker-compose.yaml, nnf.sh, and a subfolder client-conf containing the client core-site.xml (ViewFS mount table) shown below. Run chmod 777 client-conf, start with docker compose -p lab72 up -d --scale datanode=3, wait 45 seconds, then run federation_lab.sh.

Lab files

x-hadoop: &hadoop
  image: apache/hadoop:3.5.0
  env_file: [./config]
  volumes: [./nnf.sh:/opt/nnf.sh:ro, ./client-conf:/opt/client-conf]
services:
  nn-canteen:
    <<: *hadoop
    hostname: nn-canteen
    command: ["bash", "/opt/nnf.sh"]
    environment: { HDFS-SITE.XML_dfs.nameservice.id: nsc }
  nn-hostel:
    <<: *hadoop
    hostname: nn-hostel
    command: ["bash", "/opt/nnf.sh"]
    environment: { HDFS-SITE.XML_dfs.nameservice.id: nsh }
  datanode:
    <<: *hadoop
    command: ["hdfs", "datanode"]
    depends_on: [nn-canteen, nn-hostel]

# ---- config ----
CORE-SITE.XML_fs.defaultFS=hdfs://nn-canteen:8020
HDFS-SITE.XML_dfs.nameservices=nsc,nsh
HDFS-SITE.XML_dfs.namenode.rpc-address.nsc=nn-canteen:8020
HDFS-SITE.XML_dfs.namenode.rpc-address.nsh=nn-hostel:8020
HDFS-SITE.XML_dfs.namenode.http-address.nsc=nn-canteen:9870
HDFS-SITE.XML_dfs.namenode.http-address.nsh=nn-hostel:9870
HDFS-SITE.XML_dfs.namenode.name.dir=/tmp/hadoop-hadoop/dfs/name
HDFS-SITE.XML_dfs.replication=3

# ---- nnf.sh ----
#!/bin/bash
# Format this NameNode once with the SHARED cluster ID, then run it.
NAME=/tmp/hadoop-hadoop/dfs/name
[ -d $NAME/current ] || hdfs namenode -format -nonInteractive -clusterId campus-cluster
exec hdfs namenode

# ---- client-conf/core-site.xml ----
<?xml version="1.0"?>
<!-- Client view of the federated cluster: one tree, two NameNodes behind it (ViewFS mount table). -->
<configuration>
  <property><name>fs.defaultFS</name><value>viewfs://campus</value></property>
  <property><name>fs.viewfs.mounttable.campus.link./canteen</name><value>hdfs://nn-canteen:8020/canteen</value></property>
  <property><name>fs.viewfs.mounttable.campus.link./hostel</name><value>hdfs://nn-hostel:8020/hostel</value></property>
  <property><name>fs.viewfs.mounttable.campus.link./tmp</name><value>hdfs://nn-hostel:8020/tmp</value></property>
</configuration>
lab72-datanode-1 Up 45 seconds lab72-datanode-2 Up 45 seconds lab72-datanode-3 Up 45 seconds lab72-nn-canteen-1 Up 45 seconds lab72-nn-hostel-1 Up 46 seconds $ docker exec lab72-datanode-1 ls /tmp/hadoop-hadoop/dfs/data/current/ BP-1200013783-172.21.0.3-1792598083981 BP-343349822-172.21.0.2-1792598083339 VERSION

Real output. ViewFS mount entries contain “/”, which Docker env files don't allow, so the mount table lives in a separate client config folder used with HADOOP_CONF_DIR=/opt/client-conf.

The federation experiments

#!/usr/bin/env bash
# federation_lab.sh: two NameNodes (canteen, hostel) share the same 3 DataNodes.
P=lab72
C="docker exec $P-datanode-1"
V='HADOOP_CONF_DIR=/opt/client-conf'          # client config with the ViewFS mount table
run() { echo "\$ $1"; $C bash -c "$1" 2>&1 | grep -v -E "WARN|^\s*$"; echo; }
$C bash -c 'cp /opt/hadoop/etc/hadoop/hdfs-site.xml /opt/hadoop/etc/hadoop/log4j.properties /opt/client-conf/'
run "hdfs dfs -mkdir -p hdfs://nn-canteen:8020/canteen hdfs://nn-hostel:8020/hostel hdfs://nn-hostel:8020/tmp"
run "seq 1 200000 | sed 's/^/order,/' > /tmp/orders.csv; seq 1 50000 | sed 's/^/room,/' > /tmp/rooms.csv"
run "$V hdfs dfs -put -f /tmp/orders.csv /canteen/ && $V hdfs dfs -put -f /tmp/rooms.csv /hostel/"
run "$V hdfs dfs -ls /"
run "$V hdfs dfs -ls /canteen /hostel"
run "hdfs dfs -ls -R hdfs://nn-canteen:8020/ ; echo ---; hdfs dfs -ls -R hdfs://nn-hostel:8020/"
for n in canteen hostel; do echo "nn-$n: $(docker exec $P-nn-$n-1 grep -E 'clusterID|blockpoolID' /tmp/hadoop-hadoop/dfs/name/current/VERSION | tr '\n' ' ')"; done; echo
run "ls /tmp/hadoop-hadoop/dfs/data/current/ ; du -sh /tmp/hadoop-hadoop/dfs/data/current/BP-*"
run "for nn in nn-canteen nn-hostel; do echo \$nn: \$(hdfs dfsadmin -fs hdfs://\$nn:8020 -report 2>/dev/null | grep -m1 'Live datanodes'); done"
run "$V hdfs dfs -mv /canteen/orders.csv /hostel/orders.csv"
echo ">>> docker stop $P-nn-canteen-1"; docker stop $P-nn-canteen-1 > /dev/null; echo
run "$V hdfs dfs -ls /hostel"
run "$V timeout 40 hdfs dfs -ls /canteen 2>&1 | grep -m1 -- -ls:"
docker start $P-nn-canteen-1 > /dev/null

# Run:  bash federation_lab.sh
$ hdfs dfs -mkdir -p hdfs://nn-canteen:8020/canteen hdfs://nn-hostel:8020/hostel hdfs://nn-hostel:8020/tmp $ seq 1 200000 | sed 's/^/order,/' > /tmp/orders.csv; seq 1 50000 | sed 's/^/room,/' > /tmp/rooms.csv $ HADOOP_CONF_DIR=/opt/client-conf hdfs dfs -put -f /tmp/orders.csv /canteen/ && HADOOP_CONF_DIR=/opt/client-conf hdfs dfs -put -f /tmp/rooms.csv /hostel/ $ HADOOP_CONF_DIR=/opt/client-conf hdfs dfs -ls / Found 3 items -r-xr-xr-x - hadoop users 0 2026-10-21 15:58 /canteen -r-xr-xr-x - hadoop users 0 2026-10-21 15:58 /hostel -r-xr-xr-x - hadoop users 0 2026-10-21 15:58 /tmp $ HADOOP_CONF_DIR=/opt/client-conf hdfs dfs -ls /canteen /hostel Found 1 items -rw-r--r-- 3 hadoop supergroup 2488895 2026-10-21 15:58 /canteen/orders.csv Found 1 items -rw-r--r-- 3 hadoop supergroup 538894 2026-10-21 15:58 /hostel/rooms.csv $ hdfs dfs -ls -R hdfs://nn-canteen:8020/ ; echo ---; hdfs dfs -ls -R hdfs://nn-hostel:8020/ drwxr-xr-x - hadoop supergroup 0 2026-10-21 15:58 hdfs://nn-canteen:8020/canteen -rw-r--r-- 3 hadoop supergroup 2488895 2026-10-21 15:58 hdfs://nn-canteen:8020/canteen/orders.csv --- drwxr-xr-x - hadoop supergroup 0 2026-10-21 15:58 hdfs://nn-hostel:8020/hostel -rw-r--r-- 3 hadoop supergroup 538894 2026-10-21 15:58 hdfs://nn-hostel:8020/hostel/rooms.csv drwxr-xr-x - hadoop supergroup 0 2026-10-21 15:55 hdfs://nn-hostel:8020/tmp nn-canteen: blockpoolID=BP-1200013783-172.21.0.3-1792598083981 clusterID=campus-cluster nn-hostel: blockpoolID=BP-343349822-172.21.0.2-1792598083339 clusterID=campus-cluster $ ls /tmp/hadoop-hadoop/dfs/data/current/ ; du -sh /tmp/hadoop-hadoop/dfs/data/current/BP-* BP-1200013783-172.21.0.3-1792598083981 BP-343349822-172.21.0.2-1792598083339 VERSION 2.5M /tmp/hadoop-hadoop/dfs/data/current/BP-1200013783-172.21.0.3-1792598083981 1.1M /tmp/hadoop-hadoop/dfs/data/current/BP-343349822-172.21.0.2-1792598083339 $ for nn in nn-canteen nn-hostel; do echo $nn: $(hdfs dfsadmin -fs hdfs://$nn:8020 -report 2>/dev/null | grep -m1 'Live datanodes'); done nn-canteen: Live datanodes (3): nn-hostel: Live datanodes (3): $ HADOOP_CONF_DIR=/opt/client-conf hdfs dfs -mv /canteen/orders.csv /hostel/orders.csv mv: Renames across Mount points not supported >>> docker stop lab72-nn-canteen-1 $ HADOOP_CONF_DIR=/opt/client-conf hdfs dfs -ls /hostel Found 1 items -rw-r--r-- 3 hadoop supergroup 538894 2026-10-21 15:58 /hostel/rooms.csv $ HADOOP_CONF_DIR=/opt/client-conf timeout 40 hdfs dfs -ls /canteen 2>&1 | grep -m1 -- -ls: -ls: java.net.UnknownHostException: nn-canteen

Real output. Your block pool IDs and IP addresses will differ.

8 Line by line

A DataNode registering with two NameNodes

At start-up, a DataNode reads every nameservice from its configuration and registers with each, creating one block pool folder per NameNode.

Worked examples: real problems, solved and traced in memory

Three federation calculations: when one NameNode is too small, how to split, and what federation buys in failure isolation. Each runs live and is traced in memory.

Example 1BeginnerSizing · heap

When does one NameNode stop being enough?

Problem statement

A NameNode server can give the NameNode at most 192 GB of heap. Using the rule of thumb of 150 bytes per object, how many objects fit, and how many files is that if, on average, each file brings 0.1 folders and 1.5 blocks with it?

Input
192 GB · 150 B/object · 2.6 objects per file
Expected output
1.37 billion objects -> about 529 million files

Approach

  1. Objects = heap / 150 bytes.
  2. Each file costs 1 + 0.1 + 1.5 = 2.6 objects.
  3. Files = objects / 2.6.

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 2IntermediateDesign · split

Two namespaces from five top-level folders

Problem statement

Split /warehouse (12 crore objects), /tmp (9 crore), /logs (7 crore), /user (6 crore) and /ml (4 crore) between two NameNodes as evenly as possible, keeping each folder whole.

Input
5 folders, 38 crore objects
Expected output
nn1: [('/warehouse', 12), ('/user', 6)] 18 crore
nn2: [('/tmp', 9), ('/logs', 7), ('/ml', 4)] 20 crore

Approach

  1. Sort folders by size.
  2. Give each to the NameNode with fewer objects so far.
  3. Compare totals.

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 3AdvancedAvailability · isolation

How much keeps working when one NameNode fails?

Problem statement

Jobs touch namespaces in this pattern: 50% only nsA, 30% only nsB, 20% both. If nsA becomes unavailable (and is not HA), what fraction of jobs can still run?

Input
50% A · 30% B · 20% both
Expected output
federated: 30% of jobs keep running; single NameNode: 0%

Approach

  1. Jobs needing A fail.
  2. Only B-only jobs survive.
  3. Compare with a single NameNode, where all fail.

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 7.2 in one screen

  • Federation = several independent NameNodes, each with its own namespace and block pool, sharing DataNodes.
  • Same cluster ID (-clusterId at format); dfs.nameservices lists all; DataNodes register with each.
  • DataNode disk: one current/BP-… folder per namespace (lab: 2.5 M canteen, 572 K hostel).
  • Unified view: ViewFS (client mount table) or RBF (routers + state store).
  • No rename across namespaces (“Renames across Mount points not supported”); copy + delete instead.
  • Failure isolation: one NameNode down affects only its namespace; combine with HA per nameservice.
  • Why: NameNode heap ~150 bytes/object (rule of thumb) and RPC load; split busy or small-file-heavy trees.

Interview and viva questions

What is HDFS federation?

A way to scale the HDFS namespace by running multiple independent NameNodes. Each manages its own namespace and block pool, while all of them share the same DataNodes, which store blocks for every pool in separate directories. Clients see a unified namespace through ViewFS or Router-Based Federation.

What is the difference between HDFS HA and federation?

HA provides availability for one namespace: an active and standby NameNode hold the same metadata and the standby takes over on failure. Federation provides scalability and isolation: several NameNodes hold different parts of the namespace. They can be combined, with each federated nameservice running as an HA pair.

What is ViewFS?

A client-side file system (viewfs://) that uses a mount table in the client configuration to map paths like /canteen and /hostel to directories in different HDFS namespaces, giving one logical tree.

What is Router-Based Federation?

A server-side approach introduced in Hadoop 2.9/3.0: stateless router processes accept client requests on one address and forward them to the right nameservice using a mount table kept in a shared state store. Mount points can be changed centrally without updating clients.

Does federation increase the size limit of a single directory tree?

No. Each namespace still lives in one NameNode. Federation helps when the overall namespace can be split into separate subtrees across NameNodes.

Practice problems

Federation exercises using the real IDs, sizes and messages from the lab.

P1Easy

Parse a block pool ID

Extract the random part, the NameNode IP and the creation time (ms) from a block pool ID.

Input
BP-1200013783-172.21.0.3-1792598083981
Expected output
1200013783 172.21.0.3 1792598083981
Show solution and explanation
bp = "BP-1200013783-172.21.0.3-1792598083981"
_, rnd, ip, ms = bp.split("-")
print(rnd, ip, ms)
1200013783 172.21.0.3 1792598083981

How it works: 1200013783, 172.21.0.3 (the NameNode that created it), 1792598083981 ms since 1970.

P2Easy

Which NameNode?

Using the lab mount table, print which NameNode serves /tmp/x.

Input
/canteen, /hostel, /tmp mounts
Expected output
nn-hostel
Show solution and explanation
mounts = {"/canteen": "nn-canteen", "/hostel": "nn-hostel", "/tmp": "nn-hostel"}
print(next(nn for m, nn in mounts.items() if "/tmp/x".startswith(m + "/")))
nn-hostel

How it works: nn-hostel: /tmp was mounted on the hostel namespace.

P3Easy

Pool shares

From du -sh: 2.5 M and 572 K. What percentage of the DataNode's HDFS data belongs to each pool?

Input
2.5 MB, 0.572 MB
Expected output
canteen 81%, hostel 19%
Show solution and explanation
a, b = 2.5, 0.572
print(f"canteen {a / (a + b):.0%}, hostel {b / (a + b):.0%}")
canteen 81%, hostel 19%

How it works: About 81% and 19%: one disk, two namespaces.

P4Medium

Heap check

A NameNode has 120 GB of heap. Using 150 bytes per object, will 50 crore objects fit?

Input
120 GB · 50 crore
Expected output
needs 70 GB -> fits
Show solution and explanation
need = 500_000_000 * 150 / 1024**3
print(f"needs {need:.0f} GB -> {'fits' if need <= 120 else 'does not fit: federate or reduce objects'}")
needs 70 GB -> fits

How it works: About 70 GB: fits, with headroom for growth and GC.

P5Medium

Cross-mount moves

List which of these moves are renames (same mount) and which need copy + delete.

Input
3 moves
Expected output
/canteen/a -> /canteen/archive/a : rename
/canteen/a -> /hostel/a : copy + delete
/hostel/r -> /hostel/old/r : rename
Show solution and explanation
moves = [("/canteen/a", "/canteen/archive/a"), ("/canteen/a", "/hostel/a"), ("/hostel/r", "/hostel/old/r")]
mount = lambda p: "/" + p.split("/")[1]
for s, d in moves:
    print(s, "->", d, ":", "rename" if mount(s) == mount(d) else "copy + delete")
/canteen/a -> /canteen/archive/a : rename /canteen/a -> /hostel/a : copy + delete /hostel/r -> /hostel/old/r : rename

How it works: Only the canteen→hostel move crosses mount points.

P6Medium

Live DataNodes per NameNode

Parse the report lines and check both NameNodes see the same number of DataNodes.

Input
two lines
Expected output
[3, 3] same
Show solution and explanation
lines = ["nn-canteen: Live datanodes (3):", "nn-hostel: Live datanodes (3):"]
counts = [int(l.split("(")[1].split(")")[0]) for l in lines]
print(counts, "same" if len(set(counts)) == 1 else "different")
[3, 3] same

How it works: 3 and 3: every DataNode serves both namespaces.

P7Business problem

Bigger server or federation?

Option A: one NameNode server with 512 GB RAM, ₹40 lakh. Option B: two 256 GB servers, ₹14 lakh each, plus ₹3 lakh/year extra operations for 3 years. Which is cheaper over 3 years?

Input
A ₹40 lakh · B 2 × ₹14 lakh + 3 × ₹3 lakh
Expected output
A: Rs 40 lakh, B: Rs 37 lakh -> federation cheaper
Show solution and explanation
a = 40
b = 2 * 14 + 3 * 3
print(f"A: Rs {a} lakh, B: Rs {b} lakh ->", "federation cheaper" if b < a else "bigger server cheaper")
A: Rs 40 lakh, B: Rs 37 lakh -> federation cheaper

How it works: ₹37 lakh vs ₹40 lakh (illustrative), and B also isolates failures and avoids one giant JVM heap with long GC pauses.

P8Advanced

Mount table resolver

Implement longest-prefix resolution with nested mounts /data → nn1 and /data/logs → nn2.

Input
2 nested mounts
Expected output
/data/sales/x -> nn1
/data/logs/app.log -> nn2
/data/logsheet.csv -> nn1
Show solution and explanation
mounts = {"/data": "nn1", "/data/logs": "nn2"}
def ns(path):
    return mounts[max((m for m in mounts if path == m or path.startswith(m + "/")), key=len)]
for p in ["/data/sales/x", "/data/logs/app.log", "/data/logsheet.csv"]:
    print(p, "->", ns(p))
/data/sales/x -> nn1 /data/logs/app.log -> nn2 /data/logsheet.csv -> nn1

How it works: /data/logs/app.log goes to nn2; /data/logsheet.csv still goes to nn1 because the match is on whole path components.

Real-world scenario questions (asked in company interviews)

Federation questions appear in senior Hadoop administrator and platform architect interviews.

HDFS · conceptsFresher

“HA and federation: what's the difference?”

Often asked right after HA.

The interviewer is checking: availability vs scalability.

Show a strong answer
  • HA: same namespace on an active and standby NameNode; protects against NameNode failure.
  • Federation: different namespaces on independent NameNodes sharing DataNodes; scales metadata and isolates workloads.
  • They combine: each federated nameservice can be an HA pair.
Operations · capacityExperienced

NameNode heap at 90% and GC pauses growing

A 600-million-object namespace on one HA pair; RPC queue times are rising during the day.

The interviewer is checking: options in order of effort.

Show a strong answer
  • First reduce objects: find small-file-heavy folders, compact them, clean /tmp and old data, use HAR or table compaction.
  • Tune heap and GC; consider Observer NameNodes for read-heavy load.
  • If growth continues, federate: move high-churn trees (/tmp, staging, a big tenant) to a new nameservice, behind routers so paths don't change.
Design · ViewFS vs RBFExperienced

Rolling out federation to 2,000 client machines

You add a second nameservice. Edge nodes, Spark jobs, Airflow workers and BI tools all access HDFS.

The interviewer is checking: client configuration management.

Show a strong answer
  • With ViewFS, every client needs the new mount table; any stale config breaks paths. Manageable with strong config management.
  • With Router-Based Federation, clients point to the routers once; mount changes are made centrally with dfsrouteradmin.
  • Run several routers behind a nameservice for availability, and monitor the state store.
TroubleshootingExperienced

A new NameNode is up, but no DataNode registers with it

The second NameNode shows 0 live DataNodes; DataNode logs show an incompatible cluster ID.

The interviewer is checking: cluster ID and block pools.

Show a strong answer
  • The new NameNode was formatted without the existing cluster ID, so DataNodes refuse it.
  • Reformat the empty new NameNode with -clusterId <existing id> (from any DataNode's VERSION file), add it to dfs.nameservices, and refresh DataNodes (dfsadmin -refreshNamenodes).
  • Never reformat a NameNode that already holds data.