容器运行时与镜像管理
容器运行时接口(CRI)、crictl 与 ctr 命令、镜像导入导出、K3s containerd 注意事项。
1. 容器运行时接口(CRI)
1.1 是什么
CRI (Container Runtime Interface) 是 kubelet 与容器运行时之间的标准通信协议。它将 kubelet 与具体运行时解耦,实现了 CRI 接口的容器引擎都可以作为 K8s 的容器运行时。
kubelet ←→ CRI (gRPC) ←→ containerd / CRI-O / cri-dockerd1.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/bash2.2 常见问题
# 如果在 K3s 中遇到权限问题:
# WARN: Failed to stat /var/lib/rancher/k3s/agent/etc/crictl.yaml: permission denied
# 解决:使用 sudo 或 k3s 前缀
sudo crictl ps
sudo k3s crictl ps3. 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.154.3 K3s 中的工具对照表
| 用途 | 命令 |
|---|---|
| 容器管理(CRI 层) | sudo k3s crictl ps 或 sudo 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:v15.2 为 ServiceAccount 添加 imagePullSecrets
# 给 default ServiceAccount 添加拉取凭证,该命名空间下的 Pod 自动使用
kubectl patch serviceaccount default -p '{"imagePullSecrets": [{"name": "my-registry-secret"}]}'