1. 程式人生 > >動手搭建docker並在docker容器中建spark集群

動手搭建docker並在docker容器中建spark集群

本地ip files 提交 端口 依賴包 spark2 num 裏的 .sh

本人親自測試搭建,由於是初學一路搭建下來走了不少彎路。如有不對或更簡潔的步驟請提出
環境: win10上安裝的虛擬機,虛擬機裝的centos7,並liunx界面化(之前搭建一次在網和端口都可以telnet前提下,就是訪問不了docker容器中的服務地址,此次是為了防止宿機不能訪問下用虛擬機界面瀏覽器),centos7的命令和centos6有區別,而且centos7中是沒有iptables命令,如要使用自己安裝.
本人搭建的 虛擬機ip:192.168.20.129
spark master節點IP: 172.17.0.2 對應docker容器名稱cloud1
spark worker節點IP: 172.17.0.3 對應docker容器名稱cloud2
spark worker節點IP: 172.17.0.4 對應docker容器名稱cloud3

安裝docker容器步驟:
1.root權限下命令查看當前內核版本 $uname -r , docker要求CentOS系統內核版本高於3.10
技術分享圖片
2.使用root權限登陸Centos,確保yum包更新到最新
命令: yum update
技術分享圖片
3.如果有安裝舊版本先卸載舊的docker
命令: yum remove docker docker-common docker-selinux docker-engine
4.安裝需要的軟件包(或叫依賴包)
命令: yum install -y yum-utils device-mapper-persistent-data lvm2
技術分享圖片
5.設置yum源
命令: yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
技術分享圖片
6.查看倉庫中所有docker版本,並選擇
命令: yum list docker-ce --showduplicates | sort -r
技術分享圖片
7.安裝docker
命令: yum install docker-ce #由於repo中默認只開啟stable倉庫,故這裏安裝的是最新穩定版17.12.0
命令: yum install <FQPN> # 例如:sudo yum install docker-ce-17.12.0.ce
8.啟動並加入開機啟動
命令: systemctl start docker
systemctl enable docker
9.檢查是否安裝成功
命令: docker version
技術分享圖片

docker容器裏搭建spark集群,這裏安裝的 hadoop2.7,jdk1.8, spark2.4, scala2.12.8, zookeeper3.4.12
docker容器搭建spark集群步驟:
1.先拉取一個ubuntn到docker中
命令: docker pull ubuntu
如果pull太慢可以配置加速鏡像https://www.daocloud.io註冊自己的用戶,然後在加速頁面找到自己的liun加速命令拷貝在liunx執行即可,具體參考網址: http://blog.51cto.com/14159501/2338377
2.下載好的ubuntu到本地後可以查看鏡像
命令: docker images
技術分享圖片
在centos7中 路徑/usr/local下建一個java目錄(命令 mkdir java),該目錄存放要安裝的jdk,spark,scala等安裝包,用SSH直接拖到這個目錄即可。目錄的安裝包後面要copy到docker容器中.本人安裝完centos7後SSH端口是默認開啟的可以用命令 ps -ef|grep ssh查看SSH是否啟動(註意:docker 容器中也要安裝並自啟動SSH,否則在後面啟動Hadoop節點時候會有問題,後面建容器時具體講)
3.運行鏡像
命令: docker run --name cloud1 -h cloud1 --add-host cloud1:172.17.0.2 -it ubuntu
運行鏡像給起一個cloud1的名稱並且分配IP地址為172.17.0.2
技術分享圖片
技術分享圖片
通過命令: docker network inspect bridge可以看到container中有啟動的容器名稱以及IP地址
技術分享圖片
根據命令 docker inspect 容器名稱 |grep IPAddress 查看容器的ip地址
4.配置容器中的SSH
查看SSH狀態: service ssh status
如果沒有就安裝:
apt-get update ---更新
apt install net-tools ----如果ifconfig命令沒有安裝
apt install iputils-ping ----如果ping命令沒有安裝
apt-get install vim ----安裝vim命令
apt-get install ssh ---安裝SSH
安裝完成後命令 vim ~/.bashrc 中加入 /usr/sbin/sshd
如果ssh默認配置root無法登陸將 /etc/ssh/sshd_config中PermitRootLogin no改為yes
生成訪問密鑰
cd ~/ 切換到根目錄
ssh-keygen -t rsa -P ‘’ -f ~/.ssh/id_rsa
cd .ssh進入ssh目錄
cat id_rsa.pub >> authorized_keys
service ssh start 開啟ssh
ssh localhost date 驗證是否可以使用SSH
ssh root@cloud1 測試是否能連接成功
檢查是否安裝SSH: which ssh
Which sshd
技術分享圖片
查看SSH服務是否啟動:
ps aux |grep ssh
技術分享圖片
5.在容器 /usr/local 裏建一個java目錄放置要安裝的工具包
在liunx下而不是容器,用命令
docker cp /usr/local/java/ 容器ID:/usr/local/ 這樣就把所有java下的安 裝工具全部拷貝到容器中了(同一個路徑下)。 這裏還有一種方式 就是在啟動鏡像的時候把liunx下的/usr/local/java 目錄映射到容器中 命令:docker run -v /usr/local/java/:/usr/local -it ubuntu 或者命令 docker run -i -t -v /usr/local/java:/usr/local/java 鏡像ID /bin/bash
6.開始安裝 JDK. ZOOKEEPER, SCALA,HADOOP,SPARK
切換目錄到 /usr/local/java中,所有的安裝包都在這個此目錄下
6.1:安裝JDK:
命令: tar -xzvf jdk.xx.xx.tar.gz 解壓壓縮包
賦權: chmod 777 解壓後的jdk包
刪除壓縮包: rm -rf jdk.xx.xx.tar.gz
vim ~/.bashrc添加JDK的參數
export JAVA_HOME=/usr/local/java/jdk1.8.0_191
export PATH=$PATH:$JAVA_HOME/bin
保存退出 命令: source ~/.bashrc 讓更改後的文件生效
檢查是否安裝成功 java -version
技術分享圖片

6.2:安裝 scala
解壓: tar -zxvf scala-2.12.8.tgz
賦權: chmod 777 scala-2.12.8
刪除壓縮包:rm -rf scala-2.12.8
vim ~/.bashrc 添加scala的參數
export SCALA_HOME=/usr/local/java/scal-2.12.8
export PATH=$PATH:$SCALA_HOME/bin
保存退出 命令 source ~/.bashrc
命令檢查安裝成功否: scala -version
技術分享圖片

6.3:Zookeeper安裝
解壓: tar -zxvf zookeeper-3.4.12.tar.gz
賦權: chmod 777 zookeeper-3.4.12
刪除壓縮包: rm -rf zookeeper-3.4.12.tar.gz
vim ~/.bashrc 添加zookeeper的參數
export ZOOKEEPER_HOME=/usr/local/java/zookeeper-3.4.12
export PATH=$PATH:$ZOOKEEPER_HOME/bin
保存退出 命令 source ~/.bashrc
生成zookeeper配置文件
在zookeeper解壓包下 zookeeper-3.4.12/conf下執行命令 cp /usr/local/java/zookeeper-3.4.12/conf/zoo_sample.cfg /usr/local/java/zookeeper-3.4.12/conf/zoo.cfg

修改zoo.cfg文件
#數據存儲目錄修改為:
dataDir=/root/zookeeper/tmp (要先在root下建zookeeper目錄,tmp目錄 命令: mkdir ~/zookeeper ; mkdir ~/zookeeper/tmp)
#在最後添加Zkserver配置信息:
server.1=cloud1:2888:3888
server.2=cloud2:2888:3888
server.3=cloud3:2888:3888
在 /root/zookeeper/tmp 路徑下建文件myid 命令: touch ~/zookeeper/tmp/myid
/root/zookeeper/tmp下執行命令:echo 1 > ~/zookeeper/tmp/myid
打開vim myid 可以看到myid裏寫入了1
6.4: 安裝Hadoop
命令 tar -zxvf Hadoop-2.7.7.tar.gz
vim ~/.bashrc 添加hadoop的參數(命令: vi ~/.bashrc)
export HADOOP_HOME=/usr/local/java/hadoop-2.7.7(根據實際目錄填寫)
export PATH=$PATH:$HADOOP_HOME/bin:$HADOOP_HOME/sbin

6.4.1: 修改Hadoop啟動配置文件(/usr/local/java/hadoop-2.6.4/etc/hadoop/hadoop-env.sh):
#修改JAVA_HOME
export JAVA_HOE=/usr/local/java/jdk1.8.0_191

6.4.2:配置核心配置文件(/usr/local/java/Hadoop-2.6.4/etc/Hadoop/core-site.xml)
<property>
<name>fs.defaultFS</name>
<value>hdfs://ns1</value>
</property>
<property>
<name>hadoop.tmp.dir</name>
<value>/root/hadoop/tmp</value>
</property>
<property>
<name>ha.zookeeper.quorum</name>
<value>cloud1:2181,cloud2:2181,cloud3:2181</value>
</property>

6.4.3: 修改HDFS配置文件(/usr/local/java/Hadoop-2.6.4/etc/Hadoop/hdfs-site.xml)
<property>
<name>dfs.nameservices</name>
<value>ns1</value>
</property>
<property>
<name>dfs.ha.namenodes.ns1</name>
<value>nn1,nn2</value>
</property>
<property>
<name>dfs.namenode.rpc-address.ns1.nn1</name>
<value>cloud1:9000</value>
</property>
<property>
<name>dfs.namenode.http-address.ns1.nn1</name>
<value>cloud1:50070</value>
</property>
<property>
<name>dfs.namenode.rpc-address.ns1.nn2</name>
<value>cloud2:9000</value>
</property>
<property>
<name>dfs.namenode.http-address.ns1.nn2</name>
<value>cloud2:50070</value>
</property>
<property>
<name>dfs.namenode.shared.edits.dir</name>
<value>qjournal://cloud1:8485;cloud2:8485;cloud3:8485/ns1</value>
</property>
<property>
<name>dfs.journalnode.edits.dir</name>
<value>/root/hadoop/journal</value>
</property>
<property>
<name>dfs.ha.automatic-failover.enabled</name>
<value>true</value>
</property>
<property>
<name>dfs.client.failover.proxy.provider.ns1</name>
<value>
org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider
</value>
</property>
<property>
<name>dfs.ha.fencing.methods</name>
<value>
sshfence
shell(/bin/true)
</value>
</property>
<property>
<name>dfs.ha.fencing.ssh.private-key-files</name>
<value>/root/.ssh/id_rsa</value>
</property>
<property>
<name>dfs.ha.fencing.ssh.connect-timeout</name>
<value>30000</value>
</property>
<property>
<name>dfs.http.address</name>
<value>0.0.0.0:50070</value>
</property>

6.4.4:修改Yarn的配置文件(/usr/local/java/Hadoop-2.6.4/etc/Hadoop/yarn-site.xml)
<property>
<name>yarn.resourcemanager.hostname</name>
<value>cloud1</value>
</property>
<property>
<name>yarn.nodemanager.aux-services</name>
<value>mapreduce_shuffle</value>
</property>

6.4.5:修改maprep-site.xml 文件(/usr/local/java/Hadoop-2.6.4/etc/Hadoop/maprep-site.xml)
mv mapred-site.xml.template mapred-site.xml

vim mapred-site.xml

<property>
<name>mapreduce.framework.name</name>
<value>yarn</value>
</property>

6.4.6:修改指定DataNode和NodeManager的配置文件(/usr/local/java/Hadoop-2.6.4/etc/Hadoop/slaves)
cloud1
cloud2
cloud3

5安裝spark
命令 tar -zxvf spark-2.4.0-bin-hadoop2.7.tgz
在宿主機 ~/.bashrc 添加scala的參數(命令: vi ~/.bashrc)
export SPARK_HOME=/usr/local/java/spark-1.6.1-bin-hadoop2.6
export PATH=PATH:$SPARK_HOME/bin:$SPARK_HOME/sbin
spark啟動配置文件:
cp /usr/spark-1.6.1-bin-hadoop2.6/conf/spark-env.sh.template /usr/spark-1.6.1-bin-hadoop2.6/conf/spark-env.sh
修改spark-env.sh配置文件內容:
export SPARK_MASTER_IP=cloud1
export SPARK_WORKER_MEMORY=128m
export JAVA_HOME=/usr/local/java/jdk1.8.0_191
export SCALA_HOME=/usr/local/java/scala-2.12.8
export SPARK_HOME=/usr/local/java/spark-1.6.1-hadoop2.6
export HADOOP_CONF_DIR=/usr/local/java/hadoop-2.6.4/etc/hadoop
export SPARK_LIBRARY_PATH=$$SPARK_HOME/lib
export SCALA_LIBRARY_PATH=$SPARK_LIBRARY_PATH
export SPARK_WORKER_CORES=1
export SPARK_WORKER_INSTANCES=1
export SPARK_MASTER_PORT=7077

修改指定Worker的配置文件(/usr/local/java/spark-1.6.1-bin-hadoop2.6/conf/slaves):
cloud1
cloud2
cloud3

集群部署:
1 #提交cloud1容器,命令返回新鏡像的編號
2 docker commit cloud1
4 返回一個id
3 #為新鏡像打標簽為Spark
4 docker tag <mirror id> cloud1
將這個容器commit成一個新的image
然後用這個image運行2個容器,分別是cloud2~cloud3
#-h指定容器運行起來後的hostname
docker run --name cloud2 -h cloud2 --add-host cloud2:172.17.0.3 --add-host cloud3:172.17.0.4 --add-host cloud1:172.17.0.2 -it cloud1
docker run --name cloud3 -h cloud3 --add-host cloud3:172.17.0.4 --add-host cloud1:172.17.0.2 --add-host cloud2:172.17.0.3 -it cloud1...
#在cloud2~cloud3中分別手動修改myid
cloud2中: echo 2 > ~/zookeeper/tmp/myid 打開myid裏面就是一個2
cloud3中: echo 3 > ~/zookeeper/tmp/myid 打開myid裏面就是一個3

#啟動zookeeper集群(分別在cloud1、cloud2、cloud3上啟動zk)
~/zookeeper/bin/zkServer.sh start

#使用status查看是否啟動(cloud1到cloud3 全部啟動才能看到status)
~/zookeeper/bin/zkServer.sh status

#啟動journalnode(在cloud1上啟動所有journalnode,註意:是調用的hadoop-daemons.sh這個腳本,註意是復數s的那個腳本)
#運行jps命令檢驗,cloud1、cloud2、cloud3上多了JournalNode進程
~/hadoop/sbin/hadoop-daemon.sh start journalnode ===》每一個cloud中啟動
~/hadoop/sbin/hadoop-daemons.sh start journalnode ===》啟動的是所有的

#格式化HDFS(在bin目錄下),在cloud1上執行命令:
~/hadoop/bin/hdfs namenode -format

#格式化ZK(在cloud1上執行即可,在bin目錄下)
~/hadoop/bin/hdfs zkfc -formatZK

#啟動HDFS(在cloud1上執行)
~/hadoop/sbin/start-dfs.sh

#在cloud1上執行start-yarn.sh
~/hadoop/sbin/start-yarn.sh

#啟動spark集群
~/spark/sbin/start-all.sh
~/spark/sbin/start-master.sh ---啟動主節點
~/spark/sbin/slaves.sh --啟動所有的worker節點,slave不帶s的是單獨啟用本地worker節點

啟動完成後瀏覽器訪問 spark=>cloud1:8080 yarn=>cloud1:8088 hdfs=> cloud1:50070
註意:三個容器 cloud1, cloud2, cloud3 必須要保證SSH是開啟的,各個節點之間通訊要用到
保證每一個容器 /etc/hosts 中都有三個節點ip和名稱, 必須保證 虛擬機防火墻是關閉的

=========================================================
搭建過程中遇到的解決問題:
安裝curl命令:>sudo apt-get install curl
如果安裝curl過程中提示“Temporary failure resolving ‘archive.ubuntu.com‘”, 在/etc/resolv.conf 文件中添加 nameserver 202.96.134.133 nameserver 8.8.8.8

如果想在虛擬機中用本地ip訪問的化就得從docker容器中映射出端口:
添加端口映射 (來源:https://blog.csdn.net/hp_satan/article/details/77531794)
a, 獲取容器ip
docker inspect $container_name | grep IPAddress
b. 添加轉發規則
iptables -t nat -A DOCKER -p tcp --dport $host_port -j DNAT --to-destination $docker_ip:$docker_port
123456
刪除端口映射規則

a. 獲取規則編號
iptables -t nat -nL --line-number
b. 根據編號刪除規則
iptables -t nat -D DOCKER $num

[root@localhost ~]# iptables -t nat -A DOCKER -p tcp --dport 8080 -j DNAT --to-destination 172.17.0.2:8080
[root@localhost ~]# iptables -t nat -A DOCKER -p tcp --dport 50070 -j DNAT --to-destination 172.17.0.2:50070

liunx查看進程命令:
查看進程:
1、ps 命令用於查看當前正在運行的進程。
grep 是搜索
例如: ps -ef | grep java
表示查看所有進程裏 CMD 是 java 的進程信息
2、ps -aux | grep java
-aux 顯示所有狀態
ps

  1. kill 命令用於終止進程
    例如: kill -9 [PID]
    -9 表示強迫進程立即停止
    通常用 ps 查看進程 PID ,用 kill 命令終止進程

centos7中關閉防火墻的命令
systemctl stop firewalld.service #停止firewall
systemctl disable firewalld.service #禁止firewall開機啟動
firewall-cmd --state #查看默認防火墻狀態(關閉後顯示notrunning,開啟後顯示running)
技術分享圖片

Docker網絡問題:
docker network ls 展現docker的網絡連接方式
docker network inspect bridge 此時container中為空的
docker run --name cloud1 -h cloud1 --add-host cloud1:172.17.0.2 -it ubuntu 執行後container裏就有cloud1名稱了
systemctl restart docker
docker inspect container_name | grep IPAddress 查看容器的ip地址
Docker的Ubuntu鏡像安裝的容器無ifconfig命令和ping命令
解決:
apt-get update
apt install net-tools # ifconfig
apt install iputils-ping # ping
apt-get install vim命令
從主機復制到容器 docker cp host_path containerID:container_path
從容器復制到主機 docker cp containerID:container_path host_path
技術分享圖片
技術分享圖片

啟動容器
? 啟動容器並啟動bash(交互方式):
$docker run -i -t <image_name/continar_id> /bin/bash
? 啟動容器以後臺方式運行(更通用的方式):
$docker run -d -it image_name
ps:這裏的 image_name 包含了tag:hello.demo.kdemo:v1.0
docker start 容器ID或容器名 ----》此啟動沒有交互式
docker run -d -p 80:12345 weba:v0.1(容器名) ----》後臺線程啟動把主機的80端口和鏡像內的12345端口映射在一起
docker run -d -p 80:12345 –name web weba:v0.1(容器名) --?就是把容器名weba:v0.1的改為web
docker attach 容器名或容器ID ?一般生產環境不用此命令,進入一些web服務會一直卡無反應,猜測是監聽阻塞進入了
docker exec -it 容器ID /bin/bash 如果 /bin/bash未找到 可以改成: docker exec -it 容器ID sh

? 附著到正在運行的容器
docker attach <id、container_name>
? 進入正在運行的容器內部,同時運行bash(比attach更好用)
docker exec -t -i <id/container_name
docker關於時間問題:
統一兩者的時區有下面幾種方法
1)共享主機的localtime
創建容器的時候指定啟動參數,掛載localtime文件到容器內,保證兩者所采用的時區是一致的。

docker run -ti -d --name my-nginx -v /etc/localtime:/etc/localtime:ro docker.io/nginx /bin/bash

2)復制主機的localtime
[root@slave-1 ~]# docker cp /etc/localtime 87986863838b:/etc/

進入Centos後使用ps -ef | grep docker查看docker進程。
進入Centos後管理docker服務:
service docker start
service docker stop
service docker restart
docker守護進程的配置和操作模式:
docker -d [OPTIONS]
-d 以後臺方式運行容器。

查看網絡模式:docker network ls
查看docker裏容器的IP地址: docker inspect 容器ID | grep IPAddress

使用start命令來啟動一個容器:
docker start -a <container id|name>
docker run -it 鏡像id /bin/bash
刪除一個鏡像(我們直接刪除某個name,系統只會刪除latest標簽的那一條記錄):
Docker rmi imagesname
我們要從v1升級到v2,首先我們將導入的v2鏡像強制重命名為image:latest,命令為docker tag -f image:v2 image:latest
啟用docker run image,此時image的等價鏡像image:latest就是最新的V2鏡像。
刪除image
1:先停掉container
命令docker ps -a 查詢出容器
停止容器 docker stop 容器id(即:container id)
刪除容器 docker rm 容器id(即:container id)
2: 查看當前的images
命令 docker images
3: 刪除images
Docker rmi <image Id>

停止所有的container: docker stop $(docker ps -a -p)
刪除所有的container: docker rm $(docker ps -a -p)
刪除全部image: docker rmi $(docker images -q)
技術分享圖片
運行鏡像(鏡像id),並將宿主機/opt/soft目錄掛載到容器的/opt/soft上 :
docker run -i -t -v /opt/soft/:/opt/soft/ 9b9cb95443b5 /bin/bash
(docker run -i -t -v 宿主機文件目錄 : 容器文件目錄 鏡像id /bin/bash)
例如:
技術分享圖片

如果bashrc中配置錯誤 ,ls,ll所有命令不好使的情況下用命令: 在命令行中輸入:export PATH=/usr/bin:/usr/sbin:/bin:/sbin:/usr/X11R6/bin 這樣可以保證命令行命令暫時可以使用。

動手搭建docker並在docker容器中建spark集群