主要参考资料:

主要步骤

安装ubuntu系统 -> 下载docker -> 在docker里拉取hadoop镜像 -> 在此镜像里创建三个容器 (Master、Slave1、Slave2) -> 完成分布式部署

TODO

安装 ubuntu 系统

我使用 VMware虚拟机 安装 ubuntu 系统,具体原因与安装 SQL Server有关。

下载 docker

参照链接:https://docs.docker.com/engine/install/ubuntu/

根据官方安装步骤来就可以。

Screen Shot 2020-10-13 at 8.39.55 AM

拉取 hadoop 镜像

这里我选择使用阿里云库拉取 hadoop 镜像 registry.cn-beijing.aliyuncs.com/bitnp/docker-spark-hadoop,这个镜像已经提前下载好了我们需要的工具:jdk, hadoop, spark等。

在虚拟机的终端(以下简称终端)里配置加速器:

sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
  "registry-mirrors": ["https://lqbkkmob.mirror.aliyuncs.com"]
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker

创建容器并配置

接下来创建容器 Master、Slave1、Slave2,并对容器进行配置及ssh的互联。

step 1

在终端执行命令:

docker pull registry.cn-beijing.aliyuncs.com/bitnp/docker-spark-hadoop

Screen Shot 2020-10-13 at 9.15.50 AM

step 2

经过一段时间后,镜像已经下载到本地计算机,可使用指令sudo docker images查看是否下载成功:

renyimeng@renyimeng-virtual-machine:~$ sudo docker images
[sudo] password for renyimeng: 
REPOSITORY                                                   TAG                 IMAGE ID            CREATED             SIZE
hello-world                                                  latest              bf756fb1ae65        9 months ago        13.3kB
registry.cn-beijing.aliyuncs.com/bitnp/docker-spark-hadoop   latest              8b768e1604ad        2 years ago         2.11GB

step 3

这时,我们要在这个hadoop镜像里创建三个容器 (Master、Slave1、Slave2),敲上如下指令:(我们先把三个容器创建出来,再慢慢里面添加配置)

renyimeng@renyimeng-virtual-machine:~$ sudo docker run -it --name Master -h Master registry.cn-beijing.aliyuncs.com/bitnp/docker-spark-hadoop /bin/bash
[root@Master local]#

step 4

此时把Master空的容器创建出来了,当然里面什么也没配置,这时候敲上Ctrl+P+Q,会返回到初始目录,并且不会退出Master容器,假如你按下Ctrl+C,也会退出到初始目录,但是,这时候也把Master容器退出了,敲上Ctrl+P+Q后会出现下面情景,代码如下:

[root@Master local]# read escape sequence
renyimeng@renyimeng-virtual-machine:~$ 

step 5

修改一下代码的容器名,依次创建出容器Slave1和容器Slave2:

renyimeng@renyimeng-virtual-machine:~$ sudo docker run -it --name Slave1 -h Slave1 registry.cn-beijing.aliyuncs.com/bitnp/docker-spark-hadoop /bin/bash
[root@Master local]#
renyimeng@renyimeng-virtual-machine:~$ sudo docker run -it --name Slave2 -h Slave2 registry.cn-beijing.aliyuncs.com/bitnp/docker-spark-hadoop /bin/bash
[root@Master local]#

step 6

至此,三个空容器已经创建完成,接下来我们要使用ssh把三个容器连接起来。

我的 docker 中目前只有 yum,因此可以用 yum 下载 vim 来编辑文件,还可以用 yum 下载 openssh-clients、openssh-server,如果你在 docker 里面连 yum 都没有,那么你先使用Ctrl+P+Q退出,在初始目录用apt-get下载一个 yum (指令是 sudo apt-get install yum ),然后在 docker 里面就可以使用了。

先对Master容器进行配置,进入Master容器,敲上指令 docker attach Master

renyimeng@renyimeng-virtual-machine:~$ sudo docker attach Master
[root@Master local]#

我们先下载vim,敲上指令yum -y install vim

[root@Master local]# yum -y install vim
.......过程省略
Complete!
[root@Master local]#

再把openssh-clientsopenssh-server下载下来,注意按我说的顺序下载,先下openssh-clients

[root@Master local]# yum -y install openssh-clients
.......
Complete!
[root@Master local]# yum -y install openssh-server
.......
Complete!
[root@Master local]

step 7

这时我们配置Master容器的ssh密钥。先执行指令 /usr/sbin/sshd,会出现下列情景:

[root@Master local]# /usr/sbin/sshd
Could not load host key: /etc/ssh/ssh_host_rsa_key
Could not load host key: /etc/ssh/ssh_host_ecdsa_key
Could not load host key: /etc/ssh/ssh_host_ed25519_key
sshd: no hostkeys available -- exiting.

再执行指令 /usr/sbin/sshd-keygen -A ,之后再输入一遍 /usr/sbin/sshd 即可:

[root@Master local]# /usr/sbin/sshd
[root@Master local]# 

上述三步必不可少,不然会出现 ssh: connect to host localhost port 22: Cannot assign requested address 等错误,错误参考链接

然后我们就开始制作密钥,输入指令 ssh-keygen -t rsa ,然后一路回车:

[root@Master local]# ssh-keygen -t rsa
Generating public/private rsa key pair.
Enter file in which to save the key (/root/.ssh/id_rsa): 
Created directory '/root/.ssh'.
Enter passphrase (empty for no passphrase): 
Enter same passphrase again: 
Your identification has been saved in /root/.ssh/id_rsa.
Your public key has been saved in /root/.ssh/id_rsa.pub.
The key fingerprint is:
SHA256:BPC1QSB9LcIro8HoVtPSFoHMvDjMqgmdkhCoi+M167c root@Master
The key's randomart image is:
+---[RSA 2048]----+
|. + +=+o+.       |
|o  = ++ooo.      |
|++. + o+o.       |
|+=o=o+..         |
|=+o++o  S        |
|Oo+o             |
|=+. o            |
|o. . .           |
|  ...E.          |
+----[SHA256]-----+
[root@Master local]#

生成的密钥如图所示存在 /root/.ssh/id_rsa.pub 文件中了,我们需要把密钥存储在 /root/.ssh/authorized_keys 文件中,指令是: cat /root/.ssh/id_rsa.pub >> /root/.ssh/authorized_keys

[root@Master local]# cat /root/.ssh/id_rsa.pub >> /root/.ssh/authorized_keys

此时,你可以使用指令 cat /root/.ssh/authorized_keys 查看authorized_keys 文件中是否有你刚才存入的密钥:

renyimeng@renyimeng-virtual-machine:~$ sudo docker attach Master
[sudo] password for renyimeng: 
[root@Master local]# cat /root/.ssh/authorized_keys
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC0P4iS91BK9KuHoupZFTnzNi0iz9LxSvCU/JkAceI5Ypgjecf0OhLDkaZbu07A9vPUJ6zBYdypwvgT6sMnGpqCxsmePo8iObcUyxl7WzPYS0xlFJgJOkYFqtcNs4hOAdV8+uiU+58SJYVtIYuIoW50BNOkoELaVI+0QRWvul9M0UKEwAJFKGfAadYLRlgbcfZmMmzJbyxflBZK0ArfY3uF2zJWLN9ID38CziVFxB1QTTfrNuKvzMUuWR1UcjhDU5bNVUC14mbixYihWSkfBIxDMAtsPw1RRauYaieFSm5xVhf4yaQegIZ+4dnA9SxqSIdG0pUS+CJbeljDpLzlTM5n root@Master

到这里,Master 容器的 ssh 已经配好了,可以使用指令 ssh localhost 验证一下 ,敲上之后,需要再输入 yes,虽然有 warning,但是不用管它,带回配置了 /etc/ssh/sshd_config 文件就什么警告也没了,验证完敲上 Ctrl+D 即可断开与localhost 的 ssh 连接。

[root@Master local]# ssh localhost
[root@Master ~]# 

为了ssh链接时的美观简洁,我们配置其 /etc/ssh/sshd_config 文件,输入指令 vim /etc/ssh/sshd_config 进入编辑文件模式:

[root@Master local]# vim /etc/ssh/sshd_config

进去编辑文件之后,敲上 i ,此时进入编辑模式,按照我下面所列的代码,找到它,并改成这样:

Port 22

PermitRootLogin yes

PubkeyAuthentication yes

PasswordAuthentication yes

ChallengeResponseAuthentication no

UsePAM yes

PrintLastLog no

然后按下 Esc 键,进入命令模式, 再敲上指令 :wq 退出这个编辑文件界面,回到Master 容器界面。

再敲上指令 vim /etc/ssh/ssh_config ,找到 StrictHostKeyChecking no (大约在第35行) ,将注释去掉,并把 ask 改成 no:

[root@Master local]# vim /etc/ssh/ssh_config 
StrictHostKeyChecking no

改完之后同样敲上 Esc 键,进入命令模式, 再敲上指令 :wq 退出这个编辑文件界面,回到 Master 容器界面。

这时候按下Ctrl+P+Q,返回到初始目录,查看此时三个容器的ip地址,输入命令: sudo docker inspect -f '' $(sudo docker ps -aq) 如下:

renyimeng@renyimeng-virtual-machine:~$ sudo docker inspect -f '' $(sudo docker ps -aq) 
/Slave2 - 172.17.0.4
/Slave1 - 172.17.0.3
/Master - 172.17.0.2

然后进入 Master 容器 (指令是 sudo docker attach Master ),打开 /etc/hosts 文件,把上述内容填上,目的是给每个节点的 ip 附上名字,ssh 连接的时候就可以直接 ssh Slave1,而不是 ssh 172.17.0.3 这么麻烦了,所以,我们再次进入Master 容器 ,编辑 /etc/hosts 文件,所以敲上指令 vim /etc/hosts ,进入编辑模式,将容器名及其对应的 ip 填入 ,修改完之后回到Master 容器:

renyimeng@renyimeng-virtual-machine:~$ sudo docker attach Master
[root@Master ~]# vim /etc/hosts
127.0.0.1       localhost
172.17.0.2      Master
172.17.0.3      Slave1
172.17.0.4      Slave2

::1     localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters

至此,Master 容器已经配置完成,然后我们敲上 Ctrl+P+Q 退出当前的 Master 容器,然后敲上 sudo docker attach Slave1 ,进入 Slave1 容器,用和 Master 容器相同的方法,把 Slave1 也配置一遍 (就是从下载 vim 开始到配置 /etc/hosts 文件这几个步骤),再用相同的方式 把 Slave2 也配置完。

step 8

三个容器Master、Slave1、Slave2 的配置终于接近尾声,仅差最后一步,我们需要把三个容器的每个密钥都要放在自己容器的 /root/.ssh/authorized_keys 文件中,只有这样才能把三个容器的互信建立起来,假如你不这样做,你在 Master 容器中用 ssh 连接其他容器 (比如连接 Slave1),那么它会提示你输入 Slave1 的密码,而这个密码你输入什么也不对

因为每个容器的 /root/.ssh/authorized_keys 文件都需要填入 所有容器的密钥,而此时我们刚配置完 Slave2 容器,那么直接输入 vim /root/.ssh/authorized_keys ,进去文件,然后按 i 进入编辑模式,把 Slave2 的密钥拷贝到一个文件中 (你在电脑桌面新建一个临时文件即可),保存结束,退出文件,然后Ctrl+P+Q退出 Slave2 容器,然后 敲上 sudo docker attach Slave1 ,进入 Slave1 容器,相同的方式把 Slave1 的密钥也拷贝出来,然后退出 Slave1,进入 Master 容器,把刚才拷贝的两个密钥追加到/root/.ssh/authorized_keys 文件中(就是进入这个文件切换为编辑模式,把那两个密钥复制过来就行),然后把这个三个密钥拷贝出来,复制到 Slave1 的 /root/.ssh/authorized_keys 文件中,也同样复制到 Slave1 的 root/.ssh/authorized_keys 文件中。用到的详细指令如下:

在所有密钥都放入各个容器之后,我们进行验证一下,在 Master 容器中,我们输入指令 ssh Slave1 ,看到的情景有下面几个情况

如果你出现下面错误,那么你肯定没在每个容器中的 /etc/hosts 文件中输入所有的容器的名字及其对应的 ip 地址。

注意:这个问题在重新启动虚拟机后存在自动回复一个容器的hosts文件对应一个ip地址的问题,需要手动再添加一次。

[root@Master local]# ssh Slave1
ssh: Could not resolve hostname slave1: Name or service not known
[root@Master local]# ssh Slave2
ssh: Could not resolve hostname slave2: Name or service not known

假如你出现下面错误,那么你肯定没在退出每个容器前敲上指令 /usr/sbin/sshd ,看上述13个步骤的加粗部分,很重要!

[root@Master local]# ssh Slave1
ssh: connect to host slave1 port 22: Connection refused
[root@Master local]#
[root@Master local]# ssh Slave2
ssh: connect to host slave1 port 22: Connection refused
[root@Master local]#

现在我们终于可以成功的验证了,现在 Master 容器中连接 Slave1 ,指令是 ssh Slave1 如下:

[root@Master local]# ssh Slave1
[root@Slave1 ~]#

由图可知,成功了,敲上 Ctrl +D 断开与 Slave1 的连接 ,再验证与 Slave2 的连接,指令是 ssh Slave2 ,成功后,Ctrl+D 断开与 Slave2 的连接。

[root@Master local]# ssh Slave1
[root@Slave1 ~]# logout
Connection to slave1 closed.
[root@Master local]# ssh Slave2
[root@Slave2 ~]# 
[root@Slave2 ~]# logout
Connection to slave1 closed.
[root@Master local]#

假如你连接 Slave1 时,还提示了很多信息,不像我这样简洁,比如还有 LastLogin 之类的提示信息,那你肯定是每个容器vim /etc/ssh/sshd_configvim /etc/ssh/ssh_config 文件的配置没有跟我的一样,在上述步骤中,会有这两个文件的配置。

[root@Master local]# hdfs namenode -format
..........一堆代码,此处省略
[root@Master local]#

到此,我们的 docker 环境下的 hadoop 集群已经搭建成功!开酒庆祝!