炒個(gè)冷飯LXC,試問(wèn)Docker你憑啥這么火?
事情是這樣的,這兩年我們不斷聽(tīng)到container、“容器”、Container、Docker...... “容器”大火,但大多數(shù)人知道“容器”,估計(jì)不是從linux,不是從LXC, 都是因?yàn)镈ocker才知道的吧?不得不說(shuō),這就是Docker的厲害之處。
先說(shuō)說(shuō)LXC~~LXC中文就是Linux容器工具,linux原生支持的容器,可以追溯到2009年,源于cgroup和namespaces在Linux內(nèi)核方面的發(fā)展,是一種輕量級(jí)的容器虛擬化技術(shù),***效率隔離進(jìn)程和資源。它可以把傳統(tǒng)虛擬技術(shù)以及后來(lái)的Xen、KVM的VM進(jìn)程像HOST進(jìn)程一樣運(yùn)行管理, 所以創(chuàng)建和銷毀都非常輕。
2013年,Docker橫空出世,Docker是啥呢?就是一個(gè)基于LXC 的高級(jí)容器引擎。Docker做了件什么事呢?打包!你可以在一個(gè)容器里寫完之后,裝箱打包成一個(gè)鏡像,然后輕松部署在不同的運(yùn)行環(huán)境里。Docker解決了運(yùn)行環(huán)境依賴問(wèn)題,不再有“為啥明明剛才在我那里可以跑起來(lái)到你這里就不行”的問(wèn)題。如果說(shuō)LXC著眼點(diǎn)在于提供輕量級(jí)的虛擬技術(shù),扎根在虛擬機(jī),那Docker則定位于應(yīng)用。Docker所為人稱道的portability、application-centric、versioning等等超越傳統(tǒng)虛擬技術(shù)的優(yōu)點(diǎn)都跟它的封裝性密不可分。開(kāi)發(fā)和測(cè)試裝個(gè)docker, pull下image,再也不用受困于不同的開(kāi)發(fā)環(huán)境、系統(tǒng)依賴和配置文件。。。是不是瞬間天亮了?
Docker這個(gè)發(fā)明magic package的故事,就完了嗎?當(dāng)然不是,問(wèn)題來(lái)了~~ 為什么呢?有人就問(wèn)了,那我log怎么辦呢?掛在數(shù)據(jù)卷里!ssh怎么搞呢?用docker exec! 說(shuō)了那么多,Docker的底層鏡像操作系統(tǒng)的設(shè)計(jì),僅僅是把一個(gè)個(gè)進(jìn)程打包封裝在一個(gè)個(gè)盒子里,相互隔離,運(yùn)來(lái)運(yùn)去,別的事情,它一概就不管了。。。。Docker不管多進(jìn)程應(yīng)用程序、不管設(shè)計(jì)、也不管其他服務(wù),而且還stateless... 你是不是要崩潰了??
真相了,是不是?有一個(gè)比喻說(shuō)的很好,Docker不是萬(wàn)靈藥,它本身也不是一個(gè)app或者app的一個(gè)部件,而是OS/ubuntu的一個(gè)最小單位的磚頭塊,盡管這是史上最牛X的黃金磚。。。然而在生產(chǎn)環(huán)境下,實(shí)際上更具有挑戰(zhàn)性的問(wèn)題是,如何能讓成千上萬(wàn)個(gè)Docker封裝的executable magic package有機(jī)協(xié)同工作,誰(shuí)來(lái)安排誰(shuí)來(lái)管?那就需要一個(gè)強(qiáng)大高能的編排系統(tǒng)來(lái)運(yùn)作,Caicloud就是這個(gè)高能者~~~(頓時(shí)形象高大起來(lái)^ ^)
之前Docker的libcontainer,到最近Docker***版本1.10里移除了對(duì)LXC的support,Docker和LXC的分家有很多原因,也勢(shì)在必行,但不管未來(lái)咋樣,也無(wú)法抹殺Docker和LXC之間的傳承。呃,我不是LXC派來(lái)的臥底,今天炒的這碗冷飯是說(shuō),LXC雖然已經(jīng)不被Docker支持,但并沒(méi)有過(guò)時(shí),依然是經(jīng)典的容器技術(shù);兒子不要爹了,可爹還是那個(gè)爹。。。。。。有興趣就來(lái)一起玩一玩Docker的老爹吧~~~ 只要你有比較新版本的linux kernel, 就可以建立一個(gè)LXC虛機(jī)系統(tǒng)來(lái)生成運(yùn)行容器,LXC容器也可以嵌套,可以用cgroup來(lái)限定資源。。。
下面參考的這是一篇翻譯自Stephane Graber主頁(yè)的文章,LXC系統(tǒng)目前由一個(gè)兩人的團(tuán)隊(duì)領(lǐng)導(dǎo):來(lái)自Ubuntu的Stephane Graber和Serge Hallyn, LXC是由Ubuntu支持的。
那么什么是LXC?
你們之中大部分人很應(yīng)該已經(jīng)知道什么是LXC了,但是在這里,我們這樣定義:
“LXC是一個(gè)為L(zhǎng)inux內(nèi)核包含特征的用戶接口。通過(guò)強(qiáng)大的API和簡(jiǎn)單的工具,它可以讓Linux用戶輕松的創(chuàng)建和托管系統(tǒng)或者應(yīng)用程序容器。”
我和Serge Hallyn是LXC的兩個(gè)上游維護(hù)者之一。每個(gè)月,項(xiàng)目都有著里程碑式的積極發(fā)展,并且在二月份會(huì)發(fā)布一個(gè)穩(wěn)定版本。到目前為止,它已經(jīng)被67個(gè)來(lái)自不同背景和公司的貢獻(xiàn)者開(kāi)發(fā)。
LXC1.0
那么1.0版本到底發(fā)布了什么呢?
好的,簡(jiǎn)單的說(shuō),它將是***個(gè)真正穩(wěn)定的LXC版本,也是***個(gè)我們將
支持5年的bug修正版本。它也是包括在Ubuntu14.04LTS里面的一個(gè),將和Ubuntu在2014年4月一起發(fā)布。
與之一起的是,穩(wěn)定的API,一組綁定,很多有趣的新特點(diǎn)。這些新的特點(diǎn)會(huì)在下一期的帖子里詳細(xì)闡述,并且支持大范圍的主機(jī)和客機(jī)分布(包括Andriod)。
如何使用它?
我猜你們之中大部分人都將會(huì)一直使用Ubuntu。在接下來(lái)的少數(shù)帖子中,我會(huì)一直在Ubuntu14.04上使用目前上游的每日構(gòu)建,我們維護(hù)每日構(gòu)建的時(shí)間分別是:12.04,12.10,13.04,13.10,以及14.04,所以如果想要***的上游代碼,可以使用我們的PPA。
另外,LXC也是在Ubuntu中直接使用的,在Ubuntu12.04LTS之后也十分有用。你可以選擇這樣一個(gè)版本,就是無(wú)論你在發(fā)布哪個(gè),它都會(huì)跟著這個(gè)版本,或者你可以使用我們維護(hù)的那個(gè)布丁版本。
如果想要自己創(chuàng)建,可以這么做(但是如果你在你的linux發(fā)行版上面可以是直接使用軟件包,我們不推薦這個(gè)方法):
- git clone git://github.com/lxc/lxc
- cd lxc
- sh autogen.sh
- You will probably want to run theconfigure script with --help and then set the paths
- ./configure
- make
- sudo make install
關(guān)于***個(gè)容器
對(duì)了, 容器才是我們這篇帖子真正的目標(biāo)對(duì)吧?
好的,那既然你已經(jīng)安裝了LXC,滿懷希望地使用Ubuntu打包,那么事情就簡(jiǎn)單了:
- Create a "p1" container usingthe "ubuntu" template and the same version of Ubuntu
- and architecture as the host. Pass"-- --help" to list all available options.
- sudo lxc-create -t ubuntu -n p1
- Start the container (in the background)
- sudo lxc-start -n p1 -d
- Enter the container in one of thoseways## Attach to the container's console (ctrl-a + q to detach)
- sudo lxc-console -n p1
- Spawn bash directly in the container(bypassing the console login), requires a >= 3.8 kernel
- sudo lxc-attach -n p1
- SSH into it
- sudo lxc-info -n p1
- ssh ubuntu@
- Stop the container in one of those ways
- Stop it from within
- sudo poweroff
- Stop it cleanly from the outside
- sudo lxc-stop -n p1
- Kill it from the outside
- sudo lxc-stop -n p1 -k
好了!這就是你的***個(gè)容器了。你會(huì)注意到,所有東西都是在Ubuntu上面運(yùn)行的。我們的內(nèi)核支持所有LXC可能使用到的特點(diǎn),我們的packages構(gòu)建了橋梁和DHCP服務(wù)器,這樣容器在默認(rèn)情況下就會(huì)使用。
LXC2.0 你的第二個(gè)容器
更多模版
現(xiàn)在呢,你應(yīng)該已經(jīng)有一個(gè)在運(yùn)行的Ubuntu容器了,叫做“p1”,是使用默認(rèn)模版簡(jiǎn)潔“ubuntu”創(chuàng)建的。
但是LXC支持的比標(biāo)準(zhǔn)Ubuntu多很多。事實(shí)上,在目前的上游git(以及日常PPA),我們支持AlpineLinux,Alt Linux,Arch Linux,busybox,CentOS,Cirros,Debian,F(xiàn)edora,OpenMandriva,OpenSUSE,Oracle,Plamo,sshd,Ubuntu云端以及Ubuntu。
以上那些都可以在/usr/share/lxc/templates里面找到。他們通常還有額外的高級(jí)選項(xiàng),可以通過(guò)在“lxc-create”呼叫之后輸入“—help”來(lái)實(shí)現(xiàn)(“--”可以從模版里分裂出“lxc-create”選項(xiàng))。
再寫一個(gè)額外的模版也不是很困難的事情,他們基本上都是可執(zhí)行文件(都是shell腳本,但是這不是必須的),采取了一整套標(biāo)準(zhǔn)參數(shù),預(yù)計(jì)會(huì)在路徑中生成一個(gè)工作的根文件系統(tǒng)傳遞給他們。
需要注意的一點(diǎn)就是,由于工具丟失,所以不是所有的發(fā)行版都可以在發(fā)行版上自我啟動(dòng)的。通常還是要試一試。我們總是喜歡將這些工作運(yùn)行在更多的發(fā)行版上面,即使這么做意味著使用一些小技倆也在所不惜(比如,在fedora模版里,我們就是這么做的)。所以,如果你現(xiàn)下有不能運(yùn)行的特定組合,歡迎使用補(bǔ)丁~
不管怎樣,先談現(xiàn)下,讓我們繼續(xù)往下說(shuō),現(xiàn)在我們來(lái)創(chuàng)建一個(gè)Oracle Linux容器,將其強(qiáng)制為32bit。
- sudo lxc-create -t oracle -n p2 -- -a i386
在很多系統(tǒng)上,它一開(kāi)始就會(huì)運(yùn)行失敗,并告訴你要安裝“rpm”包才可以,bootstrap也有需要這樣的安裝的理由。所以安裝“rpm”,然后再次嘗試。
在下載完RPMs之后一段時(shí)間,容器就會(huì)被創(chuàng)建了,然后再:
- sudo lxc-start -n p2
你會(huì)被Oracle Linux登陸提示歡迎使用(root/root)
那么現(xiàn)在,既然你已經(jīng)開(kāi)啟容器了,沒(méi)有將“-d”傳遞給“lxc-start”,那么你就不得不將其關(guān)閉,再將shell弄回來(lái)(你不能將一個(gè)在背景情境下沒(méi)有初始化開(kāi)的的容器分離)。
那現(xiàn)在如果你很好奇為什么Ubuntu有兩個(gè)版本。目前我正在使用的Ubuntu模版用“deboostrap”基本上從頭創(chuàng)建您的容器,但是Ubuntu云端模版(ubuntucloud)下載了一個(gè)預(yù)生成云鏡像(與你在EC2或者其他云端服務(wù)上得到的完全一樣),并開(kāi)啟。這個(gè)鏡像包括初始化云,還支持標(biāo)準(zhǔn)云元數(shù)據(jù)。
這完全是個(gè)人選擇問(wèn)題,個(gè)人喜歡哪個(gè)就可以選哪個(gè)。我個(gè)人建議是擁有一個(gè)本地鏡像,這樣的話“ubuntu”模版對(duì)我來(lái)說(shuō)就快多了,我知道所有東西都已經(jīng)在我之前從檔案文件那里下載,并且已經(jīng)在本地組裝了,因此我更加信任它。
關(guān)于模版的***一個(gè)注解。大多數(shù)都使用本地緩存,所以最初的容器引導(dǎo)程序進(jìn)程緩慢,對(duì)于一種架構(gòu),容器的***啟動(dòng)會(huì)比較緩慢,之后的啟動(dòng)會(huì)比較快,因?yàn)橛斜镜鼐彺妗?/p>
自動(dòng)啟動(dòng)
那么,如果你想要在開(kāi)機(jī)時(shí)序自動(dòng)開(kāi)啟容器會(huì)怎么樣呢?
其實(shí),上述情況在Ubuntu上和其他的通過(guò)使用一些初始腳本和符號(hào)連接的發(fā)行版上面早就已經(jīng)是支持的了,但是最近(兩天前),這就已經(jīng)在上游實(shí)施了,干勁利落。
所以這就是自動(dòng)啟動(dòng)容器如何的:
可能就像你所知道的,每個(gè)容器通常在/var/lib/lxc/
那個(gè)文件就是key=value,在lxc.conf(5),有效keys清單會(huì)被詳細(xì)列出來(lái)。
可用的啟動(dòng)相關(guān)值有:
- § lxc.start.auto = 0 (disabled) or 1(enabled)
- § lxc.start.delay = 0 (delay in second towait after starting the container)
- § lxc.start.order = 0 (priority of thecontainer, higher value means starts earlier)
- § lxc.group = group1,group2,group3,… (groupsthe container is a member of)
當(dāng)你的機(jī)器啟動(dòng)的時(shí)候,初始腳本就會(huì)要求“lxc-autostart”來(lái)以正確順序開(kāi)啟所有已經(jīng)給定的組的容器(默認(rèn)情況下,是所有容器而不是任意一個(gè)),并且等待這些容器之間的特定時(shí)間。
要闡述清楚,編輯/var/lib/lxc/p1/config 并且貼這幾行到文件里:
- lxc.start.auto = 1
- lxc.group = Ubuntu
以及 /var/lib/lxc/p2/config,并貼上這幾行:
- lxc.start.auto = 1
- lxc.start.delay = 5
- lxc.start.order = 100
那么做意味著,只有p2容器會(huì)在開(kāi)機(jī)時(shí)間啟動(dòng)(因?yàn)檫@些如果沒(méi)有一個(gè)組的話就是系統(tǒng)默認(rèn)情況),順序值是沒(méi)有關(guān)系的,因?yàn)樗仟?dú)立的,初始腳本在你繼續(xù)之前會(huì)停留5秒。
通過(guò)“lxc-ls”可以檢查什么容器是自動(dòng)啟動(dòng)的:
- stgraber@castiana:~$ sudo lxc-ls --fancy
- NAME STATE IPV4 IPV6 AUTOSTART
- p1 RUNNING 10.0.3.128 2607:f2c0:f00f:2751:216:3eff:feb1:4c7f YES (ubuntu)
- p2 RUNNING 10.0.3.165 2607:f2c0:f00f:2751:216:3eff:fe3a:f1c1 YES
你也可以通過(guò)“lxc-autostart“命令手動(dòng)啟動(dòng)那些容器,這個(gè)命令可以讓你啟動(dòng)/停止/中止/重新啟動(dòng)任意用lxc.start.auto=1標(biāo)記的容器。
比如,你可以這么做:
- sudo lxc-autostart –a
這個(gè)命令會(huì)開(kāi)啟任意有l(wèi)xc.start.auto=1(忽略lxc.group值),這在我們的情況下意味著它將***開(kāi)啟p2(由于order=100),然后等待5秒(因?yàn)閐elay=5),然后開(kāi)啟p1,并且之后馬上調(diào)回來(lái)。
如果在那時(shí)你想要中止ubuntu里面的所有容器,你可以這么做:
sudo lxc-autostart -r -g Ubuntu
你也可以通過(guò)這些命令中的任意一個(gè)來(lái)輸入“-L”,這些命令僅僅只是影響打印哪個(gè)容器,以及會(huì)造成怎樣的延遲,但是事實(shí)上并不會(huì)有影響(對(duì)于與其它腳本集成還是有好處的)。
凍結(jié)你的容器
有時(shí)候容器可能正在運(yùn)行守護(hù)進(jìn)程,這個(gè)進(jìn)程需要時(shí)間來(lái)關(guān)閉或者重啟,但是你不要想去運(yùn)行容器,因?yàn)槟阍谀莻€(gè)時(shí)間點(diǎn)不是主動(dòng)使用它的。
在這些情況下,可以使用“sudo lxc-freeze -n
一旦你再次需要服務(wù),只要調(diào)用 “sudo lxc-unfreeze -n
連網(wǎng)
你可能已經(jīng)注意到在配置文件里,當(dāng)你正在設(shè)置自動(dòng)啟動(dòng)設(shè)置的時(shí)候,LXC有一個(gè)相對(duì)靈活的網(wǎng)絡(luò)配置。
系統(tǒng)默認(rèn)設(shè)置下,在Ubuntu里,我們每個(gè)容器指定一個(gè)“veth”設(shè)備,這個(gè)在主機(jī)上橋接成一個(gè)“lxcbr0”橋,在這個(gè)上面,我們跑一個(gè)最小 dnsmasq DHCP 服務(wù)器。
對(duì)于大多數(shù)人,那都是很好的。你可能想要一些東西略微再?gòu)?fù)雜一點(diǎn),比如容器里的多網(wǎng)絡(luò)接口,或者通過(guò)物理的網(wǎng)絡(luò)接口,等等。這些的細(xì)節(jié)都列在lxc.conf(5)里面了,所以我在這里就不再贅述,但是這里有個(gè)簡(jiǎn)單的例子可以做:
- lxc.network.type = veth
- lxc.network.hwaddr = 00:16:3e:3a:f1:c1
- lxc.network.flags = up
- lxc.network.link = lxcbr0
- lxc.network.name = eth0
- lxc.network.type = veth
- lxc.network.link = virbr0
- lxc.network.name = virt0
- lxc.network.type = phys
- lxc.network.link = eth2
- lxc.network.name = eth1
有了這個(gè)設(shè)置,我的容器就會(huì)有3個(gè)接口,虛擬接口0在lxcbro橋都是尋常VETH設(shè)備,虛擬接口1是主機(jī)的,虛擬接口2是移動(dòng)到容器里面(它會(huì)在容器正運(yùn)行的時(shí)候從主機(jī)上面消失),virt0則是虛擬網(wǎng)橋的兩個(gè)接口。
那兩個(gè)接口都沒(méi)有mac地址或者網(wǎng)絡(luò)信號(hào)設(shè)置,所以他們會(huì)在啟動(dòng)時(shí)間獲得一個(gè)隨機(jī)的mac地址(非***),而且,它將由容器決定連接。
附接
如果你正在運(yùn)行一個(gè)最近的內(nèi)核,也就是3.8以及3.8版本以上,你可能會(huì)用到“lxc-attach”工具。它最基本的特點(diǎn)就是在運(yùn)行的容器里面給你一個(gè)標(biāo)準(zhǔn)的shell:
- sudo lxc-attach -n p1
你可能也會(huì)從腳本使用它在容器里運(yùn)行動(dòng)作,比如:
- sudo lxc-attach -n p1 -- restart ssh
但是,它的效率遠(yuǎn)大于上述,舉個(gè)例子,比如:
- sudo lxc-attach -n p1 -e -s'NETWORK|UTSNAME'
在上述情況下,你會(huì)得到一個(gè)shell,就是 “root@p1” (thanks toUTSNAME),正在運(yùn)行“ifconfig -a” ,從這里可以列出一個(gè)容器的網(wǎng)絡(luò)接口清單。輸入“e“也意味著cgroup,apparmor,… 從那個(gè)shell開(kāi)啟的任意進(jìn)程都不會(huì)被限制。
這有時(shí)候?qū)τ诜毖芤粋€(gè)位于主機(jī)上并且在容器里面或者pid域名里面的軟件是很有幫助的。
通過(guò)設(shè)備到一個(gè)運(yùn)行的容器上面
能夠按照意愿進(jìn)入或者脫離一個(gè)容器當(dāng)然是很好的,但是如果能夠在你的主機(jī)上通過(guò)一些隨機(jī)設(shè)備進(jìn)入,那會(huì)是怎么樣的?
系統(tǒng)默認(rèn)設(shè)置,LXC將會(huì)避免任意的,比如通過(guò)運(yùn)用設(shè)備cgroup當(dāng)成過(guò)濾機(jī)制作為通道進(jìn)入。你也可以編輯容器配置來(lái)允許額外設(shè)備,然后重啟容器。
但是有一個(gè)只提一次的事情,就是這里也有一個(gè)非常方便的工具叫“lxc-device”,有了它,你就只需要做:
- sudo lxc-device add -n p1 /dev/ttyUSB0/dev/ttyS0
sudo lxc-device add -n p1 /dev/ttyUSB0/dev/ttyS0
這個(gè)命令會(huì)添加 (mknod) /dev/ttyS0,以及同類型的/major/minor as /dev/ttyUSB0 到容器里,然后添加相匹配的cgroup入口來(lái)允許從容器進(jìn)入。
同樣,這個(gè)容器也允許從主機(jī)移動(dòng)網(wǎng)絡(luò)設(shè)備到容器里面。