那么,問題來了!
有沒有更有可行性的辦法?提到虛擬化, Docker 最近很是火熱!不妨拿來在本地做虛擬化,搭建Hadoop的偽分布式集群環境。雖然有點大材小用,但是學習學習,練練手也是極好的。
文章比較長,建議先倒杯水,聽我慢慢到來……
先說一下我的思路吧:
先使用Docker構建一個Hadoop運行環境的鏡像然后使用這個鏡像分別啟動3個容器:1個Master節點,兩個Slave節點在Master節點上配置Slave節點信息在Master上啟動Hadoop使用Docker搭建Hadoop環境什么是 Docker?
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 :列出正在運行的(容器)containersdocker 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 ,可以列出所有本地的鏡像:
king@king:~$ docker images REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZEubuntu 14.04 5ba9dab47459 4 weeks ago 188.3 MBubuntu 14.04.1 5ba9dab47459 4 weeks ago 188.3 MBubuntu latest 5ba9dab47459 4 weeks ago 188.3 MBubuntu trusty 5ba9dab47459 4 weeks ago 188.3 MB啟動第一個容器下面,我們準備以ubuntu鏡像作為基準鏡像,構建我們的Hadoop運行環境鏡像。
先使用命令如下命令啟動容器:
docker run -ti ubuntu注意:我們在不指定Tag的情況下,默認選擇Tag為 latest 的鏡像啟動容器。 指定Tag啟動命令為:
docker run -ti ubuntu:14.04另外,每次容器啟動的時候需要指定一個命令,容器啟動后便會執行這個命令。例如執行下面的命令:
king@king:~$ docker run ubuntu /bin/echo 'Hello world'Hello worldking@king:~$可以看到,容器啟動了馬上又退出了,因為容器之做了一件事情:就是打印 Hello world ,打印完了,自然就退出了。
如果你想做多件事情,可以自己寫一個shell腳本,把你要的操作寫入進去,然后在 run 后面指定這個腳本路徑。
我們剛剛的 docker run -ti ubuntu 命令中沒有指定執行程序,Docker默認執行 /bin/bash 。
其他啟動參數,大家可以自己在網上查,這里不再陳述了。好了我們回到剛剛 docker run -ti ubuntu 啟動的容器,可以看到容器幾乎瞬間就啟動起來了,比虛擬機不知快了多少倍!!
king@king:~$ docker run -ti ubunturoot@009fe5728aba:/#容器啟動起來了,接下來就是安裝Java、Hadoop及相關配置了。
Java安裝依次執行如下命令:
sudo apt-get install software-properties-common python-software-propertiessudo add-apt-repository ppa:webupd8team/javasodu apt-get updateapt-get install oracle-java7-installerjava -version注意:
這里安裝的Java7(JDK1.7),如需其他版本請自行修改 apt-get install oracle-java7-installer 為 apt-get install oracle-java6-installer默認使用的是Ubuntu的官方源,如果下載比較慢,請自行修改更新源,不知道如何使用命令行修改的,參考 這里 。另外,大家可以將裝好java的鏡像保存為一個副本,他日可以在此基礎上構建其他鏡像。命令如下:
root@122a2cecdd14:~# exitdocker commit -m "java install" 122a2cecdd14 ubuntu:java上面命令中 122a2cecdd14 為當前容器的ID, ubuntu:java 是為新的鏡像指定一個標識, ubuntu 為 倉庫名 , java 是 Tag 。
如何獲取容器ID:
有個簡便的辦法找到此ID,就是命令行用戶名 @ 后面的那一串字符。這個方法只在容器啟動時沒有指定hostname時才能用。使用 docker ps 列出所有運行的容器,在命令結果中查看Hadoop安裝漸漸切入正題了O(∩_∩)O~
使用剛剛已經安裝了Java的容器鏡像啟動:
docker run -ti ubuntu:java啟動成功了,我們開始安裝Hadoop。這里,我們直接使用wget下載安裝文件。
1.先安裝wget:
sudo apt-get install -y wget2.下載并解壓安裝文件:
root@8ef06706f88d:cd ~root@8ef06706f88d:~# mkdir softroot@8ef06706f88d:~# cd soft/root@8ef06706f88d:~/soft# mkdir apacheroot@8ef06706f88d:~/soft# cd apache/root@8ef06706f88d:~/soft/apache# mkdir hadooproot@8ef06706f88d:~/soft/apache# cd hadoop/root@8ef06706f88d:~/soft/apache/hadoop# wget http://mirrors.sonic.net/apache/hadoop/common/hadoop-2.6.0/hadoop-2.6.0.tar.gzroot@8ef06706f88d:~/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-oracleexport HADOOP_HOME=/root/soft/apache/hadoop/hadoop-2.6.0export HADOOP_CONFIG_HOME=$HADOOP_HOME/etc/hadoopexport PATH=$PATH:$HADOOP_HOME/binexport PATH=$PATH:$HADOOP_HOME/sbin注意:我們使用 apt-get 安裝java,不知道java裝在什么地方的話可以使用下面的命令查看:
root@8ef06706f88d:~# update-alternatives --config javaThere is only one alternative in link group java (providing /usr/bin/java): /usr/lib/jvm/java-7-oracle/jre/bin/javaNothing to configure.root@8ef06706f88d:~#4.配置Hadoop
下面,我們開始修改Hadoop的配置文件。主要配置 core-site.xml 、 hdfs-site.xml 、 mapred-site.xml 這三個文件。
開始配置之前,執行下面命令:
root@8ef06706f88d:~# cd $HADOOP_HOME/root@8ef06706f88d:~/soft/apache/hadoop/hadoop-2.6.0# mkdir tmproot@8ef06706f88d:~/soft/apache/hadoop/hadoop-2.6.0# cd tmp/root@8ef06706f88d:~/soft/apache/hadoop/hadoop-2.6.0/tmp# pwd/root/soft/apache/hadoop/hadoop-2.6.0/tmproot@8ef06706f88d:~/soft/apache/hadoop/hadoop-2.6.0/tmp# cd ../root@8ef06706f88d:~/soft/apache/hadoop/hadoop-2.6.0# mkdir namenoderoot@8ef06706f88d:~/soft/apache/hadoop/hadoop-2.6.0# cd namenode/root@8ef06706f88d:~/soft/apache/hadoop/hadoop-2.6.0/namenode# pwd/root/soft/apache/hadoop/hadoop-2.6.0/namenoderoot@8ef06706f88d:~/soft/apache/hadoop/hadoop-2.6.0/namenode# cd ../root@8ef06706f88d:~/soft/apache/hadoop/hadoop-2.6.0# mkdir datanoderoot@8ef06706f88d:~/soft/apache/hadoop/hadoop-2.6.0# cd datanode/root@8ef06706f88d:~/soft/apache/hadoop/hadoop-2.6.0/datanode# pwd/root/soft/apache/hadoop/hadoop-2.6.0/datanoderoot@8ef06706f88d:~/soft/apache/hadoop/hadoop-2.6.0/datanode# cd $HADOOP_CONFIG_HOME/root@8ef06706f88d:~/soft/apache/hadoop/hadoop-2.6.0/etc/hadoop# cp mapred-site.xml.template mapred-site.xmlroot@8ef06706f88d:~/soft/apache/hadoop/hadoop-2.6.0/etc/hadoop# nano hdfs-site.xml這里創建了三個目錄,后續配置的時候會用到:
tmp:作為Hadoop的臨時目錄namenode:作為NameNode的存放目錄datanode:作為DataNode的存放目錄1).core-site.xml配置注意:
hadoop.tmp.dir 配置項值即為此前命令中創建的臨時目錄路徑。fs.default.name 配置為 hdfs://master:9000 ,指向的是一個Master節點的主機(后續我們做集群配置的時候,自然會配置這個節點,先寫在這里)2).hdfs-site.xml配置使用命令 nano hdfs-site.xml 編輯 hdfs-site.xml 文件:
注意:
我們后續搭建集群環境時,將配置一個Master節點和兩個Slave節點。所以 dfs.replication 配置為2。dfs.namenode.name.dir 和 dfs.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 編輯這個文件:
這里只有一個配置項 mapred.job.tracker ,我們指向master節點機器。
4)修改JAVA_HOME環境變量使用命令 .nano hadoop-env.sh ,修改如下配置:
# The java implementation to use.export JAVA_HOME=/usr/lib/jvm/java-7-oracle5.格式化 namenode
這是很重要的一步,執行命令 hadoop namenode -format
4.安裝SSH
搭建集群環境,自然少不了使用SSH。這可以實現無密碼訪問,訪問集群機器的時候很方便。
root@8ef06706f88d:~# sudo apt-get install sshSSH裝好了以后,由于我們是Docker容器中運行,所以SSH服務不會自動啟動。需要我們在容器啟動以后,手動通過 /usr/sbin/sshd 手動打開SSH服務。未免有些麻煩,為了方便,我們把這個命令加入到 ~/.bashrc 文件中。通過 nano ~/.bashrc 編輯 .bashrc 文件(nano沒有安裝的自行安裝,也可用vi),在文件后追加下面內容:
#autorun/usr/sbin/sshd5.生成訪問密鑰
root@8ef06706f88d:/# cd ~/root@8ef06706f88d:~# ssh-keygen -t rsa -P '' -f ~/.ssh/id_dsaroot@8ef06706f88d:~# cd .sshroot@8ef06706f88d:~/.ssh# cat id_dsa.pub >> authorized_keys注意: 這里,我的思路是直接將密鑰生成后寫入鏡像,免得在買個容器里面再單獨生成一次,還要相互拷貝公鑰,比較麻煩。當然這只是學習使用,實際操作時,應該不會這么搞,因為這樣所有容器的密鑰都是一樣的!!
6.保存鏡像副本
這里我們將安裝好Hadoop的鏡像保存為一個副本。
root@8ef06706f88d:~# exitking@king:~$ docker commit -m "hadoop install" 8ef06706f88d ubuntu:hadoopHadoop分布式集群搭建重點來了!
按照 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啟動容器使用的是 run 命令:
docker run -ti ubuntu:hadoop這里有幾個問題:
Docker容器中的ip地址是啟動之后自動分配的,且不能手動更改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通過 ifconfig 命令獲取各節點ip。環境不同獲取的ip可能不一樣,例如我本機獲取的ip如下:master:10.0.0.5slave1:10.0.0.6slave2:10.0.0.7
使用 sudo nano /etc/hosts 命令將如下配置寫入各節點的hosts文件,注意修改ip地址:
10.0.0.5 master10.0.0.6 slave110.0.0.7 slave2配置slaves
下面我們來配置哪些節點是slave。在較老的Hadoop版本中有一個masters文件和一個slaves文件,但新版本中只有slaves文件了。
在master節點容器中執行如下命令:
root@master:~# cd $HADOOP_CONFIG_HOME/root@master:~/soft/apache/hadoop/hadoop-2.6.0/etc/hadoop# nano slaves將如下slave節點的hostname信息寫入該文件:
slave1slave2啟動Hadoop在master節點上執行 start-all.sh 命令,啟動Hadoop。
激動人心的一刻……
如果看到如下信息,則說明啟動成功了:
root@master:~/soft/apache/hadoop/hadoop-2.6.0/etc/hadoop# start-all.sh This script is Deprecated. Instead use start-dfs.sh and start-yarn.shStarting namenodes on [master]master: starting namenode, logging to /root/soft/apache/hadoop/hadoop-2.6.0/logs/hadoop-root-namenode-master.outslave1: starting datanode, logging to /root/soft/apache/hadoop/hadoop-2.6.0/logs/hadoop-root-datanode-slave1.outslave2: starting datanode, logging to /root/soft/apache/hadoop/hadoop-2.6.0/logs/hadoop-root-datanode-slave2.outStarting 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.outstarting yarn daemonsstarting resourcemanager, logging to /root/soft/apache/hadoop/hadoop-2.6.0/logs/yarn--resourcemanager-master.outslave1: starting nodemanager, logging to /root/soft/apache/hadoop/hadoop-2.6.0/logs/yarn-root-nodemanager-slave1.outslave2: starting nodemanager, logging to /root/soft/apache/hadoop/hadoop-2.6.0/logs/yarn-root-nodemanager-slave2.out在個節點上執行 jps 命令,結果如下:
master節點root@master:~/soft/apache/hadoop/hadoop-2.6.0/etc/hadoop# jps1223 Jps992 SecondaryNameNode813 NameNode1140 ResourceManagerslave1節點root@slave1:~/soft/apache/hadoop/hadoop-2.6.0/etc/hadoop# jps258 NodeManager352 Jps159 DataNodeslave2節點root@slave2:~/soft/apache/hadoop/hadoop-2.6.0/etc/hadoop# jps371 Jps277 NodeManager178 DataNode下面,我們在master節點上通過命令 hdfs dfsadmin -report 查看DataNode是否正常啟動:
root@master:~/soft/apache/hadoop/hadoop-2.6.0/etc/hadoop# hdfs dfsadmin -reportConfigured 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: 0Blocks with corrupt replicas: 0Missing blocks: 0-------------------------------------------------Live datanodes (2):Name: 10.0.0.7:50010 (slave2)Hostname: slave2Decommission Status : NormalConfigured 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: 1Last contact: Sat Feb 28 07:27:05 UTC 2015Name: 10.0.0.6:50010 (slave1)Hostname: slave1Decommission Status : NormalConfigured 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: 1Last contact: Sat Feb 28 07:27:05 UTC 2015還可以通過Web頁面看到查看DataNode和NameNode的狀態: http://10.0.0.5:50070/ (由于我宿主機器上沒有配置master的hosts解析,所以只能用ip地址訪問,大家將ip改為各自的master節點容器的ip即可):
執行WordCount實例
(待續……)