马踏飞燕——奔跑在Docker上的Spark
目录
- 为什么要在Docker上搭建Spark集群
- 网络拓扑
- Docker安装及配置
- ssh安装及配置
- 基础环境安装
- Zookeeper安装及配置
- Hadoop安装及配置
- Spark安装及配置
- 集群部署
- 总结
- 参考资料
1 为什么要在Docker上搭建Spark集群
他:为什么要在Docker上搭建Spark集群啊?
我:因为……我行啊!
MR和Spark都提供了local模式,即在单机上模拟多计算节点来执行任务。但是,像我这等手贱的新手,怎么会满足于“模拟”?很容易想到在单机上运行多个虚拟机作为计算节点,可是考虑到PC的资源有限,即使能将集群运行起来,再做其他的工作已经是超负荷了。Docker是一种相比虚拟机更加轻量级的虚拟化解决方案,所以在Docker上搭建Spark集群具有可行性。
2 网络拓扑
搭建一个有意义的小规模集群,我选择了3台服务器作为Spark计算节点(Worker)。集群中光有计算节点还不够,这3台服务器同时也作为分布式文件系统(HDFS)的数据节点(DataNode)。指定了哪些服务器用来计算,哪些用来存储之后,我们还需要指定来管理计算和存储的主节点。一个简单方案:我们可以让cloud1作为管理计算节点的主节点(Master),同时它也作为管理数据节点的主节点(NameNode)。
很容易看到简单方案不够完美:首先,要是cloud1作为NameNode宕机,整个分布式文件系统则无法工作。此时,我们应当采用基于HA的HDFS方案:由多个NameNode共同管理DataNode,但是只有一个NameNode处于活动(Active)状态,当活动的NameNode无法工作时,则需要其他NameNode候补。这里至少涉及2个关键技术:
- 如何共享NameNode的信息(EditLog)?NameNode存储的信息包括但不限于:数据在各DataNode上如何存储,哪些DataNode是可用的。所以,当活动的NameNode无法工作时,应当将这些信息传递给下一个被选中的NameNode。与其传递,不如所有的NameNode共享这些信息。这些信息将被分布式地存储在JournalNode上。在本集群中,我们使用所有3台服务器都作为JournalNode。cloud1和cloud2作为NameNode。
- 如何确保只有一个NameNode是活动的?当活动的NameNode无法工作时,如何确定下一个活动的Namenode?Zookeeper可以解决这两个问题,在本集群中,3台服务器都作为Zkserver节点。
再者,选用cloud1作为Master来管理计算(standalone)的方式对资源的利用率不比Yarn方式。所以,在本集群中选用cloud1做为ResourceManager,3台服务器都作为NodeManager)。
改进后的集群描述如下:
节点 | Zkserver | NameNode | JournalNode | ResourceManager | NodeManager |
Master |
Worker |
cloud1 | √ | √ | √ | √ | √ | √ | √ |
cloud2 | √ | √ | √ | × | √ | × | √ |
cloud3 | √ | × | √ | × | √ | × | √ |
3 Docker安装及配置
Docker有Windows/Mac/Linux版本。起初我处于对Docker的误解选择了Windows版本,Docker的核心程序必须运行在Linux上,故Windows版本的Docker实际上是利用VirtualBox运行着一个精简的Linux,然后在此Linux上运行Docker,最后在Docker上运行安装好应用的镜像。好家伙,盗梦空间!最终,我选择在CentOS上安装Linux版本的Docker。关于Docker,我们需要理解一个重要的概念:容器(Container)。容器是镜像运行的场所,可以在多个容器中运行同一个镜像。
Docker安装好之后,我们启动Docker服务:
1 systemctl start docker.service
我们可以拉一个Ubuntu镜像,基于该镜像我们搭建Spark集群:
1 docker pull ubuntu
下载好镜像到本地后,我们可以查看镜像:
1 docker images
使用run命令,创建一个容器来运行镜像:
1 docker run -it ubuntu
使用ps命令查看容器:
1 docker ps -a
使用commit命令来将容器提交为一个镜像:
1 docker commit <container id|name>
使用tag命令来为一个镜像打标签:
1 docker tag <mirror id> <tag>
使用start命令来启动一个容器:
1 docker start -a <container id|name>
在掌握了以上操作后,在Docker上搭建Spark集群的技术路线如下:
4 ssh安装及配置
试想一下如何启动集群?手动去每个节点启动相应的服务?这显然是不合理的。HDFS,Yarn,Spark都支持单命令启动全部节点。在某个节点上执行的命令是如何发送至其他节点的呢?ssh服务帮助实现这一功能。关于ssh我们需要知道其分为服务端和客户端,服务端默认监听22号端口,客户端可与服务端建立连接,从而实现命令的传输。
docker服务启动后,可以看到宿主机上多了一块虚拟网卡(docker0),在我的机器中为172.17.0.1。启动容器后,容器的IP从172.17.0.2开始分配。我们不妨为集群分配IP地址如下:
域名 | IP |
cloud1 | 172.17.0.2 |
cloud2 | 172.17.0.3 |
cloud3 | 172.17.0.4 |
关闭所有容器后,新建一个容器,命名为cloud1:
1 #新建容器时需要指定这个容器的域名以及hosts文件 2 #参数: 3 #name:容器名称 4 #h:域名 5 #add-host:/etc/hosts文件中的域名与IP的映射 6 docker --name cloud1 -h cloud1 --add-host cloud1:172.17.0.2 --add-host cloud2:172.17.0.3 --add-host cloud3:172.17.0.4 -it ubuntu
在容器cloud1中通过apt工具来安装ssh:
1 apt-get install ssh
往~/.bashrc中加入ssh服务启动命令:
1 /usr/sbin/sshd
客户端不能任意地与服务端建立连接,或通过密码,或通过密钥认证。在这里我们使用密钥认证,生成客户端的私钥和公钥:
1 #私钥(~/.ssh/id_rsa)由客户端持有 2 #公钥(~/.ssh/id_rsa.pub)交给服务端 3 #已认证的公钥(~/.ssh/authorized_keys)由服务端持有,只有已认证公钥的客户端才能连接至服务端 4 #参数: 5 #t:加密方式 6 #P:密码 7 ssh-keygen -t rsa -P ""
根据技术路线,由cloud1容器提交的镜像将生成cloud2容器和cloud3容器。要实现cloud1对cloud2和cloud3的ssh密钥认证连接,其实只要实现cloud1对本身的连接就可以了:
1 cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys
测试是否能连接成功:
1 ssh root@cloud1
5 基础环境安装
Java与Scala版本需要与其他软件的版本相匹配:
软件 | 版本 |
Java | 1.8.0_77 |
Scala | 2.10.6 |
Zookeeper | 3.4.8 |
Hadoop | 2.6.4 |
Spark | 1.6.1 |
Java与Scala安装包下载后,均解压在/usr目录下。在~/.bashrc中添加环境变量:
1 export JAVA_HOME=/usr/jdk1.8.0_77 2 export PATH=$PATH:$JAVA_HOME/bin 3 export SCALA_HOME=/usr/scala-2.10.6 4 export PATH=$PATH:$SCALA_HOME/bin
6 Zookeeper安装及配置
Zookeeper安装包下载后,解压在/usr目录下。在~/.bashrc中添加环境变量:
1 export ZOOKEEPER_HOME=/usr/zookeeper-3.4.8 2 export PATH=$PATH:$ZOOKEEPER_HOME/bin
生成Zookeeper配置文件:
1 cp /usr/zookeeper-3.4.8/conf/zoo_sample.cfg /usr/zookeeper-3.4.8/conf/zoo.cfg
修改Zookeeper配置文件:
1 #数据存储目录修改为: 2 dataDir=/root/zookeeper/tmp 3 #在最后添加Zkserver配置信息: 4 server.1=cloud1:2888:3888 5 server.2=cloud2:2888:3888 6 server.3=cloud3:2888:3888
设置当前Zkserver信息:
1 #~/zookeeper/tmp/myid文件中保存的数字代表本机的Zkserver编号 2 #在此设置cloud1为编号为1的Zkserver,之后生成cloud2和cloud3之后还需要分别修改此文件 3 echo 1 > ~/zookeeper/tmp/myid
7 Hadoop安装及配置
Hadoop安装包下载后,解压在/usr目录下。在~/.bashrc中添加环境变量:
1 export HADOOP_HOME=/usr/hadoop-2.6.4 2 export PATH=$PATH:$HADOOP_HOME/bin:$HADOOP_HOME/sbin
修改Hadoop启动配置文件(/usr/hadoop-2.6.4/etc/hadoop/hadoop-env.sh):
1 #修改JAVA_HOME 2 export JAVA_HOME=/usr/jdk1.8.0_77
修改核心配置文件(/usr/hadoop-2.6.4/etc/hadoop/core-site.xml):
参数 | 说明 |
fs.defaultFS | 默认的文件系统 |
hadoop.tmp.dir | 临时文件目录 |
ha.zookeeper.quorum | Zkserver信息 |
1 <property> 2 <name>fs.defaultFS</name> 3 <value>hdfs://ns1</value> 4 </property> 5 <property> 6 <name>hadoop.tmp.dir</name> 7 <value>/root/hadoop/tmp</value> 8 </property> 9 <property> 10 <name>ha.zookeeper.quorum</name> 11 <value>cloud1:2181,cloud2:2181,cloud3:2181</value> 12 </property>
修改HDFS配置文件(/usr/hadoop-2.6.4/etc/hadoop/hdfs-site.xml):
参数 | 说明 |
dfs.nameservices | 名称服务,在基于HA的HDFS中,用名称服务来表示当前活动的NameNode |
dfs.ha.namenodes.<nameservie> | 配置名称服务下有哪些NameNode |
dfs.namenode.rpc-address.<nameservice>.<namenode> | 配置NameNode远程调用地址 |
dfs.namenode.http-address.<nameservice>.<namenode> | 配置NameNode浏览器访问地址 |
dfs.namenode.shared.edits.dir | 配置名称服务对应的JournalNode |
dfs.journalnode.edits.dir | JournalNode存储数据的路径 |
1 <property> 2 <name>dfs.nameservices</name> 3 <value>ns1</value> 4 </property> 5 <property> 6 <name>dfs.ha.namenodes.ns1</name> 7 <value>nn1,nn2</value> 8 </property> 9 <property> 10 <name>dfs.namenode.rpc-address.ns1.nn1</name> 11 <value>cloud1:9000</value> 12 </property> 13 <property> 14 <name>dfs.namenode.http-address.ns1.nn1</name> 15 <value>cloud1:50070</value> 16 </property> 17 <property> 18 <name>dfs.namenode.rpc-address.ns1.nn2</name> 19 <value>cloud2:9000</value> 20 </property> 21 <property> 22 <name>dfs.namenode.http-address.ns1.nn2</name> 23 <value>cloud2:50070</value> 24 </property> 25 <property> 26 <name>dfs.namenode.shared.edits.dir</name> 27 <value>qjournal://cloud1:8485;cloud2:8485;cloud3:8485/ns1</value> 28 </property> 29 <property> 30 <name>dfs.journalnode.edits.dir</name> 31 <value>/root/hadoop/journal</value> 32 </property> 33 <property> 34 <name>dfs.ha.automatic-failover.enabled</name> 35 <value>true</value> 36 </property> 37 <property> 38 <name>dfs.client.failover.proxy.provider.ns1</name> 39 <value> 40 org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider 41 </value> 42 </property> 43 <property> 44 <name>dfs.ha.fencing.methods</name> 45 <value> 46 sshfence 47 shell(/bin/true) 48 </value> 49 </property> 50 <property> 51 <name>dfs.ha.fencing.ssh.private-key-files</name> 52 <value>/root/.ssh/id_rsa</value> 53 </property> 54 <property> 55 <name>dfs.ha.fencing.ssh.connect-timeout</name> 56 <value>30000</value> 57 </property>
修改Yarn的配置文件(/usr/hadoop-2.6.4/etc/hadoop/yarn-site.xml):
参数 | 说明 |
yarn.resourcemanager.hostname | RescourceManager的地址,NodeManager的地址在slaves文件中定义 |
1 <property> 2 <name>yarn.resourcemanager.hostname</name> 3 <value>cloud1</value> 4 </property> 5 <property> 6 <name>yarn.nodemanager.aux-services</name> 7 <value>mapreduce_shuffle</value> 8 </property>
修改指定DataNode和NodeManager的配置文件(/usr/hadoop-2.6.4/etc/hadoop/slaves):
1 cloud1 2 cloud2 3 cloud3
8 Spark安装及配置
Spark安装包下载后,解压在/usr目录下。在~/.bashrc中添加环境变量:
1 export SPARK_HOME=/usr/spark-1.6.1-bin-hadoop2.6 2 export PATH=$SPARK_HOME/bin:$SPARK_HOME/sbin:$PATH
Spark启动配置文件:
1 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启动配置文件(/usr/spark-1.6.1-bin-hadoop2.6/conf/spark-env.sh):
参数 | 说明 |
SPARK_MASTER_IP | Master的地址,Worker的地址在slaves文件中定义 |
1 export SPARK_MASTER_IP=cloud1 2 export SPARK_WORKER_MEMORY=128m 3 export JAVA_HOME=/usr/jdk1.8.0_77 4 export SCALA_HOME=/usr/scala-2.10.6 5 export SPARK_HOME=/usr/spark-1.6.1-hadoop2.6 6 export HADOOP_CONF_DIR=/usr/hadoop-2.6.4/etc/hadoop 7 export SPARK_LIBRARY_PATH=$$SPARK_HOME/lib 8 export SCALA_LIBRARY_PATH=$SPARK_LIBRARY_PATH 9 export SPARK_WORKER_CORES=1 10 export SPARK_WORKER_INSTANCES=1 11 export SPARK_MASTER_PORT=7077
修改指定Worker的配置文件(/usr/spark-1.6.1-bin-hadoop2.6/conf/slaves):
1 cloud1 2 cloud2 3 cloud3
9 集群部署
在宿主机上提交cloud1容器为新的镜像,并打其标签为Spark:
1 #提交cloud1容器,命令返回新镜像的编号 2 docker commit cloud1 3 #为新镜像打标签为Spark 4 docker tag <mirror id> Spark
基于Spark镜像创建cloud2和cloud3容器:
1 docker --name cloud2 -h cloud2 --add-host cloud1:172.17.0.2 --add-host cloud2:172.17.0.3 --add-host cloud3:172.17.0.4 -it Spark 2 docker --name cloud3 -h cloud3 --add-host cloud1:172.17.0.2 --add-host cloud2:172.17.0.3 --add-host cloud3:172.17.0.4 -it Spark
还记得之前提到的cloud2和cloud3的当前Zkserver还未配置吗?分别在cloud2和cloud3容器中修改Zookeeper配置:
1 #在cloud2执行 2 echo 2 > ~/zookeeper/tmp/myid 3 #在cloud3执行 4 echo 3 > ~/zookeeper/tmp/myid
在所有节点启动Zkserver(Zkserver并不是用ssh启动的,呵呵):
1 zkServer.sh start
在所有节点查看Zkserver运行状态:
1 #显示连接不到Zkserver的错误,可稍后查看 2 #Master表示主Zkserver,Follower表示从Zkserver 3 Zkserver.sh status
初始化其中一个NameNode,就选cloud1吧:
1 #格式化zkfc 2 hdfs zkfc -formatZK 3 #格式化NameNode 4 hdfs namenode -format
在cloud1启动HDFS,Yarn,Spark:
1 #启动NameNode,DataNode,zkfc,JournalNode 2 start-dfs.sh 3 #启动ResouceManager,NodeManager 4 start-yarn.sh 5 #启动Master,Worker 6 start-all.sh
使用jps命令查看各节点服务运行情况:
1 jps
还可以登录web管理台来查看运行状况:
服务 | 地址 |
HDFS | cloud1:50070 |
Yarn | cloud1:8088 |
Spark | cloud1:8080 |
10 总结
- 环境搭建切不可知其然,但不知其所以然
- 明确自己的需求是什么,不可能一开始就弄懂所有配置项,掌握一个最小的知识集就好
11 参考资料
- 在Docker中从头部署自己的Spark集群
- Docker (软件)
- HDFS-HA的配置-----自动Failover
- Spark:Yarn-cluster和Yarn-client区别与联系
- Installation On CentOS
转载于:https://www.cnblogs.com/jasonfreak/p/5391190.html
马踏飞燕——奔跑在Docker上的Spark相关推荐
- 使用docker安装部署Spark集群来训练CNN(含Python实例)
使用docker安装部署Spark集群来训练CNN(含Python实例) 本博客仅为作者记录笔记之用,不免有很多细节不对之处. 还望各位看官能够见谅,欢迎批评指正. 博客虽水,然亦博主之苦劳也. 如需 ...
- 在阿里云Serverless K8S集群上部署Spark任务并连接OSS(详细步骤)
在阿里云ASK集群上部署Spark任务并连接OSS 简介 ASK是阿里云的一个产品,属于Serverless Kubernetes 集群,这次实验是要在ASK集群上运行Spark计算任务(以WordC ...
- 【吐血经验】在 windows 上安装 spark 遇到的一些坑 | 避坑指南
在 windows 上安装 spark 遇到的一些坑 | 避坑指南 最近有个活:给了我一个阿里云桌面(windows 10系统),让我在上面用 scala + spark 写一些东西. 总是报错不断, ...
- docker 上传到自己的容器
使用 docker commit 命令来提交更新后的副本: sudo docker commit -m "swq Added" -a "Docker New" ...
- Docker上的虚拟网络-Weave Net
2019独角兽企业重金招聘Python工程师标准>>> Weave Net( https://www.weave.works )是Docker上的虚拟网络,可以将分布式的Docker ...
- DOCKER上运行DOTNET CORE
DOCKER上运行DOTNET CORE 原文:DOCKER上运行DOTNET CORE 下载microsoft/dotnet镜像 运行命令: docker pull microsoft/dotnet ...
- 把AspDotNetCoreMvc程序运行在Docker上-part2:修改容器以及发布镜像
在上一个part<把AspDotNetCoreMvc程序运行在Docker上-part1>,已经将成功将aspdotnetcore程序运行在两个不同的容器中,目前两个容器的内容完全相同,只 ...
- java客户端运行hadoop_JAVA客户端连接部署在docker上的hdfs
docker上已经成功部署了hdfs应用,jps命令也显示了namenode和datanode启动正常.浏览器显示 宿主机ip:50070 页面 我在eclipse使用java连接hdfs,代码如下: ...
- .NET Core 3.0 部署在docker上运行
自从.NET Core3.0发布之后,写了几篇关于.NET Core 3.0的文章,有助于你快速入门.NET Core3.0. 本篇文章主要讲解如何一步步创建一个mvc项目,然后发布并部署在Docke ...
- 解决微服务在docker上部署后无法连接数据库的问题
在利用docker部署完应用程序后,就接着考虑如何将程序连接到数据库. 但是过程中发现一些问题: 本地程序在打包后连接的是本地的数据库,在服务器上部署之后必须提供相同的环境才能部署成功. 这里博主用的 ...
最新文章
- pyspark常用API
- window.setTimeout() 和 window.setInterval() 使用说明
- Ubuntu下面的Keras可视化+权重维度获取-Netron的安装使用
- java Switch里面的类型问题
- 三步教你解决Invalid bound statement (not found): com.xxx.dao.xxxDao.selectByxx错误!!!!很简单
- 嘉年华回顾丨李圣陶带你了解阿里巴巴智能化运维的奥秘
- Node.js下载安装及各种npm、cnpm、nvm、nrm配置(保姆式教程—提供全套安装包)—cnpm的安装与配置(3)
- java1.6升级1.7_jdk从1.6升级到1.7可能会遇到的Version问题
- 【BZOJ1475】方格取数 [最小割]
- 常用网络协议的端口号
- bp神经网络matlab feedfollownet,BP神经网络模型:Matlab
- Vue/vant——使用阿里巴巴矢量图引入图标
- 惠普暗影精灵2 Mojave(几乎完美黑苹果)
- html嵌入百度地图无法显示
- 2022-07-04-5万字长文说清楚到底什么是“车规级”
- linux 系统管理员l,系统管理员的 SELinux 指南
- Echarts 学习系列(3)-Echarts动态数据交互
- STM32F103最小系统原理图
- 雷军:只要不让公司翻船 你就能去做
- 带你玩转IntelliJ IDEA操作手册
热门文章
- moss 自定义文档库文档图标
- oracle 自增字段设置
- jQuery设置iframe的高度根据页面内容自适应
- akamai 指纹 和 akamai BMP 移动端sensor 风控分析
- Redis 彻底禁用RDB持久化
- oracle 表 队列,如何将复制队列表移出系统(SYSTEM)表空间
- python对于一元线性回归模型_Python|机器学习-一元线性回归
- (day 27 - 递归分治 )剑指 Offer 33. 二叉搜索树的后序遍历序列
- 二叉树的右视图 python_【leetcode刷题】T128-二叉树的右视图
- python requests text content_对python requests的content和text方法的区别详解