Skip to content
容器运行时与镜像管理

容器运行时与镜像管理

容器运行时接口(CRI)、crictl 与 ctr 命令、镜像导入导出、K3s containerd 注意事项。


1. 容器运行时接口(CRI)

1.1 是什么

CRI (Container Runtime Interface) 是 kubelet 与容器运行时之间的标准通信协议。它将 kubelet 与具体运行时解耦,实现了 CRI 接口的容器引擎都可以作为 K8s 的容器运行时。

kubelet ←→ CRI (gRPC) ←→ containerd / CRI-O / cri-dockerd

1.2 Docker 与 CRI

时间线 说明
K8s v1.24 之前 K8s 内置 dockershim 适配 Docker
K8s v1.24 dockershim 被移除,Docker 需通过 cri-dockerd 适配
K3s 默认使用 containerd,内置 CRI 支持

因此直接在 K8s 节点上使用 docker ps 是看不到 K8s 容器的——它们由 containerd 管理,而非 Docker。


2. crictl:CRI 命令行工具

crictl 是与 CRI 兼容的容器运行时命令行工具,用法与 docker 类似。

2.1 常用命令

# 查看运行中的容器(Pod 内的容器)
crictl ps

# 查看所有容器(含已停止的)
crictl ps -a

# 查看本地镜像
crictl images

# 查看镜像详情
crictl inspecti <IMAGE_ID>

# 拉取镜像
crictl pull nginx:1.22

# 查看容器日志
crictl logs <CONTAINER_ID>

# 查看 Pod 列表
crictl pods

# 在容器内执行命令
crictl exec -it <CONTAINER_ID> /bin/bash

2.2 常见问题

# 如果在 K3s 中遇到权限问题:
# WARN: Failed to stat /var/lib/rancher/k3s/agent/etc/crictl.yaml: permission denied
# 解决:使用 sudo 或 k3s 前缀
sudo crictl ps
sudo k3s crictl ps

3. ctr:containerd 命令行工具

🚨 警告ctr 是 containerd 的原生命令行工具,并非为 K8s 设计。它不支持 CRI,仅在需要导入导出镜像等 containerd 原生操作时使用。

3.1 与 crictl 的对比

工具 层级 用途 是否推荐日常使用
crictl CRI 层 容器/镜像/Pod 管理,与 K8s 对象对应 ✅ 是
ctr containerd 原生层 containerd 底层操作 ❌ 仅特殊场景
nerdctl containerd 原生层(Docker 兼容) Docker 风格操作 containerd ✅ 可选

3.2 使用 ctr 导入/导出镜像

在离线/内网环境无法通过互联网拉取镜像时,可使用 ctr 手动导入导出。

导出流程(在联网机器上):

# 使用 Docker 拉取并导出
docker pull alpine:3.15
docker save alpine:3.15 > alpine-3.15.tar

# 将压缩包复制到目标主机
scp alpine-3.15.tar username@<目标IP>:~/
ssh username@<目标IP>

导入流程(在 K8s 节点上):

# 导入到 K8s 使用的命名空间
ctr -n k8s.io images import alpine-3.15.tar --platform linux/amd64

# 参数说明:
#   -n k8s.io    指定命名空间,K8s 中所有镜像都保存在 k8s.io 命名空间
#   --platform    指定平台和架构(重要!)

导出已存在的镜像

ctr -n k8s.io images export alpine.tar docker.io/library/alpine:3.15 --platform linux/amd64

# 注意:必须使用全限定名(含 docker.io/library/ 前缀)
# 注意:必须指定平台

4. K3s 的 containerd 隔离问题(🚨 重要陷阱)

K3s 使用自己内置的 containerd(socket 在 /run/k3s/containerd/containerd.sock),与系统 containerd(socket 在 /run/containerd/containerd.sock相互隔离

4.1 典型错误场景

# ❌ 错误:直接使用系统 ctr 导入,镜像是导入到系统 containerd 的
sudo ctr -n k8s.io images import alpine-3.15.tar --platform=linux/amd64

# 验证失败:在 K3s 的 crictl 里看不到
sudo crictl images | grep alpine   # 无输出!

4.2 正确做法

# ✅ 正确:使用 k3s ctr 导入到 K3s 自己的 containerd
sudo k3s ctr -n k8s.io images import alpine-3.15.tar --platform=linux/amd64

# ✅ 验证
sudo k3s crictl images | grep alpine   # 有输出!

# 清理系统 containerd 中误导入的镜像(释放磁盘空间)
sudo ctr -n k8s.io images rm docker.io/library/alpine:3.15

4.3 K3s 中的工具对照表

用途 命令
容器管理(CRI 层) sudo k3s crictl pssudo crictl --runtime-endpoint unix:///run/k3s/containerd/containerd.sock ps
查看镜像(CRI 层) sudo k3s crictl images
导入/导出镜像 sudo k3s ctr -n k8s.io images import/export
拉取镜像 sudo k3s crictl pull <image>

5. 私有仓库镜像拉取

5.1 配置 authentification

创建用于私有仓库认证的 Secret:

kubectl create secret docker-registry my-registry-secret \
  --docker-server=<私有仓库地址> \
  --docker-username=<用户名> \
  --docker-password=<密码> \
  --docker-email=<邮箱>

在 Pod 中使用:

spec:
  imagePullSecrets:
    - name: my-registry-secret
  containers:
    - name: app
      image: <私有仓库地址>/myapp:v1

5.2 为 ServiceAccount 添加 imagePullSecrets

# 给 default ServiceAccount 添加拉取凭证,该命名空间下的 Pod 自动使用
kubectl patch serviceaccount default -p '{"imagePullSecrets": [{"name": "my-registry-secret"}]}'