容器标准
小刀已经和众师兄弟们开始修习 Docker 功法。
这天,小刀抓住修习的空隙找到大师兄,问道:“大师兄,经过这么多天的修习,我们师兄弟们对 Docker 的使用已经了然于心了。但是我还有一事不明。”
“哦!?”大师兄看了他一眼,说到:“说来听听。”
“我们整天练习的 docker run,docker exec 之类的好像都是表面功夫,不管什么操作系统,好像都是一样的,这到底是如何做到的呢?”
“问的好!”大师兄嘴角微微上扬,“看来你已经不止于表面的功夫了。”
大师兄心想:这小子刚来没多久,进步却已经超过同辈师兄弟了。幸好我也不断提升自己,不然可要被他难住了。
“其实 Docker 很早就开始了 libcontainer 的项目。”大师兄说到,“这是一个容器抽象层,用于将容器的实现和上层的 CLI 相隔离,提供统一的抽象接口。”
“哦!是不是就像 API 接口一样,基于一套统一的规范,底层的修改就不会影响上层?”小刀问道。
“差不多。因为 Docker 的修习太过火热,Docker 门派也难以完全控制 Docker 功法的走向,所以 Docker 门派就联合了几大门派共同成立了 Open Container Initiative,也就是大名鼎鼎的 OCI 联盟。”
大师兄停下喝了口水,继续说到:“OCI 联盟在容器界举足轻重,主要的作用就是制定相关的标准。用这些标准来约束容器界的走向。”
“都有哪些标准呢?”小刀问道。
“比如说你刚才问的运行时标准 runtime spec。”大师兄说到,“这个标准用来定义容器的创建、运行、销毁等运行时规范。理论上,只要符合这个标准,都可以被 Docker 功法用来运行容器。”
“还有就是镜像标准 image-spec,定义镜像的规范等等。”
“这么厉害!刚才说的 libcontainer 就是满足运行时标准的吗?”小刀越听越兴奋。
大师兄看小刀一脸的崇拜,也不禁来了兴致,起身说到:“libcontainer 是 Docker 门派早期的抽象,OCI 联盟成立后,Docker 就将它贡献给了 OCI,然后改名为 runc 了。”
“原来还有这么一段故事,那么我们现在练的其实都是 runc 了?”小刀继续追问。
“不错,既然你这么想知道,我就给你看点东西。”大师兄走到桌边,取出一张功法图。
“你看,我们直接接触的是 Docker Engine。而 Docker Engine 是通过 gRPC 与 containerd 交互的,containerd 用来做镜像管理和容器运行时对接,是从 Docker Daemon 进化而来的,现在也是贡献给了另一大容器同盟 CNCF 了。”
大师兄见小刀一脸惊诧,已经不知道说什么了,眼睛直直地盯着功法图。
“而每个容器,都是由一个 shim 进程与 runc 进行交互,从上到下,各司其职,层层抽象。” 大师兄接着说。
“看来我们现在练的还只是冰山一角啊!”小刀感慨道。
“确实,对于你们简单修炼来说,只要能用就行了。但是如果你想在这容器界混出名头来,这其中的奥妙,却不可不知道。不过,没有几年的道行~”大师兄故作神秘的说。
大师兄看着小刀一直沉默,好像在思考什么。心想:你还是回去好好巩固下基础吧。
他故意说得很高深,不是想打击小刀,其实他也只是懂点皮毛而已。想借此吓住小刀,又树立了自己高大的形象,想想心里就美滋滋的。
“大师兄,我一定会努力的,我一定要在容器界混出点名堂来。”小刀坚定地说。
“嗯?”大师兄立刻收了思绪,回到严肃的状态,“那你可要多加用心了。”
“好的,大师兄,我一定不会让你失望的。”说罢,小刀告别离去。
大师兄看着他离去的背影,心想:这小子,人小心不小,那就让他自己去练吧。
容器运行时
春天的清晨清冷,天还微微亮,露水顺着树叶滑落,滴落池塘,虫儿吱吱的叫个不停。
大师兄内心烦躁,便起了床。让他烦躁的是几天前掌门交代的任务,让他给出门派的容器编排方案。
“我也是半路出家,还得是自己啃啊,奈何掌门给的期限太短了。”大师兄长叹一口气,又想,“但是这个任务除了我,还有谁能胜任呢?”
大师兄打开房门,一缕阳光照在他脸上,他下意识的用手遮挡,却远远看见一少年正在广场边的树下修炼。
“这么早就出来修炼?是谁呢?”大师兄心里嘀咕到,他赶紧穿上衣服过去,想看看到底是谁。
“大师兄早!”小刀看到大师兄走来,赶紧打招呼。
“哦,是小刀啊。怎么这么早?”大师兄问道。
“大师兄,我这几天一直在修炼 Docker 之术。”小刀擦了擦额头的汗珠,略有些兴奋,“我这几天正在修炼 runc,颇有些心得,大师兄能不能给我指教下?”
“看来前几天和你小子说的,你还当真了啊!”大师兄笑到,心里却暗自嘀咕:前几天吹个牛还当真了?runc 我哪里会啊,不行,还是找个理由走吧。
“大师兄,你看!”还没等大师兄找到借口,小刀已经兴奋的运功了。
# 创建根文件系统
mkdir /mycontainer
cd /mycontainer
# 创建 rootfs 文件夹
mkdir rootfs
# 通过 Docker 导出 busybox 到 rootfs 文件夹
docker export $(docker create busybox) | tar -C rootfs -xvf -
“大师兄,我先准备一个文件环境。”小刀边运功边说,“你看看我的 runc 用的有没有问题。”
“额,那个~”
“走起!大师兄你看!”大师兄刚想借尿遁,被小刀的一声大喝吓地憋了回去。
runc spec
“这样就创建了基本的容器配置文件。”小刀说到,“然后运行容器。”
cd /mycontainer
runc run mycontainerid
“使用默认的配置文件,就会在容器中运行一个 sh 命令。”小刀演示到。
/ # ls
bin dev etc home proc root sys tmp usr var
“可以这样方便地管理容器的生命周期。”小刀继续忘我地演示。
# 查看容器的运行状态
runc list
# 启动容器
runc start mycontainerid
# 几秒之后就能看到容器已经是 stop 状态了
runc list
# 删除容器
runc delete mycontainerid
大师兄怔在原地,他也被眼前这个小师弟震惊了,想看看他到底还学了些什么。
“其实,runc run 就是一个复合操作。”小刀见大师兄没有反应,赶紧解释道,“它包含了 create,start 和 delete 三个步骤,包含了容器的整个生命周期。”
“嗯,不错不错!”大师兄边鼓掌边说,“虽然简单,但也看得出,你还是下了点功夫的。”
“大师兄,我再给你看个~”受到大师兄的夸奖,小刀更兴奋了。
“且慢!我先考考你,runc 的秘籍从哪里获得?”大师兄赶紧制止了小刀。
“哦,大师兄考我呢,这个我知道的。”小刀说到,“秘籍是 OCI 联盟公开的。”
# runc 是 Go 语言开发的
# 在 GOPATH/src 目录下创建 github.com/opencontainers 目录
cd github.com/opencontainers
git clone https://github.com/opencontainers/runc
cd runc
make
sudo make install
“嗯,很好,今天就先到这吧,时候也不早了,大家都快起床了。”说完,大师兄就一溜烟走了。
“诶~好吧!”小刀见没有展示的机会,略有些沮丧。不过想到今天大师兄表扬了自己,还是非常开心地继续练功了。
“赶紧回去学学,不然可要被这小子反超了。”大师兄边走边心想,“不过,说不定他还真能帮我一把。”
后记
小刀这边逐渐入门了 Docker 功法,并向更深层次的理论学习。作为门派新入门的弟子,他究竟能修炼到什么程度?
而大师兄领衔的容器编排方案又该怎么做,敬请期待,下回分解。
请关注「容器霸业」,知乎专栏同步更新。
上一章:容器霸业:3 秘传心法
下一章:容器霸业:5 比武大会