1 前言
Dockershim是kubelet内置的一个组件,功能是使k8s能够通过CRI(Container Runtime Interface)操作docker。一旦docker 有任何的功能特性变更,dockershim 代码必须加以改动来保证能够继续和docker通信。另外,docker的底层运行时是containerd,而containerd自身是可以支持CRI的,也就是说k8s可以绕过docker通过CRI直接与containerd通信,这也是k8s社区希望弃用dockershim的原因。
Containerd在1.0版本中虽然考虑了CRI,但是它将CRI-Containerd作为一个独立组件存在的,即:k8s需要先通过CRI接口调用CRI-Containerd,再由这个组件去调用containerd。在Containerd1.1版本之后对该特性做了重新的设计,它将CRI-plugin内嵌在containerd中,以此来达到与containerd通信的目的,调用链路更短了。Containerd1.1支持k8s1.10及以上版本作为容器运行时,并且支持k8s的全部特性。
2 docker 和 containerd
1、docker 由 docker-client ,dockerd,containerd,docker-shim,runc 组成,所以 containerd 是 docker 的基础组件之一
2、从 k8s 的角度看,可以选择 containerd 或 docker 作为运行时组件:其中 containerd 调用链更短,组件更少,更稳定,占用节点资源更少。所以 k8s 后来的版本开始默认使用 containerd 。
3、containerd 相比于 docker , 多了 namespace 概念,每个 image 和 container 都会在各自的 namespace 下可见。
4、docker 作为 k8s 容器运行时,调用关系为:<font style="color:#DF2A3F;background-color:rgb(243, 244, 244);">kubelet --> dockershim (在 kubelet 进程中) --> dockerd --> containerd</font>
5、containerd 作为 k8s 容器运行时,调用关系为:<font style="color:#DF2A3F;background-color:rgb(243, 244, 244);">kubelet --> cri plugin(在 containerd 进程中) --> containerd</font>
### 3 命令区分
ctr 是 containerd 的一个客户端工具。
crictl 是 CRI 兼容的容器运行时命令行接口,可以使用它来检查和调试 k8s 节点上的容器运行时和应用程序。
ctr -v 输出的是 containerd 的版本,crictl -v 输出的是当前 k8s 的版本,从结果显而易见你可以认为 crictl 是用于 k8s 的。
$ ctr -vctr containerd.io 1.6.22$ crictl -vcrictl version v1.26.0
一般来说某个主机安装了 k8s 后,命令行才会有 crictl 命令。而 ctr 是跟 k8s 无关的,主机安装了 containerd 服务后就可以操作 ctr 命令。
4 常用命令
| 命令 |
docker |
ctr(containerd) |
crictl(kubernetes) |
| 显示本地镜像列表 |
docker images |
ctr i ls |
crictl images |
| 下载镜像 |
docker pull |
ctr i pull |
crictl pull |
| 上传镜像 |
docker push |
ctr i push |
无 |
| 删除本地镜像 |
docker rmi |
ctr i rm |
crictl rmi |
| 查看镜像详情 |
docker inspect |
无 |
crictl inspecti |
| 重命名镜像 |
docker tag |
ctr i tag |
无 |
| 导出镜像 |
docker export |
ctr i export |
无 |
| 导入镜像 |
docker import |
ctr i import |
无 |
| 构建镜像 |
docker build |
无 |
无 |
| 显示容器列表 |
docker ps |
ctr c ls |
crictl ps |
| 创建容器 |
docker create |
ctr c create |
crictl create |
| 启动容器 |
docker start |
ctr t start |
crictl start |
| 停止容器 |
docker stop |
无 |
crictl stop |
| 删除容器 |
docker rm |
ctr c rm |
crictl rm |
| 查看容器详情 |
docker inspect |
ctr c info |
crictl inspect |
| attach |
docker attach |
ctr t attach |
crictl attach |
| exec |
docker exec |
ctr t exec |
crictl exec |
| logs |
docker logs |
无 |
crictl logs |
| stats |
docker stats |
ctr t metrics |
crictl stats |
| 显示pod列表 |
无 |
无 |
crictl pods |
| 查看pod详情 |
无 |
无 |
crictl inspectp |
| 运行pod |
无 |
无 |
crictl runp |
| 停止pod |
无 |
无 |
crictl stopp |
| 删除pod |
无 |
无 |
crictl rmp |
5 实战演示
5.1 ctr命令
containerd 相比于docker , 多了namespace概念, 每个image和container 都会在各自的namespace下可见, 目前k8s会使用k8s.io 作为命名空间
#查看命名空间ctr namespace ls# 查看 K8S 命名空间下的镜像ctr -n k8s.io images ls# 下载镜像ctr images pull docker.io/library/redis:alpine# 创建 containerctr c create docker.io/library/redis:alpine redis-container# 查看ctr c ls# 后台启动ctr t start -d redis-container# 查看 containerctr t ls# 查看 k8s 中正在运行的容器ctr -n k8s.io task ls# 打tagctr images tag docker.io/library/redis:alpine harbor.junengcloud.com/tmp/redis:alpine# push 上传镜像ctr images push harbor.junengcloud.com/tmp/redis:alpine# 注意可能会出现 ctr: content digest sha256:xxxxxx not found,解决办法,下载完整的ctr image pull --all-platforms docker.io/library/redis:alpinectr images rm harbor.junengcloud.com/tmp/redis:alpinectr images tag docker.io/library/redis:alpine harbor.junengcloud.com/tmp/redis:alpinectr images push harbor.junengcloud.com/tmp/redis:alpine# 离线导入 docker 镜像,在其他 docker 上导出, containerd 镜像导入docker save -o rabbitmq_3.7.8.tar harbor.junengcloud.com/rabbitmq/rabbitmq:3.7.8ctr images import rabbitmq_3.7.8.tarctr images ls -q# 查看ctr image可用操作ctr image list, ctr i list , ctr i ls# 镜像标记tagctr -n k8s.io i tag registry.cn-hangzhou.aliyuncs.com/google_containers/pause:3.2 k8s.gcr.io/pause:3.2注意: 若新镜像reference 已存在, 需要先删除新reference, 或者如下方式强制替换ctr -n k8s.io i tag --force registry.cn-hangzhou.aliyuncs.com/google_containers/pause:3.2 k8s.gcr.io/pause:3.2# 删除镜像ctr -n k8s.io i rm k8s.gcr.io/pause:3.2# 拉取镜像ctr -n k8s.io i pull -k k8s.gcr.io/pause:3.2# 推送镜像ctr -n k8s.io i push -k k8s.gcr.io/pause:3.2# 导出镜像ctr -n k8s.io i export pause.tar k8s.gcr.io/pause:3.2# 导入镜像# 不支持 build,commit 镜像ctr -n k8s.io i import pause.tar
5.2 crictl命令
## crictl 配置# 通过在配置文件中设置端点 --config=/etc/crictl.yamlroot@ZHDYA:~$ cat /etc/crictl.yamlruntime-endpoint: unix:///run/containerd/containerd.sock## 列出业务容器状态crictl inspect ee20ec2346fc5## 查看运行中容器root@ZHDYA:~$ crictl podsPOD ID CREATED STATE NAME NAMESPACE ATTEMPT RUNTIMEb39a7883a433d 10 minutes ago Ready canal-server-quark-b477b5d79-ql5l5 mbz-alpha 0 (default)## 打印某个固定podroot@ZHDYA:~$ crictl pods --name canal-server-quark-b477b5d79-ql5l5POD ID CREATED STATE NAME NAMESPACE ATTEMPT RUNTIMEb39a7883a433d 12 minutes ago Ready canal-server-quark-b477b5d79-ql5l5 mbz-alpha 0 (default)## 打印镜像root@ZHDYA:~$ crictl imagesIMAGE TAG IMAGE ID SIZEccr.ccs.tencentyun.com/koderover-public/library-docker stable-dind a6e51fd179fb8 74.6MBccr.ccs.tencentyun.com/koderover-public/library-nginx stable 588bb5d559c28 51MBccr.ccs.tencentyun.com/koderover-public/nsqio-nsq v1.0.0-compat 2714222e1b39d 22MB## 只打印镜像 IDroot@ZHDYA:~$ crictl images -qsha256:a6e51fd179fb849f4ec6faee318101d32830103f5615215716bd686c56afaea1sha256:588bb5d559c2813834104ecfca000c9192e795ff3af473431497176b9cb5f2c3sha256:2714222e1b39d8bd6300da72b0805061cabeca3b24def12ffddf47abd47e2263sha256:be0f9cfd2d7266fdd710744ffd40e4ba6259359fc3bc855341a8c2adad5f5015## 打印容器清单root@ZHDYA:~$ crictl ps -aCONTAINER IMAGE CREATED STATE NAME ATTEMPT POD IDee20ec2346fc5 c769a1937d035 13 minutes ago Running canal-server 0 b39a7883a433d76226ddb736be cc0c524d64c18 34 minutes ago Running mbz-rescue-manager 0 2f9d48c49e891e2a19ff0591b4 eb40a52eb437d About an hour ago Running export 0 9844b5ea5fdbc## 打印正在运行的容器清单root@ZHDYA:~$ crictl psCONTAINER IMAGE CREATED STATE NAME ATTEMPT POD IDee20ec2346fc5 c769a1937d035 13 minutes ago Running canal-server 0 b39a7883a433d## 容器上执行命令root@ZHDYA:~$ crictl exec -i -t ee20ec2346fc5 lsapp.sh bin canal-server health.sh node_exporter node_exporter-0.18.1.linux-arm64## 获取容器的所有日志root@ZHDYA:~$ crictl logs ee20ec2346fc5DOCKER_DEPLOY_TYPE=VM==> INIT /alidata/init/02init-sshd.sh==> EXIT CODE: 0==> INIT /alidata/init/fix-hosts.py## 获取最近的 N 行日志root@ZHDYA:~$ crictl logs --tail=2 ee20ec2346fc5start canal successful==> START SUCCESSFUL ...## 拉取镜像root@ZHDYA:~$ crictl pull busybox
6 总结
Kubernetes 弃用docker这一决定可能对从事相关工作的人员来说有些措手不及,但其实无需特别担心。对于k8s的终端用户来说,这仅仅是一个后端容器运行时的更改,从使用方面来说几乎感觉不到任何区别;
对于应用开发/运维人员来说,依旧可以继续使用docker来构建镜像,以相同的方式将镜像推送到 Harbor,并将这些镜像部署到k8s环境中;
对于k8s集群管理员来说,只需要将docker切换成其它的容器运行时(比如containerd),并将节点troubleshooting工具从docker CLI切换到crictl即可。