# 切换容器引擎

在k8s平台中，为了解决与容器运行时（比如Docker）集成问题，在早起社区退出CRI（Container Runtime Interface，容器运行时接口），以支持更多的容器运行时。但是Docker实在CRI出现之前就加入了Kubernetes，k8s团队通过提供dockershim对Docker进行一对一支持，Docker本身并没有实现CRI接口。所以当我们使用docker作为容器引擎时，架构时如下这样的：

![image-20220113203349382](https://github.com/yangsx95/notes/blob/master/devops/kubernetes/%E5%88%87%E6%8D%A2%E5%AE%B9%E5%99%A8%E5%BC%95%E6%93%8E.assets/image-20220113203349382.png)

Kubernetes团队因为下面几点原因计划弃用kubelet中的dockershim组件：

1. 去除dockershim减少代码规则和维护称根本
2. Docker 内部调用链复杂，多层封装和调用，导致性能降低、提升故障率、不易排查（上图）
3. Docker还会在宿主机创建网络规则、存储卷、也带来了安全隐患

弃用后，新版的k8s就无法与没有实现CNI的老版docker引擎相互通讯。

***

**如何应对？**

在未来的Kubernetes版本彻底放弃docker之前，引入受支持的容器运行时。出了docker之外，CRI支持很多容器运行时：

* containerd：与docker完全兼容，比docker轻量，较为成熟
* cri-o， podman：都是redhat项目，目前redhat主推podman

## 切换为Containerd

参考资料：<https://kubernetes.io/zh/docs/setup/production-environment/container-runtimes/#containerd>

### 配置先决条件

```
cat <<EOF | sudo tee /etc/modules-load.d/containerd.conf
overlay
br_netfilter
EOF

sudo modprobe overlay
sudo modprobe br_netfilter

# 设置必需的 sysctl 参数，这些参数在重新启动后仍然存在。
cat <<EOF | sudo tee /etc/sysctl.d/99-kubernetes-cri.conf
net.bridge.bridge-nf-call-iptables  = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.ipv4.ip_forward                 = 1
EOF

sudo sysctl --system
```

### 安装containerd

```
yum install -y yum-utils device-mapper-persistent-data lvm2
yum-config-manager \
    --add-repo \
    https://download.docker.com/linux/centos/docker-ce.repo
yum install -y containerd.io
mkdir -p /etc/containerd
containerd config default > /etc/containerd/config.toml
```

### 修改配置文件

* pause镜像设置过阿里云镜像仓库地址
* cgroups驱动设置为systemd
* 拉取Docker Hub镜像配置加速地址设置为阿里云镜像仓库地址

```
vi /etc/containerd/config.toml
   [plugins."io.containerd.grpc.v1.cri"]
      sandbox_image = "registry.aliyuncs.com/google_containers/pause:3.2"  
         ...
         [plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options]
             SystemdCgroup = true
             ...
        [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"]
          endpoint = ["https://b9pmyelo.mirror.aliyuncs.com"]
          
systemctl restart containerd
```

### 配置kubelet使用containerd

```
vi /etc/sysconfig/kubelet 
加入以下内容：
KUBELET_EXTRA_ARGS=--container-runtime=remote --container-runtime-endpoint=unix:///run/containerd/containerd.sock --cgroup-driver=systemd

systemctl restart kubelet
```

### 验证

```
kubectl get node -o wide

k8s-node1  xxx  containerd://1.4.4
```

## crictl 管理CRI容器

containerd提供了ctr命令行工具管理容器，但功能比较简单，所以一般会用crictl工具检查和调试容器。

项目地址：<https://github.com/kubernetes-sigs/cri-tools/>

**设置crictl连接containerd：**

```
vi /etc/crictl.yaml
runtime-endpoint: unix:///run/containerd/containerd.sock
image-endpoint: unix:///run/containerd/containerd.sock
timeout: 10
debug: false
```

下面是docker与crictl命令对照表：

| 镜像相关功能   | Docker                  | Containerd               |
| -------- | ----------------------- | ------------------------ |
| 显示本地镜像列表 | docker images           | crictl images            |
| 下载镜像     | docker pull             | crictl pull              |
| 上传镜像     | docker push             | 无，例如buildk               |
| 删除本地镜像   | docker rmi              | crictl rmi               |
| 查看镜像详情   | docker inspect IMAGE-ID | crictl inspecti IMAGE-ID |

| 容器相关功能 | Docker         | Containerd     |
| ------ | -------------- | -------------- |
| 显示容器列表 | docker ps      | crictl ps      |
| 创建容器   | docker create  | crictl create  |
| 启动容器   | docker start   | crictl start   |
| 停止容器   | docker stop    | crictl stop    |
| 删除容器   | docker rm      | crictl rm      |
| 查看容器详情 | docker inspect | crictl inspect |
| 附加容器   | docker attach  | crictl attach  |
| 执行命令   | docker exec    | crictl exec    |
| 查看日志   | docker logs    | crictl logs    |
| 查看容器资源 | docker stats   | crictl stats   |

| POD相关功能   | Docker | Containerd      |
| --------- | ------ | --------------- |
| 显示 POD 列表 | 无      | crictl pods     |
| 查看 POD 详情 | 无      | crictl inspectp |
| 运行 POD    | 无      | crictl runp     |
| 停止 POD    | 无      | crictl stopp    |

## 镜像构建工具

可以使用Buildkit替代docker，支持构建dockerfile。
