飞驰在Mesos的涡轮引擎上

回想起第一次接触Mesos, 当时有不少困惑: "这究竟是用来作啥的?跟YARN比有什么优点?有哪些大公司在使用么?"java

然而如今技术突飞猛进地发展, Mesos这个生态圈也开始被愈来愈多的团队熟悉关注, 像k8s,Swarm之类的重量级竞品一个个地涌现。node

clipboard.png

在踩了或多或少的坑, 如今从新回到这个问题, 简而言之:python

Q1: 这究竟是用来作啥的?ios

通俗地讲, 就是把N台机器当作1台机器使用nginx

Q2: 跟YARN比有什么优点?git

更加通用, 不局限在数据分析领域github

Q3: 有哪些大公司在使用么?web

作技术预研的时候由于看到苹果在用, 内心倍儿踏实docker

Mesos在团队的变迁史


(一) 为Spark而Mesos

咱们的分析团队一直都是在传统的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

DC/OS可谓Mesos生态里的Cloudera。但因为其商业收费, 对于咱们这样的初创团队一直都是"可远观而不可亵玩"。
直到其开放了社区版, 咱们才得以略窥一斑。

在没有引入DC/OS以前, 对于管理Mesos集群咱们碰到如下几个痛点:

  1. 没有自动化运维脚本。新增、删除节点、变动配置均须要手工介入。

  2. 没有直观的可视化图表来查看各项运行指标。Mesos自带的界面相对比较简单,体验不佳。

  3. 没有集中的日志管理。

  4. 安装一些通用的服务比较繁琐。

经过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图示)

DC/OS默认也给咱们安装了mesos-dns, 咱们可使用DNS的A记录轮询来实现简陋的服务发现。经过marathon部署服务如今能够直接使用服务名.marathon.mesos直接定位服务所在节点。

在某些场合下这已经足够好用。Universe集成的HDFS也使用了DNS来定位各种型的节点, 这样带来的很大的方便就是像core-site.xml,hdfs-site.xml这样的配置文件就相对稳定(以前咱们使用主机hostname来管理, 当节点发生变更时须要全部程序变动配置文件)。

接下来咱们开始尝试改造以前的基础服务。

HDFS

综上的几个优势, 咱们将以前Spark的HDFS切换到Universe提供的版本, 这个版本的好处是其本身实现了一个Mesos的framework来实现HA, 其数据也使用了Mesos的持久化卷。美中不足的是其使用了mesos原生的隔离, 而没有使用docker, 鉴于国内的网络环境, 其下载速度惨不忍睹。为此咱们搭建了Universe私服, 改写了全部的资源文件指向到内网, 加快了部署速度。官方的教程很详细, 这里是传送门

HBase

对于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给你随机安排端口。

Spark

虽然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官方的升级速度了)

(三) marathon-lb, 你值得拥有

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便可, 很是方便。这样最终的形态就变成以下的架构:

引入marathon-lb以后的部署架构图
(部署架构)

在小范围的服务迁移测试稳定以后, 团队陆续将一些其余服务迁移过来, 也释放了一些服务器资源, 将这些空闲的服务器也从新回收归入到咱们的Mesos集群中。

在此以后, 维护这些服务变得简单便捷, 泡杯咖啡, 点点鼠标就能够轻松搞定, 运维压力减少了不少。

将来的愿景(补轮子篇)


拥有了以上的这些基础架构服务以后, 一切均可以运转起来。但总有一些痛点须要咱们本身造轮子去解决。

做业管理

当你有大量的Spark批处理做业时, 一个很头疼的事情就是如何去调度这些做业。

之前咱们经过chronos来作执行管理, 但这个工具太过简陋, 对于cluster-mode下的spark做业, 若是你想定义依赖, 则须要使用它的异步回调来通知做业已完成, 这样一来无可避免须要侵入业务代码。(程序猿表示若是要妥协强行写这些跟业务半点关系都没有的代码, 我选择狗带)

咱们须要一个零侵入的Spark通用做业流程解决方案。为此咱们本身实现了一个小项目(Armyant), 旨在解决这个问题。

总体架构很简单, 经过Activiti作流程引擎, Quartz作定时调度, Zookeeper来作状态通知:

armyant架构图
(armyant架构图)

外加一套易用的UI, 第一个版本就能顺利跑起来。

armyant1
(armyant图示1)

后续又实现了一个mesos framework, 这样也能够定义一些one-off形式的任意docker任务。接着再向上封装一下, 包装一层任意的Java服务也很方便。固然mesos生态圈其实也有不少专门为one-off形式的做业而生的工具, 如eremetic等等。

armyant1
(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头版

一个JAVA码农的Node之旅

对移动研发相关技术/活动感兴趣的小伙伴,欢迎扫如下二维码,关注微信公众号:

clipboard.png


活动预告

clipboard.png

报名连接:http://t.cn/Rt9ooRw

相关文章
相关标签/搜索