noqqe » blog | sammelsurium | photos | projects | about

Hadoop Filesystem Informationen können echt ziemlich verwirrend sein. Zuerst, sieht so aus als würden erstmal 3.69 TB benutzt werden. Als Admin ist dann erstmal alles cool. Bis man das Cluster verkleinern will und Daten wegschmeissen muss.

$ hdfs dfsadmin -report | head -11
Configured Capacity: 10498624905216 (9.55 TB)
Present Capacity: 10496880074752 (9.55 TB)
DFS Remaining: 6441878704128 (5.86 TB)
DFS Used: 4055001370624 (3.69 TB)
DFS Used%: 38.63%
Under replicated blocks: 0
Blocks with corrupt replicas: 0
Missing blocks: 0
Missing blocks (with replication factor 1): 0

Irgendwo müssten sich die 3 TB aber jetzt auch finden lassen. Das FS kann natürlich Auskunft darüber geben, wo was für Files welche Größe haben.

$ hdfs dfs -du -h /
1.7 G    3.4 G    /data
73.8 M   147.5 M  /jars
545.6 M  5.1 G    /tmp
27.2 G   54.4 G   /user
62.3 M   124.5 M  /var

Der aufmerksame Leser merkt schnell, dass das so garnicht hinhaut. Was heissen die beiden Zahlen überhaupt. In der Manpage findet man die Spaltenbeschriftung mit size, disk space consumed, name.

Für den Unterschied zwischen Size und Diskspace muss man wissen, dass es auch bei Hadoop Blocksizes gibt. Bei Hadoop nur um einiges größer. Dieses Limit sollte man in der hdfs-site.xml finden.

<property>
  <name>dfs.blocksize</name>
  <value>134217728</value>
</property>

Na gut, das sind halt jetzt ~134MB pro File. Die nächste Baustelle lauter replicationFactor. Auch die kann in der hdfs-site.xml gesetzt werden. Das muss aber nicht ausschliesslich der Fall sein. Spezielle ReplicationFactors können pro File/Directory via Commandline gesetzt werden.

<property>
  <name>dfs.replication</name>
  <value>2</value>
</property>

Im Klartext heisst das jetzt: Ich lade eine 1,5KB grosse foobar.txt in HDFS und verbrauche dafür 268MB (= 134MB * 2 Replication Factor).

Man kann sich außerdem noch einen kleinen Überblick verschaffen indem man die count Option benutzt. Die Spaltenbeschriftung hab ich mir von Stackoverflow ausgeliehen. Normalerweise ist die nicht dabei. Und überhaupt Hadoop, Spaltenbenamsung!

$ hdfs dfs -count -q -h '/var/*'
QUOTA REMAINING_QUOTA SPACE_QUOTA REMAINING_SPACE_QUOTA DIR_COUNT FILE_COUNT CONTENT_SIZE FILE_NAME
none      inf            none             inf            187        367            61.7 M /var/log

Das haut aber immernoch nicht alles hin. Ein weiterer Befehl für die Inspektion ist hdfs fsck. Indem man genau Anzahl der Blocks im HDFS ausliesst, muss man sich nicht mit dem über den Daumen gepeilten ReplFactor aus der hdfs-site.xml zufrieden geben.

$ hdfs fsck -blocks
Total size:    31726972623 B (Total open files size: 16694 B)
Total dirs:    705
Total files:   3545
Total symlinks:                0 (Files currently being written: 1)
Total blocks (validated):      3721 (avg. block size 8526464 B) (Total open file blocks (not validated): 1)
Minimally replicated blocks:   3721 (100.0 %)
Over-replicated blocks:        0 (0.0 %)
Under-replicated blocks:       0 (0.0 %)
Mis-replicated blocks:         0 (0.0 %)
Default replication factor:    2

Also gut, 3721 Blocks * 134MB = 496GB. Immernoch nicht genug. Irgendwas geht falsch. Bei einem Blick in die Node details hdfs dfsadmin -report fiel mir auf, dass auf ein paar Nodes 600GB used und auf anderen nur 2GB used sind. Ein Fall für den Balancer. Dieser verteilt bei Ungleichgewicht alle Daten neu und gerecht über alle Nodes.

$ hdfs balancer
INFO balancer.Balancer: 5 over-utilized:
[192.168.4.26:50010:DISK, 192.168.4.22:50010:DISK, 192.168.4.25:50010:DISK,
192.168.4.24:50010:DISK, 192.168.4.11:50010:DISK]
INFO balancer.Balancer: 7 underutilized:
[192.168.4.23:50010:DISK, 192.168.4.29:50010:DISK, 192.168.4.30:50010:DISK,
192.168.4.32:50010:DISK, 192.168.4.31:50010:DISK, 192.168.4.27:50010:DISK,
192.168.4.28:50010:DISK]
INFO balancer.Balancer: Need to move 1.33 TB to make the
cluster balanced.
INFO balancer.Balancer: Decided to move 10 GB bytes from
192.168.4.26:50010:DISK to 192.168.4.23:50010:DISK
INFO balancer.Balancer: Decided to move 10 GB bytes from
192.168.4.22:50010:DISK to 192.168.4.29:50010:DISK
INFO balancer.Balancer: Decided to move 10 GB bytes from
192.168.4.25:50010:DISK to 192.168.4.30:50010:DISK

Dann wurde es mir klar, dass beim letzten Upgrade des HDFS Clusters vergessen wurde das Upgrade via hdfs dfsadmin -finalizeUpgrade abzuschliessen. Alle Changes wurden in eine Art Snapshot vorgehalten, aber nicht wirklich applied. So kam es zum Ungleichgewicht im Cluster. Das Upgrade hab ich im Anschluss finalisiert und den Balancer in der Endlosschleife laufen lassen.

$ while true; do hdfs balancer ; done
INFO balancer.Dispatcher: Successfully moved
blk_1074285727_545003 with size=285553 from 192.168.4.24:50010:DISK to
192.168.4.29:50010:DISK through 192.168.4.24:50010
INFO balancer.Dispatcher: Successfully moved
blk_1074285725_545001 with size=285240 from 192.168.4.24:50010:DISK to
192.168.4.29:50010:DISK through 192.168.4.24:50010

Führte dann auch zum gewünschten Ergebnis. Der Balancer wird mit Sicherheit noch längere Zeit laufen und unnötige Daten beim verteilen verwerfen. Aber erste Veränderungen kann man bereits erkennen.

Configured Capacity: 10498624905216 (9.55 TB)
Present Capacity: 10496611639336 (9.55 TB)
DFS Remaining: 8326884075111 (7.57 TB)
DFS Used: 2169727564225 (1.97 TB)
DFS Used%: 20.67%
Under replicated blocks: 0
Blocks with corrupt replicas: 0
Missing blocks: 0
Missing blocks (with replication factor 1): 0

Außerdem hab ich gelernt, mir fürs Finaliseren des Upgrades einen Kalendereintrag zu machen ;)