使用Docker在本地搭建hadoop,spark集群

jopen 8年前發布 | 19K 次閱讀 Docker Hadoop Spark 分布式/云計算/大數據

使用Docker在本地搭建hadoop,spark集群

簡介和環境說明

本環境使用的單個宿主主機,而不是跨主機集群,本spark集群環境存在的意義可能在于便于本地開發測試使用,非常輕量級和便捷。這個部署過程,最好在之前有過一定的hadoop,spark集群部署經驗的基礎,本文重點在于docker相關的操作,至于hadoop和spark集群的部署,極力推薦這兩個網頁:

Hadoop集群: http://blog.csdn.net/stark_sum ... 24279

Spark集群: http://blog.csdn.net/stark_sum ... 58081

----------

時間:寫于2016/1/6。

地點:某高校實驗室。

作者:duweike。

原因:項目初期調研探索。

主機系統:ubuntu14.04,64位,內存4G,主機名docker。(實際上是在虛擬機上安裝的)

軟件版本:hadoop-2.6.0,jdk1.7.0_79,scala-2.10.5,spark-1.2.0-bin-hadoop2.4,docker版本:1.9.1,鏡像:ubuntu14.04。

----------

搭建環境前調研結果描述:

目前網上在docker上部署spark的介紹比較簡單和沒有相關啟動使用的操作,部署大致分為兩類情況:

1. 直接在docker倉庫pull下來。這個方法我嘗試了一下,不建議使用,首先下載鏡像比較大,2G多,其次下載之后貌似只能單機啟動,也就是偽分布式,并不是集群(我自己沒有實際使用過,看到的相關資料是這樣說的)。如下sequenceiq/spark:1.2.0這個鏡像:

REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE

sequenceiq/spark 1.2.0 334aabfef5f1 10 months ago 2.115 GB

2. 自己使用基礎鏡像搭建環境。本文采用這種方式,由于自己也是剛接觸docker一個多月,還不會使用dockerfile,所以使用的是commit方式制作的集群。

----------

具體部署過程

第一步,相關軟件準備。

----------

通過對spark源碼當中docker文件夾的閱讀得出的思路,利用數據卷共享數據。相關的集群軟件都放在/opt目錄下,目的是為后面啟動集群的時候使用docker數據卷共享和永久保存數據,不會隨著容器的刪除而丟失。spark源碼docker文件夾解讀參考網頁: http://blog.csdn.net/yunlong34 ... 33731

操作說明,直接把java等軟件解壓到/opt下,總共是四個,java,hadoop,scala,spark。不需要在宿主主機做任何修改,包括/etc/hosts,/etc/profile添加變量等,因為是在容器當中使用,宿主主機并不會用到。解壓之后如下:

root@docker:/opt# ll

total 32

drwxr-xr-x 7 root root 4096 12月 22 22:12 ./

drwxr-xr-x 23 root root 4096 11月 30 19:35 ../

drwxr-xr-x 12 root root 4096 12月 22 22:07 hadoop-2.6.0/

drwxr-xr-x 8 root root 4096 4月 11 2015 jdk1.7.0_79/

drwxr-xr-x 9 root root 4096 12月 22 13:54 scala-2.10.5/

drwxrwxr-x 12 root root 4096 12月 22 22:19 spark-1.2.0-bin-hadoop2.4/

然后把hadoop和spark 的配置文件修改,這一步主要是靠之前的相關基礎操作了,可以參考上面給出的兩個網站修改配置文件,我是直接拷貝我之前集群的配置文件替換的,然后再結合后面的主機名,ip等行稍作修改就行了。如果之前沒有部署過集群,這一步的工作量是相當大的。

需要特別注意的一點是hadoop的配置文件中的hdfs-sit.xml中的dfs.datanode.data.dir,這個也就是hdfs的datanode的文件夾,也是通過小技巧修改為file:/root/data,為什么這么修改后面有講解,最終的想要的目的是通過鏈接文件,鏈接到數據卷/opt的hadoop目錄里面,這樣數據就能保存在容器之外了,不會隨著容器的刪除而丟失。修改如下:

<property>

<name>dfs.datanode.data.dir</name>

<value>file:/root/data</value>

</property>

----------

第二步,制作基礎鏡像。(主要工作)

本集群的思路是盡可能的減少額外的工作量,使用的是固定網絡環境,這可能和docker本身的網絡不固定性相悖,所以使用了一點小技巧修改的網絡,這也是這個方法不能大規模使用的原因,也算是一個弊端吧。我看到有人使用動態的ip注冊,我還沒有理解到哪個地步,在后期的學習中再慢慢完善吧。節點容器主機名和ip規劃如下:

主節點容器主機名hostname:node0,IP:172.17.0.150。

從節點容器主機名hostname:node1,IP:172.17.0.151。

從節點容器主機名hostname:node2,IP:172.17.0.152。

下面就開始一步一步的來設置:

1.查看鏡像,使用ubuntu:14.04做為基礎鏡像,如果沒有就pull一個吧。

root@docker:/opt# docker images

REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE

ubuntu 14.04 ca4d7b1b9a51 8 weeks ago 187.9 MB

2.啟動一個容器,安裝vim和ssh。

root@docker:/opt# docker run -it ubuntu:14.04 /bin/bash

root@67f272584448:/# apt-get -y install vim openssh-server

3.修改ssh配置文件,允許root登陸。

root@67f272584448:/# vim /etc/ssh/sshd_config

找到:PermitRootLogin without-password

修改為:PermitRootLogin yes

4.生成ssh公鑰,輸入ssh-keygen,一直回車就行了。著里需要說明的是,三個節點的公鑰都是一樣的,為了簡單起見而利用了小技巧。如果比較了解ssh的話,我說的這些相當于廢話了,后面還會有涉及的。

root@67f272584448:/# ssh-keygen

此時/root/.ssh文件夾里如下:

root@67f272584448:/# ls /root/.ssh/

id_rsa id_rsa.pub

root@67f272584448:/# cat /root/.ssh/id_rsa.pub >> /root/.ssh/authorized_keys

root@67f272584448:/# ls /root/.ssh/

authorized_keys id_rsa id_rsa.pub

5.下面開始關鍵步驟了。

把需要的變量寫入/root/.bashrc,為什么不寫入/etc/profile呢,因為我試了一下,寫入/etc/proflie生成鏡像啟動容器的時候變量不能生效。

看到這里,相信下面的變量都是很熟悉吧:

export JAVA_HOME=/opt/jdk1.7.0_79

export CLASSPATH=.:/opt/jdk1.7.0_79/lib/dt.jar:/opt/jdk1.7.0_79/lib/tools.jar

export HADOOP_HOME=/opt/hadoop-2.6.0

export SCALA_HOME=/opt/scala-2.10.5

export SPARK_HOME=/opt/spark-1.2.0-bin-hadoop2.4

export PATH=$JAVA_HOME/bin:$PATH:$SCALA_HOME/bin:$SPARK_HOME/bin

6.這個是最后一步了,在/root下新建一個run.sh腳本,對容器所做的修改,全部寫入這個腳本了,先把腳本貼出來,再解釋吧。

1  #!/bin/bash

 2  

 3  echo "172.17.0.150 node0" > /etc/hosts

 4  echo "172.17.0.151 node1" >> /etc/hosts

 5  echo "172.17.0.152 node2" >> /etc/hosts

 6  

 7  case $HOSTNAME in

 8  "node0")

 9      ifconfig eth0 172.17.0.150

10      sed -i 's/root@.*$/root@node0/g' /root/.ssh/authorized_keys

11      ;;

12  "node1")

13      ifconfig eth0 172.17.0.151

14      sed -i 's/root@.*$/root@node0/g' /root/.ssh/authorized_keys

15      ln -s /opt/hadoop-2.6.0/dfs/node1 /root/data

16      ;;

17  "node2")

18      ifconfig eth0 172.17.0.152

19      sed -i 's/root@.*$/root@node0/g' /root/.ssh/authorized_keys

20      ln -s /opt/hadoop-2.6.0/dfs/node2 /root/data

21      ;;

22  *)

23      echo "null"

24      ;;

25  esac

26  

27  /etc/init.d/ssh start -D

28

1)3,4,5行,替換hosts。啟動集群的時候,習慣性的喜歡使用主機名,而不是使用ip,所以做了這個修改。另一個原因是,容器在重啟之后hosts和ip是會變化的,所以每次啟動都要修改。

2)7到25行,是利用容器的主機名來做三個修改。

第一,修改主機的IP,也就是我們的三個節點都是固定ip的,這個命令需要privileged。

第二,設置ssh免登錄,也就authorized_keys中最后一個字段root@......全部修改為root@node0,這樣node0節點就能免登錄到node1,node2,和自己node0。

第三,利用連接文件,把hdfs的數據保存到數據卷的相關目錄,也就是保存到了容器之外。利用連接文件時一個技巧,hdfs的配置文件都是/root/data,實際上卻保存到了不同的文件目錄上去。在上面的hadoop的配置文件中做的一個特殊的修改<name>dfs.datanode.data.dir</name>,<value>file:/root/data</value>,這個是hdfs的實際存儲數據的目錄,通過軟連接到數據卷目錄,最終把數據保存在容器之外,這樣當容器刪除時,hdfs里面的數據并沒有消失,新建容器就可以再次使用數據了。

3)27行,這個就是啟動ssh的,關鍵的是-D這個參數,如果不加,啟動容器的時候run -d容器就會停止,不會運行。

4)最后保存退出,再修改一下執行權限,退出容器

root@67f272584448:~# chmod 744 /root/run.sh

root@67f272584448:~# exit

7.使用commit提交鏡像吧。

root@docker:~/docker# docker commit 67 ubuntu:base-spark

35341d63645cb5c23f88a6f4ac51d1000dc4431646ac3a948bd9c9f171dcbeeb

root@docker:~/docker# docker images

REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE

ubuntu base-spark 35341d63645c 4 minutes ago 261.1 MB

從上面可以看出,鏡像只有260MB,是非常小的。

到此整個基礎鏡像就做好了,其中有可能出錯的地方是,hadoop和spark的配置文件修改的問題,這里是無關docker知識的“準備工作”。

----------

第三步,啟動容器,啟動集群,并測試。

最后這步是最最爽的時候了,一個命令,集群就啟動起來了。

其實下面大部分的篇幅是在講解我的思路,啟動集群本身是很簡單的hadoop,spark知識。

----------

一,啟動容器集群。

我寫了一個小腳本docker_start.sh,里面三行是啟動三個容器的命令,先看一眼:

root@docker:~/docker# cat docker_start.sh

#!/bin/bash

docker run -d --name node0 -h node0 -v /opt:/opt --privileged ubuntu:base-spark /root/run.sh

docker run -d --name node1 -h node1 -v /opt:/opt --privileged ubuntu:base-spark /root/run.sh

docker run -d --name node2 -h node2 -v /opt:/opt --privileged ubuntu:base-spark /root/run.sh

下面解釋一下這個啟動命令的各個參數:

1)-d這個命令能夠成功執行的原因是run.sh這個腳本的/etc/init.d/ssh start -D這一行的-D這個參數,容器才能成功后臺up。

2)--name node0,這個是node0的容器名。

3)-h node0,這里的node0是容器主機名,也就是hostname。

4)-v /opt:/opt,就是數據卷,四個目錄在這里java,hadoop,scala,spark,并且hdfs的數據存儲目錄在hadoop-2.6.0目錄里,dfs文件夾里有三個目錄,最好手動提前新建name,node1和node2,其實是可以寫入run.sh腳本里面新建的,但是我已經不想回頭去修改run.sh了。

root@docker:/opt/hadoop-2.6.0/dfs# pwd

/opt/hadoop-2.6.0/dfs

root@docker:/opt/hadoop-2.6.0/dfs# ls

name node1 node2

name文件夾是hadoop的配置文件指定的:

<property>

<name>dfs.namenode.name.dir</name>

<value>file:/opt/hadoop-2.6.0/dfs/name</value>

node1和node2是run.sh腳本通過連接文件過去的實際hdfs存儲數據的目錄:

<property>

<name>dfs.datanode.data.dir</name>

<value>file:/root/data</value>

</property>

ln -s /opt/hadoop-2.6.0/dfs/node1 /root/data

ln -s /opt/hadoop-2.6.0/dfs/node2 /root/data

5)--privileged,這個參數是獲得最高權限,才能夠執行run.sh腳本里面的修改ip的命令。

ifconfig eth0 172.17.0.150

6)/root/run.sh,就是啟動容器的時候,執行一下我們提前寫好的腳本,對容器做一下修改了,雖然這些修改扭曲了docker的一些特性,不過對于我們這個本地的小環境來說,應該還是有點實際使用的價值的。

----------

二,進入node0容器,啟動并測試hdfs。

其實,到這里,就已經差不多結束了,下面就是hadoop和spark的知識了

首先,先看一下啟動的三個節點高興一下吧

root@docker:~/docker# docker ps

CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES

7268b191b8fd ubuntu:base-spark "/root/run.sh" About an hour ago Up About an hour node2

acce5919ed63 ubuntu:base-spark "/root/run.sh" About an hour ago Up About an hour node1

6494f90e1ecc ubuntu:base-spark "/root/run.sh" About an hour ago Up About an hour node0

進入node0容器

root@docker:/# docker exec -it node0 /bin/bash

root@node0:/#

此時的容器都是已經做過修改的,可以參看以下相關的信息,比如,ifconfig,/etc/hosts,hostname,/root/.ssh/authorized_keys,等。

下面就啟動hadoop的hdfs吧,因為這里只用到hdfs所以就不管yarn了,第一次啟動hdfs先來個格式化,然后,還要輸入若干個yes,這個yes是第一次ssh登陸的時候需要的,我就不貼出來格式化等相關的代碼了。

然后就是啟動hdfs:

root@node0:/# /opt/hadoop-2.6.0/sbin/start-dfs.sh

輸入jps查看一下node0上的進程

root@node0:/# jps

1310 Jps

843 NameNode

1025 SecondaryNameNode

下面就可以使用hdfs了,可以向hdfs上傳幾個文件試試,也可以通過webUI瀏覽器看一下hdfs的情況,總而言之,就是hdfs的知識了,我就不廢話了。

----------

三,以standalone方式啟動spark集群。

到這里直接啟動spark進程就可以了:

root@node0:/# /opt/spark-1.2.0-bin-hadoop2.4/sbin/start-all.sh

再次jps一下看看啟動的情況

root@node0:/# jps

1532 Jps

843 NameNode

1025 SecondaryNameNode

1393 Master

一切正常,就可以開始啟動spark-shell進行測試了,以standalone方式啟動:

root@node0:/# /opt/spark-1.2.0-bin-hadoop2.4/bin/spark-shell --master spark://node0:7077

到這里也基本已經結束了,可以跑一個wordcount的例子,同樣也可以使用webUI查看spark的情況,到此我覺得已經沒什么可說的了。

由于我不會往上面貼圖片,并且圖片很占篇幅,我不截圖給大家看了

----------

結束語

總結,這個三個節點真實可用,在單個普通電腦上部署hadoop和spark集群非常可行,當然,我是剛接觸docker的,其中有很多方法可能和docker的理論相違背,各位盡管批評指教,謝謝。

這是我第一次寫文檔,寫的不好,望見諒,如果遇到什么相關的問題,可以給我留言,再次謝謝。

QQ:604212506,非誠勿擾。

下一步學習kubernetes,在多個主機上部署spark集群,如果有必要再寫文檔和大家分享。

----------

來自: http://dockone.io/article/944

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!