Spark on Mesos 多節點部署

Spark + Mesos 叢集是由多個主節點與工作節點組合而成,它實作了兩層的排程(Scheduler)來提供粗/細粒度的排程。在 Mesos 中主節點(Master)主要負責資料的分配與排程,然而從節點(Slave)則是主要執行任務負載的角色。Mesos 也提供了高可靠的部署模式,可利用多個主節點的 ZooKeeper 來做服務發現。

在 Mesos 上所執行的應用程式都被稱為框架(Framework),該框架會被 Mesos 以 API 方式處理資源的提供,並將任務提交給 Mesos。其任務執行流程有以下幾個步驟構成:

  • Slave 提供可用資源給 Master
  • Master 向 Framework 的資源供應,並說明 Slave 資源
  • Framework Scheduler 回應任務以及每個任務的資源需求
  • Master 將任務發送到適當的 Slave 執行器(Executor)

事前準備

以下為節點配置:

IP Address HostName
192.168.1.10 mesos-master
192.168.1.11 mesos-slave-1
192.168.1.12 mesos-slave-2

首先我們要在各節點先安裝 ssh-server 與 Java JDK,並配置需要的相關環境:

$ sudo apt-get install openssh-server

設定(hadoop)不用需打 sudo 密碼:

$ echo "hadoop ALL = (root) NOPASSWD:ALL" | sudo tee /etc/sudoers.d/hadoop && sudo chmod 440 /etc/sudoers.d/hadoop

P.S 要注意 hadoop 要隨著現在使用的 User 變動。

建立ssh key,並複製 key 使之不用密碼登入:

$ ssh-keygen -t rsa
$ ssh-copy-id localhost

安裝Java 1.8 JDK:

$ sudo apt-get purge openjdk*
$ sudo apt-get -y autoremove
$ sudo apt-get install -y software-properties-common
$ sudo add-apt-repository -y ppa:webupd8team/java
$ sudo apt-get update
$ echo debconf shared/accepted-oracle-license-v1-1 select true | sudo debconf-set-selections
$ echo debconf shared/accepted-oracle-license-v1-1 seen true | sudo debconf-set-selections
$ sudo apt-get -y install oracle-java8-installer

新增各節點 Hostname 至/etc/hosts檔案:

127.0.0.1 localhost

192.168.1.10 mesos-master
192.168.1.11 mesos-slave-1
192.168.1.12 mesos-slave-2

並在Master節點複製所有Slave的 ssh key:

$ ssh-copy-id ubuntu@mesos-slave-1
$ ssh-copy-id ubuntu@mesos-slave-2

Mesos 安裝

首先要安裝 Mesos 於系統上,可以採用以下方式獲取最新版本的 Respository:

$ sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv E56151BF
$ DISTRO=$(lsb_release -is | tr '[:upper:]' '[:lower:]')
$ CODENAME=$(lsb_release -cs)
$ echo "deb http://repos.mesosphere.com/${DISTRO} ${CODENAME} main" | sudo tee /etc/apt/sources.list.d/mesosphere.list

加入 key 與 repository 後,即可透過apt-get安裝:

sudo apt-get update
sudo apt-get -y install mesos

P.S Master需要再安裝 Marathon

Master 節點設定

首先設定 Zookeeper ID:

$ echo 1 | sudo tee /etc/zookeeper/conf/myid

設定 Zookeeper configuration:

HOST_IP=$(ip route get 8.8.8.8 | awk '{print $NF; exit}')
echo server.1=$HOST_IP:2888:3888 | sudo tee -a /etc/zookeeper/conf/zoo.cfg

若要部署 HA 需要加入多個 Master 節點的 Zookeeper。

完成後,重新啟動 Zookeeper 服務:

$ sudo service zookeeper restart

接著設定 Mesos zk configuration:

$ echo zk://$HOST_IP:2181/mesos | sudo tee /etc/mesos/zk

設定 Mesos quorum 參數:

$ echo 1 | sudo tee /etc/mesos-master/quorum

若是 OpenStack VM 需要設定 Host IP 和 EXENTAL_IP 為 區網 IP 而非 Flaot IP:(Optional)

EXENTAL_IP='192.168.1.10'
echo $EXENTAL_IP | sudo tee /etc/mesos-master/hostname
echo $HOST_IP | sudo tee /etc/mesos-master/ip
echo 'mesos-cluster' | sudo tee /etc/mesos-master/cluster

接著設定advertise_ip

$ echo $HOST_IP | sudo tee /etc/mesos-master/advertise_ip

當設定完成,要接著設定 Marathon,首先建立組態目錄:

sudo mkdir /etc/marathon/
sudo mkdir /etc/marathon/conf

設定 hostname:

$ echo $EXENTAL_IP | sudo tee /etc/marathon/conf/hostname

設定 master ip :

$ echo zk://$HOST_IP:2181/mesos | sudo tee /etc/marathon/conf/master

設定 master zookeeper :

$ echo zk://$HOST_IP:2181/marathon | sudo tee /etc/marathon/conf/zk

關閉 Master 節點的mesos-slave service:

sudo service mesos-slave stop
sudo sh -c "echo manual > /etc/init/mesos-slave.override"

重新啟動 Mesos 與 Marathon 服務:

sudo service mesos-master restart
sudo service marathon restart

Slave 節點設定

由於我們是使用 ubuntu 套件,Zookeeper 會以相依套件被自動下載至環境上,故我們要手動停止服務:

sudo service zookeeper stop
sudo sh -c "echo manual > /etc/init/zookeeper.override"

設定 Mesos 與 Marathon:

若使用 OpenStack VM,需要將 MASTER_IP 和 PUBlIC_IP 設定為區網 IP

MASTER_IP="192.168.1.10"
PUBlIC_IP="192.168.1.11"
HOST_IP=$(ip route get 8.8.8.8 | awk '{print $NF; exit}')
echo zk://$MASTER_IP:2181/mesos | sudo tee /etc/mesos/zk

設定 Hostname 可以使用 OpenStack Float IP(Optional):

echo $PUBlIC_IP | sudo tee /etc/mesos-slave/hostname

設定 slave ip:

$ echo $HOST_IP | sudo tee /etc/mesos-slave/ip

關閉 mesos-master 服務,並取消自動開機啟動:

sudo service mesos-master stop
sudo sh -c "echo manual > /etc/init/mesos-master.override"

重新啟動 Mesos slave 服務:

$ sudo service mesos-slave restart

驗證安裝結果

當安裝完成,我們要驗證系統是否正常運行,可以透過以下指令運行:

MASTER=$(mesos-resolve `cat /etc/mesos/zk`)
mesos-execute --master=$MASTER --name="cluster-test" --command="sleep 5"

若要查看細節資訊,可以用瀏覽器開啟 Mesos ConsoleMarathon console

安裝 Spark Driver

首先下載 Spark,並修改權限:

$ curl -s "http://archive.apache.org/dist/spark/spark-1.5.2/spark-1.5.2-bin-hadoop2.6.tgz" | sudo tar -xz -C /opt/
$ sudo mv /opt/spark-1.5.2-bin-hadoop2.6 /opt/spark
$ sudo chown $USER:$USER -R /opt/spark

之後到spark/conf目錄,將spark-env.sh.template複製為park-env.sh

$ cp spark-env.sh.template spark-env.sh

spark-env.sh這內容最下方增加這幾筆環境參數:

export MESOS_NATIVE_JAVA_LIBRARY="/usr/lib/libmesos.so"
export MASTER="mesos://192.168.1.10:5050"
export SPARK_EXECUTOR_URI="/opt/spark-1.5.2.tgz"

export JAVA_HOME=$(readlink -f /usr/bin/java | sed "s:jre/bin/java::")

export SPARK_LOCAL_IP=$(ifconfig eth0 | awk '/inet addr/{print substr($2,6)}')
export SPARK_LOCAL_HOSTNAME=$(ifconfig eth0 | awk '/inet addr/{print substr($2,6)}')

接著下載一個新的spark-1.5.2-bin-hadoop2.6.tgz,並解壓縮:

$ cd ~/
$ wget "http://archive.apache.org/dist/spark/spark-1.5.2/spark-1.5.2-bin-hadoop2.6.tgz"
$ tar -xvf spark-1.5.2-bin-hadoop2.6.tgz
$ sudo mv spark-1.5.2-bin-hadoop2.6 spark-1.5.2
$ sudo vim spark-1.5.2/conf/spark-env.sh
export MESOS_NATIVE_LIBRARY=/usr/local/lib/libmesos.so
export SPARK_EXECUTOR_URI="/opt/spark-1.5.2.tgz"
export MASTER=mesos://192.168.1.10:5050
export JAVA_HOME=$(readlink -f /usr/bin/java | sed "s:jre/bin/java::")

完成後壓縮資料夾:

$ sudo tar -czvf spark-1.5.2.tgz spark-1.5.2/

並在Master節點複製到所有Slave並解壓縮:

$ scp spark-1.5.2.tgz mesos-slave-1:~/ && ssh mesos-slave-1 sudo mv ~/spark-1.5.2.tgz /opt
$ scp spark-1.5.2.tgz mesos-slave-2:~/ && ssh mesos-slave-2 sudo mv ~/spark-1.5.2.tgz /opt
$ sudo tar -xvf /opt/spark-1.5.2.tgz

設定使用者環境參數:

$ echo "export SPARK_HOME=/opt/spark" | sudo tee -a ~/.bashrc
$ echo "export PATH=\$SPARK_HOME/bin:\$PATH" | sudo tee -a ~/.bashrc

執行spark-shell,來驗證 Spark 可否正常執行:

$ spark-shell --master mesos://192.168.1.34:5050
val data = 1 to 10000
val distData = sc.parallelize(data)
distData.filter(_< 10).collect()

或使用範例程式提交 Job:

$ spark-submit --class org.apache.spark.examples.SparkPi \
--master mesos://192.168.1.10:5050 \
--num-executors 1 \
--executor-memory 1g \
--executor-cores 1 \
lib/spark-examples*.jar \
1
Share Comments