1. docker与containerd对比
在 V1.24 版本以前 k8s 默认使用docker容器引擎
在 V1.24 版本以后 k8s 移除了dockershim,改为默认使用Containerd
1.1. 调用链路的区别
- 使用docker作为容器引擎时需要通过dockershim对接docker再调用containerd。
- 使用containerd作为容器引擎时kubelt可以通过CRI-containerd直接调用containerd。
1.2. 标准输出日志的区别
docker | containerd | |
储存路径 | 如果 Kubernetes 使用 Docker 作为容器运行时,容器日志的落盘由docker来完成, 日志通常存储在 /var/lib/docker/containers/<container-id>-json.log。 | 如果 Kubernetes 使用 containerd 作为容器运行时,容器日志的落盘由kubelet来完成,路径 为/var/log/pods/<namespace>_<pod-name>_<pod-uid>/<container-name>/<container-id>,同时在/var/log/containers目录下创建软链接,指向日志文件。 |
日志轮转配置 | 在docker配置文件中指定: “log-driver”: “json-file”, “log-opts”: {“max-size”: “100m”,”max-file”: “5”} | 方法一:在 kubelet 启动时指定参数 –container-log-max-files=5 –container-log-max-size=”100Mi” 方法二:在配置文件KubeletConfiguration中指定 containerLogMaxFiles: 5, containerLogMaxSize: “100Mi”,配置文件路径/var/lib/kubelet/config.yaml |
1.3. 配置文件路径
Containerd:
# containerd 配置文件路径
/etc/containerd/config.toml
# 默认配置中还有两个关于存储的配置路径:
# 1、保存持久化数据,包括 Snapshots, Content, Metadata 以及各种插件的数据
root = "/var/lib/containerd"
# 2、保存运行时的临时数据的,包括 sockets、pid、挂载点、运行时状态以及不需要持久化的插件数据。
state = "/run/containerd"
BashDocker:
/etc/docker/daemon.json
Bash1.4. stream server
在 Kubernetes 和容器生态中,Stream Server 是容器运行时(如 containerd
或 CRI-O
)提供的一个关键服务,主要用于处理容器 标准输入(stdin)、输出(stdout)和错误(stderr)流 的转发和管理。如 kubectl exec/logs 等命令需要在 apiserver 跟容器运行时之间建立流转发通道。
docker API 本身提供 stream 服务,kubelet 内部的 docker-shim 会通过 docker API 做流转发。而 containerd 或 CRI-O 容器运行时需要单独配置 Stream Server 服务。
Stream Server 配置:
# /etc/containerd/config.toml
...
[plugins."io.containerd.grpc.v1.cri"]
...
stream_server_address = "127.0.0.1"
stream_server_port = "0"
...
# stream_server_address = "127.0.0.1"
## 作用:指定 Stream Server 监听的网络地址。
## 127.0.0.1:仅允许本地(节点内部)访问 Stream Server,禁止外部直接连接。
## 若需允许远程访问(不推荐),可改为 0.0.0.0,但必须配合 TLS 加密。
## Kubernetes API Server 通过每个节点的 kubelet 代理访问 Stream Server,所以 Stream Server 无需对外暴露。
# stream_server_port = "0"
## 作用:指定 Stream Server 监听的端口。
## "0":表示由系统自动分配一个空闲端口(通常通过临时端口范围)。
Bash2. containerd 客户端命令介绍
2.1. crictl、ctr 命令
更换 containerd 后,以往我们常用的 docker 命令也不再使用,取而代之的分别是 crictl 和 ctr 两个命令客户端。
- crictl 命令(k8s提供):crictl 是遵循 CRI 接口规范的一个命令行工具,用于直接与 实现了 CRI 的容器运行时(如 containerd、CRI-O)交互,通常用它来检查和管理 k8s 节点上的容器运行时和镜像(不涉及非 CRI 管理的容器或镜像)。
- ctr 命令(containerd提供):ctr 是 containerd 原生管理工具,管理所有由 containerd 托管的容器、镜像和快照(包括非 Kubernetes 容器)。
注意:
# 使用crictl命令之前,需要先配置/etc/crictl.yaml如下(不配置的话,你用该命令会一直报warn警告)
cat > /etc/crictl.yaml << 'EOF'
runtime-endpoint: unix:///run/containerd/containerd.sock
image-endpoint: unix:///run/containerd/containerd.sock
timeout: 10
debug: false
EOF
# 也可以通过命令进行设置(会自动生成/etc/crictl.yaml)
sudo crictl config runtime-endpoint unix:///run/containerd/containerd.sock
sudo crictl config image-endpoint unix:///run/containerd/containerd.sock
Bash2.2. nerdctl 命令
前面我们介绍了可以使用 ctr 操作管理 containerd 镜像容器,但是大家都习惯了使用 docker cli,ctr 使用起来可能还是不太顺手,为了能够让大家更好的转到 containerd 上面来,社区提供了一个新的命令行工具:nerdctl。
nerdctl 是一个与 docker cli 风格兼容的 containerd 客户端工具,而且直接兼容 docker compose 的语法,这就大大提高了直接将 containerd 作为本地开发、测试或者单机容器部署使用的效率。
安装:
# 如果没有安装 nerdctl,则可以下载 nerdctl-full-<VERSION>-linux-amd64.tar.gz 包进行安装
wget https://github.com/containerd/nerdctl/releases/download/v1.7.6/nerdctl-1.7.6-linux-amd64.tar.gz
mkdir -p /usr/local/containerd/ && tar -zxvf nerdctl-1.7.6-linux-amd64.tar.gz nerdctl && mv nerdctl /usr/local/containerd/
ln -s /usr/local/containerd/nerdctl /usr/local/sbin/nerdctl
# 查看 nerdctl
nerdctl version # 报错warn,提示buildkit未安装
WARN[0000] unable to determine buildctl version: exec: "buildctl": executable file not found in $PATH
Client:
Version: v1.7.6
OS/Arch: linux/amd64
Git commit: 845e989f69d25b420ae325fedc8e70186243fd93
buildctl:
Version:
Server:
containerd:
Version: 1.7.27
GitCommit: 05044ec0a9a75232cad458027ca83437aae3f4da
runc:
Version: 1.2.5
GitCommit: v1.2.5-0-g59923ef
# BuildKit 是 Docker 官方推出的下一代镜像构建工具,旨在解决传统 Docker 构建(docker build)的性能、灵活性和安全性问题。自 Docker 18.09 起,BuildKit 成为默认构建引擎(需显式启用),它通过并行化构建、缓存优化和跨平台支持,显著提升了容器镜像的构建效率。
# 同时,新版本 k8s 弃用了 docker,默认使用 containerd,则不能使用 docker build 构建镜像,所以需要使用 BuildKit 工具来构建镜像。
# 安装 buildkit 见下文 nerdctl 镜像命令详解
# 参考文档:https://zhuanlan.zhihu.com/p/366671300
Bash配置 nerdctl 命令补全:
# 安装 Bash 自动补全功能
sudo yum install bash-completion* -y
sudo apt install bash-completion* -y
# 生成补全脚本并保存到 ~/.nerdctl-completion.bash
nerdctl completion bash > ~/.nerdctl-completion.bash
echo "source '$HOME/.nerdctl-completion.bash'" >> $HOME/.bash_profile
# 立即生效
source $HOME/.bash_profile
# 全局配置,所有用户生效
nerdctl completion bash > /etc/bash_completion.d/nerdctl
Bash2.3. 客户端命令 docker、ctr、crictl、nerdctl 详解
2.3.1. 名称空间
可以用 -n 指定名称空间,可以将镜像或者容器分散到不同的空间内,但并非所有命令都支持。
docker | ctr (containerd) | crictl(k8s) | nerdctl | |
是否支持 | 不支持 | 支持 | 不支持 | 支持 |
示例 | ctr ns ls ctr -n k8s.io image ls # 查看指定名称空间下的镜像 ctr -n k8s.io container ls # 查看指定名称空间下的容器 | 默认所有操作都在k8s.io名称空间下 | nerdctl -n k8s.io image ls nerdctl -n k8s.io container ls |
2.3.2. 镜像相关命令
工具对比
命令 | docker | ctr | crictl | nerdctl |
查看本地镜像 | docker images | ctr image ls | crictl images | 同docker命令 |
下载/拉取镜像 | docker pull | ctr image pull | ctictl pull | 同docker命令 |
给镜像打标签 | docker tag | ctr image tag | 无 | 同docker命令 |
上传/推送镜像 | docker push | ctr image push | 无 | 同docker命令 |
删除本地镜像 | docker rmi | ctr image rm | crictl rmi | 同docker命令 |
查看镜像详情 | docker inspect | 无 | crictl inspecti # 注意末尾是小写字母 i | 同docker命令 |
导出镜像 | docker save | ctr image export | 无 | 同docker命令 |
导入镜像 | docker load | ctr image import xx.tar docker.io/library/nginx:alpine | 无 | 同docker命令 |
登录镜像仓库 | docker login | 不支持,理由:ctr 工具主要是用于底层的容器操作和管 理,而不是直接与镜像仓库进行交互如推拉镜像等。 | 不支持,理由:主要用于管理 Pod 和容器,而非直接与镜像仓库交互。 | 支持 |
ctr(containerd)镜像命令详解
# 1、查看全部镜像
sudo ctr image ls # 分字段展示
sudo ctr image ls -q # 列出本地存储中的镜像(images)的 ID 列表,而不显示详细的镜像信息。
sudo ctr image check # 检测default名称空间下所有镜像的可用性,主要看STATUS为complete代表可用
# 2、拉取 Docker Hub 官方镜像 nginx:alpine,需要注意的是镜像地址需要加上 docker.io Host 地址
sudo ctr images pull docker.io/library/nginx:alpine
# 3、重新打标签
sudo ctr image tag docker.io/library/nginx:alpine harbor.k8s.local/course/nginx:alpine
# 4、上传镜像
sudo ctr images push docker.io/library/nginx:alpine --user xxx
# 5、删除镜像
sudo ctr image rm harbor.k8s.local/course/nginx:alpine
# 6、查看镜像详情
无
# 7、将镜像导出为压缩包
sudo ctr image export nginx.tar.gz docker.io/library/nginx:alpine
sudo ctr -n k8s.io image export a.tar.gz registry.cn-hangzhou.aliyuncs.com/google_containers/coredns:v1.11.1
# 8、从压缩包导入镜像
sudo ctr image import nginx.tar.gz
sudo ctr -n default image import a.tar.gz
# 直接导入可能会出现类似于 ctr: content digest sha256:xxxxxx not found 的错误,要解决这个办法需要 pull 可以通用/适用所有平台的镜像:
sudo ctr i pull --all-platforms docker.io/library/nginx:alpine
sudo ctr i export --all-platforms nginx.tar.gz docker.io/library/nginx:alpine
sudo ctr i rm docker.io/library/nginx:alpine
sudo ctr i import nginx.tar.gz
# 9、将镜像挂载到主机目录
sudo ctr image mount docker.io/library/nginx:alpine /mnt
sudo ctr image unmount /mnt
# 10、命名空间:Containerd 也有 namespaces 的概念,镜像或容器可以分散到不同的空间,对于多租户的场景十分有用
sudo ctr ns ls
sudo ctr ns create test
sudo ctr ns rm test
sudo ctr -n test image ls
# 说明:
# 1、Docker 其实也是默认调用的 containerd,事实上 Docker 使用的 containerd 下面的命名空间默认是 moby,而不是 default
# 2、Kubernetes 下使用的 containerd 默认命名空间是 k8s.io
Bashcrictl(kubernetes)镜像命令详解
# crictl 没有-n参数,操作都在`k8s.io`命名空间下。
# sudo crictl image list 等同于 sudo ctr -n=k8s.io image list
# sudo crictl image ls 等同于 sudo ctr -n=k8s.io image ls
# 注意:
# sudo ctr images pull 拉取的镜像默认放在 default 而 sudo crictl pull 和 kubelet 默认拉取的镜像都在 k8s.io 命名空间下。所以通过 ctr 导入镜像的时候特别注意一点,最好指定命名空间。
Bashnerdctl 镜像命令详解
# 镜像管理
nerdctl images
nerdctl pull docker.io/library/busybox:latest
nerdctl login --username=xxx --password yyy registry.cn-shanghai.aliyuncs.com
nerdctl tag centos:7 registry.cn-shanghai.aliyuncs.com/egon/test:v1.0
nerdctl push registry.cn-shanghai.aliyuncs.com/egon/test:v1.0
nerdctl save -o busybox.tar.gz busybox:latest
nerdctl load -i busybox.tar.gz
nerdctl rmi busybox
# ctr不能 build 镜像,我们可以用 nerdctl
# 1、Containerfile文件如下
FROM ubuntu
CMD sleep 1000
# 2、构建镜像
nerdctl build -t test:v1.0 -f Containerfile .
# 可以看到有一个错误提示,需要我们安装 `buildctl` 并运行 `buildkitd`,这是因为 `nerdctl build` 需要依赖 `buildkit` 工具。
# buildkit 项目也是 Docker 公司开源的一个构建工具包,支持 OCI 标准的镜像构建。它主要包含以下部分:
# 1、服务端 `buildkitd`:当前支持 runc 和 containerd 作为 worker,默认是 runc,我们这里使用 containerd
# 2、客户端 `buildctl`:负责解析 Dockerfile,并向服务端 buildkitd 发出构建请求
# buildkit 是典型的 C/S 架构,客户端和服务端是可以不在一台服务器上,而 `nerdctl` 在构建镜像的时候也作为 `buildkitd` 的客户端,所以需要我们安装并运行 `buildkitd`。
# 安装 buildkit
wget https://github.com/moby/buildkit/releases/download/v0.13.2/buildkit-v0.13.2.linux-amd64.tar.gz
tar -zxvf buildkit-v0.13.2.linux-amd64.tar.gz -C /usr/local/containerd/
ln -s /usr/local/containerd/bin/buildkitd /usr/local/sbin/buildkitd
ln -s /usr/local/containerd/bin/buildctl /usr/local/sbin/buildctl
cat > /etc/systemd/system/buildkit.service << "EOF"
[Unit]
Description=BuildKit
Documentation=https://github.com/moby/buildkit
[Service]
ExecStart=/usr/local/sbin/buildkitd --oci-worker=false --containerd-worker=true
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
systemctl enable buildkit --now
systemctl status buildkit.service
# 如果 containerd 服务使用了代理,那么在使用 BuildKit 构建镜像时,仅配置 containerd 的代理是不够的,因为 BuildKit 服务 (buildkitd) 是一个独立的服务进程,需要单独配置代理。
# containerd 代理:仅影响 nerdctl pull 等镜像拉取操作。
# BuildKit 代理:影响镜像构建时的基础镜像拉取和层下载。
# 创建代理配置文件
mkdir -p /etc/systemd/system/buildkit.service.d/
tee /etc/systemd/system/buildkit.service.d/proxy.conf <<'EOF'
[Service]
Environment="HTTP_PROXY=http://hypervisor-01:20172"
Environment="HTTPS_PROXY=http://hypervisor-01:20172"
Environment="NO_PROXY=localhost,127.0.0.1,.internal,192.168.2.0/24"
EOF
# 重载配置
sudo systemctl daemon-reload
sudo systemctl restart buildkit
# 重新构建镜像
nerdctl build -t test:v1.0 -f Containerfile .
nerdctl images
REPOSITORY TAG IMAGE ID CREATED PLATFORM SIZE BLOB SIZE
test v1.0 2c93d0cc2e4b 10 seconds ago linux/amd64 81.1 MiB 28.3 MiB
ubuntu latest a08e551cb338 18 minutes ago linux/amd64 81.1 MiB 28.4 MiB
# 启动测试
nerdctl run -d --name=test test:v1.0
nerdctl container ls
nerdctl exec -ti test sh
Bash2.3.2. 容器相关命令
工具对比
命令 | docker | ctr | crictl | nerdctl |
显示本地运行的容器 | docker ps | ctr task ls/ctr container ls | crictl ps | 同docker命令 |
创建一个新容器 | docker create | ctr container create | crictl create | 同docker命令 |
运行一个新容器 | docker run | ctr run | 无(最小单元为 pod) | 同docker命令 |
启动容器 | docker start | ctr task start | crictl start | 同docker命令 |
关闭容器 | docker stop | ctr task kill | crictl stop | 同docker命令 |
删除容器 | docker rm | ctr container rm | crictl rm | 同docker命令 |
查看容器详情 | docker inspect | ctr container info | crictl inspect | 同docker命令 |
查看容器日志 | docker logs | 无 | crictl logs | 同docker命令 |
查看容器资源 | docker stats | 无 | crictl stats | 同docker命令 |
进入容器内部 | docker exec | 无 | crictl exec | 同docker命令 |
清空不用的容器 | docker image prune | 无 | crictl rmi –prune | 同docker命令 |
ctr(containerd)容器命令详解
# 容器操作
## 创建容器
ctr image pull docker.io/library/nginx:alpine --hosts-dir=/etc/containerd/certs.d
ctr container create docker.io/library/nginx:alpine nginx
## 查看容器
ctr container ls
ctr container ls -q
ctr container info nginx
## 删除容器
ctr container rm nginx
# 任务
## (1)任务介绍
# 上面用container create只是创建了一个静态的容器对象,把运行容器需要的资源及配置数据例如namespaces、rootfs和容器的配置都初始化完毕了,但是容器内的进程还没有启动,即容器尚未处于运行状态
## (2) 启动任务(激活容器)
ctr task start -d nginx # nginx是你创建的容器名字
## (3)查看
ctr task ls
## (4)进入容器
# 注意必须要指定 --exec-id 参数,这个 id 可以随便写,只要唯一就行。
ctr task exec --exec-id 0 -t nginx sh
## (5)暂停容器
ctr task pause nginx # 可以查看容器ctr task ls发现状态变成PAUSED
## (6)恢复容器
ctr task resume nginx
## (7)ctr无法stop容器,只能暂停或杀死
ctr task kill nginx # 可以查看容器ctr task ls发现状态变成STOPPED
## (8)删掉
ctr task rm nginx
## (9)获取容器cgroup相关信息(内存、CPU 和 PID 的限额与使用量。)
ctr task metrics nginx # 记得要先启动才能看:ctr task start -d nginx
## (10)看容器中所有进程在宿主机中的 PID
ctr task ps nginx # 第一行的就对应容器内的1号进程
ShellScriptnerdctl 容器命令详解
# 容器管理
nerdctl run -d -p 80:80 --name=nginx --restart=always nginx:alpine
nerdctl exec -it nginx /bin/sh
nerdctl ps
nerdctl ps -a
nerdctl inspect nginx
nerdctl logs
nerdctl logs -f
nerdctl stop nginx
nerdctl rm nginx
nerdctl rm -f nginx
# 更多命令操作,可以直接在命令行输入命令查看帮助。
docker --help
ctr --help
crictl --help
ShellScript