简介
安装hadoop集群真的很麻烦, 我在网上找各种资料看来看去, 最后花了差不多4天时间才算搞好环境. 如果你希望用5分钟装好hadoop, 那么你可以看这篇懒人版:
https://www.jianshu.com/p/6d294b515bda
如果你希望按着我走的步骤重新走一次安装流程, 加深对hadoop的印象, 你可以继续往下看.
在安装之前, 你应该先装好docker, 下载好 jdk8, 下载好 hadoop 3.3.1 版本 , 你还需要一点docker的知识, 和编写 Dockerfile的知识.
构建所需镜像
参考: https://www.cnblogs.com/rmxd/p/12051866.html
构建ubuntu-ssh
from ubuntu:18.04
# 镜像的作者
MAINTAINER cys
# 更换源
RUN sed -i s@/archive.ubuntu.com/@/mirrors.aliyun.com/@g /etc/apt/sources.list
# 安装 ping / ifconfig 等工具
RUN apt-get update \
&& apt-get install -y vim \
&& apt-get install -y zip \
&& apt-get install -y net-tools \
&& apt-get install -y iputils-ping \
&& apt-get install -y openssh-server \
&& apt-get install -y openssh-client
# 修改root用户密码
RUN echo "root:root" | chpasswd
# 允许root ssh 登录
RUN echo 'PermitRootLogin yes' >> /etc/ssh/sshd_config
RUN echo 'PasswordAuthentication yes' >> /etc/ssh/sshd_config
# 启动sshd服务并且暴露22端口
RUN mkdir /var/run/sshd
EXPOSE 22
CMD ["/usr/sbin/sshd", "-D"]
然后运行:
sudo docker build -t 'cys/ubuntu-ssh' . # 末尾的.表示当前目录
构建ubuntu-ssh-jdk8
#基于上一个ssh镜像构建
FROM cys/ubuntu-ssh
#拷贝并解压jdk
ADD jdk8.tar.gz /usr/local/
ENV JAVA_HOME /usr/local/jdk8
ENV PATH $JAVA_HOME/bin:$PATH
然后运行:
sudo docker build -t 'cys/ubuntu-ssh-jdk8' . # 末尾的.表示当前目录
测试jdk的容器
先用 sudo docker images 查找镜像id , 然后:
sudo docker run -it image_xxxxx /bin/bash
# 测试看jdk是否正确
java -version
echo $JAVA_HOME
构建 ubuntu-ssh-jdk8-hadoop
FROM cys/ubuntu-ssh-jdk8
ADD hadoop-3.3.1.tar.gz /usr/local
RUN mv /usr/local/hadoop-3.3.1 /usr/local/hadoop
ENV HADOOP_HOME /usr/local/hadoop
ENV PATH $HADOOP_HOME/bin:$PATH
然后运行:
sudo docker build -t 'cys/ubuntu-ssh-jdk8-hadoop' . # 末尾的.表示当前目录
构建自定义网络
如果没有固定分配的 IP ,容器提供的服务将是不可靠的.每次主机重启时,如果容器没有固定 IP ,容器的 IP 将由启动顺序决定。这将导致类似无法远程访问数据库等等情况时,发送错误的请求,从而使得服务提供失败。
参考: https://www.cnblogs.com/Yogile/p/12944741.html
运行以下命令:
# 格式: sudo docker network create --subnet=[自定义网络广播地址]/[子网掩码位数] [自定义网络名]
# --subnet :设置前 24 位为网络位,后 8 位为主机位,该网段可用 IP 地址:172.20.0.1 到 172.20.0.254
sudo docker network create --subnet=172.20.0.0/24 my_net
其中, 172.20.0.1 为网关, 其他容器不能再使用.
规划hadoop 集群
主节点:hadoop1 ip: 172.20.0.2
从节点1:hadoop2 ip: 172.20.0.3
从节点2:hadoop3 ip: 172.20.0.4
启动容器
# hadoop 1 : 172.20.0.2
sudo docker run --name hadoop1 --hostname hadoop1 --net my_net --ip 172.20.0.2 -d -P -p 50070:50070 -p 8088:8088 cys/ubuntu-ssh-jdk8-hadoop # hadoop1 对外开放端口50070和8088
sudo docker run --name hadoop2 --hostname hadoop2 --net my_net --ip 172.20.0.3 -d -P cys/ubuntu-ssh-jdk8-hadoop
sudo docker run --name hadoop3 --hostname hadoop3 --net my_net --ip 172.20.0.4 -d -P cys/ubuntu-ssh-jdk8-hadoop
进入主节点
sudo docker exec -it hadoop1 /bin/bash
ping 172.20.0.3
可以看到该容器能够ping 通其余两台机器. 后续的所有操作如无提示, 都是在主节点机器进行操作.
配置hosts
vim /etc/hosts
输入:
172.20.0.2 hadoop1
172.20.0.3 hadoop2
172.20.0.4 hadoop3
设置免密码登录
ssh-keygen
# 一路回车
# 提示输入密码, 密码是 root
ssh-copy-id hadoop1
ssh-copy-id hadoop2
ssh-copy-id hadoop3
设置 hadoop-env.sh
进入/usr/local/hadoop/etc/hadoop目录,涉及的配置文件有:core-site.xml、hdfs-site.xml、yarn-site.xml、mapred-site.xml
export JAVA_HOME=/usr/local/jdk8 #修改JAVA_HOME
core-site.xml
<configuration>
<!-- 设置默认的hdfs 路径 -->
<property>
<name>fs.defaultFS</name>
<value>hdfs://hadoop1:9000</value>
</property>
<property>
<name>hadoop.tmp.dir</name>
<value>/usr/local/hadoop/tmp</value>
</property>
<property>
<name>fs.trash.interval</name>
<value>1440</value>
</property>
</configuration>
hdfs-site.xml
<configuration>
<property>
<name>dfs.replication</name>
<value>1</value>
<description>副本个数,配置默认是3,应小于datanode机器数量</description>
</property>
<property>
<name>dfs.permissions</name>
<value>false</value>
</property>
</configuration>
yarn-site.xml
<configuration>
<property>
<name>yarn.nodemanager.aux-services</name>
<value>mapreduce_shuffle</value>
</property>
<property>
<name>yarn.log-aggregation-enable</name>
<value>true</value>
</property>
<property>
<description>The hostname of the RM.</description>
<name>yarn.resourcemanager.hostname</name>
<value>hadoop1</value>
</property>
</configuration>
mapred-site.xml
<configuration>
<property>
<name>mapreduce.framework.name</name>
<value>yarn</value>
</property>
<property>
<name>yarn.app.mapreduce.am.env</name>
<value>HADOOP_MAPRED_HOME=/usr/local/hadoop</value>
</property>
<property>
<name>mapreduce.map.env</name>
<value>HADOOP_MAPRED_HOME=/usr/local/hadoop</value>
</property>
<property>
<name>mapreduce.reduce.env</name>
<value>HADOOP_MAPRED_HOME=/usr/local/hadoop</value>
</property>
</configuration>
修改 start-dfs.sh 和 stop-dfs.sh
切换到目录 /usr/local/hadoop/sbin, 修改这两个文件, 在最开头加上:
HDFS_DATANODE_USER=root
HDFS_DATANODE_SECURE_USER=hdfs
HDFS_NAMENODE_USER=root
HDFS_SECONDARYNAMENODE_USER=root
修改 start-yarn.sh 和 stop-yarn.sh
同样, 在开头的合适位置添加下列参数:
YARN_RESOURCEMANAGER_USER=root
HADOOP_SECURE_DN_USER=yarn
YARN_NODEMANAGER_USER=root
修改workers文件
位置在 /usr/local/hadoop/etc/hadoop 目录下
hadoop2
hadoop3
复制配置到其他节点
scp -rq /usr/local/hadoop/ hadoop2:/usr/local/
scp -rq /usr/local/hadoop/ hadoop3:/usr/local/
执行命令
cd /usr/local/hadoop
bin/hdfs namenode -format
sbin/start-all.sh
这其中, namenode -format 不能经常用, 否则datanode 会无法启动. 参考 "常见问题" 1子节点 datanode 没有启动
检查
在主节点 hadoop1, 敲入 jps, 应该看到以下进程:
在从节点 hadoop2 和 hadoop3 应该看到以下进程:
这样, hadoop 就算安装成功了.
测试
在主节点创建文件并上传
创建 a.txt
vim a.txt
hello hadoop
hello spark
hello flink
上传
hdfs dfs -put a.txt /
hadoop fs -ls /
应该能看到文件已成功上传
提交job至集群测试
cd /usr/local/hadoop/share/hadoop/mapreduce
hadoop jar hadoop-mapreduce-examples-3.3.1.jar wordcount /a.txt /out
首先应该能看到类似如下输出:
然后执行:
hadoop fs -ls /out
可以看到 out 的内容如下:
再查看输出内容:
hadoop fs -cat /out/part-r-00000
可以看到:
这样, hadoop 总算安装好了.
常见问题
1 子节点 datanode 没有启动
进入子节点的目录 /usr/local/hadoop/logs 看log, 一般会遇到这个错误: Incompatible clusterIDs in /tmp/hadoop-root/dfs/data: namenode
这是由于多次运行格式化命令引起的(这个命令: bin/hdfs namenode -format) , 解决的办法是:
先到主节点关闭和删除缓存
/usr/local/hadoop/sbin/stop-all.sh
rm /usr/local/hadoop/tmp/* -rf
删除所有从节点的缓存
rm /usr/local/hadoop/tmp/* -rf
回到主节点:
/usr/local/hadoop/bin/hdfs namenode -format
/usr/local/hadoop/sbin/start-all.sh