HDFS 는 블록 복제본을 배치할 때 노드가 어느 랙에 있는지를 고려한다. 복제 수가 3 이면 첫 복제본은 쓰기를 수행한 노드(또는 임의 노드), 둘째는 다른 랙의 노드, 셋째는 둘째와 같은 랙의 다른 노드에 둔다. 랙 하나가 통째로 죽어도 데이터가 남고, 랙 간 네트워크 사용은 최소로 줄이는 절충이다.
랙 정보를 주지 않으면 모든 노드가 /default-rack 하나에 속한 것으로 간주되어 이 배치 정책이 아무 일도 하지 않는다.
NameNode 는 외부 스크립트에 호스트 이름 또는 IP 를 인자로 넘기고, 표준 출력으로 랙 경로를 받는다. 인자는 여러 개가 한꺼번에 올 수 있으며, 입력 개수와 출력 개수가 정확히 같아야 한다. 하나라도 빠지면 NameNode 가 매핑을 신뢰하지 않는다.
#!/bin/bash
# /etc/hadoop/conf/topology.sh
while [ $# -gt 0 ]; do
case "$1" in
10.0.1.*|node1[0-9].example.com) echo "/rack1" ;;
10.0.2.*|node2[0-9].example.com) echo "/rack2" ;;
10.0.3.*|node3[0-9].example.com) echo "/rack3" ;;
*) echo "/default-rack" ;;
esac
shift
done
호스트 이름과 IP 가 모두 들어올 수 있으므로 둘 다 처리한다. 스크립트는 빠르게 끝나야 하고 외부 조회(DNS · 데이터베이스)에 의존하지 않는 편이 좋다 — NameNode 가 노드 등록 때마다 호출한다.
<property>
<name>net.topology.script.file.name</name>
<value>/etc/hadoop/conf/topology.sh</value>
</property>
스크립트 대신 정적 파일로 주는 방법도 있다.
<property>
<name>net.topology.node.switch.mapping.impl</name>
<value>org.apache.hadoop.net.TableMapping</value>
</property>
<property>
<name>net.topology.table.file.name</name>
<value>/etc/hadoop/conf/topology.data</value>
</property>
Cloudera Manager 로 관리하는 클러스터에서는 파일을 직접 두지 않고 호스트 화면에서 랙을 지정한다. 직접 만든 스크립트와 섞으면 관리 도구가 덮어쓴다.
스크립트를 모든 NameNode 에 같은 경로로 배포하고 실행 권한을 준 뒤 NameNode 를 재시작한다.
전체 노드의 랙 배치는 다음으로 본다.
hdfs dfsadmin -printTopology
Rack: /rack1
10.0.1.11:9866 (node11.example.com)
10.0.1.12:9866 (node12.example.com)
Rack: /rack2
10.0.2.11:9866 (node21.example.com)
/default-rack 에 남아 있는 노드가 있으면 스크립트가 그 주소를 처리하지 못한 것이다. 스크립트를 직접 호출해 확인한다.
/etc/hadoop/conf/topology.sh node11.example.com 10.0.2.11
특정 파일의 블록이 실제로 어디에 있는지는 fsck 로 본다.
hdfs fsck /path/to/file -files -blocks -locations
출력의 각 복제본 뒤에 /rack1/10.0.1.11:9866 처럼 랙 경로가 붙는다. 같은 블록의 복제본이 모두 한 랙에 있다면 랙 인식이 적용되기 전에 쓰인 데이터다.
랙 정보는 새로 쓰는 블록의 배치에만 쓰인다. 설정을 켜도 기존 블록은 그대로 있다.
hdfs balancer 는 노드 간 사용률을 고르게 맞추는 도구이고, 랙 정책을 만족시키기 위해 옮기는 도구가 아니다. 다만 랙 정보를 알고 나면 균형을 맞추는 과정에서 배치가 함께 개선되는 효과는 있다.
hdfs balancer -threshold 10
정책을 실제로 다시 적용하려면 블록을 다시 쓰게 만들어야 한다. 방법은 셋이다.
복제 수를 줄였다가 되돌리면 NameNode 가 부족해진 복제본을 현재 정책에 따라 새로 만든다. 가장 부담이 적다.
hdfs dfs -setrep -w 2 /data/path
hdfs dfs -setrep -w 3 /data/path
또는 임시 위치로 복사했다가 되돌린다. 쓰기가 새로 일어나므로 정책이 적용된다.
hadoop distcp /data/old /data/tmp
hdfs dfs -rm -r -skipTrash /data/old
hadoop distcp /data/tmp /data/old
어느 쪽이든 대상 경로의 스냅숏을 먼저 떠 두고, 클러스터 부하가 낮은 시간대에 나눠서 수행한다.
hdfs dfsadmin -allowSnapshot /data/old
hdfs dfs -createSnapshot /data/old before-rack
작업 뒤에는 무결성과 배치를 함께 확인한다.
hdfs fsck /data/old -files -blocks -locations | grep -c 'default-rack'
hdfs fsck / | tail -20
랙 정보를 잘못 주면 복제본이 물리적으로 같은 랙에 몰리는데도 정책은 만족한 것으로 보인다. 스위치 · 전원 계통 기준으로 실제 장애 도메인을 반영해야 의미가 있다.
가상화 환경에서 여러 노드가 같은 하이퍼바이저에 올라가 있으면 네트워크상 랙이 달라도 실제 장애 도메인은 하나다. 이 경우 하이퍼바이저를 랙 단위로 매핑한다.
랙 수가 복제 수보다 적으면 정책을 완전히 만족시킬 수 없다. 복제 3 에 랙이 2 개면 둘 중 한 랙에 복제본 두 개가 놓이며, 이는 정상 동작이다.