繁体   English   中英

无法连接到 docker 主机外部的 docker 容器

[英]Unable connect to docker container outside docker host

我有两个 docker 容器在 ubuntu 上运行,其中一个用于 hadoop namenode,另一个用于 hadoop datanode。

现在我在 Windows 上运行我的 java 代码使用 Hadoop FileSystem api 将文件从我的 Windows 文件系统复制到远程 docker hdfs 。

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.FileUtil;
import org.apache.hadoop.fs.Path;
import org.junit.Test;

import java.io.File;

public class HadoopTest {

    @Test
    public void testCopyFileToHDFS() throws Exception {
        Configuration configuration = new Configuration();
        configuration.addResource(getClass().getClassLoader().getResourceAsStream("hadoop/core-site.xml"));
        configuration.addResource(getClass().getClassLoader().getResourceAsStream("hadoop/yarn-site.xml"));
        FileSystem fileSystem = FileSystem.get(configuration);
        FileUtil.copy(new File("c:\\windows-version.txt"),fileSystem,   new Path("/testsa"), false,configuration);
    }
}

但我收到以下错误:

16:57:05.669 [Thread-4] DEBUG org.apache.hadoop.hdfs.DFSClient - Connecting to datanode 172.18.0.2:50010
16:57:15.654 [IPC Client (547201549) connection to /192.168.56.102:9000 from ignis] DEBUG org.apache.hadoop.ipc.Client - IPC Client (547201549) connection to /192.168.56.102:9000 from ignis: closed
16:57:15.655 [IPC Client (547201549) connection to /192.168.56.102:9000 from ignis] DEBUG org.apache.hadoop.ipc.Client - IPC Client (547201549) connection to /192.168.56.102:9000 from ignis: stopped, remaining connections 0
16:57:26.670 [Thread-4] INFO org.apache.hadoop.hdfs.DFSClient - Exception in createBlockOutputStream
java.net.ConnectException: Connection timed out: no further information
    at sun.nio.ch.SocketChannelImpl.checkConnect(Native Method)
    at sun.nio.ch.SocketChannelImpl.finishConnect(SocketChannelImpl.java:717)
    at org.apache.hadoop.net.SocketIOWithTimeout.connect(SocketIOWithTimeout.java:206)
    at org.apache.hadoop.net.NetUtils.connect(NetUtils.java:531)
    at org.apache.hadoop.hdfs.DFSOutputStream.createSocketForPipeline(DFSOutputStream.java:1533)
    at org.apache.hadoop.hdfs.DFSOutputStream$DataStreamer.createBlockOutputStream(DFSOutputStream.java:1309)
    at org.apache.hadoop.hdfs.DFSOutputStream$DataStreamer.nextBlockOutputStream(DFSOutputStream.java:1262)
    at org.apache.hadoop.hdfs.DFSOutputStream$DataStreamer.run(DFSOutputStream.java:448)
16:57:26.673 [Thread-4] INFO org.apache.hadoop.hdfs.DFSClient - Abandoning BP-53577818-172.18.0.2-1500882061263:blk_1073741827_1003

您可以看到第一行错误,上面写着“Connecting to datanode 172.18.0.2:50010”是一个docker内部 IP 地址。

我的 Java 代码在 docker 主机之外的真实 Windows 机器上运行。

我已经将 Hadoop HDFS 端口(例如 9000 和 50010)映射到我的 docker 主机(ubuntu)。所以我可以通过 docker 主机 ip 地址和 HDFS 的端口访问 HDFS 名称节点。

下面是我的java代码的逻辑:

1)Java代码在windows机器上运行

2)Java 代码使用 FileSystem api 将文件从 Windows 复制到远程 HDFS。

3)客户端可以使用docker主机的IP地址和docker容器映射的端口(例如9000)连接到HDFS名称节点

4)HDFS Namenode服务器将处理客户端发送的请求,并将数据节点的IP地址返回给客户端。

5)客户端尝试使用数据节点的IP地址从本地复制文件

6) 客户端收到错误,说数据节点的 ip 地址无法访问,因为它是 docker 容器内的 ip 地址

在此处输入图片说明

最后,我通过为 datanode 引入主机名找到了解决方案,并启用 hdfs 客户端在连接到 datanode 时使用主机名而不是 ip 地址,我的客户端还需要将 datanode 主机名映射为 docker 主机 ip 地址,以下是详细步骤:

  1. 在 docker-compose.xml 中为 docker datanode 容器添加主机名

    主机名:datanode.company.com

  2. 启用 hdfs(服务器和客户端)以使用主机名而不是 ip 地址。

 <configuration> <property> <name>dfs.client.use.datanode.hostname</name> <value>true</value> </property> <property> <name>dfs.datanode.use.datanode.hostname</name> <value>true</value> </property> </configuration>

  1. 通过在 etc/hosts 文件中添加一个条目,将 docker datanode 主机名映射为 docker 主机 ip 地址

    192.168.1.25 datanode.company.com

您可以在不为 datanode 容器添加主机名的情况下解决此问题。 我在本地 docker 容器上运行 hadoop,所以我的示例将使用 localhost,将其更改为 docker 可访问的外部地址。

如果您尝试将文件写入 docker 容器内的 hdfs,则会发生以下情况:

  1. new FileSystem.get(configuration) 使用fs.defaultFS属性连接到在core-site.xml 中配置的 namenode:
    <property>
        <name>fs.defaultFS</name>
        <value>hdfs://0.0.0.0:9000</value>
    </property>
  1. Namenode 响应 datanode 主机名,上传数据的位置。 它配置了hdfs-site.xml属性dfs.datanode.hostname - 可访问的 docker 外部地址:
    <property>
        <name>dfs.datanode.hostname</name>
        <value>localhost</value>
    </property>

我的主机名是本地 docker 容器的 localhost

  1. 客户端 new FileSystem.get(configuration) 连接到 namenode 并检索 datanode 主机以上传数据。 它配置为:
    Configuration configuration = new Configuration();
    // Namenode connection on local docker container
    configuration.set("fs.defaultFS", hdfs://localhost:9000);
    // Configure client to ask namenode for datanode hostname to upload data
    configuration.setBoolean("dfs.client.use.datanode.hostname", true);
    FileSystem fileSystem = FileSystem.get(configuration);

配置属性说明: https : //hadoop.apache.org/docs/current/hadoop-project-dist/hadoop-hdfs/hdfs-default.xml

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM