什么是容器:
Namespaces:命名空间,容器的独立资源
Cgroups:控制组
资源限制:对进程组使用的资源总额进行限制。例如设定应用运行时的内存上限,当超过该限额就会 OOM(Out of Memory)
优先级分配:通过分配CPU时间片数量、硬盘IO及带宽大小来控制进程的优先级
资源统计:统计系统的资源使用量,如CPU使用量,内存用量等
进程控制:可以对进程组执行挂起、恢复等操作
层状文件系统,当进程需要修改文件时,AUFS创建该文件的一个副本
镜像:多个镜像层 (Image Layer) 叠加而成的只读文件系统 (UnionFile System)
容器:在镜像的基础上,增加了一个读写层 (Top Layer)。运行状态下的容器,由一个可读写的文件系统、隔离的进程空间和进程构成
Docker 使用 Go 语言 进行开发实现,基于 Linux
内核的 cgroup,namespace,以及 OverlayFS 类的 Union FS 等技术,对进程进行封装隔离,属于操作系统层面的虚拟化技术。由于隔离的进程独立于宿主和其它的隔离的进程,因此也称其为容器。最初实现是基于 LXC,从 0.7
版本以后开始去除 LXC
,转而使用自行开发的 libcontainer,从 1.11
版本开始,则进一步演进为使用 runC 和 containerd
docker ctr(独立于docker时)
| |
V V
dockerd -> containerd ---> shim -> runc -> runc init -> process
|-- > shim -> runc -> runc init -> process
+-- > shim -> runc -> runc init -> process
组件通信流程:
Containerd 标准化的产物,主要负责:
Containerd 标准化:
Containerd 架构:
runC 是标准化的产物,它根据 OCI 标准来创建和运行容器。
RunC 默认要支持 seccomp ( secure computing mode,即安全计算模型),编译时,先安装 libseccomp-dev
容器的状态转移:
Container Runtime Interface (CRI), it defines an API between Kubernetes and the container runtime
containerd: it is a high-level container runtime that came from Docker, and implements the CRI spec. It pulls images from registries, manages them and then hands over to a lower-level runtime, which actually creates and runs the container processes.
CRI-O: it is another high-level container runtime which implements the Container Runtime Interface (CRI). It’s an alternative to containerd. It pulls container images from registries, manages them on disk, and launches a lower-level runtime to run container processes. It was born out of Red Hat, IBM, Intel, SUSE and others.
总结:CRI 是 K8S 调用 容器的 API 接口
Open Container Initiative (OCI), it is a group of tech companies who maintain a specification for the container image format, and how containers should be run.
runsc
.总结:OCI 规定容器镜像格式和容器运行的标准
k8s 调用 docker:
kubelet:k8s 容器管理组件,负责对容器的创建、删除等调度行为的管理
docker-shim:kubelet和dockerd交互的中间接口。docker-shim 提供了一个标准接口,让kubelet能够专注于容器调度逻辑本身,而不用去适配 dockerd 接口变动。而其他实现了相同标准接口的容器技术也可以被kubelet集成使用,这个接口称作CRI。docker-shim 是对 CRI 接口调用 dockerd 的一种实现, docker-shim 并不是docker技术的一部分,而是k8s系统的一部分。
k8s 1.20+ 默认不再使用dockershim,并将在后续版本中删除dockershim,这意味着kubelet不再通过dockerd操作容器。在新架构中,kubelet直接与containerd交互,跳过了dockershim和dockerd这两个步骤。
cri-containerd:在k8s和containerd的适配过程中,还曾经出现过cri-containerd这个组件。在containerd1.0版本中,containerd提供了cri-containerd作为独立进程来实现CRI接口,其定位和docker-shim类似。但在containerd1.1版本中,就将这个功能改写成了插件形式直接集成到了containerd进程内部,使containerd可以直接支持CRI接口,cri-containerd也被合入了containerd,作为其一个内置插件包存在。
Podman主要由红帽发起和推动,原来是 CRI-O 项目的一部分,后来被分离成一个单独的项目叫 libpod。其包括如下三个模块:
Podman 的不足:因为没有类似 docker daemon 守护进程,所以不支持 --restart 策略,不过使用 k8s 编排就不存在这个问题。
Podman 兼容大部分 Docker 命令,可配置简单
yum install podman
podman –version
alias docker=podman
# podman 网桥
ip addr show cni-podman0
LXC:LinuX Containers ,它是一个加强版的Chroot。其作用是将不同的应用隔离开来,有点类似于chroot,chroot是将应用隔离到一个虚拟的私有root下,而LXC在这之上更进了一步。LXC依赖 Kernel 的3种隔离机制(isolation infrastructure):Chroot、Cgroups、Namespaces。LXC提供一个共享kernel的OS级虚拟化方法,在执行时不用重复加载kernel,且conatiner的kernel与host共享,因此大大加快了container的启动过程,并显著减少了内存消耗。
libcontainer:docker0.9 开发了 libcontainer 模块来作为 LXC 的替代品实现容器底层特性,并在1.10版本彻底去除了LXC。在1.11版本拆分出runc后,libcontainer 也随之成为了runc的核心功能模块。
moby:docker公司发起的开源项目,其中最主要的部分就是同名组件moby,事实上这个moby就是dockerd目前使用的开源项目名称,docker项目中的engine(dockerd)仓库现在就是从moby仓库fork而来的。
docker-ce:docker的开源版本,CE指Community Edition。docker-ce中的组件来自于moby、containerd等其他项目。
docker-ee:docker的收费版本,EE指Enterprise Edition。
rkt与rktlet:CoreOS公司主导的容器技术,在早期得到了k8s的支持成为k8s集成的两种容器技术之一。随着CRI接口的提出,k8s团队也为rkt提供了rktlet模块用于与rkt交互,rktlet和dockersim的意义基本相同。随着CoreOS被Redhat收购,rkt已经停止了研发,rktlet已停止维护了。
CRI-O:Redhat公司推出的容器技术。从名字就能看出CRI-O的出发点就是一种原生支持CRI接口规范的容器技术。CRI-O同时兼容OCI接口和docker镜像格式。CRI-O的设计目标和特点在于它是一项轻量级的技术,k8s可以通过使用CRI-O来调用不同的底层容器运行时模块,例如runc。