实验环境:共三台机器,Redhat7.1操作系统,其中一台master,两台slave。三台机器上已经安装配置了Spark2.2.1(参考 Spark2.2.1安装配置)。
本文主要记录mesos安装配置的过程,以及Spark的wor在wordcount例子运行的过程。
一、mesos安装配置
尝试了两种安装方式,一种是下载mesos源码包然后自己编译安装(编译过程中有错误,暂时没有解决,虽然安装失败但是过程也贴出来吧);另一种是直接用第三方包,也就是用的yum install mesos进行的安装。
1.mesos源码编译安装过程
下载源码:mesos下载
参考官网:mesos源码编译,按照centOS7的教程安装就好。
由于实验室环境的问题,机器不能直接上网,因此开了代理,要设置好网络不然会导致编译失败。
贴一下命令:
# 解压缩下载好的源码包,不需要执行git clone那一步
tar -zxf mesos-1.7.0.tar.gz
# Fetch the Apache Maven repo file,我的编译失败就是maven会报错
wget http://repos.fedorapeople.org/repos/dchen/apache-maven/epel-apache-maven.repo -O /etc/yum.repos.d/epel-apache-maven.repo
# 为最后一步的安装很多包做点准备
yum install -y epel-release
# 为能够安装到版本正确的各种包做点准备
bash -c 'cat > /etc/yum.repos.d/wandisco-svn.repo <<EOF
[WANdiscoSVN]
name=WANdisco SVN Repo 1.9
enabled=1
baseurl=http://opensource.wandisco.com/centos/7/svn-1.9/RPMS/\$basearch/
gpgcheck=1
gpgkey=http://opensource.wandisco.com/RPM-GPG-KEY-WANdisco
EOF'
# 升级一个包,报了包冲突的错,删除掉了有冲突的包,解决问题
yum update systemd
# 安装就好
yum groupinstall -y "Development Tools"
# 重点来了,安装mesos的依赖包,最好全部都成功安装好,不然编译会出错,如果全部一起安装报错,那就有点# 耐心一个一个安装
yum install -y apache-maven python-devel python-six python-virtualenv java-1.8.0-openjdk-devel zlib-devel libcurl-devel openssl-devel cyrus-sasl-devel cyrus-sasl-md5 apr-devel subversion-devel apr-util-devel
上面是前期准备工作,接下来开始编译
# 进入到解压的mesos文件夹下
cd mesos
# 新建一个文件夹build
mkdir build
cd build
# 进行编译前的配置
../configure
# 开始编译,多个核同时编译的话加参数 make -j
make
我编译的过程中遇到的错误,还没解决,怀疑是repo源的问题,用的阿里的源,后来换成了163的源,还没尝试再次编译
[ERROR] The build could not read 1 project -> [Help 1]
[ERROR]
[ERROR] The project org.apache.mesos:mesos:1.7.0 (/home/spark/mesos/mesos-1.7.0/build/src/java/mesos.pom) has 1 error
[ERROR] Non-resolvable parent POM for org.apache.mesos:mesos:1.7.0: Could not transfer artifact org.apache:apache:pom:11 from/to alimaven (http://maven.aliyun.com/nexus/content/repositories/central/): Connect to maven.aliyun.com:80 [maven.aliyun.com/59.110.251.12, maven.aliyun.com/182.92.29.13, maven.aliyun.com/182.92.29.53, maven.aliyun.com/59.110.251.4, maven.aliyun.com/59.110.251.9, maven.aliyun.com/59.110.251.10, maven.aliyun.com/182.92.29.16, maven.aliyun.com/182.92.29.54, maven.aliyun.com/59.110.251.11, maven.aliyun.com/182.92.29.40] failed: Connection timed out (Connection timed out) and 'parent.relativePath' points at wrong local POM @ line 18, column 11 -> [Help 2]
[ERROR]
[ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
[ERROR] Re-run Maven using the -X switch to enable full debug logging.
[ERROR]
[ERROR] For more information about the errors and possible solutions, please read the following articles:
[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/ProjectBuildingException
[ERROR] [Help 2] http://cwiki.apache.org/confluence/display/MAVEN/UnresolvableModelException
make[1]: *** [java/target/mesos-1.7.0.jar] Error 1
make[1]: Leaving directory `/home/spark/mesos/mesos-1.7.0/build/src'
make: *** [all-recursive] Error 1
2.第三方的包安装配置
参考了两篇文章:CentOS 7下使用yum安装Mesos、mesos运行spark框架,还有官网的document:Running Spark on Mesos
先在master机器上进行以下安装配置,再在slave1和slave2进行一遍。
关于zookeeper的部分都不做配置,我的实验环境只有一台master机器,所以不需要zookeeper,如果有多台master,就做一下相应配置就好。
# 配置yum源
yum install http://repos.mesosphere.io/el/7/noarch/RPMS/mesosphere-el-repo-7-1.noarch.rpm
# 安装
yum install -y mesos
# 以下配置在master机器上进行
# 进入etc目录,配置mesos-master
cd /etc/default
vi mesos-master
# 只有一个master所以不需要zookeeper,去掉一行zk=,加入以下内容,ip修改为自己的地址
PORT=5050
IP=172.19.0.XXX
# 同一个目录下,配置mesos-slave
IP=172.19.0.XXX
MASTER=172.19.0.XXX:5050/mesos
ISOLATION=cgroups/cpu,cgroups/mem,docker/runtime,filesystem/linux
# 进入/usr/etc/mesos目录下,进行配置
cd /usr/etc/mesos
cat mesos-agent-env.sh.template > mesos-agent-env.sh
cat mesos-deploy-env.sh.template > mesos-deploy-env.sh
cat mesos-master-env.sh.template > mesos-master-env.sh
cat mesos-slave-env.sh.template > mesos-slave-env.sh
# 配置mesos-master,主要配置log目录和work目录
vi mesos-master-env.sh
# 加入内容,其实也可以不加,我设置的目录就是mesos默认的目录
export MESOS_log_dir=/var/log/mesos
# 配置mesos-slave-env.sh和mesos-agent-env.sh,相同的配置
vi mesos-slave-env.sh
# 加入以下内容
export MESOS_log_dir=/var/log/mesos
export MESOS_work_dir=/var/run/mesos
export MESOS_master=172.19.0.XXX:5050
export MESOS_isolation=cgroups
# 添加masters文件并经master信息加进去:
vi masters
master
# 添加slaves信息
vi slaves
slave1
slave2
在master机器上启动mesos,此时没有执行spark中的start-mesos-dispatcher.sh,所以启动起来了三台机器,分别是master、slave1和slave2,如果执行了$SPARK_HOME/sbin/start-mesos-dispatcher.sh文件,则只会启动两台机器slave1和slave2
systemctl start mesos-master.service
systemctl start mesos-slave.service
启动成功后在浏览器中打开网页master:5050,这里需要做一些配置,首先在服务器上的/etc/hosts文件中要配置主机ip和主机名,如果像我一样是在Windows中通过xshell连接完成上述安装配置,则还需要在Windows中的C:\Windows\System32\drivers\etc\hosts中配置master及其对应的ip地址,也顺便配置一下slave及其对应的ip地址,这样就能在Windows中打开mesos网页了,其中Agent页面中有启动了的slave机器就表示成功安装启动成功了。
二、Running Spark on Mesos
参考官方文档:Running Spark on Mesos
首先spark一定要已经安装好,sparkhome等环境变量都要配置好。
需要做的配置非常简单,
# 编辑spark-env.sh,加入以下内容
export MESOS_NATIVE_LIBRARY=/usr/local/lib/libmesos.so
# export SPARK_EXECUTOR_URI=hdfs://master:9000/spark-2.2.1-bin-hadoop2.6.tgz
但是世上哪有什么简单不简单(摔),我被卡住了,卡了三天,第一行就是配置mesos的库,第二行是配置一个URI,这个URI必须是slave机器能够访问到的,因为slave机器要根据这个URI去找到spark二进制包,从而slave机器上也可以启动executor跑spark的task,我在这里做了上述配置,但是报错:
I1228 11:46:05.096580 19494 fetcher.cpp:225] Fetching URI 'hdfs://master:9000/spark-2.2.1-bin-hadoop2.6.tgz' E1228 11:46:05.200762 19494 fetcher.cpp:613] EXIT with status 1: Failed to fetch 'hdfs://master:9000/spark-2.2.1-bin-hadoop2.6.tgz': Failed to create HDFS client: Hadoop client is not available, exit status: 32512 Failed to synchronize with agent (it's probably exited)
所以就暂时没有解决掉这个错误,不明白为什么mesos不能访问hdfs,有人说是不能以root用户的身份访问,我换成拥有root权限的普通用户也还是报错,只好曲线救国,搞清楚这个SPARK_EXECUTOR_URI参数的作用,查看spark运行环境参数,发现这么一个参数:
spark.mesos.executor.home | driver side SPARK_HOME | 设置安装在Mesos的executor上的Spark的目录。默认情况下,executors将使用driver的Spark本地(home)目录,这个目录对它们不可见。注意,如果没有通过spark.executor.uri 指定Spark的二进制包,这个设置才起作用 |
我已经配置好sparkhome等等环境变量,所以是不是可以不配置SPARK_EXECUTOR_URI,这样slave上的executor就会用默认的spark的环境,试了一下,果然成功了,slave1机器上也可以成功执行wordcount作业了,yeah~
作业提交命令:
spark-submit --master mesos://master:5050 --name spark-mesos-wordcount --class wordcount /home/spark/spark-2.2.1-bin-hadoop2.6/input/spark-mesos-wordcount.jar hdfs://master:9000/wordcount/input/
执行作业的过程中有几个master机器中重要的目录需要注意,查看mesos日志:/var/log/mesos,作业执行日志:/var/lib/mesos/slaves,executor的执行日志就在这文件夹下,不过也可以直接在网页中查看,sanbox中的stderr就是从这个文件夹下读取日志并显示在网页中。
最后贴一下wordcount代码,其实就是从spark的examples文件夹下拷贝出来的代码:
import scala.Tuple2;
import org.apache.spark.api.java.JavaPairRDD;
import org.apache.spark.api.java.JavaRDD;
import org.apache.spark.sql.SparkSession;
import java.util.Arrays;
import java.util.List;
import java.util.regex.Pattern;
public class wordcount
{
private static final Pattern SPACE = Pattern.compile(" ");
public static void main(String[] args)
{
if (args.length < 1) {
System.err.println("Usage: JavaWordCount <file>");
System.exit(1);
}
SparkSession spark = SparkSession
.builder()
.appName("JaWordCount")
.getOrCreate();
JavaRDD<String> lines = spark.read().textFile(args[0]).javaRDD();
JavaRDD<String> words = lines.flatMap(s -> Arrays.asList(SPACE.split(s)).iterator());
JavaPairRDD<String, Integer> ones = words.mapToPair(s -> new Tuple2<>(s, 1));
JavaPairRDD<String, Integer> counts = ones.reduceByKey((i1, i2) -> i1 + i2);
List<Tuple2<String, Integer>> output = counts.collect();
for (Tuple2<?,?> tuple : output) {
System.out.println(tuple._1() + ": " + tuple._2());
}
spark.stop();
}
}