容器运行时(容器运行环境)
运行时:一般是用来支持程序运行的实现。例如JVM就是一种运行时,
容器运行时:具体到容器运行时,就是运行容器所需要的一系列程序。
具体来说,运行容器会遇到以下问题:
- A container image format
- A method for building container images (Dockerfile/docker build)
- A way to manage container images (docker images, docker rm , etc.)
- A way to manage instances of containers (docker ps, docker rm , etc.)
- A way to share container images (docker push/pull)
- A way to run containers (docker run)
docker一开始是解决了以上的问题,但是后来大家为了标准化,就分别进行了拆分,成立了OCI(Open Contanier Initiative)。提出了两个标准:
- 容器运行时标准:主要指定容器的运行状态和运行时需要的指令,docker公司给社区捐献了一个OCI容器的实现,就是runc。
- 容器镜像标准:主要是说明容器的镜像格式,一般是以OCI runtime filesystem bundle形式存在。
而OCI标准只包含了容器的创建,运行,销毁等功能(low-level container runtimes,runc,lxc),还缺失例如镜像创建、下载、管理等功能(high-level container runtimes,containerd,docker)。
low-level container runtime
low-level container runtime从原理上来讲是用linux namespace实现命名空间的隔离、资源的虚拟化和用cgroup来实现资源的使用控制。
所以一个最基本的low-level容器运行时需要做的包括:
- Create cgroup
- Run command(s) in cgroup
- Unshare to move to its own namespaces
- Clean up cgroup after command completes (namespaces are deleted automatically when not referenced by a running process)
最最简单的一个运行时就是把容器文件放到一个文件夹里面,用chroot控制文件访问,再把cgroups,还有namespace创建好,就算是实现隔离了。
典型的low level runtime实现有:lmctfy,runc,rkt
high-level container runtime
low-level container runtime负责实际运行容器,而high-level container runtime负责容器映像的传输和管理,解压缩映像,然后传递到低级运行时以运行容器。高级运行时提供了守护程序应用程序和API,远程应用程序可使用它们来逻辑运行容器并对其进行监视,但是它们位于底层并委托低级运行时或其他高级运行时进行实际工作。
Docker是一个包含了构建,打包,共享和运行容器的容器运行时。Docker将low-level和high-level分为了单独的项目。Docker现在包括dockerd守护程序,docker-containerd守护程序以及docker-runc。 docker-containerd和docker-runc是containerd和runc的vanilla版本。
containerd是从Docker分离出来的high-level运行时。containerd实现下载镜像,管理镜像以及从镜像运行容器。当需要运行容器时,它将映像解压缩到OCI运行时捆绑包中,然后将其打包到runc来运行它。同时也提供了可用于与其交互的API和客户端应用程序。
dockerd提供如构建映像之类的功能,而dockerd使用docker-containerd提供如映像管理和运行中的容器之类的功能。