前言
在涉及到容器時你常常聽到一個術語:容器運行時。每一個人對這個術語都有不一樣的理解,即便在容器社區也是這種狀況。這篇文章是這個系列文章的第一篇,它們分別是:程序員
Low-Level
運行時High-Level
運行時Kubernetes運行時和CRIdocker
這篇文章將會介紹容器運行時是什麼和爲何會讓人如此困惑,而後深刻介容器運行時不一樣的類型,它們是如何工做的以及它們之間的不一樣點。網絡
一般來講,一個計算機程序員可能將一個程序的運行週期理解爲"運行時",或者是支持其運行的語言的特定實現,其中的一個例子是`Java HotSpot
運行時,後者更接近"容器運行時"的概念。容器運行時負責一個容器運行的全部部分,而容器實際上並未在運行程序自己。正如咱們將從本系列文章中看到的那樣,運行時實現了各個級別的功能特性,但實際上運行一個容器就是調用容器運行時所需的所有。工具
Docker於2013年發佈,它端到端地解決了開發者運行容器的諸多問題:ui
Dcokerfile/docker build
)Docker images, docker rm, etc
)docker ps, docker rm, etc
)docker push/pull
)docker run
)在那時,Docker是一個一體化的系統,然而事實上這些功能特性彼此之間並無相互依賴,它們中的每個均可以在一個更小更專一的工具實現,每一個工具均可以在一個通用的標準(容器標準)下一塊兒使用。由於這個緣故,Docker,Google,CoreOS
以及其餘的供應商一塊兒創立了開放容器規範(OCI
),同時他們拆分了容器運行這部分的代碼將其做爲一個工具或lib庫稱之爲run c
,而後捐贈給OCI
做爲OCI
運行標準的參考範例。
最初,這使Docker對OCI
的捐贈感到困惑,他們捐贈的是一個標準而不是運行容器的方法,其中並無包含鏡像格式或者鏡像倉庫拉取推送規則,當你運行一個Docker容器的時候,它們實際上通過了如下的步驟:spa
bundle
文件,將一個文件系統拆分紅多層bundle
文件運行容器Docker標準化的僅僅是第三步。在此以前,每一個人都認爲容器運行時支持Docker支持的全部功能。最終,Docker方面澄清:原始OCI規範指出,只有「運行容器」的部分組成了runtime
。這種「概念失聯」一直持續到今天,並使「容器運行時」成爲一個使人困惑的話題。但願我能證實雙方都不是徹底錯誤的,而且在本博文中將普遍使用該術語。操作系統
當人們想到容器運行時時,可能會想到許多示例。runc,lxc,lmctfy,Docker(containerd),rkt,cri-o
。這些中的每個都是針對不一樣的狀況而構建的,並實現了不一樣的功能。有些容器(例如containerd
和cri-o
容器)實際上使用runc來運行容器,在runc
之上實現了鏡像管理和API接口。與runc
的Low-Level
特性相比,您能夠將這些功能(包括圖像傳輸,圖像管理,圖像解壓縮和API)視爲High-Level
特性。考慮到這點,能夠看到容器運行時空間至關複雜,每一個運行時涵蓋了從Low-Level
到High-Level
的不一樣部分,這裏有一張很是直觀的圖:code
所以,從實際出發,一般只專一於正在運行的容器的runtime一般稱爲「Low-Level
容器運行時」,支持更多高級功能(如鏡像管理和gRPC / Web API
)的運行時一般稱爲「High-Level
容器運行時」,「High-Level
容器運行時」或一般僅稱爲「容器運行時」,我將它們稱爲「高級容器運行時」。值得注意的是,Low-Level
容器運行時和High-Level
容器運行時是解決不一樣問題的、從根本上不一樣的事物。容器是經過Linux nanespace
和Cgroups
實現的,Namespace
能讓你爲每一個容器提供虛擬化系統資源,像是文件系統和網絡,Cgroups
提供了限制每一個容器所能使用的資源的如內存和CPU使用量的方法。在最低級別的運行時中,容器運行時負責爲容器創建namespaces
和cgroups
,而後在其中運行命令,Low-Level
容器運行時支持在容器中使用這些操做系統特性。接口
一般狀況下,開發人員想要運行一個容器不只僅須要Low-Level
容器運行時提供的這些特性,同時也須要與鏡像格式、鏡像管理和共享鏡像相關的API接口和特性,而這些特性通常由High-Level
容器運行時提供。就平常使用來講,Low-Level
容器運行時提供的這些特性可能知足不了平常所需,由於這個緣故,惟一會使用Low-Level
容器運行時的人是那些實現High-Level
容器運行時以及容器工具的開發人員。那些實現Low-Level
容器運行時的開發者會說High-Level
容器運行時好比containerd
和cri-o
不像真正的容器運行時,由於從他們的角度來看,他們將容器運行的實現外包給了runc
。可是從用戶的角度來看,它們只是提供容器功能的單個組件,能夠被另外一個的實現替換,所以從這個角度將其稱爲runtime
仍然是有意義的。即便containerd
和cri-o
都使用runc
,可是它們是大相徑庭的項目,支持的特性也是很是不一樣的。內存