回想起第一次接触Mesos, 当时有不少困惑: "这究竟是用来作啥的?跟YARN比有什么优点?有哪些大公司在使用么?"。java
然而如今技术突飞猛进地发展, Mesos这个生态圈也开始被愈来愈多的团队熟悉关注, 像k8s,Swarm之类的重量级竞品一个个地涌现。node
在踩了或多或少的坑, 如今从新回到这个问题, 简而言之:python
Q1: 这究竟是用来作啥的?ios
通俗地讲, 就是把N台机器当作1台机器使用nginx
Q2: 跟YARN比有什么优点?git
更加通用, 不局限在数据分析领域github
Q3: 有哪些大公司在使用么?web
作技术预研的时候由于看到苹果在用, 内心倍儿踏实docker
咱们的分析团队一直都是在传统的CDH上跑Hadoop生态。对新业务评估时决定拥抱Spark, 但CDH升级困难, Spark版本滞后, 使用起来也远比Hadoop繁琐。最后咱们决定基于Mesos从头构建新的数据分析基础环境。shell
可是Mesos上缺少咱们必须的HDFS和HBase。通过讨论咱们决议了两种方案。
将HDFS,HBase和Mesos独立部署在裸机上, 以下图
(前期方案一)
但实际使用时会由于HDFS和HBase并不是在Mesos的隔离环境下运行, 与Mesos会竞争系统资源。基于这样的考虑,咱们否决了这种方案。
HDFS和HBase也运行在Mesos中。这种方案避免了上述问题, 但也意味着咱们须要本身实现这两个服务在Mesos中的部署。团队的大神担起了这个任务, 制做了HDFS和HBase的Docker镜像, 经过marathon部署在Mesos中。
(前期方案二)
基于这样的部署形式, 团队顺利地过渡到Spark生态, 让咱们的分析系统更加飞快地运转。
DC/OS可谓Mesos生态里的Cloudera。但因为其商业收费, 对于咱们这样的初创团队一直都是"可远观而不可亵玩"。
直到其开放了社区版, 咱们才得以略窥一斑。
在没有引入DC/OS以前, 对于管理Mesos集群咱们碰到如下几个痛点:
没有自动化运维脚本。新增、删除节点、变动配置均须要手工介入。
没有直观的可视化图表来查看各项运行指标。Mesos自带的界面相对比较简单,体验不佳。
没有集中的日志管理。
安装一些通用的服务比较繁琐。
经过DC/OS管理Mesos集群, 能够轻松地使用Bootstrap节点方便地管理各个节点, 其服务也都经过systemd来管理依赖, 避免了手工管理的繁琐。
经过官方的教程, 能够很方便地配置安装节点, 如下是范例:
agent_list: - 10.10.11.48 - 10.10.11.29 - 10.10.11.56 - 10.10.10.188 - 10.10.11.57 - 10.10.11.88 - 10.10.11.89 - 10.10.10.113 - 10.10.10.168 # Use this bootstrap_url value unless you have moved the DC/OS installer assets. bootstrap_url: file:///opt/dcos_install_tmp cluster_name: maxleap exhibitor_storage_backend: zookeeper exhibitor_zk_hosts: 10.10.10.125:2181,10.10.10.149:2181,10.10.10.122:2181 exhibitor_zk_path: /dcos_uat log_directory: /genconf/logs master_discovery: static master_list: - 10.10.10.187 - 10.10.10.176 - 10.10.10.164 process_timeout: 600 resolvers: - 10.10.10.156 ssh_key_path: /genconf/ssh_key ssh_port: 22 ssh_user: root oauth_enabled: 'false' telemetry_enabled: 'false' #roles: slave_public #weights: slave_public=2
UI简洁易用, 比较经常使用的一些功能大多都已包含。经过使用Universe的包管理器, 咱们能够很方便地一键安装各类常见服务。
(DC/OS图示)
DC/OS默认也给咱们安装了mesos-dns, 咱们可使用DNS的A记录轮询来实现简陋的服务发现。经过marathon部署服务如今能够直接使用服务名.marathon.mesos
直接定位服务所在节点。
在某些场合下这已经足够好用。Universe集成的HDFS也使用了DNS来定位各种型的节点, 这样带来的很大的方便就是像core-site.xml
,hdfs-site.xml
这样的配置文件就相对稳定(以前咱们使用主机hostname来管理, 当节点发生变更时须要全部程序变动配置文件)。
接下来咱们开始尝试改造以前的基础服务。
综上的几个优势, 咱们将以前Spark的HDFS切换到Universe提供的版本, 这个版本的好处是其本身实现了一个Mesos的framework来实现HA, 其数据也使用了Mesos的持久化卷。美中不足的是其使用了mesos原生的隔离, 而没有使用docker, 鉴于国内的网络环境, 其下载速度惨不忍睹。为此咱们搭建了Universe私服, 改写了全部的资源文件指向到内网, 加快了部署速度。官方的教程很详细, 这里是传送门。
对于HBase, 咱们也从新制做了docker镜像。如下是Dockerfile:
# 基于debian的oracle-jdk8 FROM 10.10.10.160:8010/zero/java:8 MAINTAINER wcai wcai@maxleap.com ENV \ HBASE_VERSION="1.2.1" \ HADOOP_VERSION="2.5.2" \ HBASE_HOME="/hbase" \ HADOOP_CONF_DIR="/etc/hadoop" \ JAVA_LIBRARY_PATH="/usr/lib/hadoop" \ HBASE_CLASSPATH="/etc/hadoop" \ HBASE_MANAGES_ZK="false" RUN \ apt-get update -y && \ apt-get install curl -y && \ mkdir -p /var/log/hbase && \ curl -o /tmp/hbase.tar.gz http://mirrors.aliyun.com/apache/hbase/${HBASE_VERSION}/hbase-${HBASE_VERSION}-bin.tar.gz && \ tar xvzf /tmp/hbase.tar.gz -C /tmp/ && \ rm -f /tmp/hbase.tar.gz && \ mv /tmp/hbase* ${HBASE_HOME} && \ rm -rf ${HBASE_HOME}/docs \ ${HBASE_HOME}/bin/*.cmd \ ${HBASE_HOME}/conf/*.cmd \ ${HBASE_HOME}/*.txt && \ curl -o /tmp/hadoop.tar.gz http://mirrors.aliyun.com/apache/hadoop/core/hadoop-${HADOOP_VERSION}/hadoop-${HADOOP_VERSION}.tar.gz && \ tar xvzf /tmp/hadoop.tar.gz -C /tmp && \ rm -f /tmp/hadoop.tar.gz && \ mv /tmp/hadoop* /tmp/hadoop && \ mv /tmp/hadoop/lib/native /usr/lib/hadoop && \ rm -rf /tmp/hadoop && \ mkdir -p ${HADOOP_CONF_DIR} && \ apt-get remove curl -y && \ apt-get clean && \ rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* WORKDIR ${HBASE_HOME} # 默认集成的hdfs配置, 也可经过marathon的uris挂载进去。 COPY ./conf/* /etc/hadoop/ ENTRYPOINT [ "bin/hbase" ]
HMaster的marathon配置范例:
{ "id": "/hbase/master", "args": [ "master", "-Dhbase.master.port=6000", "-Dhbase.master.info.port=6010", "-Dhbase.zookeeper.quorum=master.mesos", "-Dzookeeper.znode.parent=/hbase", "-Dhbase.rootdir=hdfs:///hbase", "-Dhbase.cluster.distributed=true", "start" ], "instances": 1, "cpus": 1, "mem": 2048, "container": { "type": "DOCKER", "docker": { "image": "10.10.10.160:8010/zero/hbase:1.2.1", "forcePullImage": true, "network": "HOST" } } }
HRegion的marathon配置范例:
{ "id": "/hbase/region", "args": [ "regionserver", "-Dhbase.regionserver.port=6020", "-Dhbase.regionserver.info.port=6021", "-Dhbase.zookeeper.quorum=master.mesos", "-Dzookeeper.znode.parent=/hbase", "-Dhbase.rootdir=hdfs:///hbase", "-Dhbase.cluster.distributed=true", "start" ], "instances": 4, "constraints": [["hostname", "UNIQUE"]], "cpus": 1, "mem": 1024, "container": { "type": "DOCKER", "docker": { "image": "10.10.10.160:8010/zero/hbase:1.2.1", "forcePullImage": true, "network": "HOST" } } }
以上仅为范例, 其余类型的实例也可相似启动, 如backup, thrift2, rest等, 在此略过。
另外能够进一步定制entrypoint, 启动的端口能够经过marathon管理的PORT?
来定义。甚至可让marathon给你随机安排端口。
虽然Universe自带了Spark的dispatcher服务,默认使用了dist-url的方式, 但咱们想让Spark运行时所有在docker中。(老板~ 再来几串Dockerfile)
首先是mesos基础镜像
FROM 10.10.10.160:8010/zero/java:8 MAINTAINER wcai wcai@maxleap.com # 0.28.0-2.0.16.debian81 # 0.28.1-2.0.20.debian81 # 0.28.2-2.0.27.debian81 ENV \ MESOS_PACKAGE_VERSION="0.28.1-2.0.20.debian81" \ MESOS_NATIVE_LIBRARY="/usr/lib/libmesos.so" \ MESOS_NATIVE_JAVA_LIBRARY="/usr/lib/libmesos.so" # 顺带把hdfs的native-lib也集成进去 COPY lib/* /usr/lib/ RUN \ apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv E56151BF && \ echo "deb http://repos.mesosphere.com/debian jessie main" | tee /etc/apt/sources.list.d/mesosphere.list && \ apt-get update && \ apt-get install --no-install-recommends -y --force-yes mesos=${MESOS_PACKAGE_VERSION} && \ apt-get clean && \ rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* && \ ln -snf /opt/jdk/bin/java /etc/alternatives/java CMD [ "bash" ]
而后是Spark的
FROM 10.10.10.160:8010/zero/mesos:0.28.1 MAINTAINER wcai wcai@maxleap.com ENV \ SPARK_HOME="/opt/spark" \ SPARK_VERSION="2.0.0" \ HADOOP_VERSION="2.6" RUN \ apt-get update -y && \ apt-get install curl -y && \ curl -o /tmp/spark.tar.gz http://mirrors.aliyun.com/apache/spark/spark-${SPARK_VERSION}/spark-${SPARK_VERSION}-bin-hadoop${HADOOP_VERSION}.tgz && \ tar xvzf /tmp/spark.tar.gz -C /opt && \ mv /opt/spark* /opt/spark && \ rm -rf /tmp/spark.tar.gz \ $SPARK_HOME/jars/*yarn*.jar \ $SPARK_HOME/bin/*.cmd \ $SPARK_HOME/data \ $SPARK_HOME/examples \ $SPARK_HOME/python \ $SPARK_HOME/yarn \ $SPARK_HOME/R \ $SPARK_HOME/licenses \ $SPARK_HOME/CHANGES.txt \ $SPARK_HOME/README.md \ $SPARK_HOME/NOTICE \ $SPARK_HOME/LICENSE \ $SPARK_HOME/conf/* && \ apt-get remove curl -y && \ apt-get clean && \ rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* # 若是你想加入一些本身的配置 COPY ./spark-defaults.conf $SPARK_HOME/conf/spark-defaults.conf ENV TZ=Asia/Shanghai WORKDIR $SPARK_HOME CMD [ "bash" ]
最后是spark-mesos-dispatcher的
FROM 10.10.10.160:8010/zero/spark:2.0.0 MAINTAINER wcai wcai@maxleap.com ENV \ PORT0="8081" \ PORT1="7077" \ SPARK_DISPATCHER_NAME="spark" \ ZK="master.mesos:2181" \ ZK_MESOS_ROOT="mesos" COPY ./entrypoint.sh /usr/local/bin/entrypoint CMD [ "entrypoint" ]
其中的entrypoint脚本
#! /bin/sh export PATH=$PATH:$HADOOP_PREFIX/bin if [ -z ${LIBPROCESS_IP} ]; then export LIBPROCESS_IP=$(ip addr show eth0 | grep -Eo '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' | head -1) export SPARK_LOCAL_IP=${LIBPROCESS_IP} fi if [ -z ${LIBPROCESS_IP} ]; then echo "error: LIBPROCESS_IP is blank." exit 1 fi export MESOS_MASTER="mesos://zk://${ZK}/${ZK_MESOS_ROOT}" echo "************************************************************" echo "LIBPROCESS_IP: ${LIBPROCESS_IP}" echo "MASTER: ${MESOS_MASTER}" echo "WEBUI PORT: ${PORT0}" echo "RPC PORT: ${PORT1}" echo "************************************************************" $SPARK_HOME/bin/spark-class \ org.apache.spark.deploy.mesos.MesosClusterDispatcher \ --master ${MESOS_MASTER} \ --host ${LIBPROCESS_IP} \ --port ${PORT1} \ --webui-port ${PORT0} \ --name "${SPARK_DISPATCHER_NAME}" \ --zk ${ZK} \ --properties-file ${SPARK_HOME}/conf/spark-defaults.conf
大功告成, 只须要在marathon中启动dispatcher。spark-submit时指定spark.mesos.executor.docker.image
为spark的docker镜像便可。你能够制做不一样版本的spark镜像, 随意切换。(麻麻不再用担忧我追不上spark官方的升级速度了)
Mesos的资源专供数据分析团队使用是至关浪费的。为此团队开始尝试将公司的其余服务陆续迁移进来。
公司已有的Rest API大多都是docker容器形式部署在各个服务器上。原本的计划是经过marathon部署, 使用域名作服务发现, 而后nginx反向代理到公网。但实际实施中踩了个坑。由于nginx的配置域名的upstream很成问题, 一旦指向的ip变更就会致使解析失败。尝试使用网上的各类方法(如配置resolver设置upstrem变量, 改用tengine的ngx_http_upstream_dynamic_module) 都没法完美解决这个问题。
最后团队仍是决定引入marathon-lb, 替代原先基于mesos-dns的服务发现。
marathon-lb实际上是一个HAProxy的包装, 它能动态地绑定marathon的服务。咱们以internal形式部署, 某个服务若是须要作服务发现负载匀衡, 只须要加一个label为HAPROXY_GROUP: internal
便可, 很是方便。这样最终的形态就变成以下的架构:
(部署架构)
在小范围的服务迁移测试稳定以后, 团队陆续将一些其余服务迁移过来, 也释放了一些服务器资源, 将这些空闲的服务器也从新回收归入到咱们的Mesos集群中。
在此以后, 维护这些服务变得简单便捷, 泡杯咖啡, 点点鼠标就能够轻松搞定, 运维压力减少了不少。
拥有了以上的这些基础架构服务以后, 一切均可以运转起来。但总有一些痛点须要咱们本身造轮子去解决。
当你有大量的Spark批处理做业时, 一个很头疼的事情就是如何去调度这些做业。
之前咱们经过chronos来作执行管理, 但这个工具太过简陋, 对于cluster-mode下的spark做业, 若是你想定义依赖, 则须要使用它的异步回调来通知做业已完成, 这样一来无可避免须要侵入业务代码。(程序猿表示若是要妥协强行写这些跟业务半点关系都没有的代码, 我选择狗带)
咱们须要一个零侵入的Spark通用做业流程解决方案。为此咱们本身实现了一个小项目(Armyant), 旨在解决这个问题。
总体架构很简单, 经过Activiti作流程引擎, Quartz作定时调度, Zookeeper来作状态通知:
(armyant架构图)
外加一套易用的UI, 第一个版本就能顺利跑起来。
(armyant图示1)
后续又实现了一个mesos framework, 这样也能够定义一些one-off形式的任意docker任务。接着再向上封装一下, 包装一层任意的Java服务也很方便。固然mesos生态圈其实也有不少专门为one-off形式的做业而生的工具, 如eremetic等等。
(armyant图示2)
虽然DC/OS社区版能够查看当前的运行状态, 但它没有监控报警相关的功能(天下没有免费的午饭)。目前咱们在每一个节点上部署了传统的nagios。
在接下来的阶段, 团队也会对此作进一步的探索。
DC/OS再配合mesos自带的日志其实已经很大程度上方便了查看日志的需求。甚至DC/OS自己也能够接入ELK。但咱们指望有更高级的日志分类收集, 这须要定制一些收集处理模块。团队的大神亲自操刀正在实现这些高级的功能, 随着业务的扩张,能有一个能够灵活定制的日志处理系统是颇有好处的。个人Leader也常说, 大厂和小厂的东西, 区别就在于大厂的监控报警运维系统作得很是完善易用。
文末最后, 做为一个初创小团队, 笔者以为Mesos对咱们的利好是不言而喻的。也但愿让咱们的集群更加稳定健壮, 来支撑咱们日益增加的业务系统。
技术活动预告
主题:技术分享沙龙 | 知云善用,让移动研发更快速简单
时间:2016年8月28日 周日 14:00-17:00
地点:COCOSPACE北虹桥站·上海市嘉定区鹤望路679弄2号楼一层
报名连接:http://t.cn/Rt9ooRw
做者信息
本文系力谱宿云LeapCloud旗下MaxLeap团队_数据分析组成员:蔡伟伟 【原创】
力谱宿云LeapCloud首发地址:https://blog.maxleap.cn/archi...
蔡伟伟,本科毕业于同济大学,从事Java开发多年,后端码农一枚。前后从事ETL、AdHoc报表、垂直爬虫、App制做云服务、动态用户分群等产品的设计研发工做。在互联网领域混迹多年,各方面均有所涉猎。现任MaxLeap数据分析组开发人员,负责Hadoop、Spark相关的分析系统架构设计与开发。
相关文章
做者往期佳做_曾选登CSDN头版
对移动研发相关技术/活动感兴趣的小伙伴,欢迎扫如下二维码,关注微信公众号:
活动预告
报名连接:http://t.cn/Rt9ooRw