# 關于Spark集群的容器封裝與部署
定稿人 | 定稿日期 | 系統環境
| :--------: | :-----: | :----: |
黃鎮城 | 2018.1.28 | centos7 + docker1.13 + docker-compose1.16
平時我們搭建hadoop集群的時候都是部署在物理機上,然而我們通過大量實驗發現使用容器搭建hadoop集群不僅啟動速度更快,而且資源利用率更高,本節主要講述如何使用dockerfile封裝hadoop,然后使用docker-compose編排集群。
### 封裝Spark鏡像
```
FROM openjdk:8u131-jre-alpine
# openjdk:8u131-jre-alpine作為基礎鏡像,體積小,自帶jvm環境。
MAINTAINER <eway>
# 切換root用戶避免權限問題,utf8字符集,bash解釋器。安裝一個同步為上海時區的時間
USER root
ENV LANG=C.UTF-8
RUN apk add --no-cache --update-cache bash
ENV TZ=Asia/Shanghai
RUN apk --update add wget bash tzdata \
&& cp /usr/share/zoneinfo/$TZ /etc/localtime \
&& echo $TZ > /etc/timezone
# 下載解壓spark
WORKDIR /usr/local
RUN wget "http://www.apache.org/dist/spark/spark-2.0.2/spark-2.0.2-bin-hadoop2.7.tgz" \
&& tar -zxvf spark-* \
&& mv spark-2.0.2-bin-hadoop2.7 spark \
&& rm -rf spark-2.0.2-bin-hadoop2.7.tgz
# 配置環境變量、暴露端口
ENV SPARK_HOME=/usr/local/spark
ENV JAVA_HOME=/usr/lib/jvm/java-1.8-openjdk
ENV PATH=${PATH}:${JAVA_HOME}/bin:${SPARK_HOME}/bin
EXPOSE 6066 7077 8080 8081 4044
WORKDIR $SPARK_HOME
CMD ["/bin/bash"]
```
dockerfile 編寫完后我們就可以基于此構建鏡像了
```powershell
# 構建Dockerfile構建鏡像
$ docker build -f Dockerfile -t spark:v1 .
```
### DockerFile代碼注意事項
#### 源鏡像選擇
通常我們封裝鏡像時,一般都采用Centos或Ubuntu的源鏡像,但是這樣做有一個很大的缺點就是封裝后的鏡像體積太大,所以為了減少鏡像體積,我們使用了體積小巧的alpine作為源鏡像,同時考慮到HDFS和YARN都需要JAVA環境,所以最終我們使用了自帶JDK的openjdk:8u131-jre-alpine。
#### 時區同步
源鏡像默認是CTS時區,所以需要添加tzdata包獲取各時區的相關數據,以更改為中國上海的時區。
> 注: tzdata安裝更改時區后不可卸載,否則時區會變回CTS。
### 在本地啟動服務
```powershell
# 啟動 master 容器
$ docker run -itd --name spark-master -p 6066:6066 -p 7077:7077 -p 8080:8080 spark:v1 spark-class org.apache.spark.deploy.master.Master
# 啟動 worker 容器
$ docker run -itd -P --link spark-master:worker01 spark:v1 spark-class org.apache.spark.deploy.worker.Worker spark://spark-master:7077
# 啟動 historyserver 容器
$ docker run -itd --name spark-history -p 18080:18080 \
-e SPARK_HISTORY_OPTS="-Dspark.history.ui.port=18080 \
-Dspark.history.retainedApplications=10 \
-Dspark.history.fs.logDirectory=hdfs://namenode:9000/user/spark/history" \
spark:v1 spark-class org.apache.spark.deploy.history.HistoryServer
# 運行spark程序
$ spark-submit --conf spark.eventLog.enabled=true \
--conf spark.eventLog.dir=hdfs://namenode:9000/user/spark/history \
--master spark://namenode:7077 --class org.apache.spark.examples.SparkPi ./examples/jars/spark-examples_2.11-2.0.2.jar
```
---
# 擴展
* master節點相當于hadoop的namenode節點
* worker節點相當于hadoop的datanode節點
* historyserver節點,是為了記錄我們運行的spark程序。通過瀏覽器訪問` http://ip-addr:18080`。可以通過web詳細的查詢運行后的spark程序結果或過程。
* 運行spark程序例子
```shell
spark-submit \ #提交spark程序
--conf spark.eventLog.enabled=true \ # 允許spark程序日志的記錄,最后在ip:18080能查詢到
--conf spark.eventLog.dir=hdfs://namenode:9000/user/spark/history \
# 將spark程序日志放在hadoop的【hdfs】分布式文件系統。也可以掛在在本地。
但分布式文件系統因為分布式的原因他更安全,和能跨主機。 \
--master spark://namenode:7077 \ # spark-submit提交spark程序到--master指定的master節點
--class org.apache.spark.examples.SparkPi ./examples/jars/spark-examples_2.11-2.0.2.jar
```
---
### 使用docker-compose部署服務
```
version: "2"
master:
image: spark:v1
command: bin/spark-class org.apache.spark.deploy.master.Master -h master
hostname: master
environment:
MASTER: spark://master:7077
SPARK_MASTER_OPTS: "-Dspark.eventLog.dir=hdfs://namenode:9000/user/spark/history"
SPARK_PUBLIC_DNS: master
ports:
- 4040:4040
- 6066:6066
- 7077:7077
- 8080:8080
worker:
image: spark:v1
command: bin/spark-class org.apache.spark.deploy.worker.Worker spark://master:7077
hostname: worker
environment:
SPARK_WORKER_CORES: 1
SPARK_WORKER_MEMORY: 1g
SPARK_WORKER_PORT: 8881
SPARK_WORKER_WEBUI_PORT: 8081
SPARK_PUBLIC_DNS: master
links:
- master
ports:
- 8081:8081
historyServer:
image: spark:v1
command: spark-class org.apache.spark.deploy.history.HistoryServer
hostname: historyServer
environment:
MASTER: spark://master:7077
SPARK_PUBLIC_DNS: master
SPARK_HISTORY_OPTS: "-Dspark.history.ui.port=18080 -Dspark.history.retainedApplications=3 -Dspark.history.fs.logDirectory=hdfs://namenode:9000/spark/history"
links:
- master
expose:
- 18080
ports:
- 18080:18080
```
> 注:--link <目標容器名> 該參數的主要意思是本容器需要使用目標容器的服務,所以指定了容器的啟動順序,并且在該容器的hosts文件中添加目標容器名的DNS。
>
----
# 擴展

----
```
# 通過docker-compose一鍵啟動spark集群
$ docker-compose -f docker-compose.yml up -d
# 一鍵擴展worker服務到5個
$ docker-compose scale worker=5
```