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> 🐧[Containerd] ctr,crictl,Docker 关系 - 图1 ### 3 命令区分 ctr 是 containerd 的一个客户端工具。 crictl 是 CRI 兼容的容器运行时命令行接口,可以使用它来检查和调试 k8s 节点上的容器运行时和应用程序。 ctr -v 输出的是 containerd 的版本,crictl -v 输出的是当前 k8s 的版本,从结果显而易见你可以认为 crictl 是用于 k8s 的。
  1. $ ctr -v
  2. ctr containerd.io 1.6.22
  3. $ crictl -v
  4. crictl 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 作为命名空间
  1. #查看命名空间
  2. ctr namespace ls
  3. # 查看 K8S 命名空间下的镜像
  4. ctr -n k8s.io images ls
  5. # 下载镜像
  6. ctr images pull docker.io/library/redis:alpine
  7. # 创建 container
  8. ctr c create docker.io/library/redis:alpine redis-container
  9. # 查看
  10. ctr c ls
  11. # 后台启动
  12. ctr t start -d redis-container
  13. # 查看 container
  14. ctr t ls
  15. # 查看 k8s 中正在运行的容器
  16. ctr -n k8s.io task ls
  17. # 打tag
  18. ctr images tag docker.io/library/redis:alpine harbor.junengcloud.com/tmp/redis:alpine
  19. # push 上传镜像
  20. ctr images push harbor.junengcloud.com/tmp/redis:alpine
  21. # 注意可能会出现 ctr: content digest sha256:xxxxxx not found,解决办法,下载完整的
  22. ctr image pull --all-platforms docker.io/library/redis:alpine
  23. ctr images rm harbor.junengcloud.com/tmp/redis:alpine
  24. ctr images tag docker.io/library/redis:alpine harbor.junengcloud.com/tmp/redis:alpine
  25. ctr images push harbor.junengcloud.com/tmp/redis:alpine
  26. # 离线导入 docker 镜像,在其他 docker 上导出, containerd 镜像导入
  27. docker save -o rabbitmq_3.7.8.tar harbor.junengcloud.com/rabbitmq/rabbitmq:3.7.8
  28. ctr images import rabbitmq_3.7.8.tar
  29. ctr images ls -q
  30. # 查看ctr image可用操作
  31. ctr image list, ctr i list , ctr i ls
  32. # 镜像标记tag
  33. ctr -n k8s.io i tag registry.cn-hangzhou.aliyuncs.com/google_containers/pause:3.2 k8s.gcr.io/pause:3.2
  34. 注意: 若新镜像reference 已存在, 需要先删除新reference, 或者如下方式强制替换
  35. ctr -n k8s.io i tag --force registry.cn-hangzhou.aliyuncs.com/google_containers/pause:3.2 k8s.gcr.io/pause:3.2
  36. # 删除镜像
  37. ctr -n k8s.io i rm k8s.gcr.io/pause:3.2
  38. # 拉取镜像
  39. ctr -n k8s.io i pull -k k8s.gcr.io/pause:3.2
  40. # 推送镜像
  41. ctr -n k8s.io i push -k k8s.gcr.io/pause:3.2
  42. # 导出镜像
  43. ctr -n k8s.io i export pause.tar k8s.gcr.io/pause:3.2
  44. # 导入镜像
  45. # 不支持 build,commit 镜像
  46. ctr -n k8s.io i import pause.tar

5.2 crictl命令

  1. ## crictl 配置
  2. # 通过在配置文件中设置端点 --config=/etc/crictl.yaml
  3. root@ZHDYA:~$ cat /etc/crictl.yaml
  4. runtime-endpoint: unix:///run/containerd/containerd.sock
  5. ## 列出业务容器状态
  6. crictl inspect ee20ec2346fc5
  7. ## 查看运行中容器
  8. root@ZHDYA:~$ crictl pods
  9. POD ID CREATED STATE NAME NAMESPACE ATTEMPT RUNTIME
  10. b39a7883a433d 10 minutes ago Ready canal-server-quark-b477b5d79-ql5l5 mbz-alpha 0 (default)
  11. ## 打印某个固定pod
  12. root@ZHDYA:~$ crictl pods --name canal-server-quark-b477b5d79-ql5l5
  13. POD ID CREATED STATE NAME NAMESPACE ATTEMPT RUNTIME
  14. b39a7883a433d 12 minutes ago Ready canal-server-quark-b477b5d79-ql5l5 mbz-alpha 0 (default)
  15. ## 打印镜像
  16. root@ZHDYA:~$ crictl images
  17. IMAGE TAG IMAGE ID SIZE
  18. ccr.ccs.tencentyun.com/koderover-public/library-docker stable-dind a6e51fd179fb8 74.6MB
  19. ccr.ccs.tencentyun.com/koderover-public/library-nginx stable 588bb5d559c28 51MB
  20. ccr.ccs.tencentyun.com/koderover-public/nsqio-nsq v1.0.0-compat 2714222e1b39d 22MB
  21. ## 只打印镜像 ID
  22. root@ZHDYA:~$ crictl images -q
  23. sha256:a6e51fd179fb849f4ec6faee318101d32830103f5615215716bd686c56afaea1
  24. sha256:588bb5d559c2813834104ecfca000c9192e795ff3af473431497176b9cb5f2c3
  25. sha256:2714222e1b39d8bd6300da72b0805061cabeca3b24def12ffddf47abd47e2263
  26. sha256:be0f9cfd2d7266fdd710744ffd40e4ba6259359fc3bc855341a8c2adad5f5015
  27. ## 打印容器清单
  28. root@ZHDYA:~$ crictl ps -a
  29. CONTAINER IMAGE CREATED STATE NAME ATTEMPT POD ID
  30. ee20ec2346fc5 c769a1937d035 13 minutes ago Running canal-server 0 b39a7883a433d
  31. 76226ddb736be cc0c524d64c18 34 minutes ago Running mbz-rescue-manager 0 2f9d48c49e891
  32. e2a19ff0591b4 eb40a52eb437d About an hour ago Running export 0 9844b5ea5fdbc
  33. ## 打印正在运行的容器清单
  34. root@ZHDYA:~$ crictl ps
  35. CONTAINER IMAGE CREATED STATE NAME ATTEMPT POD ID
  36. ee20ec2346fc5 c769a1937d035 13 minutes ago Running canal-server 0 b39a7883a433d
  37. ## 容器上执行命令
  38. root@ZHDYA:~$ crictl exec -i -t ee20ec2346fc5 ls
  39. app.sh bin canal-server health.sh node_exporter node_exporter-0.18.1.linux-arm64
  40. ## 获取容器的所有日志
  41. root@ZHDYA:~$ crictl logs ee20ec2346fc5
  42. DOCKER_DEPLOY_TYPE=VM
  43. ==> INIT /alidata/init/02init-sshd.sh
  44. ==> EXIT CODE: 0
  45. ==> INIT /alidata/init/fix-hosts.py
  46. ## 获取最近的 N 行日志
  47. root@ZHDYA:~$ crictl logs --tail=2 ee20ec2346fc5
  48. start canal successful
  49. ==> START SUCCESSFUL ...
  50. ## 拉取镜像
  51. root@ZHDYA:~$ crictl pull busybox

6 总结

Kubernetes 弃用docker这一决定可能对从事相关工作的人员来说有些措手不及,但其实无需特别担心。对于k8s的终端用户来说,这仅仅是一个后端容器运行时的更改,从使用方面来说几乎感觉不到任何区别; 对于应用开发/运维人员来说,依旧可以继续使用docker来构建镜像,以相同的方式将镜像推送到 Harbor,并将这些镜像部署到k8s环境中; 对于k8s集群管理员来说,只需要将docker切换成其它的容器运行时(比如containerd),并将节点troubleshooting工具从docker CLI切换到crictl即可。