參考前一篇文章
目前的docker已經不是之前的docker了,技術棧進行了分層。
docker cli -> dockerd -> containerd -> oci implementation
OCI規範,簡單來說,包含容器規範和鏡像規範,具體參考:
link
由於引入了OCI,我們可以近乎透明無縫的替換 “docker run”命令 之下的具體實現。
根據自己業務場景的需求,可以選擇高性能的容器運行時,也可以選擇性能不那麼高但安全性更好的運行時。
目前符合OCI規範的容器運行時有:
- runc, docker默認的運行時,與宿主機共享內核,利用cgroup做資源隔離,安全性不是很高,由於內核共享,性能最好
- runv,基於hypervisor的容器運行時,有自己單獨的內核,安全性好很多
- kata,被螞蟻收了,號稱“容器的速度,虛擬機的安全”,貌似是基於runv做的
- gvisor,谷歌搞的,比runc安全,比VM性能要好。有一個用戶空間的內核,會攔截應用程序的系統調用,目前沒有實現所有的系統調用,因此不是所有的應用都可以運行
目前docker默認使用的容器運行時runc。
docker命令行有一個參數:runtime,可以制定底層的容器運行時,如
docker run --runtime=runc hello-world
runc官方有一個實例,介紹如何用runc運行一個容器
EXAMPLE:
To run docker's hello-world container one needs to set the args parameter
in the spec to call hello. This can be done using the sed command or a text
editor. The following commands create a bundle for hello-world, change the
default args parameter in the spec from "sh" to "/hello", then run the hello
command in a new hello-world container named container1:
mkdir hello
cd hello
docker pull hello-world
docker export $(docker create hello-world) > hello-world.tar
mkdir rootfs
tar -C rootfs -xf hello-world.tar
runc spec
sed -i 's;"sh";"/hello";' config.json
runc run container1
網上有一個runc 和 runv 運行示例的文章,參考: 鏈接
說回到kubernetes,k8s抽象出了一個CRI接口。
kubelet 通過該接口與底層不同的容器運行時進行交互,從而實現解耦。
其中的關係如下圖
kubelet通過gRPC方式調用CRI的相關接口,CRI shim是該接口的一個實現。
kubelet有一個選項“–container-runtime”,
默認爲docker,可以理解爲非CRI模式。
設置爲remote的時候,可以認爲是啓用了CRI模式,通過另外一個選項
–container-runtime-path-endpoint=
kubelet會通過指定的CRI地址來進行容器的管理。
這個圖看着可能會比較清楚