飛馳在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

相關文章
相關標籤/搜索