那么,問(wèn)題來(lái)了!
有沒(méi)有更有可行性的辦法?提到虛擬化, Docker 最近很是火熱!不妨拿來(lái)在本地做虛擬化,搭建Hadoop的偽分布式集群環(huán)境。雖然有點(diǎn)大材小用,但是學(xué)習(xí)學(xué)習(xí),練練手也是極好的。
文章比較長(zhǎng),建議先倒杯水,聽(tīng)我慢慢到來(lái)……
先說(shuō)一下我的思路吧:
先使用Docker構(gòu)建一個(gè)Hadoop運(yùn)行環(huán)境的鏡像然后使用這個(gè)鏡像分別啟動(dòng)3個(gè)容器:1個(gè)Master節(jié)點(diǎn),兩個(gè)Slave節(jié)點(diǎn)在Master節(jié)點(diǎn)上配置Slave節(jié)點(diǎn)信息在Master上啟動(dòng)Hadoop使用Docker搭建Hadoop環(huán)境什么是 Docker?
Docker 是一個(gè)開(kāi)源項(xiàng)目,誕生于 2013 年初,最初是 dotCloud 公司內(nèi)部的一個(gè)業(yè)余項(xiàng)目。它基于 Google 公司推出的 Go 語(yǔ)言實(shí)現(xiàn)。 項(xiàng)目后來(lái)加入了 Linux 基金會(huì),遵從了 Apache 2.0 協(xié)議,項(xiàng)目代碼在 GitHub 上進(jìn)行維護(hù)。
Docker 自開(kāi)源后受到廣泛的關(guān)注和討論,以至于 dotCloud 公司后來(lái)都改名為 Docker Inc。Redhat 已經(jīng)在其 RHEL6.5 中集中支持 Docker;Google 也在其 PaaS 產(chǎn)品中廣泛應(yīng)用。
Docker 項(xiàng)目的目標(biāo)是實(shí)現(xiàn)輕量級(jí)的操作系統(tǒng)虛擬化解決方案。 Docker 的基礎(chǔ)是 Linux 容器(LXC)等技術(shù)。
在 LXC 的基礎(chǔ)上 Docker 進(jìn)行了進(jìn)一步的封裝,讓用戶不需要去關(guān)心容器的管理,使得操作更為簡(jiǎn)便。用戶操作 Docker 的容器就像操作一個(gè)快速輕量級(jí)的虛擬機(jī)一樣簡(jiǎn)單。
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其余系統(tǒng)或其他版本,請(qǐng)參考 這里 。
Docker常用命令介紹docker images :列出所有鏡像(images)docker ps :列出正在運(yùn)行的(容器)containersdocker pull ubuntu :下載鏡像docker run -i -t ubuntu /bin/bash :運(yùn)行ubuntu鏡像docker commit 3a09b2588478 ubuntu:mynewimage :提交你的變更,并且把容器保存成Tag為mynewimage的新的ubuntu鏡像.(注意,這里提交只是提交到本地倉(cāng)庫(kù),類(lèi)似git)其他常用命令,參考 這里 。
Docker去sudo在Ubuntu下,在執(zhí)行Docker時(shí),每次都要輸入sudo,同時(shí)輸入密碼,這里把當(dāng)前用戶執(zhí)行權(quán)限添加到相應(yīng)的docker用戶組里面。
# 添加一個(gè)新的docker用戶組sudo groupadd docker# 添加當(dāng)前用戶到docker用戶組里,注意這里的king為ubuntu登錄用戶名sudo gpasswd -a king docker# 重啟Docker后臺(tái)監(jiān)護(hù)進(jìn)程sudo service docker restart# 重啟之后,嘗試一下,是否生效docker version#若還未生效,則系統(tǒng)重啟,則生效sudo reboot下載Ubuntu鏡像docker pull ubuntu:14.04這條命令的作用是從Docker倉(cāng)庫(kù)中獲取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啟動(dòng)第一個(gè)容器下面,我們準(zhǔn)備以u(píng)buntu鏡像作為基準(zhǔn)鏡像,構(gòu)建我們的Hadoop運(yùn)行環(huán)境鏡像。
先使用命令如下命令啟動(dòng)容器:
docker run -ti ubuntu注意:我們?cè)诓恢付═ag的情況下,默認(rèn)選擇Tag為 latest 的鏡像啟動(dòng)容器。 指定Tag啟動(dòng)命令為:
docker run -ti ubuntu:14.04另外,每次容器啟動(dòng)的時(shí)候需要指定一個(gè)命令,容器啟動(dòng)后便會(huì)執(zhí)行這個(gè)命令。例如執(zhí)行下面的命令:
king@king:~$ docker run ubuntu /bin/echo 'Hello world'Hello worldking@king:~$可以看到,容器啟動(dòng)了馬上又退出了,因?yàn)槿萜髦隽艘患虑椋壕褪谴蛴?Hello world ,打印完了,自然就退出了。
如果你想做多件事情,可以自己寫(xiě)一個(gè)shell腳本,把你要的操作寫(xiě)入進(jìn)去,然后在 run 后面指定這個(gè)腳本路徑。
我們剛剛的 docker run -ti ubuntu 命令中沒(méi)有指定執(zhí)行程序,Docker默認(rèn)執(zhí)行 /bin/bash 。
其他啟動(dòng)參數(shù),大家可以自己在網(wǎng)上查,這里不再陳述了。好了我們回到剛剛 docker run -ti ubuntu 啟動(dòng)的容器,可以看到容器幾乎瞬間就啟動(dòng)起來(lái)了,比虛擬機(jī)不知快了多少倍?。?/p> king@king:~$ docker run -ti ubunturoot@009fe5728aba:/#
容器啟動(dòng)起來(lái)了,接下來(lái)就是安裝Java、Hadoop及相關(guān)配置了。
Java安裝依次執(zhí)行如下命令:
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),如需其他版本請(qǐng)自行修改 apt-get install oracle-java7-installer 為 apt-get install oracle-java6-installer默認(rèn)使用的是Ubuntu的官方源,如果下載比較慢,請(qǐng)自行修改更新源,不知道如何使用命令行修改的,參考 這里 。另外,大家可以將裝好java的鏡像保存為一個(gè)副本,他日可以在此基礎(chǔ)上構(gòu)建其他鏡像。命令如下:
root@122a2cecdd14:~# exitdocker commit -m "java install" 122a2cecdd14 ubuntu:java上面命令中 122a2cecdd14 為當(dāng)前容器的ID, ubuntu:java 是為新的鏡像指定一個(gè)標(biāo)識(shí), ubuntu 為 倉(cāng)庫(kù)名 , java 是 Tag 。
如何獲取容器ID:
有個(gè)簡(jiǎn)便的辦法找到此ID,就是命令行用戶名 @ 后面的那一串字符。這個(gè)方法只在容器啟動(dòng)時(shí)沒(méi)有指定hostname時(shí)才能用。使用 docker ps 列出所有運(yùn)行的容器,在命令結(jié)果中查看Hadoop安裝漸漸切入正題了O(∩_∩)O~
使用剛剛已經(jīng)安裝了Java的容器鏡像啟動(dòng):
docker run -ti ubuntu:java啟動(dòng)成功了,我們開(kāi)始安裝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,如果需要其他版本,請(qǐng)?jiān)?這里 找到鏈接地址后修改命令即可。
3.配置環(huán)境變量
修改 ~/.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
下面,我們開(kāi)始修改Hadoop的配置文件。主要配置 core-site.xml 、 hdfs-site.xml 、 mapred-site.xml 這三個(gè)文件。
開(kāi)始配置之前,執(zhí)行下面命令:
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這里創(chuàng)建了三個(gè)目錄,后續(xù)配置的時(shí)候會(huì)用到:
tmp:作為Hadoop的臨時(shí)目錄namenode:作為NameNode的存放目錄datanode:作為DataNode的存放目錄1).core-site.xml配置注意:
hadoop.tmp.dir 配置項(xiàng)值即為此前命令中創(chuàng)建的臨時(shí)目錄路徑。fs.default.name 配置為 hdfs://master:9000 ,指向的是一個(gè)Master節(jié)點(diǎn)的主機(jī)(后續(xù)我們做集群配置的時(shí)候,自然會(huì)配置這個(gè)節(jié)點(diǎn),先寫(xiě)在這里)2).hdfs-site.xml配置使用命令 nano hdfs-site.xml 編輯 hdfs-site.xml 文件:
注意:
我們后續(xù)搭建集群環(huán)境時(shí),將配置一個(gè)Master節(jié)點(diǎn)和兩個(gè)Slave節(jié)點(diǎn)。所以 dfs.replication 配置為2。dfs.namenode.name.dir 和 dfs.datanode.data.dir 分別配置為之前創(chuàng)建的NameNode和DataNode的目錄路徑3).mapred-site.xml配置Hadoop安裝文件中提供了一個(gè)mapred-site.xml.template,所以我們之前使用了命令 cp mapred-site.xml.template mapred-site.xml ,創(chuàng)建了一個(gè)mapred-site.xml文件。下面使用命令 nano mapred-site.xml 編輯這個(gè)文件:
這里只有一個(gè)配置項(xiàng) mapred.job.tracker ,我們指向master節(jié)點(diǎn)機(jī)器。
4)修改JAVA_HOME環(huán)境變量使用命令 .nano hadoop-env.sh ,修改如下配置:
# The java implementation to use.export JAVA_HOME=/usr/lib/jvm/java-7-oracle5.格式化 namenode
這是很重要的一步,執(zhí)行命令 hadoop namenode -format
4.安裝SSH
搭建集群環(huán)境,自然少不了使用SSH。這可以實(shí)現(xiàn)無(wú)密碼訪問(wèn),訪問(wèn)集群機(jī)器的時(shí)候很方便。
root@8ef06706f88d:~# sudo apt-get install sshSSH裝好了以后,由于我們是Docker容器中運(yùn)行,所以SSH服務(wù)不會(huì)自動(dòng)啟動(dòng)。需要我們?cè)谌萜鲉?dòng)以后,手動(dòng)通過(guò) /usr/sbin/sshd 手動(dòng)打開(kāi)SSH服務(wù)。未免有些麻煩,為了方便,我們把這個(gè)命令加入到 ~/.bashrc 文件中。通過(guò) nano ~/.bashrc 編輯 .bashrc 文件(nano沒(méi)有安裝的自行安裝,也可用vi),在文件后追加下面內(nèi)容:
#autorun/usr/sbin/sshd5.生成訪問(wèn)密鑰
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注意: 這里,我的思路是直接將密鑰生成后寫(xiě)入鏡像,免得在買(mǎi)個(gè)容器里面再單獨(dú)生成一次,還要相互拷貝公鑰,比較麻煩。當(dāng)然這只是學(xué)習(xí)使用,實(shí)際操作時(shí),應(yīng)該不會(huì)這么搞,因?yàn)檫@樣所有容器的密鑰都是一樣的?。?/p>
6.保存鏡像副本
這里我們將安裝好Hadoop的鏡像保存為一個(gè)副本。
root@8ef06706f88d:~# exitking@king:~$ docker commit -m "hadoop install" 8ef06706f88d ubuntu:hadoopHadoop分布式集群搭建重點(diǎn)來(lái)了!
按照 hadoop 集群的基本要求,其 中一個(gè)是 master 結(jié)點(diǎn),主要是用于運(yùn)行 hadoop 程序中的 namenode、secondorynamenode 和 jobtracker(新版本名字變了) 任務(wù)。用外兩個(gè)結(jié)點(diǎn)均為 slave 結(jié)點(diǎn),其中一個(gè)是用于冗余目的,如果沒(méi)有冗 余,就不能稱(chēng)之為 hadoop 了,所以模擬 hadoop 集群至少要有 3 個(gè)結(jié)點(diǎn)。
前面已經(jīng)將Hadoop的鏡像構(gòu)建好了,下面就是使用這個(gè)鏡像搭建Master節(jié)點(diǎn)和Slave節(jié)點(diǎn)了:
節(jié)點(diǎn) | hostname | ip | 用途 | Docker啟動(dòng)腳本 |
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啟動(dòng)容器使用的是 run 命令:
docker run -ti ubuntu:hadoop這里有幾個(gè)問(wèn)題:
Docker容器中的ip地址是啟動(dòng)之后自動(dòng)分配的,且不能手動(dòng)更改hostname、hosts配置在容器內(nèi)修改了,只能在本次容器生命周期內(nèi)有效。如果容器退出了,重新啟動(dòng),這兩個(gè)配置將被還原。且這兩個(gè)配置無(wú)法通過(guò) commit 命令寫(xiě)入鏡像我們搭建集群環(huán)境的時(shí)候,需要指定節(jié)點(diǎn)的hostname,以及配置hosts。hostname可以使用Docker run 命令的 h 參數(shù)直接指定。但hosts解析有點(diǎn)麻煩,雖然可以使用 run 的 --link 參數(shù)配置hosts解析信息,但我們搭建集群時(shí)要求兩臺(tái)機(jī)器互相能夠 ping 通,其中一個(gè)容器沒(méi)有啟動(dòng),那么ip不知道,所以 --link 參數(shù)對(duì)于我們的這個(gè)場(chǎng)景不實(shí)用。要解決這個(gè)問(wèn)題,大概需要專(zhuān)門(mén)搭建一個(gè)域名解析服務(wù),即使用 --dns 參數(shù)(參考 這里 )。
我們這里只為學(xué)習(xí),就不整那么復(fù)雜了,就手動(dòng)修改hosts吧。只不過(guò)每次都得改,我Docker知識(shí)淺薄,一時(shí)還沒(méi)有解決這個(gè)問(wèn)題。相信肯定有更好的辦法。如果有高人能指定一下,感激不盡?。?/p>
啟動(dòng)master容器
docker run -ti -h master ubuntu:hadoop啟動(dòng)slave1容器
docker run -ti -h slave1 ubuntu:hadoop啟動(dòng)slave2容器
docker run -ti -h slave2 ubuntu:hadoop配置hosts通過(guò) ifconfig 命令獲取各節(jié)點(diǎn)ip。環(huán)境不同獲取的ip可能不一樣,例如我本機(jī)獲取的ip如下:master:10.0.0.5slave1:10.0.0.6slave2:10.0.0.7
使用 sudo nano /etc/hosts 命令將如下配置寫(xiě)入各節(jié)點(diǎn)的hosts文件,注意修改ip地址:
10.0.0.5 master10.0.0.6 slave110.0.0.7 slave2配置slaves
下面我們來(lái)配置哪些節(jié)點(diǎn)是slave。在較老的Hadoop版本中有一個(gè)masters文件和一個(gè)slaves文件,但新版本中只有slaves文件了。
在master節(jié)點(diǎn)容器中執(zhí)行如下命令:
root@master:~# cd $HADOOP_CONFIG_HOME/root@master:~/soft/apache/hadoop/hadoop-2.6.0/etc/hadoop# nano slaves將如下slave節(jié)點(diǎn)的hostname信息寫(xiě)入該文件:
slave1slave2啟動(dòng)Hadoop在master節(jié)點(diǎn)上執(zhí)行 start-all.sh 命令,啟動(dòng)Hadoop。
激動(dòng)人心的一刻……
如果看到如下信息,則說(shuō)明啟動(dòng)成功了:
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在個(gè)節(jié)點(diǎn)上執(zhí)行 jps 命令,結(jié)果如下:
master節(jié)點(diǎn)root@master:~/soft/apache/hadoop/hadoop-2.6.0/etc/hadoop# jps1223 Jps992 SecondaryNameNode813 NameNode1140 ResourceManagerslave1節(jié)點(diǎn)root@slave1:~/soft/apache/hadoop/hadoop-2.6.0/etc/hadoop# jps258 NodeManager352 Jps159 DataNodeslave2節(jié)點(diǎn)root@slave2:~/soft/apache/hadoop/hadoop-2.6.0/etc/hadoop# jps371 Jps277 NodeManager178 DataNode下面,我們?cè)趍aster節(jié)點(diǎn)上通過(guò)命令 hdfs dfsadmin -report 查看DataNode是否正常啟動(dòng):
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還可以通過(guò)Web頁(yè)面看到查看DataNode和NameNode的狀態(tài): http://10.0.0.5:50070/ (由于我宿主機(jī)器上沒(méi)有配置master的hosts解析,所以只能用ip地址訪問(wèn),大家將ip改為各自的master節(jié)點(diǎn)容器的ip即可):
執(zhí)行WordCount實(shí)例
(待續(xù)……)