专业 靠谱 的软件外包伙伴

您的位置:首页 > 新闻动态 > 飞驰在Mesos系统的涡轮引擎上

飞驰在Mesos系统的涡轮引擎上

2016-08-18 14:42:35

回想起第一次接触Mesos,当时有很多困惑:“这到底是用来做啥的?跟YARN比有什么优势?有哪些大公司在使用么?”

然而现在技术日新月异地发展,Mesos这个生态圈也开始被越来越多的团队熟悉关注,像k8s、Swarm之类的重量级竞品一个个地涌现。

在踩了或多或少的坑,现在重新回到这个问题,简而言之:

Q1:这到底是用来做啥的?

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

Q2:跟YARN比有什么优势?

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

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

做技术预研的时候因为看到苹果在用,心里倍儿踏实。

Mesos在团队的变迁史


(一) 为Spark而Mesos

我们的分析团队一直都是在传统的CDH上跑Hadoop生态。对新业务评估时决定拥抱Spark,但CDH升级困难,Spark版本滞后,使用起来也远比Hadoop繁琐。最后我们决定基于Mesos从头构建新的数据分析基础环境。

但是Mesos上缺乏我们必须的HDFS和HBase。经过讨论我们决议了两种方案。

方案一

将HDFS,HBase和Mesos独立部署在裸机上,如下图

HDFS,HBase,Mesos独立部署

(前期方案一)

但实际使用时会因为HDFS和HBase并非在Mesos的隔离环境下运行,与Mesos会竞争系统资源。基于这样的考虑,我们否决了这种方案。

方案二

HDFS和HBase也运行在Mesos中。这种方案避免了上述问题,但也意味着我们需要自己实现这两个服务在Mesos中的部署。团队的大神担起了这个任务,制作了HDFS和HBase的Docker镜像, 通过marathon部署在Mesos中。

HDFS,HBase运行在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为返回首页] [打印] [返回上页]   下一篇