如何使用容器實現生產級別的MongoDB sharding集羣的一鍵交付

做者介紹

魏世江 希雲聯合創始人、CTO,負責基於Docker的自動化服務管理平臺的後端研發工做。擅長Docker相關技術、PasS平臺架構及企業自動化運維繫統的設計及開發。創業以前在新浪SAE平臺任技術經理,從09年SAE立項至13年下半年的四年多時間裏,一直負責SAEPasS平臺各類基於Web的服務管理系統的設計及開發,在DevOps方面積累了豐富的經驗。Docker引擎代碼貢獻者,在Docker開源項目中代碼貢獻量全球排名50名左右。golang

開篇

Mongo在很早就支持了replication set和sharding集羣。通過了這麼多年的沉澱,Mongo集羣的成熟度已經很是穩定,被大量公司用到本身的生產環境下。如何使用容器技術來實現Mongo集羣的一鍵式交付部署,屏蔽底層實現的細節,是不少人關心的話題。mongodb

本文將給你們介紹基於進程的容器技術實現Mongo sharding集羣的一鍵部署,充分展示了容器的強大威力。數據庫

什麼是Mongo sharding集羣

Mongo(mongodb.com)做爲流行的文檔數據庫,有不少有趣的特性,好比內置failover、支持文件存儲、支持mapreduce以及能夠在服務器端直接運行js腳本,固然咱們今天最關心的是它內置的sharding功能。分佈式系統的設計向來具備很高的挑戰,在最近一些年,隨着互聯網的發展,分佈式的實踐逐步開始獲得推廣和重視。express

若是要深刻了解Mongo sharding的原理,參考:編程

https://docs.mongodb.com/manual/sharding後端

集羣編排規劃

mongo集羣涉及到多個服務,包括:bash

  • 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.conf

systemLog:
   verbosity: 0
   
operationProfiling:
   slowOpThresholdMs: 3000

processManagement:
   fork: false

storage:
   dbPath: /data/db
   journal:
      enabled: true
   engine: wiredTiger

replication:
   replSetName: {{.ReplSetName}}
   
sharding:
   clusterRole: configsvr
   
net:
   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.conf
replication:
   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.conf
systemLog:
   verbosity: 0
   
operationProfiling:
   slowOpThresholdMs: 3000
   
processManagement:
   fork: false
            
storage:
   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/bash

set -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 <<EOF
config = {
  _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.local
done

上面的腳本稍微有點複雜,基本邏輯就是,先初始化每一個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流入流出

相關文章
相關標籤/搜索