当前位置: 首页 > 面试题库 >

为什么Dockerized Hadoop数据节点注册了错误的IP地址?

林博厚
2023-03-14
问题内容

我为Hadoop(2.7.1)名称节点和数据节点分别设置了Docker(1.9.1)映像。我可以从这些容器中创建容器,并使它们通过用户定义的Docker网络进行通信。但是,datanode似乎报告自己具有网络网关的IP地址,而不是其自己的IP地址。虽然这不会对单个数据节点造成任何问题,但是在添加其他数据节点时,仍然会引起混乱。它们都使用相同的IP地址注册,并且名称节点在它们之间翻转,仅报告单个数据节点处于活动状态。

在用户定义的Docker网络上运行时,为什么服务器(名称节点)从客户端(数据节点)套接字连接中读取错误的IP地址,我该如何解决?

更新:此问题似乎在Docker方面

运行两个容器--net=bridge并执行一个netcat服务器:

nc -v -l 9000

在一个容器中,在另一个容器中,一个netcat客户端:

nc 172.17.0.2 9000

使第一个容器正确打印:

接受来自 **172.17.0.3** 端口9000 [tcp / 9000]的连接

但是创建一个用户定义的网络:

sudo docker network create --driver bridge test

并在以--net=test错误开头的容器中执行相同的命令会错误打印网关/用户定义的网络接口的IP地址:

接受来自 **172.18.0.1** 端口9000 [tcp / 9000]的连接

HDFS / Docker详细信息

dfs.datanode.address每个数据节点hdfs-site.xml文件中的属性均设置为其主机名(例如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)时,连接性报告为:

...
实时数据节点(1):

名称: **172.18.0.1** :50010(172.18.0.1)
主机名: **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本地主机
:: 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本地主机
:: 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



默认通过172.18.0.1 dev eth0
172.18.0.0/16 dev eth0原始内核作用域链接   **src 172.18.0.2**



sudo docker exec hdfs-datanode-1 ip route



默认通过172.18.0.1 dev eth0
172.18.0.0/16 dev eth0原始内核作用域链接src **172.18.0.3**

然而,当数据节点启动时,名称节点将数据节点的IP地址报告为172.18.0.1

... INFO hdfs.StateChange:BLOCK * registerDatanode:来自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)存储3abaf40c-4ce6-47e7-be2b-fbb4a7eba0e3
... INFO blockmanagement.DatanodeDescriptor:失败的存储数量从0更改为0
... INFO net.NetworkTopology:添加新节点:/默认机架/ **172.18.0.1** :50010
... INFO blockmanagement.DatanodeDescriptor:失败的存储数量从0更改为0
... INFO blockmanagement.DatanodeDescriptor:为DN **172.18.0.1:50010** 添加新的存储ID DS-4ba1a710-a4ca-4cad-8222- cc5f16c213fb
... INFO BlockStateChange:BLOCK *过程报告:来自存储DS-4ba1a710-a4ca-4cad-8222-cc5f16c213fb节点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),块:1,hasStaleStorage:false,处理时间:3毫秒

并且使用tcpdump捕获两者之间的流量(在连接到主机网络的Docker容器中运行-使用docker run --net=host)似乎表明发生了错误(br-b59d498905c5是Docker为Docker创建的网络接口的名称hadoop- network):

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 atanode协议。
    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 **6ode** 3430   **1。** $ 3abaf40c-
    ...

但是在随后的通话中这是不正确的。例如,在sendHeartbeat通话之后一秒钟的时间:

...
172.18.0.3.33987> 172.18.0.2.9000:...
    ...
    0x0050:f828 004a 0a0d 7365 6e64 4865 6172 7462 .... 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
    ...

通过datanode代码进行的调试清楚地显示了根据namenode返回的信息更新datanode注册详细信息BPServiceActor.register()时发生的错误:

bpRegistration = bpNamenode.registerDatanode(bpRegistration);

调试namenode 表示它从datanode套接字连接中读取了
错误的 IP地址,并更新了datanode注册详细信息。

补充笔记

我可以在用户定义的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);
    }
}

与这两个ServerClient运行在172.18.0.2这个正确的输出172.18.0.2,但与Client上运行172.18.0.3它错误地输出172.18.0.1

在不使用用户定义的网络的情况下运行相同的代码(在默认的bridge网络/ docker0接口上并公开port 9000)可以提供正确的输出。

我在namenode的文件中将dfs.namenode.datanode.registration.ip-hostname- check属性设置为falsehdfs- site.xml以防止反向DNS查找错误。如果我可以使用DNS,那么将来可能不需要这样做,但是现在,由于数据节点报告了错误的IP地址,我怀疑使用DNS会有所帮助。

我相信相关的有线协议registerDatanodesendHeartbeat并且blockReport都是RegisterDatanodeRequestProtoHeartbeatRequestProto而且BlockReportRequestProto和他们的定义可以在这里找到。这些都包含DatanodeRegistrationProto为其第一个数据成员。此消息在此处定义,如下所示:

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

问题答案:

这是由一个已知的docker问题引起的(我也提出了并关闭了此重复描述了问题中所述步骤的副本)。

有一个合并的拉取请求可以解决此问题,并已计划将其包含在Docker
1.10.0中。但是与此同时,可以使用以下解决方法:

  1. 使用以下命令删除所有用户创建的网络 sudo docker network rm
  2. 使用以下命令停止docker守护进程 sudo service docker stop
  3. 用清理iptables sudo iptables -F && sudo iptables -F -t nat
  4. 重新启动docker守护进程 sudo service docker start
  5. 重新创建用户定义的网络
  6. 运行容器


 类似资料:
  • 使用运行两个容器并执行netcat服务器: 在一个容器中,而在另一个容器中是netcat客户端: 使第一个容器正确打印: 数据阳极是这样开始的: 这两个节点连接良好,当查询时(使用),连接情况报告为: 但是,运行的输出: 但是,当datanode启动时,namenode报告datanode的IP地址为: 并且使用捕获两者之间的通信量(运行在连接到主机网络的Docker容器中-使用)似乎显示发生了错

  • 这是错误: 照明\数据库\查询异常SQLSTATE[42S22]:找不到列: 1054未知列"在'where子句'(SQL:选择计数(*)作为聚合从在哪里"=user@email.com) 我的Resgister控制器: }我的用户表迁移:

  • 当我的网卡连接到网络A时,我正在启动我的RMI服务器。运行我的客户端按预期成功并打印“Hello World”。一旦我将网络连接更改为网络B(无需重新启动RMI服务器!)我无法再连接到服务器。服务器和客户端总是在同一台主机上运行,所以使用localhost地址就足够了。 服务器: 客户: 例外是: 它指的是在连接到网络A时分配给我的IP地址。注册表查找按预期工作,只有对的调用失败,但有上述异常。

  • 问题内容: 节点程序员通常使用这样的范例: 为什么不简化该函数以仅接受一个参数(错误或响应)呢? 似乎更简单。我唯一看到的缺点是函数不能将错误返回为它们的实际预期返回值-但我认为这是一个非常微不足道的用例。 为什么错误优先模式被认为是标准的? 编辑:的实现: 另一个编辑:是否有可能我的替代方法比节点约定更方便,因为仅接受一个参数的回调也更有可能在非回调用例中重用? 问题答案: (有关使用该问题的回

  • 问题内容: 尝试这样做并遇到很多两种类型的错误: 第一:500 当我在浏览器中访问这些URL时,收到以下消息: 内部路由错误 抱歉,我们无法连接到目标服务器。 我们刚刚收到有关此问题的通知。我们将尽快更正。 如有任何疑问,请随时与我们联系:support@iriscouch.com 第二名:503 当我在浏览器中访问这些URL时,收到以下消息: 错误503后端读取错误 后端读取错误 大师冥想: X

  • 有一个非常有趣的错误,我不知道如何解决。在我注册为新用户并单击submit按钮后,我得到以下错误块: 注意:在第153行的public_html/mystore/系统/库/mail.php中遇到非格式良好的数值注意:在第153行的public_html/mystore/系统/库/mail.php中遇到非格式良好的数值警告:无法修改标头信息-标头已发送由(输出开始于public_html/mysto