學習Hadoop叢集環境搭建是Hadoop入門必經之路。搭建分散式叢集通常有兩個辦法:

  • 要麼找多臺機器來部署(常常找不到機器)
  • 或者在本地開多個虛擬機器(開銷很大,對宿主機器效能要求高,光是安裝多個虛擬機器系統就得搞半天……)。

那麼,問題來了!

有沒有更有可行性的辦法?

提到虛擬化,最近很是火熱!不妨拿來在本地做虛擬化,搭建Hadoop的偽分散式叢集環境。雖然有點大材小用,但是學習學習,練練手也是極好的。

文章比較長,建議先倒杯水,聽我慢慢到來……

先說一下我的思路吧:

  1. 先使用Docker構建一個Hadoop執行環境的映象
  2. 然後使用這個映象分別啟動3個容器:1個Master節點,兩個Slave節點
  3. 在Master節點上配置Slave節點資訊
  4. 在Master上啟動Hadoop

使用Docker搭建Hadoop環境

Docker 是一個開源專案,誕生於 2013 年初,最初是 dotCloud 公司內部的一個業餘專案。它基於 Google 公司推出的 Go 語言實現。 專案後來加入了 Linux 基金會,遵從了 Apache 2.0 協議,專案程式碼在 GitHub 上進行維護。

Docker 自開源後受到廣泛的關注和討論,以至於 dotCloud 公司後來都改名為 Docker Inc。Redhat 已經在其 RHEL6.5 中集中支援 Docker;Google 也在其 PaaS 產品中廣泛應用。

Docker 專案的目標是實現輕量級的作業系統虛擬化解決方案。 Docker 的基礎是 Linux 容器(LXC)等技術。

在 LXC 的基礎上 Docker 進行了進一步的封裝,讓使用者不需要去關心容器的管理,使得操作更為簡便。使用者操作 Docker 的容器就像操作一個快速輕量級的虛擬機器一樣簡單。

Docker安裝

我使用的是Ubuntu14.04,命令如下:

$ sudo apt-get install apt-transport-https
$ sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 36A1D7869245C8950F966E92D8576A8BA88D21E9
$ sudo bash -c "echo deb https://get.docker.io/ubuntu docker main > /etc/apt/sources.list.d/docker.list"
$ sudo apt-get update
$ sudo apt-get install lxc-docker

其餘系統或其他版本,請參考這裡

Docker常用命令介紹

  • docker images:列出所有映象(images)
  • docker ps:列出正在執行的(容器)containers
  • docker pull ubuntu:下載映象
  • docker run -i -t ubuntu /bin/bash:執行ubuntu映象
  • docker commit 3a09b2588478 ubuntu:mynewimage:提交你的變更,並且把容器儲存成Tag為mynewimage的新的ubuntu映象.(注意,這裡提交只是提交到本地倉庫,類似git)

其他常用命令,參考這裡

Docker去sudo

在Ubuntu下,在執行Docker時,每次都要輸入sudo,同時輸入密碼,這裡把當前使用者執行許可權新增到相應的docker使用者組裡面。

# 新增一個新的docker使用者組
sudo groupadd docker
# 添加當前使用者到docker使用者組裡,注意這裡的king為ubuntu登入使用者名稱
sudo gpasswd -a king docker
# 重啟Docker後臺監護程序
sudo service docker restart
# 重啟之後,嘗試一下,是否生效
docker version
#若還未生效,則系統重啟,則生效
sudo reboot

下載Ubuntu映象

docker pull ubuntu:14.04

這條命令的作用是從Docker倉庫中獲取ubuntu的映象,參考這裡

下載完成以後,使用docker images,可以列出所有本地的映象:

[email protected]:~$ docker images 
REPOSITORY                      TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
ubuntu                          14.04               5ba9dab47459        4 weeks ago         188.3 MB
ubuntu                          14.04.1             5ba9dab47459        4 weeks ago         188.3 MB
ubuntu                          latest              5ba9dab47459        4 weeks ago         188.3 MB
ubuntu                          trusty              5ba9dab47459        4 weeks ago         188.3 MB

啟動第一個容器

下面,我們準備以ubuntu映象作為基準映象,構建我們的Hadoop執行環境映象。

先使用命令如下命令啟動容器:

docker run -ti ubuntu

注意:我們在不指定Tag的情況下,預設選擇Tag為latest的映象啟動容器。 指定Tag啟動命令為:

docker run -ti ubuntu:14.04

另外,每次容器啟動的時候需要指定一個命令,容器啟動後便會執行這個命令。例如執行下面的命令:

[email protected]:~$ docker run ubuntu /bin/echo 'Hello world'
Hello world
[email protected]:~$  

可以看到,容器啟動了馬上又退出了,因為容器之做了一件事情:就是列印Hello world,列印完了,自然就退出了。

如果你想做多件事情,可以自己寫一個shell指令碼,把你要的操作寫入進去,然後在run後面指定這個指令碼路徑。

我們剛剛的docker run -ti ubuntu命令中沒有指定執行程式,Docker預設執行/bin/bash

其他啟動引數,大家可以自己在網上查,這裡不再陳述了。好了我們回到剛剛docker run -ti ubuntu啟動的容器,可以看到容器幾乎瞬間就啟動起來了,比虛擬機器不知快了多少倍!!

[email protected]:~$ docker run -ti ubuntu
[email protected]:/# 

容器啟動起來了,接下來就是安裝Java、Hadoop及相關配置了。

Java安裝

依次執行如下命令:

sudo apt-get install software-properties-common python-software-properties
sudo add-apt-repository ppa:webupd8team/java
sodu apt-get update
apt-get install oracle-java7-installer
java -version

注意:

  • 這裡安裝的Java7(JDK1.7),如需其他版本請自行修改apt-get install oracle-java7-installerapt-get install oracle-java6-installer
  • 預設使用的是Ubuntu的官方源,如果下載比較慢,請自行修改更新源,不知道如何使用命令列修改的,參考這裡

另外,大家可以將裝好java的映象儲存為一個副本,他日可以在此基礎上構建其他映象。命令如下:

[email protected]:~# exit
docker commit -m "java install" 122a2cecdd14 ubuntu:java

上面命令中122a2cecdd14為當前容器的ID, ubuntu:java是為新的映象指定一個標識,ubuntu倉庫名javaTag

如何獲取容器ID:

  • 有個簡便的辦法找到此ID,就是命令列使用者名稱@後面的那一串字元。這個方法只在容器啟動時沒有指定hostname時才能用。
  • 使用docker ps列出所有執行的容器,在命令結果中檢視

Hadoop安裝

漸漸切入正題了O(∩_∩)O~

使用剛剛已經安裝了Java的容器映象啟動:

docker run -ti ubuntu:java

啟動成功了,我們開始安裝Hadoop。這裡,我們直接使用wget下載安裝檔案。

1.先安裝wget:

sudo apt-get install -y wget

2.下載並解壓安裝檔案:

[email protected]:cd ~
[email protected]:~# mkdir soft
[email protected]:~# cd soft/
[email protected]:~/soft# mkdir apache
[email protected]:~/soft# cd apache/
[email protected]:~/soft/apache# mkdir hadoop
[email protected]:~/soft/apache# cd hadoop/
[email protected]:~/soft/apache/hadoop# wget http://mirrors.sonic.net/apache/hadoop/common/hadoop-2.6.0/hadoop-2.6.0.tar.gz
[email protected]:~/soft/apache/hadoop# tar xvzf hadoop-2.6.0.tar.gz

注意:這裡我們安裝的Hadoop版本是2.6.0,如果需要其他版本,請在這裡找到連結地址後修改命令即可。

3.配置環境變數

修改~/.bashrc檔案。在檔案末尾加入下面配置資訊:

export JAVA_HOME=/usr/lib/jvm/java-7-oracle
export HADOOP_HOME=/root/soft/apache/hadoop/hadoop-2.6.0
export HADOOP_CONFIG_HOME=$HADOOP_HOME/etc/hadoop
export PATH=$PATH:$HADOOP_HOME/bin
export PATH=$PATH:$HADOOP_HOME/sbin

然後要執行一下這個檔案

source ~/.bashrc

注意:我們使用apt-get安裝java,不知道java裝在什麼地方的話可以使用下面的命令檢視:

[email protected]:~# update-alternatives --config java
There is only one alternative in link group java (providing /usr/bin/java): /usr/lib/jvm/java-7-oracle/jre/bin/java
Nothing to configure.
[email protected]:~#   

4.配置Hadoop

下面,我們開始修改Hadoop的配置檔案。主要配置core-site.xmlhdfs-site.xmlmapred-site.xml這三個檔案。

開始配置之前,執行下面命令:

[email protected]:~# cd $HADOOP_HOME/
[email protected]:~/soft/apache/hadoop/hadoop-2.6.0# mkdir tmp
[email protected]:~/soft/apache/hadoop/hadoop-2.6.0# cd tmp/
[email protected]:~/soft/apache/hadoop/hadoop-2.6.0/tmp# pwd
/root/soft/apache/hadoop/hadoop-2.6.0/tmp
[email protected]:~/soft/apache/hadoop/hadoop-2.6.0/tmp# cd ../
[email protected]:~/soft/apache/hadoop/hadoop-2.6.0# mkdir namenode
[email protected]:~/soft/apache/hadoop/hadoop-2.6.0# cd namenode/
[email protected]:~/soft/apache/hadoop/hadoop-2.6.0/namenode# pwd
/root/soft/apache/hadoop/hadoop-2.6.0/namenode
[email protected]:~/soft/apache/hadoop/hadoop-2.6.0/namenode# cd ../
[email protected]:~/soft/apache/hadoop/hadoop-2.6.0# mkdir datanode
[email protected]:~/soft/apache/hadoop/hadoop-2.6.0# cd datanode/
[email protected]:~/soft/apache/hadoop/hadoop-2.6.0/datanode# pwd
/root/soft/apache/hadoop/hadoop-2.6.0/datanode
[email protected]:~/soft/apache/hadoop/hadoop-2.6.0/datanode# cd $HADOOP_CONFIG_HOME/
[email protected]:~/soft/apache/hadoop/hadoop-2.6.0/etc/hadoop# cp mapred-site.xml.template mapred-site.xml
[email protected]:~/soft/apache/hadoop/hadoop-2.6.0/etc/hadoop# nano hdfs-site.xml

這裡建立了三個目錄,後續配置的時候會用到:

  1. tmp:作為Hadoop的臨時目錄
  2. namenode:作為NameNode的存放目錄
  3. datanode:作為DataNode的存放目錄

1).core-site.xml配置

<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
<!--
  Licensed under the Apache License, Version 2.0 (the "License");
  you may not use this file except in compliance with the License.
  You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License. See accompanying LICENSE file.
-->

<!-- Put site-specific property overrides in this file. -->

<configuration>
    <property>
            <name>hadoop.tmp.dir</name>
            <value>/root/soft/apache/hadoop/hadoop-2.6.0/tmp</value>
            <description>A base for other temporary directories.</description>
    </property>

    <property>
            <name>fs.default.name</name>
            <value>hdfs://master:9000</value>
            <final>true</final>
            <description>The name of the default file system.  A URI whose
            scheme and authority determine the FileSystem implementation.  The
            uri's scheme determines the config property (fs.SCHEME.impl) naming
            the FileSystem implementation class.  The uri's authority is used to
            determine the host, port, etc. for a filesystem.</description>
    </property>
</configuration>

注意:

  • hadoop.tmp.dir配置項值即為此前命令中建立的臨時目錄路徑。
  • fs.default.name配置為hdfs://master:9000,指向的是一個Master節點的主機(後續我們做叢集配置的時候,自然會配置這個節點,先寫在這裡)

2).hdfs-site.xml配置

使用命令nano hdfs-site.xml編輯hdfs-site.xml檔案:

 <?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
<!--
  Licensed under the Apache License, Version 2.0 (the "License");
  you may not use this file except in compliance with the License.
  You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License. See accompanying LICENSE file.
-->

<!-- Put site-specific property overrides in this file. -->

<configuration>
    <property>
        <name>dfs.replication</name>
        <value>2</value>
        <final>true</final>
        <description>Default block replication.
        The actual number of replications can be specified when the file is created.
        The default is used if replication is not specified in create time.
        </description>
    </property>

    <property>
        <name>dfs.namenode.name.dir</name>
        <value>/root/soft/apache/hadoop/hadoop-2.6.0/namenode</value>
        <final>true</final>
    </property>

    <property>
        <name>dfs.datanode.data.dir</name>
        <value>/root/soft/apache/hadoop/hadoop-2.6.0/datanode</value>
        <final>true</final>
    </property>
</configuration>

注意:

  • 我們後續搭建叢集環境時,將配置一個Master節點和兩個Slave節點。所以dfs.replication配置為2。
  • dfs.namenode.name.dirdfs.datanode.data.dir分別配置為之前建立的NameNode和DataNode的目錄路徑

3).mapred-site.xml配置

Hadoop安裝檔案中提供了一個mapred-site.xml.template,所以我們之前使用了命令cp mapred-site.xml.template mapred-site.xml,建立了一個mapred-site.xml檔案。下面使用命令nano mapred-site.xml編輯這個檔案:

<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
<!--
  Licensed under the Apache License, Version 2.0 (the "License");
  you may not use this file except in compliance with the License.
  You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License. See accompanying LICENSE file.
-->

<!-- Put site-specific property overrides in this file. -->

<configuration>
    <property>
        <name>mapred.job.tracker</name>
        <value>master:9001</value>
        <description>The host and port that the MapReduce job tracker runs
        at.  If "local", then jobs are run in-process as a single map
        and reduce task.
        </description>
    </property>
</configuration>

這裡只有一個配置項mapred.job.tracker,我們指向master節點機器。

4)修改JAVA_HOME環境變數

使用命令.nano hadoop-env.sh,修改如下配置:

# The java implementation to use.
export JAVA_HOME=/usr/lib/jvm/java-7-oracle

5.格式化 namenode

這是很重要的一步,執行命令hadoop namenode -format

4.安裝SSH

搭建叢集環境,自然少不了使用SSH。這可以實現無密碼訪問,訪問叢集機器的時候很方便。

[email protected]:~# sudo apt-get install ssh

SSH裝好了以後,由於我們是Docker容器中執行,所以SSH服務不會自動啟動。需要我們在容器啟動以後,手動通過/usr/sbin/sshd 手動開啟SSH服務。未免有些麻煩,為了方便,我們把這個命令加入到~/.bashrc檔案中。通過nano ~/.bashrc編輯.bashrc檔案(nano沒有安裝的自行安裝,也可用vi),在檔案後追加下面內容:

#autorun
/usr/sbin/sshd

5.生成訪問金鑰

[email protected]:/# cd ~/
[email protected]:~# ssh-keygen -t rsa -P '' -f ~/.ssh/id_dsa
[email protected]:~# cd .ssh
[email protected]:~/.ssh# cat id_dsa.pub >> authorized_keys

注意: 這裡,我的思路是直接將金鑰生成後寫入映象,免得在買個容器裡面再單獨生成一次,還要相互拷貝公鑰,比較麻煩。當然這只是學習使用,實際操作時,應該不會這麼搞,因為這樣所有容器的金鑰都是一樣的!!

6.儲存映象副本

這裡我們將安裝好Hadoop的映象儲存為一個副本。

[email protected]:~# exit
[email protected]:~$ docker commit -m "hadoop install" 8ef06706f88d ubuntu:hadoop

Hadoop分散式叢集搭建

重點來了!

按照 hadoop 叢集的基本要求,其 中一個是 master 結點,主要是用於執行 hadoop 程式中的 namenode、secondorynamenode 和 jobtracker(新版本名字變了) 任務。用外兩個結點均為 slave 結點,其中一個是用於冗餘目的,如果沒有冗 餘,就不能稱之為 hadoop 了,所以模擬 hadoop 叢集至少要有 3 個結點。

前面已經將Hadoop的映象構建好了,下面就是使用這個映象搭建Master節點和Slave節點了:

節點 hostname ip 用途 Docker啟動指令碼
Master master 10.0.0.5

namenode

secondaryNamenode

jobTracker

docker run -ti -h master ubuntu:hadoop
Slave slave1 10.0.0.6

datanode

taskTracker

docker run -ti -h slave1 ubuntu:hadoop
Slave slave2 10.0.0.7

datanode

taskTracker

docker run -ti -h slave2 ubuntu:hadoop

啟動Docker容器

回顧一下,Docker啟動容器使用的是run命令:

docker run -ti ubuntu:hadoop

這裡有幾個問題:

  1. Docker容器中的ip地址是啟動之後自動分配的,且不能手動更改
  2. hostname、hosts配置在容器內修改了,只能在本次容器生命週期內有效。如果容器退出了,重新啟動,這兩個配置將被還原。且這兩個配置無法通過commit命令寫入映象

我們搭建叢集環境的時候,需要指定節點的hostname,以及配置hosts。hostname可以使用Docker run命令的h引數直接指定。但hosts解析有點麻煩,雖然可以使用run--link引數配置hosts解析資訊,但我們搭建叢集時要求兩臺機器互相能夠ping通,其中一個容器沒有啟動,那麼ip不知道,所以--link引數對於我們的這個場景不實用。要解決這個問題,大概需要專門搭建一個域名解析服務,即使用--dns引數(參考這裡)。

我們這裡只為學習,就不整那麼複雜了,就手動修改hosts吧。只不過每次都得改,我Docker知識淺薄,一時還沒有解決這個問題。相信肯定有更好的辦法。如果有高人能指定一下,感激不盡!!

啟動master容器

docker run -ti -h master ubuntu:hadoop

啟動slave1容器

docker run -ti -h slave1 ubuntu:hadoop

啟動slave2容器

docker run -ti -h slave2 ubuntu:hadoop

配置hosts

  1. 通過ifconfig命令獲取各節點ip。環境不同獲取的ip可能不一樣,例如我本機獲取的ip如下: 
    • master:10.0.0.5
    • slave1:10.0.0.6
    • slave2:10.0.0.7
  2. 使用sudo nano /etc/hosts命令將如下配置寫入各節點的hosts檔案,注意修改ip地址:

    10.0.0.5        master
    10.0.0.6        slave1
    10.0.0.7        slave2
    

配置slaves

下面我們來配置哪些節點是slave。在較老的Hadoop版本中有一個masters檔案和一個slaves檔案,但新版本中只有slaves檔案了。

在master節點容器中執行如下命令:

[email protected]:~# cd $HADOOP_CONFIG_HOME/
[email protected]:~/soft/apache/hadoop/hadoop-2.6.0/etc/hadoop# nano slaves 

將如下slave節點的hostname資訊寫入該檔案:

slave1
slave2

啟動Hadoop

在master節點上執行start-all.sh命令,啟動Hadoop。

激動人心的一刻……

如果看到如下資訊,則說明啟動成功了:

[email protected]:~/soft/apache/hadoop/hadoop-2.6.0/etc/hadoop# start-all.sh 
This script is Deprecated. Instead use start-dfs.sh and start-yarn.sh
Starting namenodes on [master]
master: starting namenode, logging to /root/soft/apache/hadoop/hadoop-2.6.0/logs/hadoop-root-namenode-master.out
slave1: starting datanode, logging to /root/soft/apache/hadoop/hadoop-2.6.0/logs/hadoop-root-datanode-slave1.out
slave2: starting datanode, logging to /root/soft/apache/hadoop/hadoop-2.6.0/logs/hadoop-root-datanode-slave2.out
Starting secondary namenodes [0.0.0.0]
0.0.0.0: starting secondarynamenode, logging to /root/soft/apache/hadoop/hadoop-2.6.0/logs/hadoop-root-secondarynamenode-master.out
starting yarn daemons
starting resourcemanager, logging to /root/soft/apache/hadoop/hadoop-2.6.0/logs/yarn--resourcemanager-master.out
slave1: starting nodemanager, logging to /root/soft/apache/hadoop/hadoop-2.6.0/logs/yarn-root-nodemanager-slave1.out
slave2: starting nodemanager, logging to /root/soft/apache/hadoop/hadoop-2.6.0/logs/yarn-root-nodemanager-slave2.out

在個節點上執行jps命令,結果如下:

master節點

[email protected]:~/soft/apache/hadoop/hadoop-2.6.0/etc/hadoop# jps
1223 Jps
992 SecondaryNameNode
813 NameNode
1140 ResourceManager

slave1節點

[email protected]:~/soft/apache/hadoop/hadoop-2.6.0/etc/hadoop# jps
258 NodeManager
352 Jps
159 DataNode

slave2節點

[email protected]:~/soft/apache/hadoop/hadoop-2.6.0/etc/hadoop# jps
371 Jps
277 NodeManager
178 DataNode

下面,我們在master節點上通過命令hdfs dfsadmin -report檢視DataNode是否正常啟動:

[email protected]:~/soft/apache/hadoop/hadoop-2.6.0/etc/hadoop# hdfs dfsadmin -report
Configured Capacity: 167782006784 (156.26 GB)
Present Capacity: 58979344384 (54.93 GB)
DFS Remaining: 58979295232 (54.93 GB)
DFS Used: 49152 (48 KB)
DFS Used%: 0.00%
Under replicated blocks: 0
Blocks with corrupt replicas: 0
Missing blocks: 0

-------------------------------------------------
Live datanodes (2):

Name: 10.0.0.7:50010 (slave2)
Hostname: slave2
Decommission Status : Normal
Configured Capacity: 83891003392 (78.13 GB)
DFS Used: 24576 (24 KB)
Non DFS Used: 54401331200 (50.67 GB)
DFS Remaining: 29489647616 (27.46 GB)
DFS Used%: 0.00%
DFS Remaining%: 35.15%
Configured Cache Capacity: 0 (0 B)
Cache Used: 0 (0 B)
Cache Remaining: 0 (0 B)
Cache Used%: 100.00%
Cache Remaining%: 0.00%
Xceivers: 1
Last contact: Sat Feb 28 07:27:05 UTC 2015


Name: 10.0.0.6:50010 (slave1)
Hostname: slave1
Decommission Status : Normal
Configured Capacity: 83891003392 (78.13 GB)
DFS Used: 24576 (24 KB)
Non DFS Used: 54401331200 (50.67 GB)
DFS Remaining: 29489647616 (27.46 GB)
DFS Used%: 0.00%
DFS Remaining%: 35.15%
Configured Cache Capacity: 0 (0 B)
Cache Used: 0 (0 B)
Cache Remaining: 0 (0 B)
Cache Used%: 100.00%
Cache Remaining%: 0.00%
Xceivers: 1
Last contact: Sat Feb 28 07:27:05 UTC 2015

還可以通過Web頁面看到檢視DataNode和NameNode的狀態:http://10.0.0.5:50070/ (由於我宿主機器上沒有配置master的hosts解析,所以只能用ip地址訪問,大家將ip改為各自的master節點容器的ip即可):