Docker、Containerd、RunC...:你应该知道的所有

从Docker 1.11开始,Docker容器运行已经不是简单的通过Docker daemon来启动,而是集成了containerd、runC等多个组件。Docker服务启动之后,我们也可以看见系统上启动了dockerd、docker-containerd等进程,本文主要介绍新版Docker(1.11以后)每个部分的功能和作用。

Docker Daemon

作为Docker容器管理的守护进程,Docker Daemon从最初集成在docker命令中(1.11版本前),到后来的独立成单独二进制程序(1.11版本开始),其功能正在逐渐拆分细化,被分配到各个单独的模块中去。从Docker服务的启动脚本,也能看见守护进程的逐渐剥离:

在Docker 1.8之前,Docker守护进程启动的命令为:

docker -d
这个阶段,守护进程看上去只是Docker client的一个选项。

Docker 1.8开始,启动命令变成了:

docker daemon
这个阶段,守护进程看上去是docker命令的一个模块。

Docker 1.11开始,守护进程启动命令变成了:

dockerd
此时已经和Docker client分离,独立成一个二进制程序了。

当然,守护进程模块不停的在重构,其基本功能和定位没有变化。和一般的CS架构系统一样,守护进程负责和Docker client交互,并管理Docker镜像、容器。

  下面就来介绍下独立分拆出来的其他几个模块。

Containerd

containerd是容器技术标准化之后的产物,为了能够兼容OCI标准,将容器运行时及其管理功能从Docker Daemon剥离。理论上,即使不运行dockerd,也能够直接通过containerd来管理容器。(当然,containerd本身也只是一个守护进程,容器的实际运行时由后面介绍的runC控制。)

最近,Docker刚刚宣布开源containerd。从其项目介绍页面可以看出,containerd主要职责是镜像管理(镜像、元信息等)、容器执行(调用最终运行时组件执行)。

containerd向上为Docker Daemon提供了gRPC接口,使得Docker Daemon屏蔽下面的结构变化,确保原有接口向下兼容。向下通过containerd-shim结合runC,使得引擎可以独立升级,避免之前Docker Daemon升级会导致所有容器不可用的问题。

Docker、containerd和containerd-shim之间的关系,可以通过启动一个Docker容器,观察进程之间的关联。首先启动一个容器,

docker run -d busybox sleep 1000
然后通过pstree命令查看进程之间的父子关系(其中20708是dockerd的PID):

pstree -l -a -A 20708
输出结果如下:

dockerd -H fd:// --storage-driver=overlay2 |-docker-containe -l unix:///var/run/docker/libcontainerd/docker-containerd.sock --metrics-interval=0 --start-timeout 2m --state-dir /var/run/docker/libcontainerd/containerd --shim docker-containerd-shim --runtime docker-runc | |-docker-containe b9a04a582b66206492d29444b5b7bc6ec9cf1eb83eff580fe43a039ad556e223 /var/run/docker/libcontainerd/b9a04a582b66206492d29444b5b7bc6ec9cf1eb83eff580fe43a039ad556e223 docker-runc | | |-sleep 1000
虽然pstree命令截断了命令,但我们还是能够看出,当Docker daemon启动之后,dockerd和docker-containerd进程一直存在。当启动容器之后,docker-containerd进程(也是这里介绍的containerd组件)会创建docker-containerd-shim进程,其中的参数b9a04a582b66206492d29444b5b7bc6ec9cf1eb83eff580fe43a039ad556e223就是要启动容器的id。最后docker-containerd-shim子进程,已经是实际在容器中运行的进程(既sleep 1000)。

docker-containerd-shim另一个参数,是一个和容器相关的目录/var/run/docker/libcontainerd/b9a04a582b66206492d29444b5b7bc6ec9cf1eb83eff580fe43a039ad556e223,里面的内容有:

.├── config.json├── init-stderr├── init-stdin└── init-stdout
其中包括了容器配置和标准输入、标准输出、标准错误三个管道文件。

RunC

OCI定义了容器运行时标准,runC是Docker按照开放容器格式标准(OCF, Open Container Format)制定的一种具体实现。

runC是从Docker的libcontainer中迁移而来的,实现了容器启停、资源隔离等功能。Docker默认提供了docker-runc实现,事实上,通过containerd的封装,可以在Docker Daemon启动的时候指定runc的实现。

我们可以通过启动Docker Daemon时增加--add-runtime参数来选择其他的runC现。例如:

docker daemon --add-runtime "custom=/usr/local/bin/my-runc-replacement"
下面就让我们看下这几个模块如何工作。

举个例子

这里通过Docker一些命令,实现不使用Docker Daemon直接启动一个镜像,以便了解Docker Daemon每个模块的作用。

首先,需要创建容器标准包,这部分实际上由containerd的bundle模块实现,将Docker镜像转换成容器标准包。

mkdir my_containercd my_containermkdir rootfsdocker export $(docker create busybox) | tar -C rootfs -xvf -
上述命令将busybox镜像解压缩到指定的rootfs目录中。如果本地不存在busybox镜像,containerd还会通过distribution模块去远程仓库拉取。

现在整个my_container目录结构如下:

$ tree -d my_container/my_container/└── rootfs ├── bin ├── dev │ ├── pts │ └── shm ├── etc ├── home ├── proc ├── root ├── sys ├── tmp ├── usr │ └── sbin └── var ├── spool │ └── mail └── www17 directories
此时,标准包所需的容器数据已经准备完毕,接下来我们需要创建配置文件:

docker-runc spec
此时会生成一个名为config.json的配置文件,该文件和Docker容器的配置文件类似,主要包含容器挂载信息、平台信息、进程信息等容器启动依赖的所有数据。

最后,可以通过runc命令来启动容器:

runc run busybox
注意,runc必须使用root权限启动。

执行之后,我们可以看见容器已经启动:

localhost my_container # runc run busybox/ # ps auxPID USER TIME COMMAND 1 root 0:00 sh 9 root 0:00 ps aux
此时,事实上已经可以不依赖Docker本身,如果系统上安装了runc包,即可运行容器。对于Gentoo系统来说,安装app-emulation/runc包即可。

当然,也可以使用docker-runc命令来启动容器:

localhost my_container # docker-runc run busybox/ # ps auxPID USER TIME COMMAND 1 root 0:00 sh 7 root 0:00 ps aux
从这里可以看到标准化的重要性。

总结

从Docker 1.11之后,Docker Daemon被分成了多个模块以适应OCI标准。拆分之后,结构分成了以下几个部分。

其中,containerd独立负责容器运行时和生命周期(如创建、启动、停止、中止、信号处理、删除等),其他一些如镜像构建、卷管理、日志等由Docker Daemon的其他模块处理。

Docker的模块块拥抱了开放标准,希望通过OCI的标准化,容器技术能够有很快的发展。

本文转自d1net(转载)

时间: 2024-09-08 20:48:34

Docker、Containerd、RunC...:你应该知道的所有的相关文章

容器界大事件:深度解析 containerd

美国时间12月14日,Docker公司宣布将containerd从Docker Engine中分离,并捐赠到一个新的开源社区独立发展和运营,"一个工业标准的容器运行时,注重简单. 健壮性.可移植性".containerd可以作为daemon程序运行在Linux和Windows上,管理机器上所有容器的生命周期.阿里云,AWS, Google,IBM和Microsoft作为初始成员,会为项目提供贡献和维护人员. containerd对于很多人来还是很陌生,为什么Docker公司会大张旗鼓地

容器,你还只用Docker吗?(下)

作者介绍 周晖,Pivotal大中国区云计算首席架构师,有丰富的PaaS云实际建设经验,负责过国内某知名银行已经生产上线一年的PaaS云的架构设计和部分功能的实现,参与过某超算PaaS.某超市电商PaaS.某电力PaaS等项目的建设.   上文说到CaaS生态圈的公司如何应对Docker用捆绑方式从容器入侵CaaS领域,CaaS厂商通过容器抽象.标准化容器运行时RunC以及容器功能外化插件来重新定义容器.下面我们继续来看CaaS厂商的具体方案.   一.CaaS业界通过分解重组Docker技术来

容器,你还只用Docker吗?(上)

作者介绍 周晖,Pivotal大中国区云计算首席架构师,有丰富的PaaS云实际建设经验,负责过国内某知名银行已经生产上线一年的PaaS云的架构设计和部分功能的实现,参与过某超算PaaS.某超市电商PaaS.某电力PaaS等项目的建设.   一.从一场容器的撕逼战开始说起   从2016年7月底开始,Google Kubernetes布道师 Kelsey Hightower 和Docker的CTO Solomon Hykes在Twitter上发生了一场撕逼大战,主题是要不要用RunC或其他容器来取

docker 动态映射运行的container端口实例详解_docker

docker动态映射运行的container端口,最近做项目,对于docker动态映射运行的container端口的资料有必要记录下,以便以后在用到, Docker自带了EXPOSE命令,可以通过编写dockerfile加-p参数方便的映射Container内部端口,但是对于已经运行的container,如果你想对外开放一个新的端口,只能编辑dockerfile然后重新build,有点不太方便. 其实docker本身使用了iptables来做端口映射的,所以我们可以通过一些简单的操作来实现动态映

在Docker中运行Java:为了防止失败,你应该知道的

如果你尝试在容器中运行Java程序,或者专注于Docker,你可能会遇到一些关于JVM和堆大小的问题.本篇文章将介绍如何解决这些问题. 很多开发者会(或者应该)知道,当我们为运行在Linux容器(docker, rkt, runC, lxcfs, etc,)中的Java程序去设置JVM的GC.堆大小和运行时编译器的参数时并没有得到预想的效果.当我们通过"java -jar mypplication-fat.jar"的方式而不设置任何参数来运行一个Java应用时,JVM会根据自身的许多参

A Deep Insight of Alibaba Open Source Project - Pouch

By Allen Sun, Senior Engineer at Alibaba Group Pouch's vision is to advance container ecosystem and promote container standards OCI (Open Container Initiative), so that container technologies could become the foundation for application development in

Kubernetes之“暂停”容器

本文讲的是Kubernetes之"暂停"容器[编者的话]希望这篇文章可以帮助大家更好的了解Kubernetes的相关核心内容. 当检查你的Kubernetes集群的节点时,在节点上执行命令docker ps,你可能会注意到一些被称为"暂停(/pause)"的容器. $ docker ps CONTAINER ID IMAGE COMMAND ... ... 3b45e983c859 gcr.io/google_containers/pause-amd64:3.0  

将容器变成真正的沙箱

本文讲的是将容器变成真正的沙箱,[编者的话]本文来自于Jessie Frazelle的博客,原文链接here. 容器现在非常流行,其最核心之处所使用的Linux原语和创建应用程序沙箱是一致的.大家比较熟悉的沙箱技术可能是Chrome沙箱,关于Chrome沙箱的详细介绍可以访问链接chromium.googlesource.com/chromium/src/+/master/docs/linux_sandboxing.md,其中与本文比较相关的是它使用了用户命名空间技术和seccomp机制,以及其

50招教你防止黑客入侵,适用于入门小白到专业人员

摘要: 我年少之时,保罗.西蒙的"离开爱人的50种方法"正发布畅销. 受这首歌的启发,我收集了50种适合从专业系统管理员到入门小白都可以掌握的防止系统被入侵的方法. 今天我们要讨论的是保护系统安全的50种方法,我收集了50种适合从专业系统管理员到入门小白都可以掌握的防止系统被入侵的方法: 1. 备份你的数据,如果你被勒索软件入侵,如果你有备份的话,你将毫无损失. 2. 如果你需要在公共场所充电的话,用 syncstop 或者带上你自己的充电宝. 3. 学会利用审计子系统(auditin

云计算:容器技术变革云计算,SaaS带动CaaS市场

报告摘要: 1.容器技术增速惊人,市场认可度提高 虚拟化是云计算的重要基础,Docker定义了一套容器从构建到执行的标准化体系,改变了传统的虚拟化技术,深度影响了云计算领域. 随着谷歌.亚马逊.微软等云计算厂商纷纷加大对Docker开源技术的投入,CaaS(Container-as-a-Service)的市场大门正式被开启.根据统计,到2015年全球已有46万个应用Docker化,两年实现增长3,000%.在发展速度上,已超过当时的虚拟化技术和云计算技术. 2.SaaS产业向移动和垂直领域发展,