關(guān)于容器的歷史、發(fā)展以及技術(shù)本質(zhì),在互聯(lián)網(wǎng)上已經(jīng)有非常多的文章了。這里旨在結合自身的工作經(jīng)驗和理解,通過(guò)一系列的文章,講清楚這項技術(shù)。
關(guān)于的歷史、發(fā)展以及技術(shù)本質(zhì),在互聯(lián)網(wǎng)上已經(jīng)有非常多的文章了。這里旨在結合自身的工作經(jīng)驗和理解,通過(guò)一系列的文章,講清楚這項技術(shù)。
講到容器,就不得不提LXC(Linux Container),他是的前生,或者說(shuō)Docker是LXC的使用者。完整的LXC能力在2008年合入Linux主線(xiàn),所以容器的概念在2008年就基本定型了,并不是后面Docker造出來(lái)的。關(guān)于LXC的介紹很多,大體都會(huì )說(shuō)“LXC是Linux內核提供的容器技術(shù),能提供輕量級的虛擬化能力,能隔離進(jìn)程和資源”,但總結起來(lái),無(wú)外乎就兩大知識點(diǎn)Cgroups(Linux Control Group)和Linux Namespace。搞清楚他倆,容器技術(shù)就基本掌握了。
2009年,Cloud Foundry基于LXC實(shí)現了對容器的操作,該項目取名為Warden。2010年,dotCloud公司同樣基于LXC技術(shù),使用Go語(yǔ)言實(shí)現了一款容器引擎,也就是現在的Docker。那時(shí),dotCloud公司還是個(gè)小公司,出生卑微的Docker沒(méi)什么熱度,活得相當艱難。
2013年,dotCloud公司決定將Docker開(kāi)源。開(kāi)源后,項目突然就火了。從大的說(shuō),火的原因就是Docker的這句口號“Build once,Run AnyWhere”。呵呵,是不是似曾相識?對的,和Java的Write Once,Run AnyWhere一個(gè)道理。對于一個(gè)程序員來(lái)說(shuō),程序寫(xiě)完后打包成就可以隨處部署和運行,開(kāi)發(fā)、測試和生產(chǎn)環(huán)境完全一致,這是多么大一個(gè)誘惑。程序員再也不用去定位因環(huán)境差異導致的各種坑爹問(wèn)題。
Docker開(kāi)源項目的異?;鸨?,直接驅動(dòng)dotCloud公司在2013年更名為Docker公司。Docker也快速成長(cháng),干掉了CoreOS公司的rkt容器和Google的lmctfy容器,直接變成了容器的事實(shí)標準。也就有了后來(lái)人一提到容器就認為是Docker。
總結起來(lái),Docker為什么火,靠的就是Docker鏡像。他打包了應用程序的所有依賴(lài),徹底解決了環(huán)境的一致性問(wèn)題,重新定義了軟件的交付方式,提高了生產(chǎn)效率。
Docker在容器領(lǐng)域快速成長(cháng),野心自然也變大了。2014年推出了容器云產(chǎn)品Swarm(Kubenetes的同類(lèi)產(chǎn)品),想擴張事業(yè)版圖。同時(shí)Docker在開(kāi)源社區擁有絕對話(huà)語(yǔ)權,相當強勢。這種走自己的路,讓別人無(wú)路可走的行為,讓容器領(lǐng)域的其他大廠(chǎng)玩家很是不爽,為了不讓Docker一家獨大,決定要干他。
2015年6月,在Google、Redhat等大廠(chǎng)的“運作”下,Linux基金會(huì )成立了OCI(Open Container Initiative)組織,旨在圍繞容器格式和運行時(shí)制定一個(gè)開(kāi)放的工業(yè)化標準,也就是我們常說(shuō)的OCI標準。同時(shí),Docker公司將Libcontainer模塊捐給CNCF社區,作為OCI標準的實(shí)現,這就是現在的RunC項目。說(shuō)白了,就是現在這塊兒有個(gè)標準了,大家一起玩兒,不被某個(gè)特定項目的綁定。
講到Docker,就得說(shuō)說(shuō)Google家的Kubernetes,他作為容器云平臺的事實(shí)標準,如今已被廣泛使用,儼然已成為大廠(chǎng)標配。Kubernetes原生支持Docker,讓Docker的市場(chǎng)占有率一直居高不下。如圖是2019年容器運行時(shí)的市場(chǎng)占有率。
但在2020年,Kubernetes突然宣布在1.20版本以后,也就是2021年以后,不再支持Docker作為默認的容器運行時(shí),將在代碼主干中去除dockershim。
如圖所示,Kubenetes自身定義了標準的容器運行時(shí)接口CRI(Container Runtime Interface),目的是能對接任何實(shí)現了CRI接口的容器運行時(shí)。在初期,Docker是容器運行時(shí)不容置疑的王者,Kubenetes便內置了對Docker的支持,通過(guò)dockershim來(lái)實(shí)現標準CRI接口到Docker接口的適配,以此獲得更多的用戶(hù)。隨著(zhù)開(kāi)源的容器運行時(shí)Containerd(實(shí)現了CRI接口,同樣由Docker捐給CNCF)的成熟,Kubenetes不再維護dockershim,僅負責維護標準的CRI,解除與某特定容器運行時(shí)的綁定。當然,也不是Kubenetes不支持Docker了,只是dockershim誰(shuí)維護的問(wèn)題。 隨著(zhù)Kubenetes態(tài)度的變化,預計將會(huì )有越來(lái)越多的開(kāi)發(fā)者選擇直接與開(kāi)源的Containerd對接,Docker公司和Docker開(kāi)源項目(現已改名為Moby)未來(lái)將會(huì )發(fā)生什么樣的變化,誰(shuí)也說(shuō)不好。
講到這里,不知道大家有沒(méi)有注意到,Docker公司其實(shí)是捐獻了Containerd和runC。這倆到底是啥東西。簡(jiǎn)單的說(shuō),runC是OCI標準的實(shí)現,也叫OCI運行時(shí),是真正負責操作容器的。Containerd對外提供接口,管理、控制著(zhù)runC。所以上面的圖,真正應該長(cháng)這樣。
Docker公司是一個(gè)典型的小公司因一個(gè)爆款項目火起來(lái)的案例,不管是技術(shù)層面、公司經(jīng)營(yíng)層面以及如何跟大廠(chǎng)纏斗,不管是好的方面還是壞的方面,都值得我們去學(xué)習和了解其背后的故事。
按國際慣例,在介紹一個(gè)新概念的時(shí)候,都得從大家熟悉的東西說(shuō)起。幸好容器這個(gè)概念還算好理解,喝水的杯子,洗腳的桶,養魚(yú)的缸都是容器。容器技術(shù)里面的“容器”也是類(lèi)似概念,只是裝的東西不同罷了,他裝的是應用軟件本身以及軟件運行起來(lái)需要的依賴(lài)。用魚(yú)缸來(lái)類(lèi)比,魚(yú)缸這個(gè)容器里面裝的應用軟件就是魚(yú),裝的依賴(lài)就是魚(yú)食和水。這樣大家就能理解Docker的Logo了。大海就是宿主機,Docker就是那條鯨魚(yú),鯨魚(yú)背上的集裝箱就是容器,我們的應用程序就裝在集裝箱里面。
在講容器的時(shí)候一定繞不開(kāi)容器鏡像,這里先簡(jiǎn)單的把容器鏡像理解為是一個(gè)壓縮包,后續再詳細講解。壓縮包里包含應用的可執行程序以及程序依賴(lài)的文件(例如:配置文件和需要調用的動(dòng)態(tài)庫等),接下來(lái)通過(guò)實(shí)際操作來(lái)看看容器到底是個(gè)啥。
這是Docker的標準命令。意思是使用euleros_arm:2.0SP8SPC306鏡像(鏡像名:版本號)創(chuàng )建一個(gè)新的名字為“aimar-1-container”的容器,并在容器中執行shell命令:每秒打印一次“aimar-1-container”。
參數說(shuō)明:
從輸出中,我們看到一串長(cháng)字符207b7c0cbd811791f7006cd56e17033eb430ec656f05b6cd172c77cf45ad093c。他就是容器ID,能唯一標識一個(gè)容器。當然在使用的時(shí)候,不需要使用全id,直接使用縮寫(xiě)id即可(全id的前幾位)。例如下圖中,通過(guò)docker ps查詢(xún)到的容器id為207b7c0cbd81。
aimar-1-container容器啟動(dòng)成功后,我們在宿主機上使用ps進(jìn)行查看。這時(shí)可以發(fā)現剛才啟動(dòng)的容器就是個(gè)進(jìn)程,PID為12280。
我們嘗試著(zhù)再啟動(dòng)2個(gè)容器,并再次在宿主機進(jìn)行查看,你會(huì )發(fā)現又新增了2個(gè)進(jìn)程,PID分別為20049和21097。
所以,我們可以得到一個(gè)結論。從宿主機的視角看,容器就是進(jìn)程。
docker exec也是Docker的標準命令,用于進(jìn)入某個(gè)容器。意思是進(jìn)入容器id為207b7c0cbd81的容器,進(jìn)入后執行/bin/bash命令,開(kāi)啟命令交互。
參數說(shuō)明:
從hostname從kwephispra09909變化為207b7c0cbd81,說(shuō)明我們已經(jīng)進(jìn)入到容器里面了。在容器中,我們嘗試著(zhù)啟動(dòng)一個(gè)新的進(jìn)程。
再次回到宿主機進(jìn)行ps查看,你會(huì )發(fā)現不管是直接啟動(dòng)容器,還是在容器中啟動(dòng)新的進(jìn)程,從宿主機的角度看,他們都是進(jìn)程。
前面我們已經(jīng)進(jìn)入容器里面,并啟動(dòng)了新的進(jìn)程。但是我們并沒(méi)有在容器里查看進(jìn)程的情況。在容器中執行ps,會(huì )發(fā)現得到的結果和宿主機上執行ps的結果完全不一樣。下圖是容器中的執行結果。
在Container1容器中只能看見(jiàn)剛起啟動(dòng)的shell進(jìn)程(container1和container1-embed),看不到宿主機上的其他進(jìn)程,也看不到Container2和Container3里面的進(jìn)程。這些進(jìn)程像被關(guān)進(jìn)了一個(gè)盒子里面,完全感知不到外界,甚至認為我們執行的container1是1號進(jìn)程(1號進(jìn)程也叫init進(jìn)程,是系統中所有其他用戶(hù)進(jìn)程的祖先進(jìn)程)。所以,從容器的視角,容器覺(jué)得“我就是天,我就是地,歡迎來(lái)到我的世界”。
但尷尬的是,在宿主機上,他們卻是普通得不能再普通的進(jìn)程。注意,相同的進(jìn)程,在容器里看到的進(jìn)程ID和在宿主機上看到的進(jìn)程ID是不一樣的。容器中的進(jìn)程ID分別是1和1859,宿主機上對應的進(jìn)程ID分別是12280和9775(見(jiàn)上圖)。
通過(guò)上面的實(shí)驗,對容器的定義就需要再加上一個(gè)定語(yǔ)。容器就是進(jìn)程=@gt;容器是與系統其他部分隔離開(kāi)的進(jìn)程。這個(gè)時(shí)候我們再看下圖就更容易理解,容器是跑在宿主機OS(虛機容器的宿主機OS就是Guest OS)上的進(jìn)程,容器間以及容器和宿主機間存在隔離性,例如:進(jìn)程號的隔離。
在容器內和宿主機上,同一個(gè)進(jìn)程的進(jìn)程ID不同。例如:Container1在容器內PID是1,在宿主機上是12280。那么該進(jìn)程真正的PID是什么呢?當然是12280!那為什么會(huì )造成在容器內看到的PID是1呢,造成這種幻象的,正是Linux Namespace。
Linux Namespace是Linux內核用來(lái)隔離資源的方式。每個(gè)Namespace下的資源對于其他Namespace都是不透明,不可見(jiàn)的。
Namespace按隔離的資源進(jìn)行分類(lèi):
前面提到的容器內外,看到的進(jìn)程ID不同,正是使用了PID Namespace。那么這個(gè)Namespace在哪呢?在Linux上一切皆文件。是的,這個(gè)Namespace就在文件里。在宿主機上的proc文件中(/proc/進(jìn)程號/ns)變記錄了某個(gè)進(jìn)程對應的Namespace信息。如下圖,其中的數字(例如:pid:[ 4026534312])則表示一個(gè)Namespace。
對于Container1、Container2、Container3這3個(gè)容器,我們可以看到,他們的PID Namespace是不一樣的。說(shuō)明他們3個(gè)容器中的PID相互隔離,也就是說(shuō),這3個(gè)容器里面可以同時(shí)擁有PID號相同的進(jìn)程,例如:都有PID=1的進(jìn)程。
在一個(gè)命名空間中,那這倆進(jìn)程就相互可見(jiàn),只是PID與宿主機上看到的不同而已。
至此,我們可以對容器的定義再細化一層。容器是與系統其他部分隔離開(kāi)的進(jìn)程=》容器是使用Linux Namespace實(shí)現與系統其他部分隔離開(kāi)的進(jìn)程。
免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng )、來(lái)自本網(wǎng)站內容采集于網(wǎng)絡(luò )互聯(lián)網(wǎng)轉載等其它媒體和分享為主,內容觀(guān)點(diǎn)不代表本網(wǎng)站立場(chǎng),如侵犯了原作者的版權,請告知一經(jīng)查實(shí),將立刻刪除涉嫌侵權內容,聯(lián)系我們QQ:712375056,同時(shí)歡迎投稿傳遞力量。
Copyright ? 2009-2022 56dr.com. All Rights Reserved. 特網(wǎng)科技 特網(wǎng)云 版權所有 特網(wǎng)科技 粵ICP備16109289號
域名注冊服務(wù)機構:阿里云計算有限公司(萬(wàn)網(wǎng)) 域名服務(wù)機構:煙臺帝思普網(wǎng)絡(luò )科技有限公司(DNSPod) CDN服務(wù):阿里云計算有限公司 百度云 中國互聯(lián)網(wǎng)舉報中心 增值電信業(yè)務(wù)經(jīng)營(yíng)許可證B2
建議您使用Chrome、Firefox、Edge、IE10及以上版本和360等主流瀏覽器瀏覽本網(wǎng)站