暴走漫畫的Docker實踐

jopen 9年前發布 | 36K 次閱讀 Docker

本次主要分享Docker在暴漫中的應用主要包括:開發環境的Service搭建,代碼托管、持續集成、Docker鏡像等若干Support服務、部分微服務以及整個數據服務系統。

暴走漫畫是一家文化傳媒公司。公司除了有若干視頻娛樂節目,還有相應的社區網站及移動APP。流量UV是200萬/天左右,PV大概是千萬級別。為了更加有效地運營以及推薦用戶個性化,2015年成立了數據部,負責暴漫的數據分析和數據挖掘相關服務。

暴漫沒有自己的服務器,是使用的國內某云服務。暴漫的后端主要是基于Ruby開發。也有基于Go、Python的一些微服務。

Docker在暴漫中的應用主要包括:

  • 開發環境的Service搭建
  • 代碼托管,持續集成,Docker鏡像,等若干Support服務
  • 部分微服務以及整個數據服務系統
  • </ul>
    所以今天的內容是一些中小規模以及國內云服務下的Docker實踐的相關心得,主要包括在數據服務的架構及Docker化的部署。

    1. 簡單介紹下開發環境以及Support服務Docker應用

    由于開發環境主要是Mac,也有少量Ubuntu和Windows,所以主要采用Vagrant+Docker方式。 將微服務做成鏡像,在 Vagrant 中起相應的容器,把端口暴露給 Host(Vagrant),本地跑 Ruby(on Rails)。

    Support 服務的話,其他都很簡單,只有持續集成介紹下。我們用的GitLab CI。GitLab CI支持將 task 跑在Docker Container 里面,所以我們為不同的項目準備不同的測試環境(鏡像)以及外部依賴(eg. MySQL、Redis),然后在對應的Container里面跑測試。

    關于部署的話,我們平時的開發在develop分支,一旦向Masters分支合并后,會觸發部署的task。 部署的 task 跑在特定的Container里面,這個Container共享了 Host 的docker unix sock文件,可以執行docker build、docker push等命令。

    關于開發環境和Support服務的Docker應用,因為不是今天的重點,并且前面也有很多朋友做過類似的介紹,所以先簡單介紹到這里。

    2. 微服務和數據服務系統的Docker應用

    今年我們做了很多微服務的嘗試,例如消息推送,推薦系統,反垃圾系統,數據分析系統,視頻抓取等等若干子系統的拆分上線。 雖然過程是痛苦的,但是結果卻是令人欣慰的。這些微服務,幾乎都是基于Docker的。

    2.1 Rails +Docker化的微服務

    整體來說,我們是個混合的架構,Rails是正常的跑在云主機中的,微服務跑在Docker中。為了協調好各方,我們對基礎服務做了一點小小的調整。

    這里不得不說說我做架構的一點心得。好的架構除了能滿足業務需求,還要是與特定的團隊,特定的資源所配套的。在暴漫,由于技術力量有限,開發排期滿,所以我都是盡量采用“非侵入式”的方案,這在后面的數據服務的構建中也有體現。

    首先,我們給所有的機器都裝上了Docker。 其次,我們搭建了一個 etcd集群,將所有的云主機都納入了etcd集群。而etcd也是跑Docker里的。

    為了方便的跑起來etcd,我們寫了個一套bash+Python的腳本(Python 的腳本也是跑在Docker里的),然后所有的機器直接訪問本機IP可以訪問和操作etcd。

    這里插一句,我們沒有去折騰如何讓Docker跨主機組網,而是直接采用映射到host的方式。一方面國內云主機只能這么干。另一方面,我們之前 使用云主機也是單個主機特定用途的。 另外,在生產環境中,我們大量的使用了shell + etcd來啟動Docker Container的方式。可以給大家看個 etcd 的啟動腳本。這個script放到最初的機器上就可以方便地啟動起來etcd 集群。
    #!/bin/sh

    pull pycsa docker image

    docker pull xxxx/pycsa:latest

    nodes list to init the cluster

    ClusterNodes=$(docker run —rm \ -v .:/data \ xxxx/pycsa:latest \ python initial-cluster.py getnodes)

    get host ip

    HostIP=$(ifconfig eth0 | awk '/\&amp;amp;amp;amp;amp;amp;amp;lt;inet\>/ { print $2}' | sed 's/addr://g')

    get the etcd node name

    EtcdName=$(docker run —rm \ -v .:/data \ xxxx/pycsa:latest \ python initial-cluster.py getname ${HostIP})

    create dir structure

    EtcdData=/data/etcd/data mkdir -p ${EtcdData}

    pull etcd docker image

    docker pull quay.io/coreos/etcd:latest

    create etcd container

    docker run -d \ -v /usr/share/ca-certificates/:/etc/ssl/certs \ -v ${EtcdData}:/data \ -p 4001:4001 -p 2380:2380 -p 2379:2379 \ —name etcd quay.io/coreos/etcd:latest \ -name ${EtcdName} \ -data-dir /data \ -advertise-client-urls http://${HostIP}:2379,http://${HostIP}:4001 \ -listen-client-urls http://0.0.0.0:2379,http://0.0.0.0:4001 \ -initial-advertise-peer-urls http://${HostIP}:2380 \ -listen-peer-urls http://0.0.0.0:2380 \ -initial-cluster-token bzetcd-cluster \ -initial-cluster ${ClusterNodes} \ -initial-cluster-state new</pre>
    解釋下,initial-cluster.py 是個Python的腳本,跑在一個pycassa的容器里,這個容器有Python環境以及相關的package這樣原來的服務幾乎不受任何影響,我們可 以利用 etcd+Docker+Shell Script來組建新的服務。

    2.2 數據服務

    我們的數據服務包括數據分析和數據挖掘兩大塊。數據分析主要是為了給運營提供量化的效果評估以及指導。數據挖掘則包括推薦,反垃圾等。

    數據服務的基礎是數據流,即:數據收集->數據分發->數據處理<->數據存儲。

    先給大家看個整體的架構圖,由于本人不擅作圖,所以直接用手畫的,還請見諒。。

    暴走漫畫的Docker實踐

    首先數據收集部分,就像之前說的,我盡量采用“非侵入式”的方案,所以,我們的整個數據收集都是基于日志的。我們在每個應用服務器上裝了 Logstash(跑在Docker中)來收集各個應用服務器的日志,然后打到Kafka(跑在Docker 中)里,給不同的用途使用。

    一份COPY 直接由Kafka一端的Logstash存儲到Elasticsearch(跑在Docker中)中。 一份COPY 經過Spark(跑在Docker中)Stream做實時處理(包括一些特定日志的提取),然后將處理的結果存儲在 Elasticsearch 里 還有一份 COPY 直接存儲到 HDFS(由云服務商提供)。

    這里有個小問題,比如有些數據本身日志里并沒有,比如用戶的點擊行為。這個時候,我們專門開發了一些 "ping" 接口,這些接口通過 Nginx 直接返回 200,并記錄相關日志。

    此外還有一部分數據,例如一些比較需要“較嚴格的完備”的,例如用于推薦系統,反垃圾系統學習的數據,我們存儲在 SQL 數據庫中 下面我做些稍微詳細的介紹。

    2.2.1 數據分析

    數據分析有兩種:實時數據分析和離線數據分析。

    實時數據分析從Kafka到Spark stream,處理結果進Elasticsearch,離線分析是定時任務,從 HDFS 到 Spark,處理結果進Elasticsearch。一般來說,離線的結果會逐步包含實時的結果,同時實時的結果領先于離線分析的結果。

    這里的分析有些抽象,我來舉個例子:

    Q:統計某個板塊同時在線人數的變化趨勢。
    A:用戶每次訪問都有日志,日志里包括訪問內容以及用戶標識。首先 spark stream 從日志里抽取出特定板塊不同用戶的訪問事件,以秒為單位合并相同用戶事件。


    這就是分析結果:時間戳:人數。 然后這個結果怎么用?
    Elasticsearch有很強大的agg接口。你可以以1秒、10秒、1分等等各種時間間隔單位聚合這段時間內的在線人數,聚合方式用 「平均」或「最大」。

    2.2.2 數據挖掘

    我們主要做了2個具體的數據挖掘系統:推薦+反垃圾。今天主要講下架構。

    這兩個系統基本上步驟是一樣的,分為2步:訓練(train)和 服務(serve)。

    在train階段,定時起一個spark job,從訓練數據集中讀取數據,學習出Model,然后將Model存儲成文件。

    在serve階段,起一個帶 serve 的 Spark job,load 之前學習出來的model 文件進內存,然后接受外部API調用,返回結果。

    關于服務的開發這部分因為涉及到太多額外的知識,我就不多說了。 這里講個難點:Spark的Docker化。

    2.2.3 Spark的Docker化

    Spark的Docker化分為兩個部分:

    • Docker化的Spark集群
    • Docker化的Spark調用
    • </ul>
      Spark和我們一般用的服務不太一樣,它的集群不是提供運算服務的,而是一種資源費配的調度器。

      讓 Spark 跑 Job,其實是起的一個 Spark 的本地程序,這個本地程序會向cluster(要資源其他機器),cluster 分配資源以后,這個Spark程序就把一些工作放在這些資源當中運行(進程)。

      所以Spark的Docker化分為兩個部分。

      對于Spark調用,也就是啟動Spark的本地程序,我們就是在跑程序的鏡像中集成Java環境,Spark程序。

      對于Spark集群,稍微復雜一些。Spark 支持三種集群:Mesos、Yard還有Spark自己的一個Standalone。

      我們搭建的Spark Standalone集群,這還是考慮到我們自身的資源與需求。 由于沒找到官方的Spark Docker image,我們自己做了一個,就是Java環境+Spark程序,然后利用script+etcd以不同的姿勢(master 或 slave)在不同的云主機上啟動Spark容器。

      官方推薦要起3個Master,用ZooKeeper做quorum,這個我們最近正在搞,還沒上線,就不分享。我們現在線上跑的是 1 master + 7 slave。

      Q&A

      Q:請問Docker是部署在裸機還是虛擬機,Docker的管理用的什么?部署是人工嗎?

      A:Docker 是跑在國內某云主機上的,所以應該算虛機。
      Q:傳統關系數據庫怎么Docker化的?

      A:我們傳統關系數據庫并沒有Docker化,一方面我們直接用的云主機提供的sql數據庫服務,另一方面,也許這部分原有的方案太成熟,短期Docker完全取代可能比較困難。
      Q:每臺機器上都部署Logstash,那filter部分在哪處理?為什么不用syslog來轉發日志到日志服務器?

      A:filter部分是通過spark stream來做的,Logstash純粹收集轉發, kafka是一個 MQ 系統,而且實時分析從Kafka到spark stream很方便。
      Q:如何做微服務拆分的,經驗是什么?

      A:這個問題我感覺有點大,我嘗試回答下:先做好詳細的計劃,盡量保證服務的平穩過渡,必要的時候,老系統和新系統同時保留一段時間。
      Q:Docker用的時候可以掛載存儲?就是想把靜態的網站圖文數據Docker化,這些靜態文件我們存儲在單獨的分布式存儲和陣列中,走的nfs協議和私有api的形式。

      A:這個放image里好像不是好主意,要不用一些分布式的存儲方案,要不用云存儲服務?
      Q:“一份copy存到hdfs里”考慮過其他的存儲嗎?

      A:Spark有方便的對hdfs的接口,且云服務商有現成的hdfs服務提供,所以我們就用了。
      Q:為什么選擇Logstash,而不選擇Flume,它們有什么差異,比如對安裝端的資源開銷投入產出比等?

      A:最近在研究用heka,開始用Logstash的話是因團隊本身的知識偏好(Ruby 團隊)。
      Q: 我覺得在數據服務部分講了太多,我更想知道Docker在開發,測試或生產環境怎么使用,利用什么方式管理Docker集群,部署服務?比如那個 shell+etcd來啟動Docker是怎么回事,為什么不用一些Docker生態相關的開源工具,比如k8s、swarm之類 ?

      A:關于為什么沒用k8s。我開始也說了,選擇技術架構不光要考慮技術本身,還要考慮團隊資源,以及現有的限制。我們用的國內的云主機,這樣的前提下要在生產環境中用k8s本身就不太可能。另外技術團隊人手也很欠缺。
      Q:請問Docker容器是如何進行遠程部署和自動部署的?

      A:我們用了傳統的部署工具(Ansible)。
      Q:Ansible如何獲取Docker主機列表,所有的Docker容器?

      A:Ansible 是操作云主機的,就和以前的用法一樣。
      Q:請問ping nginx獲得用戶點擊是怎么做的,可以詳細介紹下嗎?

      A:將某些統計數據放在ping接口的參數里,這樣定制nginx的日志可以記錄下來。
      Q:反垃圾系統數據庫的數據是通過什么方式進入Kafka的,ogg、sqoop嗎?

      A:樣本數據的話是rails程序推進mq的。
      Q:搜索引擎選Elasticsearch而不是Solr,可以講一下這樣選擇都有哪些考慮嗎?

      A:Elasticsearch不僅僅是個搜索引擎,更是我們用來做結果聚合的database,而且有很好的水平擴展特性。
      ===========================
      以上內容根據2015年9月29日晚微信群分享內容整理。分享人 丁彥,暴走漫畫技術總監。負責暴走漫畫數據分析、數據挖掘系統的設計與實現。 DockOne每周都會組織定向的技術分享,歡迎感興趣的同學加微信:liyingjiesx,進群參與,您有想聽的話題可以給我們留言。

      來自:http://dockone.io/article/718

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!