# 切换容器引擎

在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/切换容器引擎.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。


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://yangsx95.gitbook.io/notes/devops/kubernetes/qie-huan-rong-qi-yin-qing.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
