如果你在用 Docker 或者 Kubernetes 想必你对 容器运行时 这个概念应该不会太陌生。
在 Docker
中,当你使用 docker info
即可查看当前所使用的 runtime。
➜ ~ docker info
...
Server Version: 18.06.1-ce
Storage Driver: overlay2
Backing Filesystem: extfs
Supports d_type: true
Native Overlay Diff: true
Logging Driver: json-file
Cgroup Driver: cgroupfs
...
Swarm: inactive
Runtimes: nvidia runc
Default Runtime: runc
Init Binary: docker-init
containerd version: 468a545b9edcd5932818eb9de8e72413e616e86e
runc version: 69663f0bd4b60df09991c08812a60108003fa340
init version: fec3683
Security Options:
seccomp
Profile: default
...
同时,你还可以自己在 /etc/docker/daemon.json
中增加支持的 runtime , 以及在 docker run
的时候,通过 --runtime
参数配置所使用的 runtime 。
什么是 runc
简单来说,它是 OCI
标准的一种实现。 OCI
标准包含 运行时标准 和 镜像标准 两个部分,而 OCI
这个组织则是由 Docker, CoreOS 和其他的一些公司共同发起创建的,致力于将容器运行时和格式标准化。
即:凡是遵守此标准的实现,无论是 Docker
还是 rkt
或者其他的运行时实现,均可以通过标准的镜像启动容器。
runc
则是在 OCI
成立后,Docker
将其容器运行时 libcontainer
贡献出来后,并加以改造而成的。而 libcontainer
也是在 Docker
0.9 版本开始加入,我也是从这个版本开始使用它。
当然 libcontainer
出现的本意不仅是替换当时的 LXC
依赖,同时也希望能以此作为规范(让其他的项目使用)最终,目标达成。
runc
如何使用
runc
的使用本不是本篇的重点,稍微带过。
➜ ~ docker export -o debian.tar `docker create debian`
➜ ~ ls
debian.tar
➜ ~ tar -C rootfs -xf debian.tar
➜ ~ ls
debian.tar rootfs
➜ ~ tree -L 1 -a rootfs
rootfs
├── bin
├── boot
├── dev
├── .dockerenv
├── etc
├── home
├── lib
├── lib64
├── media
├── mnt
├── opt
├── proc
├── root
├── run
├── sbin
├── srv
├── sys
├── tmp
├── usr
└── var
19 directories, 1 file
通过以上操作,得到了运行一个容器所必须的 rootfs
,当然,上面看到我是通过 docker
来获得这个文件的,但其实这只是为了方便罢了,docker
并不是必须的。
➜ ~ runc spec
➜ ~ ls
config.json debian.tar rootfs
通过上面的操作,会得到一个基本的 config.json
的配置文件,这里面包含着运行一个容器所需要的一些配置。其中会包含着一些例如:
"ociVersion": "1.0.1-dev"
这种用于标识规范版本号的信息。
接下来稍微对 config.json
文件进行查看,便可以看到未通过 user
Namespace 进行隔离,所以我们需要以 root
权限运行我们的容器。
➜ ~ sudo runc run debian
# ls
bin boot dev etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var
# hostname
runc
# cat /etc/os-release
PRETTY_NAME="Debian GNU/Linux 9 (stretch)"
NAME="Debian GNU/Linux"
VERSION_ID="9"
VERSION="9 (stretch)"
ID=debian
HOME_URL="https://www.debian.org/"
SUPPORT_URL="https://www.debian.org/support"
BUG_REPORT_URL="https://bugs.debian.org/"
可以看到容器已经运行成功。当然,我们也可以不通过 root
权限运行容器,只要简单的通过 user
Namespace 进行隔离,并添加 user
和 group
的映射之类的便可以了。此处不做赘述。
为何有 runc 1.0-rc6
存在
我们知道,OCI
在 2015 年成立,在 2017 年 7 月的时候正式宣布 OCI
v1.0.0 release 。其实在 2017 年的 11 月还 release 了 v1.0.1 版本。
前面已经提过 runc
是 OCI
的官方实现,那为何时过一年还未正式 release 1.0 呢?这里面原因其实说来也复杂,这也是这篇文章想聊的部分。
首先:runc
1.0 我们想正式 relase 么? 答案是 想。其实早在 2017 年 8 月份的时候 runc 1.0-rc4
就已经支持 OCI
v1.0.0 了。但当时并没有进行正式版发布,转而三个月后, OCI
稍做了更新。
到 2018 年 2 月份的时候,发布了 runc 1.0-rc5 -- "The Final Stretch"
这个版本取名其实已经很明确了 The Final Stretch
已经将这个版本作为正式版本前的最后一个版本进行发布了。
但是,提笔前又发了新版本 runc 1.0-rc6 -- "For Real This Time"
,这个版本在预期中其实是想发布 1.0 的。我们讨论后总结的结论主要有以下几个:
不够规范。一方面是
runc
在持续的迭代改进,另一方面是目前很多其他的运行时实现的一些 hooks 依赖于当前的一些实现,而这些实现,并不完全符合规范。这就造成了一旦修正了这些 “错误” 势必造成其他运行时的不稳定和错误。发布周期不明确。目前容器相关生态中较为核心的项目,估计就
runc
的发布周期比较 “佛系” 了,我们甚至没有一个明确的发布周期。这次的总结中,我以 Kubernetes 的发布做了例子:
Kubernetes Release | Date | Cadence |
---|---|---|
Christening of 1.0 | 10th July 2015 | ~one year from inception |
From 1.0 to 1.1 | 9th November 2015 | 122 days |
From 1.1 to 1.2 | 16th March 2016 | 128 days |
From 1.2 to 1.3 | 1st July 2016 | 107 days |
From 1.3 to 1.4 | 26th September 2016 | 87 days |
From 1.4 to 1.5 | 12th December 2016 | 77 days |
From 1.5 to 1.6 | 28th March 2017 | 106 days |
From 1.6 to 1.7 | 30th June 2017 | 94 days |
From 1.7 to 1.8 | 28th September 2017 | 90 days |
From 1.8 to 1.9 | 15th December 2017 | 78 days |
From 1.9 to 1.10 | 28th March 2018 | 103 days |
From 1.10 to 1.11 | 3rd July 2018 | 97 days |
From 1.11 to 1.12 | ETA 25th September 2018 | 84 days |
以这个发布记录来看的话,每三个月作为以此发布相对合适,也比较通用。
至于这次,runc 1.0-rc6
的发布,将作为特性冻结发布,直到下次发布前,重点都将放在 “符合规范” 上面,同时也给其他的运行时实现充足的时间,用于做好兼容之类的。
总结
以上就是本次关于 runc 1.0-rc6
发布时的一些碎碎念,对这种情况颇有感慨,“符合规范” 并没有那么好做,尤其是做基础支撑的时候。
可以通过下面二维码订阅我的文章公众号【MoeLove】