1 制作hadoop镜像
参见 https://www.cnblogs.com/rmxd/p/12051866.html
该博客中只参考制作镜像部分,固定IP及启动集群的部分应该跳过。
这里注意,在做好的镜像里,要安装 which 工具,否则在执行 hdfs 命令时会报命令不存在异常。
yum install which -y
2 启动容器
docker run --name hmaster --hostname hmaster --network hadoop -d -P \
-p 50070:50070 \
-p 50010:50010 \
-p 9000:9000 \
-p 8088:8088 \
-p 50090:50090 \
taiga/hadoop:v1.1
docker run --name hslave1 --hostname hslave1 --network hadoop -d -P \
-p 51070:51070 \
-p 51010:51010 \
-p 9100:9100 \
-p 8188:8188 \
-p 51090:51090 \
taiga/hadoop:v1.1
docker run --name hslave2 --hostname hslave2 --network hadoop -d -P \
-p 52070:52070 \
-p 52010:52010 \
-p 9200:9200 \
-p 8288:8288 \
-p 52090:52090 \
taiga/hadoop:v1.1
可以看到,我的镜像名称是 taiga/hadoop:v1.1
这里启动了三个容器,一个master,两个slave。注意要向外映射 51010 52010 端口,这两个端口用作 datanode 的控制端口,用于远程上传文件时,可以将datanode在端口映射给宿主机。
3 master免密登陆slave
进行 hmaster 容器,执行以下命令
ssh-keygen
# 剩下的一路回车即可
ssh-copy-id hmaster
# master也是免下密,根据提示输入yes以及主机密码
ssh-copy-id hslave1
ssh-copy-id hslave2
4 配置
hmaster core-site.xml
fs.defaultFS
hdfs://hmaster:9000
hadoop.tmp.dir
/usr/local/hadoop/tmp
fs.trash.interval
1440
hmaster hdfs-site.xml
dfs.replication
2
dfs.permissions
false
dfs.namenode.name.dir
/var/bigdata/hadoop/full/dfs/name
dfs.datanode.data.dir
/var/bigdata/hadoop/full/dfs/data
dfs.namenode.secondary.http-address
hslave1:51090
dfs.namenode.checkpoint.dir
/var/bigdata/hadoop/full/dfs/secondary
hmaster hadoop-env.sh
在hadoop-env.sh里添加JAVA_HOME,这是必须要做的,因为当master节点ssh到slave节点上时,是获取不到slave节点的环境变量的,因此也拿不到 slave 节点的 $JAVA_HOME ,所以在hadoop-env.sh 里必须配置为绝对路径。
export JAVA_HOME=/usr/local/jdk1.8
hmaster slaves
在该文件里配置上slave节点的域名。因为在启动容器时已经将master和slave放在了同一个network里,所以直接使用域名即可相通通信,这也是不需要参照刚才那个博主中“固定IP”这一步骤的原因了。
hslave1
hslave2
将hmaster节点的配置分发到hslave hslave2中
cd /usr/local/hadoop/etc
scp ./hadoop hslave1:`pwd`
scp ./hadoop hslave2:`pwd`
配置slave节点
配置hslave1和hslave2的 hdfs-site.xml。为了将datanode的控制端口映射到宿主机,我们分别将 hslave1 和 hslave2的控制端口改成了 51010 和 52010, 所以要配置hslave1和hslave2的 hdfs-site.xml。
在hslave1中添加,是添加,其它的配置不动
dfs.datanode.address
hslave1:51010
在hslave2中添加,是添加,其它的配置不动
dfs.datanode.address
hslave2:52010
到这里所有的配置都完毕了。
5 启动
回到hmaster节点,执行
hdfs namenode -format
/usr/local/hadoop/sbin/start-dfs.sh
6 验证
OKAY ,集群搭建完毕。下面进行验证
浏览器访问 http://x.x.x.x:50070/dfshealth.html#tab-overview 。访问前首先保证虚拟机 50070 端口开放,或是虚拟机关闭防火墙。出现以下页面表示搭建成功:
来看一下datanode
这里的两个端口就是在 hslave1 和 hslave2里配置的
7 上传文件
在容器里上传文件肯定是会成功的了,就不验证了,下面验证一下通过 java 客户端上传个文件。
首先在电脑的 hosts 文件里加两行配置
x.x.x.x hslave1
x.x.x.x hslave1
x.x.x.x就是你虚拟机的ip
上传文件代码示例
package cn.hgd11.hadoop;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.*;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.ByteBuffer;
public class HdfsTest {
private Configuration configuration;
private long start;
private long end;
private FileSystem fs;
@Before
public void before () throws URISyntaxException, IOException, InterruptedException {
start = System.currentTimeMillis();
configuration = new Configuration(true);
// 这行代码一定要有,表示从namenode拉回的datanode信息是域名,而不是ip,因为docker里的容器ip在本机是访问不到的
configuration.set("dfs.client.use.datanode.hostname", "true");
URI uri = new URI("hdfs://node128:9000/");
fs = FileSystem.get(uri, configuration, "root");
}
@Test
public void upload () throws IOException {
try {
String pathStr = "D:\\java\\mash\\资料\\hbase-book-master\\ch07\\test-data.txt";
Path src = new Path(pathStr);
Path dst = new Path("/hbase-book-code/ch07/test-data.txt");
fs.copyFromLocalFile(src, dst);
System.out.println("上传完成");
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
@After
public void after () throws IOException {
if (fs != null) {
fs.close();
}
System.out.println("程序耗时:" + (System.currentTimeMillis() - start));
}
}