雲原生(CNCF)很火,容器開放接口規范 CRI CNI OCI
CRI - Container Runtime Interface(容器運行時接口)
CRI中定義了容器和鏡像的服務的接口,因為容器運行時與鏡像的生命周期是彼此隔離的,因此需要定義兩個服務,該接口使用Protocol Buffer(序列化),基於gRPC
Container Runtime實現了CRI gRPC Server,包括RuntimeService和ImageService。該gRPC Server需要監聽本地的Unix socket,而kubelet則作為gRPC Client運行

啟用CRI
除非集成了rktnetes,否則CRI都是被默認啟用了,kubernetes1.7版本開始舊的預集成的docker CRI已經被移除。
要想啟用CRI只需要在kubelet的啟動參數重傳入此參數:--container-runtime-endpoint
遠程運行時服務的端點。當前Linux上支持unix socket,windows上支持tcp。例如:unix:///var/run/dockershim.sock(socket)
、 tcp://localhost:373(tcp)
,默認是unix:///var/run/dockershim.sock
,即默認使用本地的docker作為容器運行時
包含了兩個gRPC服務:
- RuntimeService:容器和Sandbox運行時管理
- ImageService:提供了從鏡像倉庫拉取、查看、和移除鏡像的RPC
CNI - Container Network Interface(容器網絡接口)
CNI(Container Network Interface) 是 google 和 CoreOS 主導制定的容器網絡標准,它本身並不是實現或者代碼,可以理解成一個協議。這個標准是在 rkt 網絡提議的基礎上發展起來的,綜合考慮了靈活性、擴展性、ip 分配、多網卡等因素.這個協議連接了兩個組件:容器管理系統和網絡插件。它們之間通過 JSON 格式的文件進行通信,實現容器的網絡功能。具體的事情都是插件來實現的,包括:創建容器網絡空間(network namespace)、把網絡接口(interface)放到對應的網絡空間、給網絡接口分配 IP 等等

OCI - Open Container Initiative
Linux基金會於2015年6月成立OCI(Open Container Initiative)組織,旨在圍繞容器格式和運行時制定一個開放的工業化標准,目前主要有兩個標准文檔:容器運行時標准 (runtime spec)和 容器鏡像標准(image spec)制定容器格式標准的宗旨概括來說就是不受上層結構的綁定,如特定的客戶端、編排棧等,同時也不受特定的供應商或項目的綁定,即不限於某種特定操作系統、硬件、CPU架構、公有雲等。

image spec(容器標准包)
OCI 容器鏡像主要包括幾塊內容:
- 文件系統:以 layer 保存的文件系統,每個 layer 保存了和上層之間變化的部分,layer 應該保存哪些文件,怎么表示增加、修改和刪除的文件等
- config 文件:保存了文件系統的層級信息(每個層級的 hash 值,以及歷史信息),以及容器運行時需要的一些信息(比如環境變量、工作目錄、命令參數、mount 列表),指定了鏡像在某個特定平台和系統的配置。比較接近我們使用 docker inspect <image_id> 看到的內容
- manifest 文件:鏡像的 config 文件索引,有哪些 layer,額外的 annotation 信息,manifest 文件中保存了很多和當前平台有關的信息
- index 文件:可選的文件,指向不同平台的 manifest 文件,這個文件能保證一個鏡像可以跨平台使用,每個平台擁有不同的 manifest 文件,使用 index 作為索引
runtime spec(容器運行時和生命周期)
容器標准格式也要求容器把自身運行時的狀態持久化到磁盤中,這樣便於外部的其它工具對此信息使用和演繹。該運行時狀態以JSON格式編碼存儲。推薦把運行時狀態的JSON文件存儲在臨時文件系統中以便系統重啟后會自動移除。基於Linux內核的操作系統,該信息應該統一地存儲在/run/opencontainer/containers目錄,該目錄結構下以容器ID命名的文件夾(/run/opencontainer/containers/<containerID>/state.json)中存放容器的狀態信息並實時更新。有了這樣默認的容器狀態信息存儲位置以后,外部的應用程序就可以在系統上簡便地找到所有運行着的容器了。
state.json文件中包含的具體信息需要有:
- 版本信息:存放OCI標准的具體版本號。
- 容器ID:通常是一個哈希值,也可以是一個易讀的字符串。在state.json文件中加入容器ID是為了便於之前提到的運行時hooks只需載入state.json就- - 可以定位到容器,然后檢測state.json,發現文件不見了就認為容器關停,再執行相應預定義的腳本操作。
- PID:容器中運行的首個進程在宿主機上的進程號。
- 容器文件目錄:存放容器rootfs及相應配置的目錄。外部程序只需讀取state.json就可以定位到宿主機上的容器文件目錄。
- 容器創建:創建包括文件系統、namespaces、cgroups、用戶權限在內的各項內容。
- 容器進程的啟動:運行容器進程,進程的可執行文件定義在的config.json中,args項。
- 容器暫停:容器實際上作為進程可以被外部程序關停(kill),然后容器標准規范應該包含對容器暫停信號的捕獲,並做相應資源回收的處理,避免孤兒進程的出現。
容器生命周期

- init 狀態:這個是我自己添加的狀態,並不在標准中,表示沒有容器存在的初始狀態
- creating:使用 create 命令創建容器,這個過程稱為創建中。創建包括文件系統、namespaces、cgroups、用戶權限在內的各項內容,
- created:容器創建出來,但是還沒有運行,表示鏡像和配置沒有錯誤,容器能夠運行在當前平台。進程的可執行文件定義在的config.json中,args項
- running:容器的運行狀態,里面的進程處於 up 狀態,正在執行用戶設定的任務
- stopped:容器運行完成,或者運行出錯,或者 stop 命令之后,容器處於暫停狀態。這個狀態,容器還有很多信息保存在平台中,並沒有完全被刪除
CRI OCI區別
Open Container Initiative,也就是常說的OCI,是由多家公司共同成立的項目,並由linux基金會進行管理,致力於container runtime的標准的制定和runc的開發等工作。所謂container runtime,主要負責的是容器的生命周期的管理。oci的runtime spec標准中對於容器的狀態描述,以及對於容器的創建、刪除、查看等操作進行了定義。在k8s 1.5版本之后,kubernetes推出了自己的運行時接口api–CRI(container runtime interface)。cri接口的推出,隔離了各個容器引擎之間的差異,而通過統一的接口與各個容器引擎之間進行互動。與oci不同,cri與kubernetes的概念更加貼合,並緊密綁定。cri不僅定義了容器的生命周期的管理,還引入了k8s中pod的概念,並定義了管理pod的生命周期。在kubernetes中,pod是由一組進行了資源限制的,在隔離環境中的容器組成。而這個隔離環境,稱之為PodSandbox。在cri開始之初,主要是支持docker和rkt兩種。其中kubelet是通過cri接口,調用docker-shim,並進一步調用docker api實現的。后來,docker獨立出來了containerd,kubernetes也順應潮流,孵化了cri-containerd項目,用以將containerd接入到cri的標准中。為了進一步與oci進行兼容,kubernetes還孵化了cri-o,成為了架設在cri和oci之間的一座橋梁。
通過這種方式,可以方便更多符合oci標准的容器運行時,接入kubernetes進行集成使用。可以預見到,通過cri-o,kubernetes在使用的兼容性和廣泛性上將會得到進一步加強。

reference
https://github.com/containerd
https://github.com/kata-containers
轉載:https://www.jianshu.com/p/62e71584d1cb //很不錯的總結值得學習