背景
以Docker和Rocket為代表的容器技術(shù)現(xiàn)在正變得越來越流行,它改變著公司和用戶創(chuàng)建、發(fā)布、運(yùn)行分布式應(yīng)用的方式,在未來5年將給云計(jì)算行業(yè)帶來它應(yīng)有的價(jià)值。它的誘人之處在于:
1)資源獨(dú)立、隔離
資源隔離是云計(jì)算平臺的最基本需求。Docker通過Linux namespace, cgroup限制了硬件資源與軟件運(yùn)行環(huán)境,與宿主機(jī)上的其他應(yīng)用實(shí)現(xiàn)了隔離,做到了互不影響。不同應(yīng)用或服務(wù)以“集裝箱”(container)為單位裝“船”或卸“船”,“集裝箱船”(運(yùn)行container的宿主機(jī)或集群 )上,數(shù)千數(shù)萬個“集裝箱”排列整齊,不同公司、不同種類的“貨物”(運(yùn)行應(yīng)用所需的程序、組件、運(yùn)行環(huán)境、依賴)保持獨(dú)立。
2)環(huán)境的一致性
開發(fā)工程師完成應(yīng)用開發(fā)后build一個docker image,基于這個image創(chuàng)建的container像是一個集裝箱,里面打包了各種“散件貨物”(運(yùn)行應(yīng)用所需的程序、組件、運(yùn)行環(huán)境、依賴)。無論這個集裝箱在哪里:開發(fā)環(huán)境、測試環(huán)境、生產(chǎn)環(huán)境,都可以確保集裝箱里面的“貨物”種類與個數(shù)完全相同,軟件包不會在測試環(huán)境缺失,環(huán)境變量不會在生產(chǎn)環(huán)境忘記配置,開發(fā)環(huán)境與生產(chǎn)環(huán)境不會因?yàn)榘惭b了不同版本的依賴導(dǎo)致應(yīng)用運(yùn)行異常。這樣的一致性得益于“發(fā)貨”(build docker image)時已經(jīng)密封到“集裝箱”中,而每一個環(huán)節(jié)都是在運(yùn)輸這個完整的、不需要拆分合并的“集裝箱”。
3)輕量化
相比傳統(tǒng)的虛擬化技術(shù)(VM),使用docker在cpu, memory, disk IO, network IO上的性能損耗都有同樣水平甚至更優(yōu)的表現(xiàn)。Container的快速創(chuàng)建、啟動、銷毀受到很多贊譽(yù)。
4)Build Once, Run Everywhere
這個特性著實(shí)吸引了很多人,“貨物”(應(yīng)用)在“汽車”、“火車”、“輪船”(私有云、公有云等服務(wù))之間遷移交換時,只需要遷移符合標(biāo)準(zhǔn)規(guī)格和裝卸方式的“集裝箱”(docker container),削減了耗時費(fèi)力的人工“裝卸”(上線、下線應(yīng)用),帶來的是巨大的時間人力成本節(jié)約。這使未來僅有少數(shù)幾個運(yùn)維人員運(yùn)維超大規(guī)模裝載線上應(yīng)用的容器集群成為可能,如同60年代后少數(shù)幾個機(jī)器操作員即可在幾小時內(nèi)連裝帶卸完一艘萬級集裝箱船。
容器技術(shù)現(xiàn)在也被廣泛應(yīng)用于數(shù)據(jù)庫領(lǐng)域。它的“Build Once, Run Everywhere”的特性大大減少了花在安裝配置數(shù)據(jù)庫環(huán)境上的時間,因?yàn)榧词箤τ趶氖聰?shù)據(jù)庫多年的DBA而言,安裝配置數(shù)據(jù)庫環(huán)境依舊是一項(xiàng)看似簡單但卻經(jīng)常不順利的工作。當(dāng)然,容器技術(shù)的其他優(yōu)勢也被很好的應(yīng)用在數(shù)據(jù)庫的使用中。
SequoiaDB作為一款優(yōu)秀的國產(chǎn)分布式NewSQL數(shù)據(jù)庫,已經(jīng)得到了越來越多用戶的認(rèn)可。本文以Docker為例,著重介紹如何用Dockerfile快速構(gòu)建SequoiaDB鏡像,以及如何利用容器快速搭建和啟動SequoiaDB集群供應(yīng)用系統(tǒng)使用。
創(chuàng)新互聯(lián)建站網(wǎng)絡(luò)公司擁有十余年的成都網(wǎng)站開發(fā)建設(shè)經(jīng)驗(yàn),上千客戶的共同信賴。提供成都網(wǎng)站制作、成都網(wǎng)站建設(shè)、網(wǎng)站開發(fā)、網(wǎng)站定制、買友情鏈接、建網(wǎng)站、網(wǎng)站搭建、響應(yīng)式網(wǎng)站、網(wǎng)頁設(shè)計(jì)師打造企業(yè)風(fēng)格,提供周到的售前咨詢和貼心的售后服務(wù)
STEP 1:創(chuàng)建Dockerfile,內(nèi)容如下,只需要幾行簡單的指令即可
*# Sequoiadb DOCKERFILES PROJECT
--------------------------
This is the Dockerfile for Sequoiadb 2.8.4
REQUIRED FILES TO BUILD THIS IMAGE
----------------------------------
(1) sequoiadb-2.8.4-linuxx8664-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 INSTALLBINFILE="sequoiadb-2.8.4-linuxx8664-enterprise-installer.run" \
INSTALLSDBSCRIPT="installSDB.sh" \
INSTALLDIR="/opt/sequoiadb"
Copy binaries
ADD $INSTALLBINFILE $INSTALLSDBSCRIPT $INSTALLDIR/
Install SDB software binaries
RUN chmod 755 $INSTALLDIR/$INSTALLSDBSCRIPT \
&& $INSTALLDIR/$INSTALLSDBSCRIPT \
&& rm $INSTALLDIR/$INSTALLSDBSCRIPT**
其中installSDB.sh腳本內(nèi)容如下:
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企業(yè)版2.8.4,您也可以從巨杉官網(wǎng)下載社區(qū)版(選擇tar包,下載然后解壓),替換本例中的介質(zhì)名稱。
巨杉官網(wǎng)下載地址:http://download.sequoiadb.com/cn/
STEP 2:創(chuàng)建鏡像
root用戶執(zhí)行: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鏡像iddocker images
STEP5:標(biāo)記本地鏡像,將其歸入阿里云倉庫docker tag 04dc528f2a6f registry.cn-hangzhou.aliyuncs.com/508mars/sequoiadb:latest
其中04dc528f2a6f是筆者本地sequoiadb鏡像id,新的標(biāo)記格式有一定要求,registry.cn-hangzhou.aliyuncs.com為阿里云倉庫地址,508mars是筆者在阿里云的用戶名,sequoiadb是鏡像名,latest是tag。
STEP6:提交sequoiadb鏡像到鏡像庫docker push registry.cn-hangzhou.aliyuncs.com/508mars/sequoiadb:latest
STEP1:安裝weave網(wǎng)絡(luò)
curl -s -L git.io/weave -o /usr/local/bin/weave
chmod a+x /usr/local/bin/weave
需要在所有宿主機(jī)安裝,筆者采用了三臺虛擬機(jī)作為宿主機(jī):sdb1, sdb2和sdb3。
STEP2:啟動weave網(wǎng)絡(luò)weave launch
第一次啟動時會下載weave鏡像。
STEP3:從阿里云倉庫下載sequoiadb鏡像docker pull registry.cn-hangzhou.aliyuncs.com/508mars/sequoiadb
STEP4:在所有宿主機(jī)創(chuàng)建docker的掛載卷
cd /home/sdbadmin
mkdir -p data/disk1 data/disk2 data/disk3
mkdir -p conf/local
chmod -R 777 data
chmod -R 777 conf
掛載卷的位置可以自定義,但總的來說需要創(chuàng)建兩大類掛載卷,一類用來存放集合數(shù)據(jù),如本例中的data/disk1, data/disk2, data/disk3,一類用來存放節(jié)點(diǎn)配置信息,如本例中的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是對外暴露的集群訪問端口。宿主機(jī)存放節(jié)點(diǎn)配置信息的卷必須掛到容器的/opt/sequoiadb/conf/local目錄,存放表數(shù)據(jù)的卷可以掛載到用戶自定義的目錄,但是集群一旦創(chuàng)建后,不可更改。啟動容器的時候必須指定機(jī)器名,因?yàn)樵跇?gòu)建完集群后,機(jī)器名會被保存在SequoiaDB的系統(tǒng)表中,節(jié)點(diǎn)的機(jī)器名與系統(tǒng)表中不一致會導(dǎo)致無法加入到集群。在使用weave的場景下,建議使用--name選項(xiàng),不要使用--hostname設(shè)置機(jī)器名。后者會阻止weave將機(jī)器名添加到DNS服務(wù)器,weave會自動根據(jù)--name的值來設(shè)置機(jī)器名,同時在機(jī)器名后增加weave.local域名,并添加到的DNS服務(wù)器。
STEP6:將創(chuàng)建SequoiaDB集群的腳本拷貝到容器中docker cp create_cluster.js sdbserver1:/data
create_cluster.js內(nèi)容如下:
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("啟動臨時協(xié)調(diào)節(jié)點(diǎn)");
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("創(chuàng)建編目節(jié)點(diǎn)組:"+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("創(chuàng)建編目節(jié)點(diǎn): "+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("創(chuàng)建協(xié)調(diào)節(jié)點(diǎn)組");
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("創(chuàng)建協(xié)調(diào)節(jié)點(diǎn)組:"+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("刪除臨時協(xié)調(diào)節(jié)點(diǎn)")
var oma = new Oma(array_coordgroups[0].ghosts[0], port_sdbcm);
oma.removeCoord(port_temp_coord);
println("創(chuàng)建數(shù)據(jù)節(jié)點(diǎn)組")
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("創(chuàng)建數(shù)據(jù)節(jié)點(diǎn):"+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("創(chuàng)建域");
var db = new Sdb(array_coordgroups[0].ghosts[0], array_coordgroups[0].gport);
for (var i in array_domains) {
println("創(chuàng)建域:"+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:創(chuàng)建SequoiaDB集群docker exec sdbserver1 su - sdbadmin -c "sdb -f /data/create_cluster.js"
至此SequoiaDB集群創(chuàng)建并啟動完成,后面再啟動容器的時候集群會自動啟動。
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