回想起第一次接觸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