2021-05-12 14:32:11
Linux容器技術進化史
在過去幾年中,容器技術不僅僅在開發者中成為熱門話題,許多企業也參與其中。這種對容器興趣的日益增加,使得對其安全提升和加固的需求不斷提升,同時也對可延伸性和互操作型有了更高的要求。這些工作都是大工程,本文介紹了紅帽在企業級容器支援上所做的工作。
當我在2013年秋季首次遇到Docker公司(Docker.io)的代表時,我們還在研究如何在紅帽企業版(Red Hat Enterprise Linux,RHEL)中使用Docker容器。(現在Docker專案的一部分已經被改名為Moby。)在將這項技術融入到RHEL時,我們遇到了許多問題。首先遇到的最大障礙是找到一個支援寫時複製(Copy On Write,COW)的檔案系統來處理容器映象分層。紅帽最終為包括Device Mapper、btrfs和最初版本的OverlayFS貢獻了部分COW實現。對於RHEL,我們預設使用Device Mapper,雖然當時對OverlayFS的支援已經快完成了。
另一個大障礙是啟動容器的工具。當時,上游docker使用LXC工具來啟動容器,但是我們不希望在RHEL中支援LXC工具集。在與上游docker公司合作之前,我和libvirt團隊合作,製作了名為virt-sandbox的工具,它能夠通過libvirt-lxc來啟動容器。
當時,紅帽公司一些人認為,將LXC工具集移除,在Docker守護行程和libvirt之間通過libvirt-lxc來橋接啟動容器是個不錯的想法。但是這種實現方式令人擔憂。使用該方式通過Docker用戶端(docker-cli)來啟動容器,用戶端和容器進程(pid1OfContainer)之間的呼叫層次有:
docker-cli → docker-daemon → libvirt-lxc → pid1OfContainer
我不太贊同啟動容器的工具和實際執行容器之間有兩個守護行程。
我的團隊開始和上游docker開發者一起,通過原生Go語言實現了一個名為容器執行時庫:libcontainer。該庫最終作為OCI執行時規範runc的初始實現發布。
docker- cli → docker-daemon @ pid1OfContainer
有許多人誤以為當他們執行一個容器的時候,容器進程是docker-cli的子進程。事實上,docker是一個典型的C/S架構,容器進程執行在一個完全獨立的環境中。這樣的C/S架構,可能導致不穩定和潛在的安全隱患,另外還會導致一些系統特性無法使用。例如,systemd有一個稱為通訊端啟用(socket activation)的特性,使用者可以設定守護行程僅在進程連線到通訊端時才執行。這樣可以降低系統記憶體使用,讓服務按需執行。通訊端啟用的實現原理是systemd監聽一個TCP通訊端,當該通訊端接收到封包的時候,systemd啟用需要監聽該通訊端的服務。當這個服務啟用之後,systemd將通訊端轉交給新啟動的守護行程。將這個守護行程放到基於Docker的容器中之後,就會產生問題。通過在systemd的unit檔案中使用Docker用戶端命令可以啟動容器,但是systemd無法簡單的通過Docker用戶端命令將通訊端轉移到守護行程。
類似這樣的問題,讓我們意識到,有必要換一種執行容器的方式。
容器編排問題
上游docker專案致力於讓容器使用變得更加方便,它一直是學習Linux容器的好工具。我們可以通過簡單的使用類似docker run -ti Fedora sh
命令來啟動容器並進入容器中。
容器的真正優勢在於同時啟動大量元件,並將它們組裝成一個強大的應用程式。設定一個多容器應用的難點在於其複雜度的指數級增長,以及通過簡單的docker命令將分散的各個部分串聯起來。如何在資源有限的叢集節點中管理容器布局?如何管理這些容器的生命週期?類似問題還有很多。
在第一屆DockerCon上,至少有7個公司/開源專案展示了容器編排的方式。我們演示的是紅帽OpenShift的專案geard,它鬆散的基於OpenShift v2容器。紅帽決定我們需要在容器編排上重新審視,也可能和其他開源社群的人員合作。
Google演示的是Kubernetes容器編排工具,它是基於Google內部開發的編排工具所積累的經驗。OpenShift決定放棄Gear專案,開始和Google一起合作Kubernetes。Kubernetes目前已經稱為GitHub上最大的社群專案之一。
Kubernetes
Kubernetes最初使用Google的lmctfy作為其容器執行時庫。2014年夏天,lmctfy被移植支援Docker。Kubernetes會在叢集的每個節點執行一個名為kubelet的守護行程。這意味著原始的Kubernetes和Docker 1.8工作流程看上去是這樣的:
kubelet → dockerdaemon @ PID1
這又回到了兩個守護行程的模式。
還有更糟糕的。每次Docker發布,Kubernetes都會被破壞。Docker 1.10修改了後端儲存,導致所有映象都需要重新構建。Docker 1.11開始通過runc來啟動容器:
kubelet → dockerdaemon @ runc @PID1
Docker 1.12增加了一個容器守護行程來啟動容器。這樣的主要目的是滿足Docker Swarm(一個Kubernetes的競爭對手)的需求:
kubelet → dockerdaemon → containerd @runc @ pid1
前面提到了,每次Docker發布新版本都會破壞Kubernetes的功能,因此對於Kubernetes和OpenShift等工具都需要適配舊版本Docker。
現在,已經進化成三守護行程系統,這種架構下守護行程中的任何一部分出錯了,整個系統都會分崩離析。
走向容器標準化
CoreOS、rkt其他執行時環境
由於Docker執行時庫的各種問題,多個組織都在尋求其替代方案。其中一個組織是CoreOS。CoreOS為上游docker提供了一個替代的容器執行時環境rkt(rocket)。同時,CoreOS還引入了一個標準容器規範:appc(App Container)。簡單的說,他們希望大家在處理容器映象儲存的時候可以使用統一的標準規範。
這是一個對社群的警示。在剛開始和上游docker合作容器專案的時候,我最大的擔憂是最終會有多個標準。我不希望會出現類似RPM格式和Debian格式(deb)之間的戰爭,這場戰爭影響了後來20年的Linux軟體分發。appc提出的一個利好是它說服了上游docker和開源社群一起建立一個標準體:Open Container Initiative(OCI)。
OCI一直在制定兩種規範:
- OCI執行時規範:OCI執行時規範“旨在定義設定、執行環境和容器的生命週期。”它定義了容器在硬碟上儲存的方式,用於描述容器中應用程式的JSON檔案和如何建立和執行容器。上游docker貢獻了libcontainer,並且提供了runc作為OCI執行時規範的預設實現。
*OCI映象格式規範:映象格式規範基本上基於上游docker映象格式,同時定義了容器映象在容器倉庫中的格式。該標準允許應用程式開發者將他們的應用程式標準化成同樣的格式。appc規範描述的一些特性已經合併如OCI映象格式規範。這兩個OCI規範都已經接近1.0正式版本。(1.0正式版本已經於2017年7月20日發布,譯者注)上游docker已經統一在其正式發布之後支援OCI映象規範。rkt現在同時支援OCI映象和傳統docker映象格式。
通過提供容器映象和執行時的行業規範,OCI幫助了容器相關工具和編排框架上的革新。
抽象執行時介面
Kubernetes編排工具是這些標準的受益者之一。作為Kubernetes的一大支援者,CoreOS提交了一系列的修補程式為Kubernetes增加了通過rkt執行容器的支援。Google和Kubernetes社群發現應用了這些修補程式之後,將來要為Kubernetes增加新的容器執行時支援會使得Kubernetes程式碼變得複雜和臃腫。因此Kubernetes團隊決定實現一套名為容器執行時介面(Container Runtime Interface,CRI)的API協定規範。然後他們重構了Kubernetes,使其直接呼叫CRI,而不用呼叫Docker引擎。如果以後需要新增新的容器執行時介面,只需要實現CRI的伺服器端介面即可。同時,Kubernetes為CRI開發者提供了大量測試集用來驗證這些實現是否相容Kubernetes。CRI的抽象,還有一項需要持續進行工作:將原先Kubernetes中對Docker引擎的直接呼叫去除,移動到稱為docker-shim的適配層中去。
容器工具創新
映象倉庫創新——skopeo
幾年前我們在Atomic專案中開發atomic命令列介面。其中一個功能是,我們希望能夠有一個工具,當映象還在映象倉庫的時候,就可以驗證其中的內容。當時,唯一的變通方式是通過容器映象關聯的JSON檔案將映象拉取到本地,然後再通過docker inspect
命令來讀取映象資訊。這些映象可能非常大,佔用上G空間。有了這項功能,就能夠讓使用者能夠提前檢查映象內容,以確定是否需要拉取映象,因此我們為docker inspect
命令增加了一個--remote
的引數。但是上游docker拒絕了這個pull request,原因是他們不希望將Docker命令列介面弄的複雜,並且使用者可以通過自己的小工具來實現同樣的功能。
由Antonio Murdaca領導的我們團隊,最終完成了名為skopeo的工具。Antonio將這個工具定位不僅局限於拉取映象的組態檔,他還實現了將容器映象從映象倉庫拉取到本地伺服器,從本地伺服器推播映象到映象倉庫的雙向協定。
目前,skopeo已經重度融入在atomic命令列介面中,包括檢查容器更新、整合入atomic scan命令實現中等。Atomic也使用skopeo來拉取和推播映象,而非使用上游的docker守護行程。
Containers/image庫
我們一直在和CoreOS溝通關於在rkt中使用skopeo的可行性,但是對方一直不願意通過一個可以執行的幫助應用程式,而是希望能夠將skopeo功能作為依賴庫直接整合進去。因此我們決定將skopeo拆分成庫和可執行程式,最終建立了image工程。
containers/image庫和skopeo已經被一些上游專案和雲服務基礎設施工具使用。二者已經能夠支援除Docker外的其他多種儲存後端,並且它們提供了諸如在映象倉庫之間移動映象等許多特性。skopeo的一個優勢在於,它的工作不依賴任何守護行程。containers/image庫的突破,也讓類似容器映象簽名等增強功能的實現成為了可能。
映象處理和掃描的創新
前文提到了atomic命令列介面,該工具用來實現docker命令列介面不相容的特性和一些我們覺得上游docker不會接受的特性。另外我們還希望它能夠可延伸的支援其他容器執行時、工具和儲存。前面提到的skopeo就驗證了這點。
其中一個我們想加入到atomic的特性是atomic mount
。該命令的需求來源是能夠從Docker映象儲存(上游docker稱之為圖驅動,graph driver)獲取資料,並將其掛載到某個地方,這樣可以使用其他工具來檢查這個映象。目前如果使用原生docker,檢視映象內容的唯一方式是啟動容器。如果映象中包含不受信內容,僅僅為了檢視映象內容而執行其程式碼是非常危險的。啟動容器然後驗證內容的另外一個問題是,用於檢查的工具通常不會包含在容器映象中。
大部分容器映象掃描工具的工作流程通常如下:它們連線到Docker通訊端,執行docker save
命令建立一個壓縮包,然後將其解壓縮到硬碟上,最後檢查這些內容。這個操作流程很慢。
有了atomic mount
命令,我們可以直接通過Docker圖驅動(graph driver)來掛載映象。如果Docker守護行程使用裝置對映器(device mapper),它可以掛載這個裝置;如果使用的是overlay檔案系統,它可以掛載overlay。這樣可以快速的滿足我們的需求。現在只需要這樣做:
# atomic mount fedora /mnt # cd /mnt
然後就可以開始檢查內容。當檢查完畢之後,執行:
# atomic umount /mnt
我們將該特性融入到了atomic scan
命令中,這樣就可以構建一個快速映象掃描器了。
工具協調問題atomic mount
命令使用過程中一個大問題是它獨立工作。Docker守護行程無法感知到還有其他進程在使用映象。這可能導致一些問題(例如,有人首先用前面提到的命令掛載Fedora映象,然後其他人執行了docker rmi fedora
命令,Docker守護行程在試圖刪除Fedora映象的時候會因為裝置忙而失敗)。此時Docker守護行程會進入不可預知的狀態。
Container/storage庫
為了解決這個問題,我們開始將上游docker daemon程式碼中圖驅動相關程式碼拉取到自己的倉庫。Docker守護行程的圖驅動將所有鎖相關操作都在自己的記憶體中完成。我們希望能夠將鎖相關實現移動到檔案系統中,這樣不同的進程能夠同時操作容器儲存,而無需都通過守護行程這個單點。
最終該專案被命名為container/storage,它實現了容器在執行、構建和儲存時所需要的所有寫時複製(COW)特性,而無需使用一個進程來控制和監控(即不需要守護行程)。現在skopeo和其他一些工具和專案都能夠更好的使用儲存。還有一些其他開源專案開始使用containers/storage庫,在某個時間點我們希望這個專案能夠合併回上游的docker專案。
啟航,進行創新
下面讓我們來看下Kubernetes在一個節點上通過Docker守護行程執行一個容器時,到底發上了什麼。首先Kubernetes執行一個命令:
kubelet run nginx –image=nginx
該命令告訴kubelet在節點上執行nginx應用程式。kubelet呼叫容器執行時介面,要求其啟動nginx應用程式。此時,容器執行時介面的實現需要完成以下步驟:
- 檢查本地儲存中名為nginx的映象。如果本地不存在,容器執行時將會在映象倉庫中查詢對應的映象。
- 如果映象在本地儲存中不存在,將其從映象倉庫下載到本地系統中。
- 將下載的容器映象釋放到容器儲存中(通常是一個寫時複製儲存),並掛載到適當位置。
- 使用標準化的容器執行時來執行容器。
讓我們來看看上述過程中依賴的特性:
- OCI映象格式:用於定義映象在倉庫中的標準儲存格式。
- Containers/image庫:用於實現從映象倉庫拉取映象所需要的所有特性。
- Containers/storage庫:提供OCI映象格式解壓縮到寫時複製儲存上所需要的功能。
- OCI執行時規範和
runc
:提供執行容器所需要的工具(和Docker守護行程用來執行容器的工具相同)。
這意味著我們可以使用這些工具和庫實現使用容器所需要的能力,而無需依賴一個大型容器守護行程。
在一個中等到大型規模基於DevOps的持續整合/持續交付環境中,效率、速度和安全性是非常重要的。而一旦相關的工具符合OCI規範,那麼開發和運維就能夠在持續整合/持續交付管道和生產環境中使用最佳的工具。大部分容器操作工具都隱藏在容器編排框架或者其他上層容器平台技術之下。可以預見到未來容器執行時和映象工具的選擇會成為容器平台的一個安裝選項。
系統(獨立)容器
Atomic專案中,我們引入了atomic host
,這是一個構建作業系統的新方式,其中的軟體可以“原子的”更新,並且大部分應用程式都以容器的方式執行。使用該平台的目的是為了證明大部分軟體能夠被移植到OCI映象格式,並能夠使用標準的協定從映象倉庫下載並安裝到系統中。將軟體以容器映象的方式提供,可以讓使用者的作業系統和應用軟體以不同的速度進行更新。傳統的RPM/yum/DNF方式分發軟體包會將應用程式版本限定在主機作業系統的生命週期中。
這種將基礎設定作為容器來分發的一個問題是,有的時候應用程式需要在容器執行時守護行程啟動前執行。讓我們來看一個使用Docker守護行程的Kubernetes例子:Kubernetes在啟動前需要先完成網路設定,這樣它才能夠將pods分配到獨立的網路環境中。該場景下目前我們使用的預設守護行程是flanneld,它必須在Docker守護行程啟動之前執行,以設定Docker守護行程的網路介面。同時,flanneld使用etcd作為資料儲存。該守護行程需要在flanneld之前啟動。
如果我們將etcd和flanneld通過映象分發,就會遇到先有雞還是先有蛋的問題。在啟動容器化應用程式之前需要一個容器執行時守護行程,但是這些應用程式又需要在容器執行時守護行程之前啟動。為了解決這個問題,我找到了一些hack的方式,但是沒有一種方式是徹底的。同時,Docker守護行程目前還沒有一個像樣的方式來設定容器啟動的優先順序。我看見過這方面的建議,但是目前的實現都是使用類似於老的SysVInit方式來啟動服務(當然我也知道這帶來的複雜性。)
systemd
使用systemd來替代SysVInit的一個原因是用來處理啟動服務的優先順序和順序,為什麼容器不能利用這項技術呢?在Atomic專案中,我們決定在主機上執行容器的時候不再需要容器執行時守護行程,尤其是那些啟動早期需要的服務。因此我們增強了atomic命令列介面,允許使用者安裝容器映象。當使用者執行atomic install --system etcd
時,atomic會使用skopeo從映象倉庫拉取etcd的OCI映象,然後將映象釋放到OSTree儲存中。因為我們在生產環境中執行etcd,因此該映象是唯讀的。下一步atomic
命令從容器映象中抓取systemd的unit檔案模板,並在硬碟上建立unit檔案用以啟動映象。該unit檔案通常使用runc
在主機上啟動容器(雖然runc不是必須的)。
如果執行atomic install --system flanneld
命令會發生類似的事情,除了這次生成flanneld的unit檔案將會指定etcd需要在它啟動前執行。
當系統啟動時,systemd確保etcd會在flanneld之前執行,並且容器執行時會在flanneld啟動之後再執行。該特性可以讓使用者將Docker守護行程和Kubernetes放到系統容器中。這意味著使用者可以啟動一個atomic host或者傳統基於rpm的作業系統,其中的整個容器編排框架以容器的方式執行。這項功能非常強大,因為我們知道客戶希望能夠獨立於這些元件,持續給他們的容器主機打修補程式。此外,它能夠將主機作業系統佔用空間最小化。
當然,關於將傳統應用程式放到容器中使其既能夠作為獨立/系統容器執行,又能夠成為可編排容器仍然有所爭論。考慮一個Apache容器,我們可以使用atomic install --system httpd
命令安裝。這個容器映象可以和基於rpm的httpd服務一樣的啟動(systemctl start httpd
,除了httpd進程將會啟動在容器中)。儲存仍然可以使用原生的,意味著可以將主機的/var/www目錄掛載到容器中,這個容器也監聽這本地網路的80埠。這表明我們可以在主機的容器中執行傳統工作負載,而無需一個容器執行時守護行程。
構建容器映象
在我看來,最近4年來容器創新中最令人悲傷的事情,就是構建容器映象構建機制缺乏創新。一個容器映象是一個由映象內容的壓縮包和一些JSON檔案組成的壓縮包。容器的基礎映象是一個完成的根檔案系統和一些描述用的JSON檔案。然後使用者可以在上面增加層,每個增加的層會形成一個壓縮包和記錄變化的JSON檔案。這些層和基礎映象一起打包組合成了容器映象。
基本上所有人都通過docker build
和Dockerfile格式檔案來構建映象。上游docker在幾年前就已經停止接受修改和增強Dockerfile格式和構建方式的pull request。在容器進化過程中,Dockerfile扮演了重要的角色。開發和運維可以簡單直接的方式構建映象。然而在我看來,Dockerfile只是一個簡化的bash指令碼,到目前為止還有好多問題沒有解決。例如:
- 為了構建容器映象,Dockerfile必須依賴Docker守護行程
- 目前為止還沒有人建立出標準的工具,可以獨立於Docker命令來建立OCI格式映象。
- 諸如
ansible-containers
和OpenShift S2I(Source2Image)等工具,仍然在底層使用了Docker引擎。
- Dockerfile中的每一行都會建立一個新的映象,這能夠提升開發階段構建映象的效率,因為工具可以知道Dockerfile中的每一行是否有修改,如果沒有修改,之前構建的映象可以被複用而無需重新構建。但是這會導致產生大量的層。
- 因為這個問題許多人都要求提供一個合併層的方式以限制層的數量。最終上游docker已經接受了部分建議滿足了該需求。
- 為了能夠從安全的站點拉取映象內容,通常使用者需要一些安全措施。例如使用者需要有RHEL認證和訂閱授權才能夠在映象中增加RHEL內容。
- 這些金鑰最終會儲存在映象的層中,開發者需要在這些層中移除它們。
- 為了能夠在構建映象的時候能夠掛載卷,我們在自己分發的atomic專案和docker包中增加了
-v
引數,但是上游docker沒有接受這些修補程式。
- 構建出來的元件最終被放置在容器映象中。因此,雖然Dockerfile對於剛開始構建的開發者,可以更好的了解整個構建過程,但是這對於大規模企業環境來說不是一個高效的方式。另外,在使用自動化容器平台之後,使用者不會關注構建OCI標準映象的方式是否高效。
出發吧buildah
在2017年DevConf.cz上,我讓我們團隊的Nalin Dahyabhai看看稱之為containers-coreutils的構建工具,本質上這是一個使用了containers/storage庫和containers/image庫的一系列命令列工具,它們可以模仿Dockerfile的語法。Nalin將其命令為buildah,用來取笑我的波士頓口音。使用一些buildah原語,我們就可以構建一個容器映象:
- 關於安全性的一個主要思想是確保作業系統的映象盡可能小,以限制不需要的工具。該想法的來源是駭客需要依賴工具來攻破應用程式,如果注入gcc、make、dnf等工具不存在,攻擊可能會停止或者受到限制。
- 另外,由於這些映象的拉取和推播都需要經過網際網路,縮小映象尺寸總是沒錯的。
- Docker構建映象的主要方式是通過命令將軟體安裝或者編譯到容器的
buildroot
中。 - 執行
run
命令需要這些可執行程式包含在容器映象中。例如在映象中使用dnf
命令需要安裝整個Python棧,即使最終的應用程式不會使用Python。 ctr=$(buildah from fedora)
:- 使用containers/image庫從映象倉庫拉取Fedora映象
- 返回一個容器ID(
ctr
)
mnt=$(buildah mount $ctr)
:- 掛載剛建立的容器映象(
$ctr
)。 - 返回掛載點路徑。
- 現在可以使用這個掛載點寫入內容。
- 掛載剛建立的容器映象(
dnf install httpd –installroot=$mnt
:- 我們可以使用主機系統上的命令將內容寫入到容器中,這意味著我們可以把金鑰放在主機上,而不用放入到容器中,另外構建工具也可以儲存在主機上。
- dnf等命令也不用事先安裝到容器中,Python等依賴也是,除非應用程式依賴。
cp foobar $mnt/dir
:- 我們可以使用bash支援的任何命令來填充容器。
buildah commit $ctr
:- 我們可以在需要的時候建立層。層的建立由使用者控制而不是工具。
buildah config --env container=oci --entrypoint /usr/bin/httpd $ctr
:- 在Dockerfile中支援的命令也可以指定。
buildah run $ctr dnf -y install httpd
:- buildah同樣支援
run
命令,它不依賴容器執行時守護行程,而是通過執行runc
直接在鎖定的??器中執行命令。
- buildah同樣支援
buildah build-using-dockerfile -f Dockerfile .
:- buildah同樣支援使用Dockerfile來構建映象。
我們希望將類似ansible-containers
和OpenShift S2I這樣的工具改成buildah
,而非依賴一個容器執行時守護行程。
構建容器映象和執行容器採用相同的執行時環境,對於生產環境還會遇到一個大問題,既針對容器安全需要同時滿足二者的許可權需求。通常構建容器映象的時候需要遠多於執行容器所需要的許可權。例如,預設情況下我們會允許mknod
能力。mknod
能力允許進程能夠建立裝置節點,但是在生產環境幾乎沒有應用程式需要這個能力。在生產環境中移除mknod
能力能夠讓系統變得更加安全。
另一個例子是我們會預設給容器映象以讀寫許可權,因為安裝進程需要將軟體包安裝到/usr
目錄中。但是在生產環境中,我個人建議應該將所有容器執行在唯讀模式。容器中的進程應該只能允許寫入tmpfs
或者掛載到容器內的捲上。通過將構建映象和執行容器分離,我們可以修改這些預設設定,讓執行環境更加安全。
Kubernetes的執行時抽象:CRI-O
Kubernetes增加了一套用於插拔任何pods執行時的API,稱為容器執行時介面(Container Runtime Interface,CRI)。我不願意在我的系統上執行太多的守護行程,但是我們基於此增加了一種。由我們團隊中Mrunal Patel領導的小組,在2016年晚些時候開始實現CRI-O守護行程。這是一個用於執行基於OCI應用程式的容器執行時介面守護行程。理論上,未來我們可以將CRI-O程式碼直接編譯如kubelet,以減少一個守護行程。
和其他容器執行時不同的是,CRI-O的唯一目的是滿足Kubernetes的需求。回憶一下前面提到的關於Kubernetes執行一個容器所需要的步驟。
Kubernetes向kubelet傳送一個訊息,通知它需要啟動一個nginx服務:
- kubelet呼叫CRI-O告知其執行nginx。
- CRI-O響應CRI請求。
- CRI-O在映象倉庫中找到對應的OCI映象。
- CRI-O使用containers/image將映象從倉庫拉取到本地。
- CRI-O使用containers/storage將映象解壓到本地儲存中。
- CRI-O使用OCI執行時規範啟動容器,通常使用
runc
。我前面提到過,這和Docker守護行程使用runc
來啟動容器的方式相同。 - 如果需要,kubelet也可以使用其他的執行時來啟動容器,例如Clear Containers的
runv
CRI-O旨在成為執行Kubernetes的穩定平台,我們只會在通過了所有Kubernetes的測試集之後才會發布新的版本。所有提交到https://github.com/Kubernetes-incubator/cri-o上的pull request都需要執行整個Kubernetes測試集。開發者不能提交一個無法通過這些測試的pull request。CRI-O是一個完全開放的專案,目前已經有來自Intel、SUSE、IBM、Google、Hyper.sh等公司的貢獻者。只要CRI-O的大多數維護者同意,pull request就會被接受,即使這些修補程式功能不是紅帽公司需要的。
總結
我希望本文的深入探討能夠幫助讀者了解Linux容器的演化史。Linux一度處於每個廠商有自己標準的情形。Docker公司專注於建立映象構建的事實標準,並且簡化了容器的相關工具。Open Container Initiative的建立意味著行業正在圍繞著核心映象格式和執行時制定規範,圍繞著讓工具更有效率、更安全、高可延伸性和可用性進行創新。容器允許我們能夠用新穎的方式驗證軟體安裝,無論其是執行在主機上的傳統軟體還是執行在雲端經過編排的微服務。在很多方面,這還僅僅是個開始。
檢視英文原文:https://opensource.com/article/17/7/how-linux-containers-evolved
本文永久更新連結地址:http://www.linuxidc.com/Linux/2018-02/150821.htm
相關文章