복붙노트

[HADOOP] Dockerized Hadoop 데이터 노드가 잘못된 IP 주소로 등록하는 이유는 무엇입니까?

HADOOP

Dockerized Hadoop 데이터 노드가 잘못된 IP 주소로 등록하는 이유는 무엇입니까?

나는 Hadoop (2.7.1) namenodes와 datanode를위한 별도의 Docker (1.9.1) 이미지를 가지고있다. 컨테이너에서 컨테이너를 생성하고 사용자가 정의한 Docker 네트워크를 통해 통신하도록 할 수 있습니다. 그러나 데이터 노드는 자신의 IP 주소가 아니라 네트워크 게이트웨이의 IP 주소를 가지고 있다고보고합니다. 단일 데이터 노드에서는 문제가 발생하지 않지만 추가 데이터 노드가 추가되면 혼란이 발생합니다. 그들은 모두 동일한 IP 주소로 등록하고 namenode는 그 둘 사이를 뒤집으며 오직 하나의 datanode가 살아 있다는 것을보고합니다.

왜 서버 (namenode)가 사용자 정의 Docker 네트워크에서 실행 중일 때 클라이언트 (datanode) 소켓 연결에서 잘못된 IP 주소를 읽었으며 어떻게 수정할 수 있습니까?

업데이트 :이 문제는 Docker 측에있는 것 같습니다.

- net = bridge를 사용하여 두 개의 컨테이너를 실행하고 netcat 서버를 실행합니다.

nc -v -l 9000

한 컨테이너에는 netcat 클라이언트가 있고 다른 컨테이너에는 netcat 클라이언트가 있습니다.

nc 172.17.0.2 9000

첫 번째 컨테이너가 올바르게 인쇄되도록합니다.

Connection from 172.17.0.3 port 9000 [tcp/9000] accepted

그러나 사용자 정의 네트워크 만들기 :

sudo docker network create --driver bridge test

--net = test로 시작한 컨테이너에서 동일한 명령을 실행하면 게이트웨이 / 사용자 정의 네트워크 인터페이스의 IP 주소가 잘못 인쇄됩니다.

Connection from 172.18.0.1 port 9000 [tcp/9000] accepted

HDFS / Docker 세부 정보

각 데이터 노드의 hdfs-site.xml 파일에있는 dfs.datanode.address 등록 정보는 해당 호스트 이름으로 설정됩니다 (예 : hdfs-datanode-1).

네트워크는 다음과 같이 생성됩니다.

sudo docker network create --driver bridge hadoop-network

namenode는 다음과 같이 시작되었습니다.

sudo docker run -d \
                --name hdfs-namenode \
                -v /hdfs/name:/hdfs-name \
                --net=hadoop-network \
                --hostname hdfs-namenode \
                -p 50070:50070 \
                hadoop:namenode

그리고 datanode는 다음과 같이 시작되었습니다.

sudo docker run -d \
                --name hdfs-datanode-1 \
                -v /hdfs/data_1:/hdfs-data \
                --net=hadoop-network \
                --hostname=hdfs-datanode-1 \
                --restart=always \
                hadoop:datanode

두 노드는 정상적으로 연결되며 (sudo docker exec hdfs-namenode hdfs dfsadmin -report를 사용하여) 질의를 받으면 연결은 다음과 같이보고됩니다.

...
Live datanodes (1):

Name: 172.18.0.1:50010 (172.18.0.1)
Hostname: hdfs-datanode-1
...

그러나 실행 결과는 다음과 같습니다.

 sudo docker exec hdfs-namenode cat /etc/hosts

해당 namenode가 172.18.0.2에서 실행 중이고 datanode가 172.18.0.3에서 실행되고 있다고 생각한다는 것을 나타냅니다.

172.18.0.2      hdfs-namenode
127.0.0.1       localhost
::1     localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
172.18.0.3      hdfs-datanode-1
172.18.0.3      hdfs-datanode-1.hadoop-network

그리고 datanode에 해당하는 것은 동일한 것을 보여줍니다 :

172.18.0.3      hdfs-datanode-1
127.0.0.1       localhost
::1     localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
172.18.0.2      hdfs-namenode
172.18.0.2      hdfs-namenode.hadoop-network

두 경로 모두에서 ip route를 실행하면 다음과 같이 확인됩니다.

sudo docker exec hdfs-namenode ip route
default via 172.18.0.1 dev eth0
172.18.0.0/16 dev eth0  proto kernel  scope link  src 172.18.0.2
sudo docker exec hdfs-datanode-1 ip route
default via 172.18.0.1 dev eth0
172.18.0.0/16 dev eth0  proto kernel  scope link  src 172.18.0.3

그리고 datanode가 시작되면 namenode는 datode의 IP 주소를 172.18.0.1로보고합니다.

... INFO hdfs.StateChange: BLOCK* registerDatanode: from DatanodeRegistration(172.18.0.1:50010, datanodeUuid=3abaf40c-4ce6-47e7-be2b-fbb4a7eba0e3, infoPort=50075, infoSecurePort=0, ipcPort=50020, storageInfo=lv=-56;cid=CID-60401abd-4793-4acf-94dc-e8db02b27d59;nsid=1824008146;c=0) storage 3abaf40c-4ce6-47e7-be2b-fbb4a7eba0e3
... INFO blockmanagement.DatanodeDescriptor: Number of failed storage changes from 0 to 0
... INFO net.NetworkTopology: Adding a new node: /default-rack/172.18.0.1:50010
... INFO blockmanagement.DatanodeDescriptor: Number of failed storage changes from 0 to 0
... INFO blockmanagement.DatanodeDescriptor: Adding new storage ID DS-4ba1a710-a4ca-4cad-8222-cc5f16c213fb for DN 172.18.0.1:50010
... INFO BlockStateChange: BLOCK* processReport: from storage DS-4ba1a710-a4ca-4cad-8222-cc5f16c213fb node DatanodeRegistration(172.18.0.1:50010, datanodeUuid=3abaf40c-4ce6-47e7-be2b-fbb4a7eba0e3, infoPort=50075, infoSecurePort=0, ipcPort=50020, storageInfo=lv=-56;cid=CID-60401abd-4793-4acf-94dc-e8db02b27d59;nsid=1824008146;c=0), blocks: 1, hasStaleStorage: false, processing time: 3 msecs

tcpdump를 사용하여 호스트 네트워크에 연결된 Docker 컨테이너에서 실행 - docker run --net = host를 사용하여 두 호스트 간의 트래픽을 캡처하면 오류가 발생하는 것으로 나타납니다 (br-b59d498905c5는 생성 된 네트워크 인터페이스의 이름입니다. hadoop 네트워크 용 도커) :

tcpdump -nnvvXS -s0 -i br-b59d498905c5 \
        "(src host 172.18.0.3 or src host 172.18.0.2) and \
         (dst host 172.18.0.3 or dst host 172.18.0.2)"

IP 주소는 registerDatanode 호출 내에서 올바르게 전송 된 것 같습니다.

...
172.18.0.3.33987 > 172.18.0.2.9000: ...
    ...
    0x0050:  f828 004d 0a10 7265 6769 7374 6572 4461  .(.M..registerDa
    0x0060:  7461 6e6f 6465 1237 6f72 672e 6170 6163  tanode.7org.apac
    0x0070:  6865 2e68 6164 6f6f 702e 6864 6673 2e73  he.hadoop.hdfs.s
    0x0080:  6572 7665 722e 7072 6f74 6f63 6f6c 2e44  erver.protocol.D
    0x0090:  6174 616e 6f64 6550 726f 746f 636f 6c18  atanodeProtocol.
    0x00a0:  01a7 010a a401 0a51 0a0a 3137 322e 3138  .......Q..172.18
    0x00b0:  2e30 2e33 120f 6864 6673 2d64 6174 616e  .0.3..hdfs-datan
    0x00c0:  6f64 652d 311a 2433 6162 6166 3430 632d  ode-1.$3abaf40c-
    ...

그러나 후속 호출에서는 올바르지 않습니다. 예를 들어 sendHeartbeat 호출에서 나중에 몇 분의 1 초를 호출합니다.

...
172.18.0.3.33987 > 172.18.0.2.9000: ...
    ...
    0x0050:  f828 004a 0a0d 7365 6e64 4865 6172 7462  .(.J..sendHeartb
    0x0060:  6561 7412 376f 7267 2e61 7061 6368 652e  eat.7org.apache.
    0x0070:  6861 646f 6f70 2e68 6466 732e 7365 7276  hadoop.hdfs.serv
    0x0080:  6572 2e70 726f 746f 636f 6c2e 4461 7461  er.protocol.Data
    0x0090:  6e6f 6465 5072 6f74 6f63 6f6c 1801 9d02  nodeProtocol....
    0x00a0:  0aa4 010a 510a 0a31 3732 2e31 382e 302e  ....Q..172.18.0.
    0x00b0:  3112 0f68 6466 732d 6461 7461 6e6f 6465  1..hdfs-datanode
    0x00c0:  2d31 1a24 3361 6261 6634 3063 2d34 6365  -1.$3abaf40c-4ce
    ...

데이터 노드 코드를 통한 디버깅은 namenode에서 반환 한 정보를 기반으로 BPServiceActor.register ()에서 데이터 노드 등록 정보가 업데이트 될 때 발생하는 오류를 명확하게 보여줍니다.

bpRegistration = bpNamenode.registerDatanode(bpRegistration);

namenode 디버깅은 데이터 노드 소켓 연결에서 잘못된 IP 주소를 읽고 데이터 노드 등록 세부 정보를 업데이트 함을 보여줍니다.

추가 참고 사항

사용자 정의 Docker 네트워크에서 실행되는이 코드로이 문제를 재현 할 수 있습니다.

import java.net.ServerSocket;
import java.net.Socket;

public class Server {
    public static void main(String[] args) throws Exception {
        // 9000 is the namenode port
        ServerSocket server = new ServerSocket(9000);

        Socket socket = server.accept();
        System.out.println(socket.getInetAddress().getHostAddress());
    }
}

import java.net.Socket;

public class Client {
    public static void main(String[] args) throws Exception {
        // 172.18.0.2 is the namenode IP address
        Socket socket = new Socket("172.18.0.2", 9000);
    }
}

172.18.0.2에서 실행되는 서버와 클라이언트 모두에서 올바르게 172.18.0.2를 출력하지만 172.18.0.3에서 실행되는 클라이언트에서는 172.18.0.1을 잘못 출력합니다.

사용자 정의 네트워크 (기본 브리지 네트워크 / docker0 인터페이스 및 포트 9000 노출)를 사용하지 않고 동일한 코드를 실행하면 정확한 결과를 얻을 수 있습니다.

역방향 DNS 조회 오류를 방지하기 위해 namenode의 hdfs-site.xml 파일에서 dfs.namenode.datanode.registration.ip-hostname-check 속성을 false로 설정했습니다. 나중에 DNS를 작동 시키면 불필요 할 수 있습니다.하지만 지금은 datanode에 의해보고 된 잘못된 IP 주소로 인해 DNS 작업이 도움이 될지 의심 스럽습니다.

RegisterDatanode, sendHeartbeat 및 blockReport에 대한 관련 와이어 프로토콜은 RegisterDatanodeRequestProto, HeartbeatRequestProto 및 BlockReportRequestProto이며 해당 정의는 여기에서 찾을 수 있습니다. 이들은 모두 첫 번째 데이터 멤버로서 DatanodeRegistrationProto를 포함합니다. 이 메시지는 여기에 정의되어 있으며 다음과 같습니다.

/**
 * Identifies a Datanode
 */
message DatanodeIDProto {
  required string ipAddr = 1;    // IP address
  required string hostName = 2;  // hostname
  ...
}

해결법

  1. ==============================

    1.이것은 알려진 도커 문제 (문제가 제기 된 단계를 설명하는이 복제본)를 통해 발생합니다.

    이것은 알려진 도커 문제 (문제가 제기 된 단계를 설명하는이 복제본)를 통해 발생합니다.

    문제를 해결해야하는 병합 된 끌어 오기 요청이 있으며 Docker 1.10.0에 포함될 예정입니다. 그러나 그 동안 다음 해결 방법을 사용할 수 있습니다.

  2. from https://stackoverflow.com/questions/33860478/why-is-dockerized-hadoop-datanode-registering-with-the-wrong-ip-address by cc-by-sa and MIT license