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 -v
ctr containerd.io 1.6.22
$ crictl -v
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 作为命名空间
#查看命名空间
ctr namespace ls
# 查看 K8S 命名空间下的镜像
ctr -n k8s.io images ls
# 下载镜像
ctr images pull docker.io/library/redis:alpine
# 创建 container
ctr c create docker.io/library/redis:alpine redis-container
# 查看
ctr c ls
# 后台启动
ctr t start -d redis-container
# 查看 container
ctr t ls
# 查看 k8s 中正在运行的容器
ctr -n k8s.io task ls
# 打tag
ctr 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:alpine
ctr images rm harbor.junengcloud.com/tmp/redis:alpine
ctr images tag docker.io/library/redis:alpine harbor.junengcloud.com/tmp/redis:alpine
ctr 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.8
ctr images import rabbitmq_3.7.8.tar
ctr images ls -q
# 查看ctr image可用操作
ctr image list, ctr i list , ctr i ls
# 镜像标记tag
ctr -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.yaml
root@ZHDYA:~$ cat /etc/crictl.yaml
runtime-endpoint: unix:///run/containerd/containerd.sock
## 列出业务容器状态
crictl inspect ee20ec2346fc5
## 查看运行中容器
root@ZHDYA:~$ crictl pods
POD ID CREATED STATE NAME NAMESPACE ATTEMPT RUNTIME
b39a7883a433d 10 minutes ago Ready canal-server-quark-b477b5d79-ql5l5 mbz-alpha 0 (default)
## 打印某个固定pod
root@ZHDYA:~$ crictl pods --name canal-server-quark-b477b5d79-ql5l5
POD ID CREATED STATE NAME NAMESPACE ATTEMPT RUNTIME
b39a7883a433d 12 minutes ago Ready canal-server-quark-b477b5d79-ql5l5 mbz-alpha 0 (default)
## 打印镜像
root@ZHDYA:~$ crictl images
IMAGE TAG IMAGE ID SIZE
ccr.ccs.tencentyun.com/koderover-public/library-docker stable-dind a6e51fd179fb8 74.6MB
ccr.ccs.tencentyun.com/koderover-public/library-nginx stable 588bb5d559c28 51MB
ccr.ccs.tencentyun.com/koderover-public/nsqio-nsq v1.0.0-compat 2714222e1b39d 22MB
## 只打印镜像 ID
root@ZHDYA:~$ crictl images -q
sha256:a6e51fd179fb849f4ec6faee318101d32830103f5615215716bd686c56afaea1
sha256:588bb5d559c2813834104ecfca000c9192e795ff3af473431497176b9cb5f2c3
sha256:2714222e1b39d8bd6300da72b0805061cabeca3b24def12ffddf47abd47e2263
sha256:be0f9cfd2d7266fdd710744ffd40e4ba6259359fc3bc855341a8c2adad5f5015
## 打印容器清单
root@ZHDYA:~$ crictl ps -a
CONTAINER IMAGE CREATED STATE NAME ATTEMPT POD ID
ee20ec2346fc5 c769a1937d035 13 minutes ago Running canal-server 0 b39a7883a433d
76226ddb736be cc0c524d64c18 34 minutes ago Running mbz-rescue-manager 0 2f9d48c49e891
e2a19ff0591b4 eb40a52eb437d About an hour ago Running export 0 9844b5ea5fdbc
## 打印正在运行的容器清单
root@ZHDYA:~$ crictl ps
CONTAINER IMAGE CREATED STATE NAME ATTEMPT POD ID
ee20ec2346fc5 c769a1937d035 13 minutes ago Running canal-server 0 b39a7883a433d
## 容器上执行命令
root@ZHDYA:~$ crictl exec -i -t ee20ec2346fc5 ls
app.sh bin canal-server health.sh node_exporter node_exporter-0.18.1.linux-arm64
## 获取容器的所有日志
root@ZHDYA:~$ crictl logs ee20ec2346fc5
DOCKER_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 ee20ec2346fc5
start canal successful
==> START SUCCESSFUL ...
## 拉取镜像
root@ZHDYA:~$ crictl pull busybox
6 总结
Kubernetes 弃用docker这一决定可能对从事相关工作的人员来说有些措手不及,但其实无需特别担心。对于k8s的终端用户来说,这仅仅是一个后端容器运行时的更改,从使用方面来说几乎感觉不到任何区别;
对于应用开发/运维人员来说,依旧可以继续使用docker来构建镜像,以相同的方式将镜像推送到 Harbor,并将这些镜像部署到k8s环境中;
对于k8s集群管理员来说,只需要将docker切换成其它的容器运行时(比如containerd),并将节点troubleshooting工具从docker CLI切换到crictl即可。