hadoop3 docker 集群部署

  • 2020-12-28
  • 浏览 (1233)

网络可以使用 macvlan 网络 或 bridge 网络,可以自行选择。本教程使用 bridge 网络。

本教程使用docker原生方式搭建环境,没有使用docker compose,主要是为了可以减少学习成本,另外,整个docker容器的环境的不仅可以用于hadoop,其它需要分布式环境的也可以使用这套环境,比如kafka,flink。

机器信息

域名 ip 备注
m0 172.18.0.100 master
m1 172.18.0.101 slave
m2 172.18.0.102 slave
m3 172.18.0.103 slave

使用 macvlan 网络

使用 bridge 网络的可以忽略这一步,直接看下面的使用 bridge 网络

docker network create -d macvlan --subnet=192.168.8.0/24 --gateway=192.168.8.1 -o parent=wlp40s0f3u3 mynet
  • -d 指定 Docker 网络 driver
  • --subnet 指定 macvlan 网络所在的网络
  • --gateway 指定网关
  • -o parent 指定用来分配 macvlan 网络的物理网卡

查看网络

docker network ls

开启网卡混杂模式

网卡的混杂模式,在该模式下网卡会将网络上的数据一并抓获。

ifconfig wlp40s0f3u3 promisc  #设置混杂模式
ifconfig wlp40s0f3u3 -promisc #取消混杂模式

创建容器

#m0
docker run -d --privileged --restart always -ti -v /sys/fs/cgroup:/sys/fs/cgroup --name m0 -h m0 --net mynet --ip 192.168.8.200 centos:centos7 /usr/sbin/init

#cluster-slaves
docker run -d --privileged --restart always -ti -v /sys/fs/cgroup:/sys/fs/cgroup --name m1 -h m1 --net mynet --ip 192.168.8.201 centos:centos7 /usr/sbin/init

docker run -d --privileged --restart always -ti -v /sys/fs/cgroup:/sys/fs/cgroup --name m2 -h m2 --net mynet --ip 192.168.8.202 centos:centos7 /usr/sbin/init

docker run -d --privileged --restart always -ti -v /sys/fs/cgroup:/sys/fs/cgroup --name m3 -h m3 --net mynet --ip 192.168.8.203 centos:centos7 /usr/sbin/init

使用 bridge 网络

创建固定IP的子网

docker network create --subnet=172.18.0.0/16 netgroup

创建容器

#m0
docker run -d --privileged --restart always -ti -v /sys/fs/cgroup:/sys/fs/cgroup --name m0 -h m0 --net netgroup --ip 172.18.0.100 centos:centos7 /usr/sbin/init

#cluster-slaves
docker run -d --privileged --restart always -ti -v /sys/fs/cgroup:/sys/fs/cgroup --name m1 -h m1 --net netgroup --ip 172.18.0.101 centos:centos7 /usr/sbin/init

docker run -d --privileged --restart always -ti -v /sys/fs/cgroup:/sys/fs/cgroup --name m2 -h m2 --net netgroup --ip 172.18.0.102 centos:centos7 /usr/sbin/init

docker run -d --privileged --restart always -ti -v /sys/fs/cgroup:/sys/fs/cgroup --name m3 -h m3 --net netgroup --ip 172.18.0.103 centos:centos7 /usr/sbin/init

#mysql
docker run -d --privileged --restart always -ti -v /sys/fs/cgroup:/sys/fs/cgroup --name mysql -h mysql --net netgroup --ip 172.18.0.200 -e MYSQL_ROOT_PASSWORD=abc@123456 -d --restart always  mysql:5.7.24

解决 CentOS 8 上Docker容器内无法联网

只需要将 Docker 添加到 firewalld 的 trusted 组即可。执行:

firewall-cmd --permanent --zone=trusted --change-interface=docker0
firewall-cmd --reload

docker0 需改成相应的网卡名

m0 配置

换源

yum -y install wget
mv /etc/yum.repos.d/CentOS-Base.repo  /etc/yum.repos.d/CentOS-Base.repo.backup
wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.163.com/.help/CentOS7-Base-163.repo
yum makecache

安装openssh

yum -y install openssh openssh-server openssh-clients
systemctl start sshd
systemctl enable sshd

ssh自动接受新的公钥,master设置ssh登录自动添加kown_hosts

修改 /etc/ssh/ssh_config,将原来的StrictHostKeyChecking ask,设置StrictHostKeyChecking为no

systemctl restart sshd

m1-m3 配置

换源

yum -y install wget
mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.backup
wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.163.com/.help/CentOS7-Base-163.repo
yum makecache

安装openssh

yum -y install openssh openssh-server openssh-clients
systemctl enable sshd
systemctl start sshd

m0公钥分发

在master机上执行ssh-keygen -t rsa并一路回车,完成之后会生成~/.ssh目录,目录下有id_rsa(私钥文件)和id_rsa.pub(公钥文件)

ssh-copy-id root@172.18.0.101
ssh-copy-id root@172.18.0.102
ssh-copy-id root@172.18.0.103

至此,m0可以免密登录个slave。

Ansible安装

官方自带安装:

yum -y install epel-release
yum -y install ansible

编辑ansible的hosts文件 /etc/ansible/hosts 添加配置

[cluster]
m0
m1
m2
m3

[master]
m0

[slaves]
m1
m2
m3

配置docker容器hosts

由于/etc/hosts文件在容器启动时被重写,直接修改内容在容器重启后不能保留,为了让容器在重启之后获取集群hosts,使用了一种启动容器后重写hosts的方法。 需要在~/.bashrc中追加以下指令

:>/etc/hosts
cat >>/etc/hosts<<EOF
127.0.0.1   localhost
172.18.0.100  m0
172.18.0.101  m1
172.18.0.102  m2
172.18.0.103  m3
EOF

用ansible分发.bashrc至集群slave下

ansible slaves -m copy -a "src=~/.bashrc dest=~/"

修改时区为亚洲上海

ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime

支持中文

localedef -i zh_CN -f UTF-8 zh_CN.UTF-8

yum -y install kde-l10n-Chinese && yum -y reinstall glibc-common

# 以下内容加入~/.bashrc,加入后source ~/.bashrc
localedef -c -f UTF-8 -i zh_CN zh_CN.utf8

export LC_ALL=zh_CN.utf8

另一种方式是在Dockerfile中添加一行,如下所示:

ENV LANG C.UTF-8

重新打包制作docker镜像。

时间同步

NTP服务器【Network Time Protocol(NTP)】是用来使计算机时间同步化的一种协议,它可以使计算机对其服务器或时钟源(如石英钟,GPS等等)做同步化,它可以提供高精准度的时间校正(LAN上与标准间差小于1毫秒,WAN上几十毫秒),且可介由加密确认的方式来防止恶毒的协议攻击。

m0 配置ntp

安装ntp

yum install ntp -y
systemctl enable ntpd
systemctl start ntpd

同步网上时间

ntpdate 0.centos.pool.ntp.org #该网址为centos网络上的时间同步服务器

关于ntpd与ntpdate区别

ntpd不仅仅是时间同步服务器,它还可以做客户端与标准时间服务器进行同步时间,而且是平滑同步,并非ntpdate立即同步,在生产环境中慎用ntpdate,也正如此两者不可同时运行。

NTPD 在和时间服务器的同步过程中,会把 BIOS 计时器的振荡频率偏差——或者说 Local Clock 的自然漂移(drift)——记录下来。这样即使网络有问题,本机仍然能维持一个相当精确的走时。

m1-m3 配置ntp

安装ntp

yum install ntp -y

修改ntp配置

修改 /etc/ntp.conf,将内容删除,添加一下内容:

server m0

启动ntp

systemctl enable ntpd
systemctl start ntpd

查看与时间同步服务器的时间偏差

ntpdc -c loopinfo

查看ntp状态

ntpstat

输出信息:

time correct to within 594 ms
polling server every 128 s

这个指令可以列出我们的 NTP 服务器有跟上层联机否。由上述的输出结果可以知道,时间有校正约 594 * 10^(-3) 秒,且每隔 128 秒会主动去更新时间喔!

查看当前同步的时间服务器

ntpq -p

输出信息:

remote refid st t when poll reach delay offset jitter
*m0 193.182.111.141 3 u 61 64 377 0.104 0.031 0.011

下面的表格解释了输出列。

字段 备注
remote 源在 ntp.conf 中定义。‘*’ 表示当前使用的,也是最好的源;‘+’ 表示这些源可作为 NTP 源;‘-’ 标记的源是不可用的。
refid 用于和本地时钟同步的远程服务器的 IP 地址。
st Stratum(阶层)
t 类型。 ‘u’ 表示单播(unicast)。其它值包括本地(local)、多播(multicast)、广播(broadcast)。
when 自从上次和服务器交互后经过的时间(以秒数计)。
poll 和服务器的轮询间隔,以秒数计。
reach 表示和服务器交互是否有任何错误的八进制数。值 337 表示 100% 成功(即十进制的255)。
delay 服务器和远程服务器来回的时间。
offset 我们服务器和远程服务器的时间差异,以毫秒数计。
jitter 两次取样之间平均时差,以毫秒数计。

/sbin/hwclock: 用于 BIOS 时钟 (硬件时钟) 的修改与显示的指令。 这是一个 root 才能执行的指令,因为 Linux 系统上面 BIOS 时间与 Linux 系统时间是分开的,所以使用 date 这个指令调整了时间之后,还需要使用 hwclock 才能将修改过后的时间写入 BIOS 当中!

使用ansible在在集群中安装openjdk

ansible cluster -m yum -a "name=java-1.8.0-openjdk,java-1.8.0-openjdk-devel state=latest"

hadoop 搭建

下载最新hadoop

https://mirrors.tuna.tsinghua.edu.cn/apache/hadoop/common/stable/hadoop-3.3.0.tar.gz

下载完成之后解压安装包,并创建链接文件:

tar -xzvf hadoop-3.3.0.tar.gz 
ln -s hadoop-3.3.0 hadoop

设置java和hadoop环境变量(~/.bashrc)

#java
export JAVA_HOME=/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.272.b10-1.el7_9.x86_64/
export PATH=$HADOOP_HOME/bin:$PATH

# hadoop
export HADOOP_HOME=/opt/hadoop
export PATH=$HADOOP_HOME/bin:$HADOOP_HOME/sbin:$PATH

修改配置

修改$HADOOP_HOME/etc/hadoop/core-site.xml

<configuration>
    <property>
        <name>hadoop.tmp.dir</name>
        <value>/home/hadoop/tmp</value>
        <description>A base for other temporary directories.</description>
    </property>
    <!-- file system properties -->
    <property>
        <name>fs.default.name</name>
        <value>hdfs://m0:9000</value>
    </property>
    <property>
    <name>fs.trash.interval</name>
        <value>4320</value>
    </property>
</configuration>

修改$HADOOP_HOME/etc/hadoop/hdfs-site.xml

<property>
   <name>dfs.namenode.name.dir</name>
   <value>/home/hadoop/tmp/dfs/name</value>
 </property>
 <property>
   <name>dfs.datanode.data.dir</name>
   <value>/home/hadoop/data</value>
 </property>
 <property>
   <name>dfs.replication</name>
   <value>3</value>
 </property>
 <property>
   <name>dfs.webhdfs.enabled</name>
   <value>true</value>
 </property>
 <property>
   <name>dfs.permissions.superusergroup</name>
   <value>staff</value>
 </property>
 <property>
   <name>dfs.permissions.enabled</name>
   <value>false</value>
 </property>

修改$HADOOP_HOME/etc/hadoop/mapred-site.xml

<configuration>
<property>
  <name>mapreduce.framework.name</name>
  <value>yarn</value>
</property>
<property>
        <name>mapred.job.tracker</name>
        <value>m0:9001</value>
</property>
<property>
  <name>mapreduce.jobtracker.http.address</name>
  <value>m0:50030</value>
</property>
<property>
  <name>mapreduce.jobhisotry.address</name>
  <value>m0:10020</value>
</property>
<property>
  <name>mapreduce.jobhistory.webapp.address</name>
  <value>m0:19888</value>
</property>
<property>
  <name>mapreduce.jobhistory.done-dir</name>
  <value>/jobhistory/done</value>
</property>
<property>
  <name>mapreduce.intermediate-done-dir</name>
  <value>/jobhisotry/done_intermediate</value>
</property>
<property>
  <name>mapreduce.job.ubertask.enable</name>
  <value>true</value>
</property>
</configuration>

修改$HADOOP_HOME/etc/hadoop/yarn-site.xml

<configuration>
    <property>
   <name>yarn.resourcemanager.hostname</name>
   <value>m0</value>
 </property>
 <property>
   <name>yarn.nodemanager.aux-services</name>
   <value>mapreduce_shuffle</value>
 </property>
 <property>
   <name>yarn.nodemanager.aux-services.mapreduce.shuffle.class</name>
   <value>org.apache.hadoop.mapred.ShuffleHandler</value>
 </property>
 <property>
   <name>yarn.resourcemanager.address</name>
   <value>m0:18040</value>
 </property>
<property>
   <name>yarn.resourcemanager.scheduler.address</name>
   <value>m0:18030</value>
 </property>
 <property>
   <name>yarn.resourcemanager.resource-tracker.address</name>
   <value>m0:18025</value>
 </property> <property>
   <name>yarn.resourcemanager.admin.address</name>
   <value>m0:18141</value>
 </property>
<property>
   <name>yarn.resourcemanager.webapp.address</name>
   <value>m0:18088</value>
 </property>
<property>
   <name>yarn.log-aggregation-enable</name>
   <value>true</value>
 </property>
<property>
   <name>yarn.log-aggregation.retain-seconds</name>
   <value>86400</value>
 </property>
<property>
   <name>yarn.log-aggregation.retain-check-interval-seconds</name>
   <value>86400</value>
 </property>
<property>
   <name>yarn.nodemanager.remote-app-log-dir</name>
   <value>/tmp/logs</value>
 </property>
<property>
   <name>yarn.nodemanager.remote-app-log-dir-suffix</name>
   <value>logs</value>
 </property>
</configuration>

root 用户特殊配置

在$HADOOP_HOME/sbin/start-dfs.sh、stop-dfs.sh添加:

HDFS_DATANODE_USER=root
HADOOP_SECURE_DN_USER=hdfs
HDFS_NAMENODE_USER=root
HDFS_SECONDARYNAMENODE_USER=root

在$HADOOP_HOME/sbin/start-yarn.sh、stop-yarn.sh添加:

YARN_RESOURCEMANAGER_USER=root
HADOOP_SECURE_DN_USER=yarn
YARN_NODEMANAGER_USER=root

$HADOOP_HOME/etc/hadoop下的workers文件

新增:

m1
m2
m3

3.0.0以后的版本都不让用slaves了,现在是workers

打包hadoop文件

tar -cvf hadoop-dis.tar hadoop hadoop-3.3.0

使用ansible-playbook分发.bashrc和hadoop-dis.tar至slave主机

---
- hosts: cluster
  tasks:
    - name: copy .bashrc to slaves
      copy: src=~/.bashrc dest=~/
      notify:
        - exec source
    - name: copy hadoop-dis.tar to slaves
      unarchive: src=/opt/hadoop-dis.tar dest=/opt

  handlers:
    - name: exec source
      shell: source ~/.bashrc

将以上yaml保存为hadoop-dis.yaml,并执行

ansible-playbook hadoop-dis.yaml

在 m0 格式化namenode

hadoop namenode -format

启动hadoop集群

$HADOOP_HOME/sbin

./start-all.sh

访问hadoop web

3.x 版本 NameNode 50070端口 -> 9870端口了 访问:m0:9870 可以看到集群信息。

用命令查看集群信息

 hdfs dfsadmin -report

### 查看YARN各节点状态

 yarn node -list

存放文件

hdfs dfs -put start-all.sh /

获取文件

hdfs dfs -get /start-all.sh /root/

获取文件列表

hdfs dfs -ls /

hadoop3.x 端口变更

  • Namenode ports: 50470 –> 9871, 50070–> 9870, 8020 –> 9820

  • Secondary NN ports: 50091 –> 9869,50090 –> 9868

  • Datanode ports: 50020 –> 9867, 50010–> 9866, 50475 –> 9865, 50075 –> 9864

  • Kms server ports: 16000 –> 9600 (原先的16000与HMaster端口冲突)

Hadoop的启动和停止说明

sbin/start-all.sh 启动所有的Hadoop守护进程。包括NameNode、 Secondary NameNode、DataNode、ResourceManager、NodeManager

sbin/stop-all.sh 停止所有的Hadoop守护进程。包括NameNode、 Secondary NameNode、DataNode、ResourceManager、NodeManager

sbin/start-dfs.sh 启动Hadoop HDFS守护进程NameNode、SecondaryNameNode、DataNode

sbin/stop-dfs.sh 停止Hadoop HDFS守护进程NameNode、SecondaryNameNode和DataNode

sbin/hadoop-daemons.sh start namenode 单独启动NameNode守护进程

sbin/hadoop-daemons.sh stop namenode 单独停止NameNode守护进程

sbin/hadoop-daemons.sh start datanode 单独启动DataNode守护进程

sbin/hadoop-daemons.sh stop datanode 单独停止DataNode守护进程

sbin/hadoop-daemons.sh start secondarynamenode 单独启动SecondaryNameNode守护进程

sbin/hadoop-daemons.sh stop secondarynamenode 单独停止SecondaryNameNode守护进程

sbin/start-yarn.sh 启动ResourceManager、NodeManager

sbin/stop-yarn.sh 停止ResourceManager、NodeManager

sbin/yarn-daemon.sh start resourcemanager 单独启动ResourceManager

sbin/yarn-daemons.sh start nodemanager  单独启动NodeManager

sbin/yarn-daemon.sh stop resourcemanager 单独停止ResourceManager

sbin/yarn-daemons.sh stopnodemanager  单独停止NodeManager

sbin/mr-jobhistory-daemon.sh start historyserver 手动启动jobhistory

sbin/mr-jobhistory-daemon.sh stop historyserver 手动停止jobhistory

参考资料

0  赞