1. 背景node
以Docker和Rocket爲表明的容器技術如今正變得愈來愈流行,它改變着公司和用戶建立、發佈、運行分佈式應用的方式,在將來5年將給雲計算行業帶來它應有的價值。它的誘人之處在於:linux
1)資源獨立、隔離 git
資源隔離是雲計算平臺的最基本需求。Docker經過Linux namespace, cgroup限制了硬件資源與軟件運行環境,與宿主機上的其餘應用實現了隔離,作到了互不影響。不一樣應用或服務以「集裝箱」(container)爲單位裝「船」或卸「船」,「集裝箱船」(運行container的宿主機或集羣 )上,數千數萬個「集裝箱」排列整齊,不一樣公司、不一樣種類的「貨物」(運行應用所需的程序、組件、運行環境、依賴)保持獨立。docker
2)環境的一致性 數據庫
開發工程師完成應用開發後build一個docker image,基於這個image建立的container像是一個集裝箱,裏面打包了各類「散件貨物」(運行應用所需的程序、組件、運行環境、依賴)。不管這個集裝箱在哪裏:開發環境、測試環境、生產環境,均可以確保集裝箱裏面的「貨物」種類與個數徹底相同,軟件包不會在測試環境缺失,環境變量不會在生產環境忘記配置,開發環境與生產環境不會由於安裝了不一樣版本的依賴致使應用運行異常。這樣的一致性得益於「發貨」(build docker image)時已經密封到「集裝箱」中,而每個環節都是在運輸這個完整的、不須要拆分合並的「集裝箱」。ubuntu
3)輕量化 bash
相比傳統的虛擬化技術(VM),使用docker在cpu, memory, disk IO, network IO上的性能損耗都有一樣水平甚至更優的表現。Container的快速建立、啓動、銷燬受到不少讚譽。服務器
4)Build Once, Run Everywhere 網絡
這個特性着實吸引了不少人,「貨物」(應用)在「汽車」、「火車」、「輪船」(私有云、公有云等服務)之間遷移交換時,只須要遷移符合標準規格和裝卸方式的「集裝箱」(docker container),削減了耗時費力的人工「裝卸」(上線、下線應用),帶來的是巨大的時間人力成本節約。這使將來僅有少數幾個運維人員運維超大規模裝載線上應用的容器集羣成爲可能,如同60年代後少數幾個機器操做員便可在幾小時內連裝帶卸完一艘萬級集裝箱船。運維
容器技術如今也被普遍應用於數據庫領域。它的「Build Once, Run Everywhere」的特性大大減小了花在安裝配置數據庫環境上的時間,由於即便對於從事數據庫多年的DBA而言,安裝配置數據庫環境依舊是一項看似簡單但卻常常不順利的工做。固然,容器技術的其餘優點也被很好的應用在數據庫的使用中。
SequoiaDB做爲一款優秀的國產分佈式NewSQL數據庫,已經獲得了愈來愈多用戶的承認。本文以Docker爲例,着重介紹如何用Dockerfile快速構建SequoiaDB鏡像,以及如何利用容器快速搭建和啓動SequoiaDB集羣供應用系統使用。
2. 構建SequoiaDB鏡像
如何安裝docker以及配置鏡像倉庫不是本文的重點,網上有不少相關的技術文章。須要指出的是本文采用阿里雲鏡像倉庫,由於將鏡像上傳到Docker官方倉庫的速度實在不敢恭維。如何註冊和使用阿里雲鏡像倉庫,能夠參考文章(www.jb51.net/article/123…)。
STEP 1:建立Dockerfile,內容以下,只須要幾行簡單的指令便可
# Sequoiadb DOCKERFILES PROJECT
# --------------------------
# This is the Dockerfile for Sequoiadb
2.8.4
#
# REQUIRED FILES TO BUILD THIS
IMAGE
#
----------------------------------
# (1)
sequoiadb-2.8.4-linux_x86_64-enterprise-installer.run
# (2) installSDB.sh
#
# HOW TO BUILD THIS IMAGE
# -----------------------
# Put all downloaded files in the
same directory as this Dockerfile
# Run:
# $ sudo docker build -t sequoiadb:2.8.4 .
#
# Pull base image
FROM ubuntu
# Environment variables required
for this build
ENV
INSTALL_BIN_FILE="sequoiadb-2.8.4-linux_x86_64-enterprise-installer.run"
\
INSTALL_SDB_SCRIPT="installSDB.sh" \
INSTALL_DIR="/opt/sequoiadb"
# Copy binaries
ADD $INSTALL_BIN_FILE
$INSTALL_SDB_SCRIPT $INSTALL_DIR/
# Install SDB software binaries
RUN chmod 755 $INSTALL_DIR/$INSTALL_SDB_SCRIPT
\
&& $INSTALL_DIR/$INSTALL_SDB_SCRIPT \
&& rm
$INSTALL_DIR/$INSTALL_SDB_SCRIPT
其中installSDB.sh腳本內容以下:
chmod 755
$INSTALL_DIR/$INSTALL_BIN_FILE
$INSTALL_DIR/$INSTALL_BIN_FILE
--mode unattended
rm $INSTALL_DIR/$INSTALL_BIN_FILE
echo 'service sdbcm start'
>> /root/.bashrc複製代碼
須要注意的是本例採用Sequoiadb企業版2.8.4,您也能夠從巨杉官網下載社區版(選擇tar包,下載而後解壓),替換本例中的介質名稱。
巨杉官網下載地址:http://download.sequoiadb.com/cn/
STEP 2:建立鏡像
root用戶執行:
docker build -t
sequoiadb:2.8.4 .複製代碼
若是是普通用戶,須要使用sudo:
sudo docker build -t
sequoiadb:2.8.4 .複製代碼
STEP3:登錄阿里雲鏡像倉庫
docker login --username=xxx
registry.cn-hangzhou.aliyuncs.com複製代碼
其中xxx爲您在阿里雲註冊的帳號。
STEP4:查看本地sequoiadb鏡像id
docker images複製代碼
STEP5:標記本地鏡像,將其納入阿里雲倉庫
docker tag 04dc528f2a6f registry.cn-hangzhou.aliyuncs.com/508mars/sequoiadb:latest複製代碼
其中04dc528f2a6f是筆者本地sequoiadb鏡像id,新的標記格式有必定要求,registry.cn-hangzhou.aliyuncs.com爲阿里雲倉庫地址,508mars是筆者在阿里雲的用戶名,sequoiadb是鏡像名,latest是tag。
STEP6:提交sequoiadb鏡像到鏡像庫
docker push registry.cn-hangzhou.aliyuncs.com/508mars/sequoiadb:latest複製代碼
3. 利用容器啓動SequoiaDB集羣
Docker的網絡默認採用bridge模式,採用bridge模式的容器有以下特色:
1)同一宿主機的容器之間能夠互相ping通
2)不一樣宿主機的容器之間互相ping不一樣
可是SequoiaDB集羣要求全部節點之間是能夠互通的,因此若是運行SequoiaDB的容器跑在不一樣宿主機上,docker的默認網絡模式顯然不合適。有不少種方法能夠解決不一樣宿主機容器之間的連通性問題,本文只介紹weave虛擬網絡這個解決方案,由於weave同時提供了一個DNS server的功能,有了該功能,在利用容器部署SequoiaDB集羣時再也不須要修改各個容器內部的/etc/hosts,大大簡化了自動化部署的步驟。
STEP1:安裝weave網絡
curl -s -L git.io/weave -o
/usr/local/bin/weave
chmod a+x /usr/local/bin/weave複製代碼
須要在全部宿主機安裝,筆者採用了三臺虛擬機做爲宿主機:sdb1, sdb2和sdb3。
STEP2:啓動weave網絡
weave launch複製代碼
第一次啓動時會下載weave鏡像。
STEP3:從阿里雲倉庫下載sequoiadb鏡像
docker pull registry.cn-hangzhou.aliyuncs.com/508mars/sequoiadb複製代碼
STEP4:在全部宿主機建立docker的掛載卷
cd /home/sdbadmin
mkdir -p data/disk1
data/disk2 data/disk3
mkdir -p conf/local
chmod -R 777 data
chmod -R 777 conf複製代碼
掛載卷的位置能夠自定義,但總的來講須要建立兩大類掛載卷,一類用來存放集合數據,如本例中的data/disk1, data/disk2, data/disk3,一類用來存放節點配置信息,如本例中的conf/local。這樣即便容器被誤刪了,依舊能夠啓動一個新容器來扮演被誤刪的容器的角色。
STEP5:啓動容器
sdb1:
weave stop
weave launch
eval $(weave env)
docker run -dit --name
sdbserver1 -p 11810:11810 -v /home/sdbadmin/data:/data -v
/home/sdbadmin/conf/local:/opt/sequoiadb/conf/local
registry.cn-hangzhou.aliyuncs.com/508mars/sequoiadb複製代碼
sdb2:
weave stop
weave launch 192.168.17.132
eval $(weave env)
docker run -dit --name
sdbserver2 -p 11810:11810 -v /home/sdbadmin/data:/data -v
/home/sdbadmin/conf/local:/opt/sequoiadb/conf/local
registry.cn-hangzhou.aliyuncs.com/508mars/sequoiadb複製代碼
sdb3:
weave stop
weave launch 192.168.17.132
eval $(weave env)
docker run -dit --name
sdbserver3 -p 11810:11810 -v /home/sdbadmin/data:/data -v
/home/sdbadmin/conf/local:/opt/sequoiadb/conf/local
registry.cn-hangzhou.aliyuncs.com/508mars/sequoiadb複製代碼
其中192.168.17.132是sdb1的IP地址,11810是對外暴露的集羣訪問端口。宿主機存放節點配置信息的卷必須掛到容器的/opt/sequoiadb/conf/local目錄,存放表數據的卷能夠掛載到用戶自定義的目錄,可是集羣一旦建立後,不可更改。啓動容器的時候必須指定機器名,由於在構建完集羣后,機器名會被保存在SequoiaDB的系統表中,節點的機器名與系統表中不一致會致使沒法加入到集羣。在使用weave的場景下,建議使用--name選項,不要使用--hostname設置機器名。後者會阻止weave將機器名添加到DNS服務器,weave會自動根據--name的值來設置機器名,同時在機器名後增長weave.local域名,並添加到的DNS服務器。
STEP6:將建立SequoiaDB集羣的腳本拷貝到容器中
docker cp create_cluster.js
sdbserver1:/data複製代碼
create_cluster.js內容以下:
var array_hosts =
["sdbserver1.weave.local", "sdbserver2.weave.local",
"sdbserver3.weave.local"];
var array_dbroot =
["/data/disk1/sequoiadb/database","/data/disk2/sequoiadb/database","/data/disk3/sequoiadb/database"];
var port_sdbcm = "11790";
var port_temp_coord =
"18888";
var cataloggroup = {gname:"SYSCatalogGroup",
gport:"11820", ghosts:["sdbserver1.weave.local",
"sdbserver2.weave.local", "sdbserver3.weave.local"]};
var array_coordgroups = [
{gname:"SYSCoord",
gport:"11810", ghosts:["sdbserver1.weave.local",
"sdbserver2.weave.local", "sdbserver3.weave.local"]}
];
var array_datagroups = [
{gname:"dg1",
gport:"11830", ghosts:["sdbserver1.weave.local",
"sdbserver2.weave.local", "sdbserver3.weave.local"],
goptions:{transactionon:true}}
,{gname:"dg2",
gport:"11840", ghosts:["sdbserver1.weave.local",
"sdbserver2.weave.local", "sdbserver3.weave.local"],
goptions:{transactionon:true}}
,{gname:"dg3",
gport:"11850", ghosts:["sdbserver1.weave.local",
"sdbserver2.weave.local", "sdbserver3.weave.local"],
goptions:{transactionon:true}}
];
var array_domains = [
{dname:"allgroups",
dgroups:["dg1", "dg2", "dg3"],
doptions:{AutoSplit:true}}
];
println("啓動臨時協調節點");
var oma = new
Oma(array_coordgroups[0].ghosts[0], port_sdbcm);
oma.createCoord(port_temp_coord,
array_dbroot[0]+"/coord/"+port_temp_coord);
oma.startNode(port_temp_coord);
println("建立編目節點組:"+cataloggroup.ghosts[0]+" "+cataloggroup.gport+" "+array_dbroot[0]+"/cata/"+cataloggroup.gport);
var db = new Sdb(array_coordgroups[0].ghosts[0],
port_temp_coord);
db.createCataRG(cataloggroup.ghosts[0],
cataloggroup.gport, array_dbroot[0]+"/cata/"+cataloggroup.gport);
var cataRG =
db.getRG("SYSCatalogGroup");
for (var i in cataloggroup.ghosts)
{
if (i==0) {continue;}
println("建立編目節點: "+cataloggroup.ghosts[i]+" "+cataloggroup.gport+" "+array_dbroot[0]+"/cata/"+cataloggroup.gport);
var catanode =
cataRG.createNode(cataloggroup.ghosts[i], cataloggroup.gport,
array_dbroot[0]+"/cata/"+cataloggroup.gport);
catanode.start();
}
println("建立協調節點組");
var db = new
Sdb(array_coordgroups[0].ghosts[0], port_temp_coord);
var coordRG = db.createCoordRG();
for (var i in array_coordgroups) {
for (var j in
array_coordgroups[i].ghosts) {
println("建立協調節點組:"+array_coordgroups[i].ghosts[j]+" "+array_coordgroups[i].gport+" "+array_dbroot[0]+"/coord/"+array_coordgroups[i].gport);
coordRG.createNode(array_coordgroups[i].ghosts[j],
array_coordgroups[i].gport, array_dbroot[0]+"/coord/"+array_coordgroups[i].gport);
}
}
coordRG.start();
println("刪除臨時協調節點")
var oma = new
Oma(array_coordgroups[0].ghosts[0], port_sdbcm);
oma.removeCoord(port_temp_coord);
println("建立數據節點組")
var db = new Sdb(array_coordgroups[0].ghosts[0],
array_coordgroups[0].gport);
var k=0;
for (var i in array_datagroups) {
var dataRG =
db.createRG(array_datagroups[i].gname);
for (var j in
array_datagroups[i].ghosts) {
println("建立數據節點:"+array_datagroups[i].gname+" "+array_datagroups[i].ghosts[j]+" "+array_datagroups[i].gport+" "+array_dbroot[k]+"/data/"+array_datagroups[i].gport+" "+array_datagroups[i].goptions)
dataRG.createNode(array_datagroups[i].ghosts[j], array_datagroups[i].gport,
array_dbroot[k]+"/data/"+array_datagroups[i].gport,
array_datagroups[i].goptions);
}
dataRG.start();
k++;
}
println("建立域");
var db = new
Sdb(array_coordgroups[0].ghosts[0], array_coordgroups[0].gport);
for (var i in array_domains) {
println("建立域:"+array_domains[i].dname+" "+array_domains[i].dgroups+" "+array_domains[i].doptions)
db.createDomain(array_domains[i].dname,
array_domains[i].dgroups, array_domains[i].doptions );
}複製代碼
STEP7:建立SequoiaDB集羣
docker exec sdbserver1 su -
sdbadmin -c "sdb -f /data/create_cluster.js"複製代碼
至此SequoiaDB集羣建立並啓動完成,後面再啓動容器的時候集羣會自動啓動。
4. 結論
SequoiaDB利用容器技術很好的實現了集羣快速部署,大大簡化了初學者安裝部署的難度。後期筆者還會在SequoiaDB鏡像製做上作一些優化,由於目前作出來的鏡像有點大,主要根源是採用ADD或COPY命令將安裝介質拷貝到Docker容器中會生成一個新的鏡像image1,最終生成的鏡像image2中雖然刪除了安裝介質,可是它在image1之上,因此image2的大小依舊包含安裝介質。最好採用ADD拷貝tar包(ADD會自動解壓)或者採用相似以下的方式:
RUN mkdir -p /usr/src/things
\
&& curl -SL
http://example.com/big.tar.xz \
| tar -xJC /usr/src/things \
&& make -C /usr/src/things all複製代碼
<END>