# Docker Kubenetes CRI 联系和区别

### 概述

容器的两种标准

* **Open Container Initiative (OCI):** 定义关于容器的一系列标准，包括镜像格式、运行时状态和镜像描述等
    
* **Container Runtime Interface (CRI) in** [**Kubernetes**](https://www.tutorialworks.com/kubernetes/)**:** 一个允许你在 Kubernetes 中使用不同容器运行时的 API
    

![image.png](https://zhenng-pic.oss-cn-qingdao.aliyuncs.com/image/20230403104321.png align="left")

### Docker

Docker 是最流行的容器工具，对于一些人来说 Docker 甚至等同于容器了。

现在 Docker 引擎有两种版本：

* Docker Desktop 面向容器开发者，带有 GUI 图形用户界面，适用于 Windows, Mac and Linux 在 Windows 和 Mac 上通过创建一个 Linux 虚拟机来运行 Docker 和 Kubernetes
    
* Docker Engine，docker 服务引擎, 只有 Linux 版本 .
    

在 Linux 中 docker 是一个 command-line interface (CLI) 命令行接口，通过 docker 这个命令可以实现对镜像的拉取、创建，对容器的启动、停止等操作。docker 命令是通过调用低等级工具来实现的，containerd 负责镜像的操作，runc 负责容器进程的操作。

![image.png](https://zhenng-pic.oss-cn-qingdao.aliyuncs.com/image/20230403112249.png align="left")

* runc 低等级容器运行时(command-line interface)工具，使用 Linux 原生特性创建和启动容器，遵循 OCI 标准，包含一个 Go 的库 libcontainer
    
* containerd 高等级容器运行时，完全支持 OCI 规格，负责操作镜像，存储和网络
    
* dockerd 是一个 docker 守护进程，一直运行在后天，提供标准 API，并于 containerd 对话
    
* docker 命令是一个命令行客户端，调用 dockerd 服务来操作镜像和容器
    

### Kubernetes 与 Docker 的关系

Kubenetes 简称 K8s 是是用于自动部署、扩展和管理“容器化（containerized）应用程序”的开源系统。之前的 Kubenetes 通常采用 Docker 作为容器化工具，但 K8s 引入了与容器无关的平台 CRI，相当于一个协议，允许不同的容器运行时使用插件来兼容 CRI。因为 Docker 比 CRI 出现的早，并没有兼容这个协议，因此早期的 K8s 带有一个 dockershim (shim 垫片) 的组件来支持 docker ，后来被取消了，直接采用 containerd 容器引擎，或者采用一个满足 CRI 协议的容器运行时比如 CRI-O。docker 也可以使用，但是必须安装一个额外的服务 [cri-dockerd](https://github.com/Mirantis/cri-dockerd)

> containerd 和 CRI-O 都可以在 K8s 中运行 Docker 格式和 OCI 格式镜像，只是不需要非得使用 docker 命令了

### OCI

Open Container Initiative (OCI) 是 Docker 公司和其他公司联合指定的一个规范，包含镜像的格式，如何运行容器等。有了 OCI 这个规范之后可以自由选择容器运行时，只要满足 OCI 即可，低等级的实现可能会不同。

### CRI

CRI (Kubernetes Container Runtime Interface) 容器运行时接口，K8s 通过 CRI 接口屏蔽了底层容器运行时的不同，可以使用 containerd 或 CRI-O 等。K8s 不关系底层用的什么容器运行时，只要能管理镜像和容器即可。 不同的容器运行时都是可插拔和无缝衔接的。

在 K8s 中可以使用如下命令查看每台机器使用的是什么 container runtime

```plaintext
kubectl get nodes -o wide
```

可以使用 kubelet 命令通过 `--container-runtime`  和 `--container-runtime-endpoint` 参数切换 container runtime。

> kubelet 在 k8s 中是负责对容器运行时发送命令启动和运行容器的组件。kubelet 运行在每个节点上，每个节点可以使用不同的容器运行时。

![image.png](https://zhenng-pic.oss-cn-qingdao.aliyuncs.com/image/20230403141548.png align="left")

### CRI-O

CRI-O 是另一个实现了 CRI 的容器运行时，是 containerd 的替代品。由 Red Hat, IBM, Intel, SUSE 等等实现的，用起来与 containerd 一样。

### runc

runc 是 OCI 协议的实现，用来运行容器进程。 runc 有时被称作 reference implementation” of OCI，即 OCI 的参考实现。参考实现往往指的是接口的第一个实现，并且实现了接口的全部特性和功能。runc 就是实现了 OCI 的全部特性，例如命名空间和控制组等。 用户可以自己实现 OCI 运行时。

### 其他 low-level runtimes

除了 runc ，还有

* [**crun**](https://github.com/containers/crun) C 语言实现的容器运行时，(runc 是用 Go 实现的)
    
* [**firecracker-containerd**](https://github.com/firecracker-microvm/firecracker-containerd) AWS 实现,作为个人轻量虚拟机来实现 OCI 规格
    
* [**gVisor**](https://gvisor.dev/) Google 实现, 使用它们自己内核创建容器。包含一个 OCI 运行时 `runsc`.
    

原文：[The differences between Docker, containerd, CRI-O and runc - Tutorial Works](https://www.tutorialworks.com/difference-docker-containerd-runc-crio-oci/)
