搭建一個Hadoop叢集環境時需要多臺伺服器,對於我們個人,這通常是個門檻,需要使用虛擬機器,安裝作業系統,然後執行起來多個虛機。

安裝作業系統是個不太輕鬆的任務,並且執行多個虛機對個人電腦效能也有一定要求,這些門檻影響了很多小夥伴的實踐積極性

使用Docker的話就簡單了,不用安裝作業系統,直接下載一個映象,如centos,這樣作業系統就有了,基於這個系統映象執行多個容器,就相當於起了多個虛機,而且系統性能的消耗要遠小於虛擬機器。

假設我們有一個 centos7 映象,啟動多個容器,每個容器都有一個IP,都能通過SSH連線操作,這樣就可以在每個容器中安裝 JAVA Hadoop,從而搭建起叢集環境了。

使用Docker搭建Hadoop叢集的過程包括:

  • 1、安裝Docker
  • 2、獲取centos映象
  • 3、安裝SSH
  • 4、構建Hadoop映象
  • 5、為容器配置IP及SSH無密碼登陸
  • 6、配置Hadoop
  • 7、Hadoop叢集啟動測試

一、安裝Docker

第1步比較簡單,參考Docker系列之前的文章Docker簡介及安裝

二、獲取centos映象

$ docker pull centos

檢視映象列表的命令:

$ docker images

三、安裝SSH

以centos7映象為基礎,構建一個帶有SSH功能的centos,使用Dockerfile建立

$ vi Dockerfile

內容:

FROM centos
MAINTAINER dys

RUN yum install -y openssh-server sudo
RUN sed -i 's/UsePAM yes/UsePAM no/g' /etc/ssh/sshd_config
RUN yum  install -y openssh-clients

RUN echo "root:111111" | chpasswd
RUN echo "root   ALL=(ALL)       ALL" >> /etc/sudoers
RUN ssh-keygen -t dsa -f /etc/ssh/ssh_host_dsa_key
RUN ssh-keygen -t rsa -f /etc/ssh/ssh_host_rsa_key

RUN mkdir /var/run/sshd
EXPOSE 22
CMD ["/usr/sbin/sshd", "-D"]

這段內容的大意是:以 centos 映象為基礎,安裝SSH的相關包,設定了root使用者的密碼為 111111,並啟動SSH服務

執行構建映象的命令,新映象命名為 centos7-ssh

$ docker build -t="centos7-ssh" .

執行完成後,可以在映象列表中看到centos7-ssh映象

$ docker images

四、構建Hadoop映象

以前面構建的centos7-ssh映象為基礎,安裝Java、Hadoop構建Hadoop映象

$ vi Dockerfile

內容:

FROM centos7-ssh
ADD jdk-8u101-linux-x64.tar.gz /usr/local/
RUN mv /usr/local/jdk1.8.0_101 /usr/local/jdk1.8
ENV JAVA_HOME /usr/local/jdk1.8
ENV PATH $JAVA_HOME/bin:$PATH

ADD hadoop-2.7.3.tar.gz /usr/local
RUN mv /usr/local/hadoop-2.7.3 /usr/local/hadoop
ENV HADOOP_HOME /usr/local/hadoop
ENV PATH $HADOOP_HOME/bin:$PATH

RUN yum install -y which sudo

這裡是基於 centos7-ssh 這個映象,把 JAVA 和 Hadoop 的環境都配置好了

前提:在Dockerfile所在目錄下準備好 jdk-8u101-linux-x64.tar.gz 與 hadoop-2.7.3.tar.gz

執行構建命令,新映象命名為 hadoop

$ docker build -t="hadoop" .

執行3個hadoop容器,分別命名為 hadoop0,hadoop1,hadoop2,hadoop0 作為master

$ docker run --name hadoop0 --hostname hadoop0 -d -P -p 50070:50070 -p 8088:8088 hadoop
$ docker run --name hadoop1 --hostname hadoop1 -d -P hadoop
$ docker run --name hadoop2 --hostname hadoop2 -d -P hadoop

容器hadoop0啟動時,映射了埠號,50070和8088,是用來在瀏覽器中訪問hadoop WEB介面的。

檢視容器是否都正常啟動:

$ docker ps

五、為容器配置IP及SSH無密碼登陸

5.1、為容器配置IP

設定固定IP,需要用到 pipework,用於給容器設定IP

#先下載
$ git clone https://github.com/jpetazzo/pipework.git
$ cp pipework/pipework /usr/local/bin/

#安裝bridge-utils
$ yum -y install bridge-utils

#建立網路
$ brctl addbr br1
$ ip link set dev br1 up
$ ip addr add 192.168.10.1/24 dev br1

此時已經建立好網橋br1,為前面啟動的容器hadoop0、hadoop1、hadoop2分別指定IP

配置IP

$ pipework br1 hadoop0 192.168.10.30/24
$ pipework br1 hadoop1 192.168.10.31/24
$ pipework br1 hadoop2 192.168.10.32/24

分別使用 ping 與 ssh 命令進行驗證,看是否可以ping通和成功登入

$ ping 192.168.10.30
$ ssh 192.168.10.30

5.2、容器間SSH無密碼登陸

前面已經為容器配置IP了,在進行ssh 時需要輸入要登陸的容器的root密碼,Hadoop叢集要求叢集間機器SSH連線時無密碼登陸,下面講述容器間如何配置 SSH無密碼登陸。

新開3個終端視窗,分別連線到 hadoop0,hadoop1,hadoop2,便於操作

$ docker exec -it hadoop0 /bin/bash
$ docker exec -it hadoop1 /bin/bash
$ docker exec -it hadoop2 /bin/bash

(1)修改HOST
在各個容器中修改 /etc/hosts,新增:

192.168.10.30    hadoop0
192.168.10.31    hadoop1
192.168.10.32    hadoop2

注意:將原先容器建立時產生的host去掉,比如172.17.0.0這個網段的host,具體類似如下

172.17.0.1 hadoop0

(2)SSH無密碼登陸配置

Hadoop映象時基於centos7-ssh映象建立的,而centos7-ssh映象在centos映象基礎上安裝了SSH相關的工具包,所以在每個Hadoop容器命令視窗內執行下面命令:

$ ssh-keygen
(執行後會有多個輸入提示,不用輸入任何內容,全部直接回車即可)
$ ssh-copy-id -i /root/.ssh/id_rsa -p 22 [email protected]
$ ssh-copy-id -i /root/.ssh/id_rsa -p 22 [email protected]
$ ssh-copy-id -i /root/.ssh/id_rsa -p 22 [email protected]
#測試
$ ssh hadoop1
#測試完,回退到原先視窗
$ exit

六、配置Hadoop

(1)環境確認檢查

在配置Hadoop之前,在hadoop0、hadoop1、hadoop2各命令視窗檢查下java、hadoop環境變數是否設定正確(構建Hadoop映象的時候,已經安裝Java、Hadoop並設定了相關環境變數)

$ java
$ hadoop

如上述兩命令不起作用,則需要手動配置下兩者的環境變數

$ vi /etc/profile

新增以下環境變數

export JAVA_HOME=/opt/module/jdk1.8
export PATH=$PATH:$JAVA_HOME/bin

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

載入重新整理環境變數

source /etc/profile

重新檢查下java 和hadoop命令

(2)Hadoop檔案配置

hadoop0中執行

$ cd /opt/module/hadoop
$ mkdir tmp hdfs
$ mkdir hdfs/data hdfs/name

1、core-site.xml配置

vi /opt/module/hadoop/etc/hadoop/core-site.xml

在 < configuration> 塊兒中新增:

    <!-- 指定HDFS中NameNode的地址 -->
    <property>
        <name>fs.defaultFS</name>
        <value>hdfs://hadoop0:9000</value>
    </property>
    <!-- 指定hadoop執行時產生檔案的儲存目錄 -->
    <property>
        <name>hadoop.tmp.dir</name>
        <value>file:/opt/module/hadoop/tmp</value>
    </property>
    <property>
        <name>io.file.buffer.size</name>
        <value>131702</value>
    </property>

2、hdfs-site.xml配置

vi /opt/module/hadoop/etc/hadoop/hdfs-site.xml

在 < configuration> 塊兒中新增:

    <property>
        <name>dfs.namenode.name.dir</name>
        <value>file:/opt/module/hadoop/hdfs/name</value>
    </property>
    <property>
        <name>dfs.datanode.data.dir</name>
        <value>file:/opt/module/hadoop/hdfs/data</value>
    </property>
    <property>
        <name>dfs.replication</name>
        <value>2</value>
    </property>
    <property>
        <name>dfs.namenode.secondary.http-address</name>
        <value>hadoop0:9001</value>
    </property>
    <property>
        <name>dfs.webhdfs.enabled</name>
        <value>true</value>
    </property>

3、mapred-site.xml配置

這個檔案預設不存在,需要從 mapred-site.xml.template 複製過來

$ cp mapred-site.xml.template mapred-site.xml
vi /opt/module/hadoop/etc/hadoop/mapred-site.xml

在 < configuration> 塊兒中新增:

    <property>
        <name>mapreduce.framework.name</name>
        <value>yarn</value>
    </property>
    <property>
        <name>mapreduce.jobhistory.address</name>
        <value>hadoop0:10020</value>
    </property>
    <property>
        <name>mapreduce.jobhistory.webapp.address</name>
        <value>hadoop0:19888</value>
    </property>

4、yarn-site.xml配置

vi /opt/module/hadoop/etc/hadoop/yarn-site.xml

在 < configuration> 塊兒中新增:

    <property>
        <name>yarn.nodemanager.aux-services</name>
        <value>mapreduce_shuffle</value>
    </property>
    <property>
        <name>yarn.nodemanager.auxservices.mapreduce.shuffle.class</name>
        <value>org.apache.hadoop.mapred.ShuffleHandler</value>
    </property>
    <property>
        <name>yarn.resourcemanager.address</name>
        <value>hadoop0:8032</value>
    </property>
    <property>
        <name>yarn.resourcemanager.scheduler.address</name>
        <value>hadoop0:8030</value>
    </property>
    <property>
        <name>yarn.resourcemanager.resource-tracker.address</name>
        <value>hadoop0:8031</value>
    </property>
    <property>
        <name>yarn.resourcemanager.admin.address</name>
        <value>hadoop0:8033</value>
    </property>
    <property>
        <name>yarn.resourcemanager.webapp.address</name>
        <value>hadoop0:8088</value>
    </property>

5、slaves配置

vi /opt/module/hadoop/etc/hadoop/slaves

刪除已有內容,新增:

hadoop1
hadoop2

6、hadoop-env.sh配置

找到 export JAVA_HOME=${JAVA_HOME},改為自己JAVA_HOME的絕對路徑,比如:

export JAVA_HOME=/opt/module/hadoop/jdk1.8

7、hadoop叢集配置分發

在 hadoop0 上執行

$ scp -r /opt/module/hadoop hadoop1:/opt/module
$ scp -r /opt/module/hadoop hadoop2:/opt/module

注意:如果各臺伺服器中JAVA_HOME位置不同,記得對 hadoop-env.sh 進行相應修改

七、Hadoop叢集啟動測試

(1)、叢集啟動

在主節點(hadoop0)啟動hadoop,從節點(hadoop1、hadoop2)會自動啟動

1、初始化

第一次啟動叢集時,需要初始化

$ hdfs namenode -format

2、依次啟動配置檔案

$ hadoop-daemon.sh start namenode
$ hadoop-daemon.sh start datanode
$ start-dfs.sh
$ start-yarn.sh
$ mr-jobhistory-daemon.sh start historyserver

附:停止hadoop叢集

$ hadoop-daemon.sh stop namenode
$ hadoop-daemon.sh stop datanode
$ stop-dfs.sh
$ stop-yarn.sh
$ mr-jobhistory-daemon.sh stop historyserver

注:hadoop叢集啟動和停止可以使用start/stop-all.sh,但不推薦。

3、檢查

檢視狀態,在3臺伺服器上分別執行jps

[root@hadoop0 hadoop]# jps
10257 Jps
9122 JobHistoryServer
8675 SecondaryNameNode
8376 DataNode
8281 NameNode
8828 ResourceManager
[root@hadoop0 hadoop]# 
[root@hadoop1 hadoop]# jps
2263 NodeManager
2152 DataNode
2523 Jps
[root@hadoop1 hadoop]# 

瀏覽器中訪問(宿主機Host可以配置下hadoop0的IP地址):

這裡寫圖片描述

這裡寫圖片描述

可以正常訪問的話,可以說明叢集啟動成功了,但不一定可以正常執行,還需要下面的實際驗證。

(2)測試驗證

1、hdfs 操作

建立本地測試檔案
在/opt/module/hadoop目錄下建立測試檔案目錄

$ mkdir wcinput
$ cd wcinput
$ vi wc.input

wc.input檔案內容如下:

hadoop mapreduce
hadoop yarn
hadoop hdfs
mapreduce spark
hadoop hello

建立HDFS目錄

$ hdfs dfs -mkdir -p /user/hadoop/input

上傳檔案,把測試檔案上傳到剛剛建立的目錄中

$ hdfs dfs -put /opt/module/hadoop/wcinput/wc.input /user/hadoop/input

檢視檔案上傳是否正確

[root@hadoop0 hadoop]# hdfs dfs -ls /user/hadoop/input
Found 1 items
-rw-r--r--   2 root supergroup         71 2018-04-17 09:12 /user/hadoop/input/wc.input
[root@hadoop0 hadoop]# 

執行mapreduce程式

hadoop 安裝包中提供了一個示例程式,我們可以使用它對剛剛上傳的檔案進行測試

hadoop jar /home/hadoop/share/hadoop/mapreduce/hadoop-mapreduce-examples-2.7.3.jar wordcount /user/hadoop/input /user/hadoop/output

注:在執行過程中,如果長時間處於 running 狀態不動,雖然沒有報錯,但實際上是出錯了,後臺在不斷重試,需要到 logs 目錄下檢視日誌檔案中的錯誤資訊。

檢視輸出結果

[[email protected] hadoop]# hdfs dfs -ls /user/hadoop/output
Found 2 items
-rw-r--r--   2 root supergroup          0 2018-04-17 09:14 /user/hadoop/output/_SUCCESS
-rw-r--r--   2 root supergroup         51 2018-04-17 09:14 /user/hadoop/output/part-r-00000
[[email protected] hadoop]# 

_SUCCESS表示HDFS檔案狀態,生成的結果在part-r-00000中,可檢視

[root@hadoop0 hadoop]# hdfs dfs -cat /user/hadoop/output/part-r-00000
hadoop  4
hdfs    1
hello   1
mapreduce   2
spark   1
yarn    1
[root@hadoop0 hadoop]# 

總結:以上就是使用Docker環境搭建Hadoop映象容器,配置Hadoop叢集,並啟動和測試的例項,測試用的是hadoop官方給的一個wordcount統計,利用hadoop安裝包裡的mapreduce示例jar 計算指定HDFS檔案裡的單詞數,並將結果輸出到指定HDFS目錄。後面會介紹HDFS常用檔案操作命令。

.