暴走漫畫的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/shpull 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;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 數據服務
我們的數據服務包括數據分析和數據挖掘兩大塊。數據分析主要是為了給運營提供量化的效果評估以及指導。數據挖掘則包括推薦,反垃圾等。
數據服務的基礎是數據流,即:數據收集->數據分發->數據處理<->數據存儲。
先給大家看個整體的架構圖,由于本人不擅作圖,所以直接用手畫的,還請見諒。。
首先數據收集部分,就像之前說的,我盡量采用“非侵入式”的方案,所以,我們的整個數據收集都是基于日志的。我們在每個應用服務器上裝了 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