基於樹莓派的叢集實驗(一)--spark on yarn

黃思喆發表於2015-06-10

基於樹莓派的叢集實驗(一)--spark on yarn

終於有時間嘗試叢集安裝了,可惜沒有多餘的電腦,手頭有樹莓派就拿來湊活用了。 本文將具體講解如何再樹莓派上安裝hadoop和spark,並與自己本地的mac嘗試構建分散式系統叢集。 由於樹莓派本身效能有限,這篇文章更多的是嘗試而非可以用於大規模運算。

sudo apt-get install -y maven build-essential autoconf automake libtool cmake zlib1g-dev pkg-config libssl-dev libfuse-dev libsnappy-dev libsnappy-java libbz2-dev oracle-java8-jdk subversion

單機安裝

樹莓派叢集網路設定

樹莓派單機配置coder系統檢視我的這篇博文.

單機配置好後叢集還需要做一些設定

主機名|ip|賬戶名|用途 ---|---|---|--- coderMaster|192.168.1.40|pi|作為主機並允許外網ssh訪問 coderSlaver01|192.168.1.41|pi|作為從機 coderSlaver02|192.168.1.42|pi|作為從機 coderSlaver03|192.168.1.43|pi|作為從機 coderSta|192.168.1.30|pi|作為反向代理伺服器和通訊入口,

因此,修改各機的/etc/hosts

修改許可權:

$sudo chmod ugo+w /etc/hosts

之後在vim中修改:

再在其中新增

192.168.1.40 coderMaster
192.168.1.41 coderSlaver01
192.168.1.42 coderSlaver02
192.168.1.43 coderSlaver03
192.168.1.33 coderSta01

當然也可以用echo

$echo "192.168.1.40 coderMaster" >> /etc/hosts
$echo "192.168.1.41 coderSlaver01" >> /etc/hosts
$echo "192.168.1.42 coderSlaver02" >> /etc/hosts
$echo "192.168.1.50 coderSta01" >> /etc/hosts

不過一旦重啟修改就會失效,怎麼修改呢?

sd卡拔下來修改其中的hosts.txt檔案即可

ps: 需要將主機的127.0.1.1 coder一行刪除

ssh配置

四臺機器通訊需要使用ssh無密碼通訊

生成本機ssh密匙

首先為各自機器生成一對公鑰,私鑰

~$ ssh-keygen -t dsa -P "" //用dsa因為它比rsa速度快
~$ cat ~/.ssh/id_dsa.pub >> ~/.ssh/authorized_keys
~$ ssh localhost

第一次ssh localhost會要你設定下,以後就可以無密碼登陸了。每臺機器都這麼設定下,要求都能 ssh localhost無密碼登陸。

master與slave建立聯絡

將三臺機器上.ssh/資料夾下下載主機的公鑰

~$ ssh-copy-id -i ~/.ssh/id_dsa.pub pi@coderSlaver01
~$ ssh-copy-id -i ~/.ssh/id_dsa.pub pi@coderSlaver02
~$ ssh-copy-id -i ~/.ssh/id_dsa.pub pi@coderSlaver03
~$ ssh-copy-id -i ~/.ssh/id_dsa.pub pi@coderSta

這樣主機就可以無密碼連到從機了.

同樣的,將各個從機的公鑰傳給主機

~$ ssh-copy-id -i ~/.ssh/id_dsa.pub pi@coderMaster

這就算配置好了

編譯環境配置

  • 首先是更新apt-get版本和已安裝軟體的版本(每臺都要)

    $sudo apt-get update $sudo apt-get upgrade -y

  • 之後是安裝編譯所需庫檔案(每臺最好裝下)

    $ sudo apt-get install -y maven build-essential autoconf automake libtool cmake zlib1g-dev pkg-config libssl-dev libfuse-dev libsnappy-dev libsnappy-java libbz2-dev oracle-java8-jdk subversion

期間因為有些庫依賴java1.6所以安裝了1.6版本的jvm,需要用

$sudo update-alternatives --config java

將其選回java1.8

  • 安裝protocol buffers v2.5 (必須2.5)

    $wget https://protobuf.googlecode.com/files/protobuf-2.5.0.tar.gz $sudo tar xzvf protobuf-2.5.0.tar.gz $sudo chown -R pi protobuf-2.5.0/ $cd protobuf-2.5.0 $./configure --prefix=/usr $make $make check $sudo make install

需要注意的是編譯安裝很慢....要有耐心,不要以為是當機了

  • 安裝scala語言(每臺都要)

    $cd ~ $wget http://www.scala-lang.org/files/archive/scala-2.10.4.tgz $sudo mkdir lib/scala $sudo tar vxzf scala-2.10.4.tgz -C lib/scala

vim 修改/etc/profile

#----------------------------------------------------------------------scala

export SCALA_HOME=/home/pi/lib/scala/scala-2.10.4
export PATH=$PATH:$SCALA_HOME/bin


#---------------------------------------------------------------------------

hadoop

安裝hadoop

因為是編譯安裝所以很慢很慢,要有耐心

$cd ~
$wget http://apache.mirrors.spacedump.net/hadoop/core/hadoop-2.6.0/hadoop-2.6.0-src.tar.gz
$tar xzvf hadoop-2.6.0-src.tar.gz
$sudo chown -R pi hadoop-2.6.0-src/
$cd hadoop-2.6.0-src/

開啟其中的pom.xml檔案.將

<additionalparam>-Xdoclint:none</additionalparam>

新增進<properties></properties>標籤中然後儲存退出編輯

因為是arm處理器,所以要打個補丁

$cd hadoop-common-project/hadoop-common/src
$wget https://issues.apache.org/jira/secure/attachment/12570212/HADOOP-9320.patch
$patch < HADOOP-9320.patch

這樣安裝的準備工作就完成了,開始使用maven編譯安裝

$sudo mvn package -Pdist,native -DskipTests -Dtar

這個要花近兩個小時才能編譯完...

編譯後的hadoop在hadoop-2.6.0-src/hadoop-dist/target/hadoop2.6.0這個位置

同時會有一個你的本地編譯程式.tar包在hadoop-2.6.0-src/hadoop-dist/target/hadoop2.6.0.tar.gz

配置hadoop

首先是環境變數配置,在/etc/profile中新增如下內容(先修改為可讀$sudo chmod ugo+w /etc/profile)

#-------------------------------------------------------------------java

export JAVA_HOME=/usr/lib/jvm/jdk-8-oracle-arm-vfp-hflt
export CLASS_PATH=$JAVA_HOME/lib:$JAVA_HOME/jre/lib  

#-------------------------------------------------------------------hadoop
export HADOOP_HOME=/home/pi/lib/hadoop/hadoop-2.6.0
export HADOOP_PID_DIR=/data/hadoop/pids
export HADOOP_COMMON_LIB_NATIVE_DIR=$HADOOP_HOME/lib/native
export HADOOP_OPTS="$HADOOP_OPTS -Djava.library.path=$HADOOP_HOME/lib/native"

export HADOOP_MAPRED_HOME=$HADOOP_HOME
export HADOOP_COMMON_HOME=$HADOOP_HOME
export HADOOP_HDFS_HOME=$HADOOP_HOME
export YARN_HOME=$HADOOP_HOME

export HADOOP_CONF_DIR=$HADOOP_HOME/etc/hadoop
export HDFS_CONF_DIR=$HADOOP_HOME/etc/hadoop
export YARN_CONF_DIR=$HADOOP_HOME/etc/hadoop

export JAVA_LIBRARY_PATH=$HADOOP_HOME/lib/native

export PATH=$PATH:$HADOOP_HOME/bin:$HADOOP_HOME/sbin

#---------------------------------------------------------------------

建立用於儲存的資料夾

$sudo mkdir -p /data/hadoop/{pids,storage}
$sudo mkdir -p /data/hadoop/storage/{hdfs,tmp}
$sudo mkdir -p /data/hadoop/storage/hdfs/{name,data}
$sudo chown -R pi /data
$sudo chmod -R ugo+w /data

配置 core-site.xml

<configuration>
    <property>
        <name>fs.defaultFS</name>
        <value>hdfs://coderMaster:9000</value>
    </property>
    <property>
        <name>io.file.buffer.size</name>
        <value>131072</value>
    </property>
    <property>
        <name>hadoop.tmp.dir</name>
        <value>file:/data/hadoop/storage/tmp</value>
    </property>
    <property>
        <name>hadoop.proxyuser.hadoop.hosts</name>
        <value>*</value>
    </property>
    <property>
        <name>hadoop.proxyuser.hadoop.groups</name>
        <value>*</value>
    </property>
    <property>
        <name>hadoop.native.lib</name>
        <value>true</value>
    </property>
</configuration>

配置 hdfs-site.xml

<configuration>
    <property>
        <name>dfs.namenode.name.dir</name>
        <value>file:/data/hadoop/storage/hdfs/name</value>
    </property>
    <property>
        <name>dfs.datanode.data.dir</name>
        <value>file:/data/hadoop/storage/hdfs/data</value>
    </property>
    <property>
        <name>dfs.replication</name>
        <value>3</value>
    </property>
    <property>
        <name>dfs.webhdfs.enabled</name>
        <value>true</value>
    </property>
</configuration>

配置 mapred-site.xml

<configuration>
    <property>
        <name>mapreduce.framework.name</name>
        <value>yarn</value>
    </property>
    <property>
        <name>mapreduce.jobhistory.address</name>
        <value>coderMaster:10020</value>
    </property>

    <property>
        <name>mapreduce.jobhistory.webapp.address</name>
        <value>coderMaster:19888</value>
    </property>
</configuration>

配置 yarn-site.xml

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

配置 hadoop-env.sh

修改JAVA_HOME

JAVA_HOME=/usr/lib/jvm/jdk-8-oracle-arm-vfp-hflt

配置slaves

coderSlaver01

coderSlaver02

coderSlaver03

將 hadoop複製給子節點

$sudo scp -r ~/lib/hadoop/hadoop-2.6.0/ pi@coderSlaver01:~/lib/hadoop
$sudo scp -r ~/lib/hadoop/hadoop-2.6.0/ pi@coderSlaver02:~/lib/hadoop
$sudo scp -r ~/lib/hadoop/hadoop-2.6.0/ pi@coderSlaver03:~/lib/hadoop

嘗試執行

$hdfs namenode -format #初始化節點
$start-dfs.sh          #開啟檔案系統
$start-yarn.sh         #開啟yarn
$jps                   #檢視開啟的java程式

如果看到主節點有

ResourceManager
NameNode
SecondaryNameNode

從節點有

NodeManager
DataNode

就說明成功了

Spark

安裝spark

$cd ~
$wget http://apache.crihan.fr/dist/spark/spark-1.3.1/spark-1.3.1-bin-hadoop2.6.tgz
$sudo mkdir ~/lib/spark/
$sudo tar vxzf spark-1.3.1-bin-hadoop2.6.tgz -C ~/workspace/lib/spark/
$echo "#-----------------------------------spark" >> /etc/profile
$echo "export SPARK_HOME=/home/pi/lib/spark/spark-1.3.1-bin-hadoop2.6" >> /etc/profile
$echo "#----------------------------------------" >> /etc/profile

之後修改$SPARK_HOME/conf/slaves中的值為(沒有就新建)

coderMaster
coderSlaver01
coderSlaver02
coderSlaver03

$SPARK_HOME/conf/spark-env.sh中的值為(沒有就新建)

export JAVA_HOME=/usr/lib/jvm/jdk-8-oracle-arm-vfp-hflt
export SCALA_HOME=/home/pi/lib/scala/scala-2.10.4
export HADOOP_HOME=/home/pi/lib/hadoop/hadoop-2.6.0
export HADOOP_CONF_DIR=$HADOOP_HOME/etc/hadoop


export SPARK_WORKER_WEBUI_PORT=2023
export SPARK_MASTER_WEBUI_PORT=2022
export SPARK_MASTER_IP=192.168.1.40

export LD_LIBRARY_PATH=/home/pi/lib/hadoop/hadoop-2.6.0/lib/native

將spark複製去各個節點,並如上設定環境變數

$sudo scp -r /home/pi/lib/spark/spark-1.3.1-bin-hadoop2.6 pi@coderSlaver01:~/lib/spark
$sudo scp -r /home/pi/lib/spark/spark-1.3.1-bin-hadoop2.6 pi@coderSlaver02:~/lib/spark
$sudo scp -r /home/pi/lib/spark/spark-1.3.1-bin-hadoop2.6 pi@coderSlaver03:~/lib/spark

測試

執行

$ $SPARK_HOME/sbin/start-all.sh

依然用jps檢視程式,如果主節點多了Master,從節點多了Worker

開啟網頁http:你的Masterip:2022如果顯示有4個worker則說明叢集執行正常,如果發現有問題,可以去執行指令碼時顯示的對應log(.out) 檔案中檢視哪裡出錯.

spark on yarn 執行

事實上有兩種執行方式,一種是叢集模式,叢集模式是用來執行application的,還有一種是客戶端模式,是在spark-shell中採用叢集的方式 就用第二種寫個簡單的word count演示吧

  • 第一步 將要分析的文字送入hdfs

    $hdfs dfs -mkdir /user/pi/sources $hdfs dfs -put README.md /user/pi/sources

  • 第二步 進入spark-shell

    $$SPARK_HOME/bin/spark-shell --num-executors 3 --master yarn --executor-memory 200m

  • 第三步 執行一個word count

    scala> var text_file = spark.textFile("hdfs://localhost:9000/user/pi/source/README.md") scala> var counts = text_file.flatMap(lambda line: line.split(" ")).map(lambda word: (word, 1)).reduceByKey(lambda a, b: a + b) scala> counts.saveAsTextFile("hdfs://coderMaster:9000/user/pi/result/wc")

  • 第四步 另起一個shell 檢視結果

    $hdfs dfs -copyToLocal hdfs://coderMaster:9000/user/pi/result/wc ~/ $cd ~/wc $cat part-00000 part-00001 >result $cat result

後日談:

其實這東西娛樂都不能算,小pi記憶體太小了,加上節點少,效能差的叫人無語...只能說這是個叢集實驗了.沒錢真可憐.

相關文章