目录
环境说明:
先看一张Docker的架构图:
1) docker公司
我们常说的docker,不仅是一门技术,还是一家公司。
官网:www.docker.com
2) container
也叫容器,容器的本质是进程。这些进程很特殊,它们跑在一些特定的namespace和cgroup下。站在这些进程的角度看,它们会以为自己跑在一个独立的机器上,看不到其他进程,也看不到其他文件。这是其实是操作系统为它虚拟出来的一个独立的、隔离的环境,是假的。
namespace用来做资源隔离,cgroup用来做资源限制。
什么叫namespace, cgroup? 下一篇文章再讲吧。
3)docker client
也叫docker客户端, 这是一个命令工具,在安装在/usr/bin/docker下。当你打docker run xxx 时,它会向docker-daemon进程发起http POST请求。
4) docker-daemon
也叫dockerd进程,也叫docker-engine, 它是一个跑在宿主机上的Service服务。
它接收docker client的htttp请求,然后以grpc的方式再转给containerd进程。
5) containerd
conainerd进程也是一个长期跑在宿主机上的服务,安装正/usr/bin/containerd
当我们启动一个容器时,它接收GRPC调用,启动一个container-shim-runc-v2进程,每个容器启动一个。
containerd实现了CRI标准(Container Runtime Interface容器运行接口),它是Docker公司的核心依赖,后来捐给了CNCF基金会(Cloud Native Computing Fundation)。
为什么Docker公司要这么做?其实也是迫于无奈,Docker火起来后,Google 联合 Red Hat、IBM 等几位巨佬成立了CNCF基金会,推出了一系列的标准。Docker公司为了标榜Docker技术是一个PaaS平台,就把Docker-daemon中最核心的部分抽出来,稍微改一改,捐出来,并跟大家说,咱们家的containerd组件,实现了CRI标准。
- Containerd的Github源码:
在它的git hub上,有这么一段文字介绍:
containerd 是一个行业标准的容器运行时,强调简单性、健壮性和可移植性。它可作为 Linux 和 Windows 的守护进程使用,可以管理其主机系统的完整容器生命周期:镜像传输和存储、容器执行和监督、低级存储和网络附件等。
- contianerd官网:
- containerd已经从CNCF基金会毕多年,见下图:
landscape cncf网址:
- contianerd的安装:
- 安装docker engine时一起安装了。
- containerd也可以单独安装,压缩包:containerd-1.6.2-linux-amd64.tar.gz
我是安装docker engine时一起安装了containerd,在我的环境里,安装如下:
- containerd的架构
从上图上中可以看到,我们看到连接containerd的4种方式:
- docker container engine
- kubelet
- BuildKit,
- Ctr命令工具
我可以自己写个go客户端程序,来连接吗?答案是可以的。
- 使用go语言连接containerd
教程:https://github.com/containerd/containerd/blob/main/docs/getting-started.md
- Containerd 的故事
Containerd 的前世今生和保姆级入门教程_Docker
个人点评:
Solomon Hykes 是一位理想主义者,不甘于“寄人篱下”,不接收微软的高价收购,带着整个团队对抗一个行业的大佬,战败尤荣,英雄也!还长得这么帅!
- containerd的未来:
在kubelet组件中,内嵌了一个docker-shim模块,这个模块与containerd交互。但是,
kubernetes宣称后续不再维护docker-shim了,所以,containerd会演变成下面的例子。
参考:
源码导读系列之 containerd - 简书编辑https://www.jianshu.com/p/d8f6c40280f8
以后,从上图中看到,现在的架构还需要moby工程,见下图。以后应该不需要了。
- kubelet与containerd的交互
6) containerd-shim-runc-v2进程
containerd-shim-runc-v2进程是containerd在启动一个容器时,为每一个容器再分配的一个独立的进程。在下图中,我起了两个容器,所以有两个containerd-shim-runc-v2进程。它们的父PID是1,即systemd, 而不是containerd,这样容器起来后,就可以做到:
1)容器进程之间互不影响。
2)容器进程与containerd,docker-deamon互不影响。可以做到,在不停止容器前提下,对containerd,docker-deamon进行版本升级。
7) runC
runC只一个命令工具,启动容器时需要用到。在我的环境里,它与docker engine一起安装了。安装目录如下:
当然,runC是符合OCI规范的。
GitHub:
2015 年 6 月 22 日,由 Docker 公司牵头,CoreOS、Google、RedHat 等公司共同宣布,Docker 公司将 Libcontainer 捐出,并改名为 RunC 项目,交由一个完全中立的基金会管理,然后以 RunC 为依据,大家共同制定一套容器和镜像的标准和规范。
-- 摘自《深入剖析Kubernetes》,作者:张磊
8) OCI
OCI(Open Container Intiative)是一个中立的社区,专门做容器规范的。当前,它维护两个标准:
- runtime-spec: 容器运行时规范,要求如何从磁盘中的一个镜像文件跑出一个进程,要求按层来读取、解压镜像文件。(这点其实是docker公司的创新)
- image-spec: 镜像规范
按我的理解,应该还有一个:distribution-spec,镜像分发标准。
官网:Open Container Initiative - Open Container Initiative
看下面这个kubelet调用containerd的图,更容易理解:
OCI社区的成员:
9)CRI/CNI/CSI
CRI(Container Runtime Interface):容器运行时接口,提供计算资源
CNI(Container Network Interface):容器网络接口,提供网络资源
CSI(Container Storage Interface):容器存储接口,提供存储资源
这些是K8S的玩意了,我们留意下一篇文章再说吧。
10) libcontainer
这个其实就是runC的前身,是Docker公司捐给OCI(Open Container Intiative)社区的,后面改名为runC.
11) cri-o
既然K8S定义CRI规范,docker公司的containerd实现了CRI规范,那么,有没有别的替代方案。当然有, 它就是CRI-O。
CRI-O是一堆大佬的大作:
有了CRI-O之后,你的环境就可以不用docker-daomen进程、containerd进程了。按句话说,可以完全不用docker公司的产品了。
CRI-O运行容器的过程如下:
12) CNCF
CNCF是一家基金会(Cloud Native Computing Fundation, 云原生计算基金会),托管了全球技术基础设施的关键组件(主要是云原生的组件), 里面有多量的项目,其中有16个项目已经毕业。
目前(2022年4月),已经有16个项目毕业了,如下。其中,最出名的有:containerd, CoreDNS, envy, etcd, harbor, helm, kubernetes,都是杀手级的应用。
思考题:
问题1:
安装docker engin时,会把docker-deamon与containerd这两个服务一起安装。那么,我停止docker-deamon时,containerd也会被停止吗? 答案是不会。
从这点看来,docker-deamon与containerd这两个服务独立的,互相不影响。
问题2:
关于 /etc/docker/daemon.json文件:
安装docker engine后,可以在/etc/docker/daemon.json中,对docker-daemon进行配置。从这点看,这个文件是docker-daemon的配置。同时,这份文件也可以配置cgroup驱动。根据docker的架构图,cgroup驱动是containerd的配置。难道docker-deamon与containerd这两个服务,共用这份配置文件吗?
我在containerd的源码上,也没搜到它去读取daemon.json文件。
如果是共用配置文件,那说明它们还是会相互影响的。这点,与问题1)的结论矛盾。
问题3:
containerd配置了cgroup驱动,kubelet组件中也可以配置,为什么要配置两次?
答案:
kubelet作是CRI接口的调用方,在调用链的上游,可以要求接口的实现者使用那种驱动。而作为CRI实现者,可以有自己的配置。那么,另一个问题是,当上游的调用方kubelet与下游的实现者containerd的配置不一致时,会出现什么 ? 答案是启动kubelet时就会报错:
"failed to run Kubelet: misconfiguration: kubelet cgroup driver: \"cgroupfs\" is different from docker cgroup driver: \"systemd\""
这种错误,也有可能初始化master节点(kubeadm init)时就报错,网上有好多人踩过这个坑。
问题4:
如果我换了CRI-O,是不是也有可能报问题3那个错误?
我没试过,请碰到这个问题的高手帮忙回答一下。