標籤:
作者介紹
魏世江
希雲聯合創始人、CTO,負責基於Docker的自動化服務管理平台的後端研發工作。擅長Docker相關技術、PasS平台架構及企業自動化營運系統的設計及開發。創業之前在新浪SAE平台任技術經理,從09年SAE立項至13年下半年的四年多時間裡,一直負責SAEPasS平台各種基於Web的服務管理系統的設計及開發,在DevOps方面積累了豐富的經驗。Docker引擎代碼貢獻者,在Docker開源項目中代碼貢獻量全球排名50名左右。
開篇
Mongo在很早就支援了replication set和sharding叢集。經過了這麼多年的沉澱,Mongo叢集的成熟度等級已經非常穩定,被大量公司用到自己的生產環境下。如何使用容器技術來實現Mongo叢集的一鍵式交付部署,屏蔽底層實現的細節,是很多人關心的話題。
本文將給大家介紹基於進程的容器技術實現Mongo sharding叢集的一鍵部署,充分展現了容器的強大威力。
什麼是Mongo sharding叢集
Mongo(mongodb.com)作為流行的文檔資料庫,有很多有趣的特性,比如內建failover、支援檔案儲存體、支援mapreduce以及可以在伺服器端直接運行js指令碼,當然我們今天最關心的是它內建的sharding功能。分布式系統的設計向來具有很高的挑戰,在最近一些年,隨著互連網的發展,分布式的實踐逐步開始得到推廣和重視。
如果要深入瞭解Mongo sharding的原理,參考:
https://docs.mongodb.com/manual/sharding
叢集編排規劃
mongo叢集涉及到多個服務,包括:
- configdb, sharding叢集的中心配置,是一個replicaset叢集,監聽在27019連接埠
- mongos, 作為sharding叢集的訪問和管理入口,監聽在27017連接埠
- mongo slices,資料分區節點
- mongo replicaset,每個資料分區是一個replicaset叢集,用於保障沒有單點,並提供自動failover能力
- mongo express, mongodb的管理dashboard
拓撲圖
本次部署,configdb3台,mongo資料節點12台,分成4個分區,每個分區1主2從
首先準備mongo鏡像
Mongo官方已經提供了Mongo 3.2的鏡像,可以用來作為Mongo叢集的鏡像.為了減少後續維護工作,我們儘可能不構建自己的鏡像。
下面我們按照mongo sharding官方的部署文檔,一步步編排叢集。
https://docs.mongodb.com/manual/tutorial/deploy-shard-cluster/
部署的順序是:configdb -> mongos -> mongo-replicaset/mongo-slices -> mongo-express
部署mongo configdb準備configdb的設定檔
# cat mongo-config.confsystemLog: verbosity: 0operationProfiling: slowOpThresholdMs: 3000processManagement: fork: falsestorage: dbPath: /data/db journal: enabled: true engine: wiredTigerreplication: replSetName: {{.ReplSetName}}sharding: clusterRole: configsvrnet: port: 27019
準備 configdb叢集的初始化js指令碼
# cat configdb-init.js{{ $s := service "mongo-configsvr" }}config = { _id : "{{.ReplSetName}}", members : [ {{range $c := $s.Containers }}{_id : {{$c.Seq}}, host: "{{$c.Domain}}:27019"},{{end}} ]}rs.initiate(config)rs.status()
開始編排configdb服務第一步 建立模版
第二步 選擇mongo鏡像,指定cmd
第三步 設定容器參數,關聯設定檔
第四步 健全狀態檢查策略
第五步 設定部署策略,預設部署容器數量
初始化configdb為replicaset叢集
我們通過添加一個one-off的服務configsvr-init
,該服務執行初始化動作後將會自動結束
第一步 選擇mongo鏡像,指定cmd
第二步 設定容器參數,關聯js指令碼
第三步 設定部署策略,優先順序數字設為11(configdb優先順序10)
至此,configdb的編排算是完成了。我們接下來編排mongos服務
準備mongos設定檔
# cat mongos.confreplication: localPingThresholdMs: 2000{{ $port := .CfgPort }}{{$s := service "mongo-configsvr"}}sharding: configDB: {{.ReplSetName}}/{{range $i,$c := $s.Containers}}{{if ne $i 0}},{{end}}{{$c.Domain}}:{{$port}}{{end}}
mongo的設定檔我們一般放到/etc/下
編排mongos模版第一步 選擇鏡像,指定cmd參數
注意cmd裡執行的是mongos
第二步 設定容器參數,關聯mongos配置
第三步 健全狀態檢查
第四步 設定部署策略,注意優先順序
mongos必須在configdb叢集初始化後運行, 接下來我們開始編排mongo的資料節點服務,這是叢集中最複雜的部分
準備shard節點的設定檔
cat mongo-shard.confsystemLog: verbosity: 0operationProfiling: slowOpThresholdMs: 3000processManagement: fork: falsestorage: dbPath: /data/db journal: enabled: true engine: wiredTiger{{ $num := (parseInt .REPLICA_NUM) |add 1 }}{{ $cn := (parseInt .Container.Seq) |subtract 1 }}{{ $rsn := $cn |divide $num }}replication: replSetName: RS{{$rsn}}
變數REPLICA_NUM
表示每個主有幾個從,預設為2
這裡將123個容器編為RS0,456編為RS1,789編為RS2,10,11,12編為RS3
編排mongo shard服務第一步 添加mongo鏡像,指定cmd參數
第二步 設定參數,關聯配置
第三步 健全狀態檢查
第四步 設定部署
有了上面的資料節點後,我們發現,還沒有初始化replset,也沒有將每個replset加入到sharding裡,下面我們來做shard初始化工作
初始化sharding叢集
#!/bin/bashset -e{{$s := service "mongo"}}{{$n := (parseInt .REPLICA_NUM) |add 1}}{{$slices := $s.ContainerNum |divide $n}}{{$port := .Port}}echo begin to init replica set ...for i in {0..{{$slices |subtract 1}}}; do bn=$(( $i * {{$n}} + 1 )) en=$(( $bn + {{.REPLICA_NUM}} )) RS_NODE= RS_NODE_CONFIG= ii=$bn while [ $ii -le $en ]; do RS_NODE=$RS_NODE$ii.mongo.{{.Instance.Name}}.csphere.local:{{$port}}, RS_NODE_CONFIG=$RS_NODE_CONFIG"{_id:$ii, host: \"$ii.mongo.{{.Instance.Name}}.csphere.local:{{$port}}\"}," ii=$(($ii + 1)) done RS_NODES=$(echo $RS_NODE|sed ‘s/,$//‘) RS_NODES_CONFIG=$(echo $RS_NODE_CONFIG|sed ‘s/,$//‘) cat > /tmp/RS$i.js <<EOFconfig = { _id : "RS$i", members : [ $RS_NODES_CONFIG ]}rs.initiate(config)rs.status()EOF ## connect to 0.mongo/3.mongo... begin_mongo=$bn.mongo.{{.Instance.Name}}.csphere.local mongo $begin_mongo /tmp/RS$i.js sleep 3 j=0 while [ $j -lt 10 ]; do mongo $begin_mongo --eval "rs.status()" | grep PRIMARY && break j=$(($j + 1)) sleep 2 done if [ $j -eq 10 ]; then echo RS$i initianized failed exit 1 fi echo RS$i initinized ok echo begin to add RS$i to sharding ... mongo --eval "sh.addShard(\"RS${i}/$RS_NODES\")" 1.mongos.{{.Instance.Name}}.csphere.localdone
上面的指令碼稍微有點複雜,基本邏輯就是,先初始化每個replicaset叢集RS0..RS3,並將每個RS加入到sharding叢集當作分區slices。具體可以參考上面的部署拓撲圖。
開始編排shard-init服務
該服務是one-off執行
第一步 添加鏡像,指定cmd為init.sh
第二步 設定參數,同步指令碼init.sh
第三步 設定部署優先順序
到這裡mongo sharding叢集的編排工作基本就完成了。接下來我們為mongo服務添加一個可視化面板,方便我們的使用
編排mongo-express服務第一步 添加mongo express鏡像
第二步 設定環境變數
第三步 健全狀態檢查
第四步 設定部署優先順序
至此,編排工作全部完成。下面我們來測試剛才的工作成果。。
部署測試
點擊部署,產生一個應用執行個體,我們命名為m
。
我們看一下shard-init的初始化輸出:
我們看一下面板express的輸出:
這是mongo express的首頁,可以查看到該mongos上的訪問概括
我們查看config這個db下表裡的資料,特別是和叢集配置有關的:
mongos表:
有哪些分區呢?我們看到了RS0 RS1 RS2 RS3:
我們可以建立一個名為csphere的db試試:
後續,可以參考mongo文檔,在開發中,設定您的sharding key等。更進一步的mongodb管理,請參考官方文檔
總結
從mongodb叢集的自動化交付看整個編排過程,我們發現背後的魔法關鍵是:DISCOVERY ALL,發現所有的東西並使之具有可程式化特性。
Q&A
Q1: 你好 目前這個的實際應用情況如何?有何挑戰?
A1: 實際測試回合良好。挑戰在於編排過程,背後的discovery能力能否滿足自動化的能力。在實際生產中,可以最佳化您的設定檔,如挑戰timeout等,或日誌的loglevel
Q2: 模板檔案通過什麼語言進行渲染,通過什麼流程發現啟動容器的資訊?
A2: 希雲cSphere平台背後有一套強大的配置模版引擎,golang模版。平台的協調中心可以發現各種參數並進行可程式化去應對自動化挑戰
Q3: 你好 mongodb群集效能瓶頸,監控指標你覺得最重要的是什麼,擴容的時候要注意什嗎?
A3: mongo叢集在使用上注意儲存引擎的選擇,在3.2之前是mmap,3.2已經調整,新的預設引擎能夠更好的處理大資料量的問題。mongo的水平擴充本身很好,注意mongos代理部署的多一點,避免流量從單個mongos流入流出
聯絡希雲
電話 010-62249349
郵箱 [email protected]
官網 http://csphere.cn
如何使用容器實現生產層級的MongoDB sharding叢集的一鍵交付