Rack Awareness

Rack Awareness

Hadoop 구성요소는 **랙 인식(rack-aware)**입니다. 예를 들어 HDFS 블록 배치는 장애 허용을 위해 랙 인식을 사용해서, 하나의 블록 복제본을 다른 랙에 배치합니다. 이렇게 하면 클러스터 내 네트워크 스위치 장애나 파티션이 발생해도 데이터 가용성을 확보할 수 있습니다.

출처: Rack Awareness

Hadoop 마스터 데몬은 설정 파일에 지정된 외부 스크립트나 Java 클래스를 호출해 클러스터 워커의 랙 ID를 얻습니다. 토폴로지에 Java 클래스나 외부 스크립트 중 무엇을 사용하든 출력은 Java의 org.apache.hadoop.net.DNSToSwitchMapping 인터페이스를 따라야 합니다. 이 인터페이스는 일대일 대응을 유지할 것을 요구하며, 토폴로지 정보는 '/myrack/myhost' 형식이어야 합니다. 여기서 /는 토폴로지 구분자, myrack은 랙 식별자, myhost는 개별 호스트입니다. 랙마다 /24 서브넷 하나를 가정하면, /192.168.100.0/192.168.100.5 형식을 고유한 랙-호스트 토폴로지 매핑으로 사용할 수 있습니다.

토폴로지 매핑에 Java 클래스를 사용하려면 설정 파일의 net.topology.node.switch.mapping.impl 파라미터에 클래스 이름을 지정합니다. Hadoop 배포판에 포함된 예시 NetworkTopology.java가 있으며, Hadoop 관리자가 커스터마이즈할 수 있습니다. 외부 스크립트 대신 Java 클래스를 사용하면 새 워커 노드가 등록될 때 Hadoop이 외부 프로세스를 포크할 필요가 없어 성능상 이점이 있습니다.

외부 스크립트를 구현한다면 설정 파일의 net.topology.script.file.name 파라미터로 지정합니다. Java 클래스와 달리 외부 토폴로지 스크립트는 Hadoop 배포판에 포함되지 않으며 관리자가 제공합니다. Hadoop은 토폴로지 스크립트를 포크할 때 여러 IP 주소를 ARGV에 보냅니다. 토폴로지 스크립트에 보내지는 IP 주소 수는 net.topology.script.number.args로 제어하며 기본값은 100입니다. net.topology.script.number.args를 1로 바꾸면 DataNode 및/또는 NodeManager가 제출한 각 IP마다 토폴로지 스크립트가 포크됩니다.

net.topology.script.file.name이나 net.topology.node.switch.mapping.impl이 설정되지 않으면 전달된 어떤 IP 주소에 대해서도 랙 ID '/default-rack'이 반환됩니다. 이 동작은 바람직해 보일 수 있지만, 기본 동작이 복제 블록 하나를 오프랙(off rack)에 쓰는 HDFS 블록 복제에 문제를 일으킬 수 있습니다. 랙이 '/default-rack' 하나뿐이라 오프랙에 쓸 수 없기 때문입니다.

python 예시

#!/usr/bin/python3
# this script makes assumptions about the physical environment.
#  1) each rack is its own layer 3 network with a /24 subnet, which
# could be typical where each rack has its own
#     switch with uplinks to a central core router.
#
#             +-----------+
#             |core router|
#             +-----------+
#            /             \
#   +-----------+        +-----------+
#   |rack switch|        |rack switch|
#   +-----------+        +-----------+
#   | data node |        | data node |
#   +-----------+        +-----------+
#   | data node |        | data node |
#   +-----------+        +-----------+
#
# 2) topology script gets list of IP's as input, calculates network address, and prints '/network_address/ip'.

import netaddr
import sys
sys.argv.pop(0)                                                  # discard name of topology script from argv list as we just want IP addresses

netmask = '255.255.255.0'                                        # set netmask to what's being used in your environment.  The example uses a /24

for ip in sys.argv:                                              # loop over list of datanode IP's
    address = '{0}/{1}'.format(ip, netmask)                      # format address string so it looks like 'ip/netmask' to make netaddr work
    try:
        network_address = netaddr.IPNetwork(address).network     # calculate and print network address
        print("/{0}".format(network_address))
    except:
        print("/rack-unknown")                                   # print catch-all value if unable to calculate network address

bash 예시

#!/usr/bin/env bash
# Here's a bash example to show just how simple these scripts can be
# Assuming we have flat network with everything on a single switch, we can fake a rack topology.
# This could occur in a lab environment where we have limited nodes,like 2-8 physical machines on a unmanaged switch.
# This may also apply to multiple virtual machines running on the same physical hardware.
# The number of machines isn't important, but that we are trying to fake a network topology when there isn't one.
#
#       +----------+    +--------+
#       |jobtracker|    |datanode|
#       +----------+    +--------+
#              \        /
#  +--------+  +--------+  +--------+
#  |datanode|--| switch |--|datanode|
#  +--------+  +--------+  +--------+
#              /        \
#       +--------+    +--------+
#       |datanode|    |namenode|
#       +--------+    +--------+
#
# With this network topology, we are treating each host as a rack.  This is being done by taking the last octet
# in the datanode's IP and prepending it with the word '/rack-'.  The advantage for doing this is so HDFS
# can create its 'off-rack' block copy.
# 1) 'echo $@' will echo all ARGV values to xargs.
# 2) 'xargs' will enforce that we print a single argv value per line
# 3) 'awk' will split fields on dots and append the last field to the string '/rack-'. If awk
#    fails to split on four dots, it will still print '/rack-' last field value

echo $@ | xargs -n 1 | awk -F '.' '{print "/rack-"$NF}'

더 알아보기 (Learn more)