AI Infra 训练营
总览
  • Day 1 · 集群起步 + CNI
  • Day 2 · 控制面 + etcd
  • Day 3 · CRD + Operator + Webhook
  • Day 4 · 存储深度
  • Day 5 · 卷扩容 + 安全
  • Day 6 · 调度 + 可观测
  • Day 7 · Harbor + ArgoCD + Mesh
  • Day 8 · AI Infra
  • Day 9 · Triton + GPU
  • Day 10 · MIG + HPA + 量化
  • Day 11 · AI Agent 端到端
  • Day 12 · 灾备
  • Day 13 · Operator + 联邦 + Mesh + RAG
  • Day 14 · CKA / CKS + 总结
  • LLM 训练手册
  • RAG + Agent 手册
  • 推理优化手册
  • 上下文工程手册
  • Agent 开发手册
  • 面试深度复盘
  • 训练 v2 深度手册
  • 心智模型
  • 看懂命令输出
  • 容器网络底层
  • K8s 网络深入
  • DNS 全套
  • 故障排查方法论
  • 心智模型
  • 容器挂载完整指南
  • K8s Volumes 大全
  • PV/PVC/CSI 深入
  • NFS 深入
  • 分布式存储概览
  • 故障排查 runbook
HiHuo 主站
GitHub
总览
  • Day 1 · 集群起步 + CNI
  • Day 2 · 控制面 + etcd
  • Day 3 · CRD + Operator + Webhook
  • Day 4 · 存储深度
  • Day 5 · 卷扩容 + 安全
  • Day 6 · 调度 + 可观测
  • Day 7 · Harbor + ArgoCD + Mesh
  • Day 8 · AI Infra
  • Day 9 · Triton + GPU
  • Day 10 · MIG + HPA + 量化
  • Day 11 · AI Agent 端到端
  • Day 12 · 灾备
  • Day 13 · Operator + 联邦 + Mesh + RAG
  • Day 14 · CKA / CKS + 总结
  • LLM 训练手册
  • RAG + Agent 手册
  • 推理优化手册
  • 上下文工程手册
  • Agent 开发手册
  • 面试深度复盘
  • 训练 v2 深度手册
  • 心智模型
  • 看懂命令输出
  • 容器网络底层
  • K8s 网络深入
  • DNS 全套
  • 故障排查方法论
  • 心智模型
  • 容器挂载完整指南
  • K8s Volumes 大全
  • PV/PVC/CSI 深入
  • NFS 深入
  • 分布式存储概览
  • 故障排查 runbook
HiHuo 主站
GitHub

crictl —— 容器运行时命令行(CRI 层)

一句话定义

crictl 是 K8s 节点上容器运行时(containerd / CRI-O)的命令行工具。它直接和 CRI 接口对话,绕开 kubectl 和 apiserver——当 kubelet 出问题、容器没起来、kubectl 看不到东西时,crictl 是最后的诊断工具。

典型场景

  • kubelet 起不来 / 节点 NotReady:crictl ps 看节点上有什么容器在跑
  • ImagePullBackOff:crictl images 看镜像有没有、crictl pull 手动拉
  • 容器一直 crash:crictl logs <id> 直接看容器日志(不经 kubectl)
  • 磁盘满了:crictl rmi --prune 清没用的镜像
  • 排查"kubectl 看到 Running,节点上是不是真的":crictl ps

crictl 与 kubectl / docker 的关系

你 ─► kubectl ─► apiserver ─► kubelet ─► containerd / CRI-O ◄─ crictl
                                                    │
                                                    └─► containers
  • kubectl 走 apiserver,看的是 K8s 视角的 pod
  • crictl 直接连容器运行时 socket,看的是节点本地的真实容器

Docker 时代的 docker ps 在 K8s 节点上不再适用(K8s 1.24+ 已经移除 Docker 作 runtime)。crictl 是它的合法继承者。


配置:连接哪个 runtime

crictl 默认配置在 /etc/crictl.yaml:

runtime-endpoint: unix:///run/containerd/containerd.sock
image-endpoint: unix:///run/containerd/containerd.sock
timeout: 10
debug: false

第一次跑 crictl ps 报错 "no runtime endpoint" 就是没配。

修复:

cat > /etc/crictl.yaml <<'EOF'
runtime-endpoint: unix:///run/containerd/containerd.sock
image-endpoint: unix:///run/containerd/containerd.sock
timeout: 10
EOF

或者命令行 crictl --runtime-endpoint unix:///run/containerd/containerd.sock ps。


核心命令一览

crictl 命令docker 等价用途
crictl psdocker ps看容器
crictl ps -adocker ps -a含已退出的
crictl pods(无)看 Pod sandbox
crictl imagesdocker images镜像列表
crictl pull <img>docker pull手动拉镜像
crictl rmi <img>docker rmi删镜像
crictl rmi --prunedocker image prune清没用的
crictl logs <ctr>docker logs容器日志
crictl exec -it <ctr> shdocker exec进容器
crictl inspect <ctr>docker inspect看容器详情
crictl stop <ctr>docker stop停容器(kubelet 会拉起新的)
crictl rm <ctr>docker rm删容器
crictl infodocker inforuntime 信息
crictl statsdocker stats实时资源
crictl versiondocker version版本

记住一条:crictl 是从节点本地视角看的。kubectl 是从集群视角看的。两者对得上才正常。


crictl ps —— 看容器

$ crictl ps
CONTAINER     IMAGE          CREATED         STATE     NAME                    POD          NAMESPACE
abc123...     nginx:1.25     5 minutes ago   Running   nginx                   nginx-abc    default
def456...     etcd:3.5.10    1 day ago       Running   etcd                    etcd-m1      kube-system
...

字段:

  • CONTAINER —— 容器 ID(前缀,完整 ID 用 -v)
  • POD —— 这个容器属于哪个 pod(K8s 一个 pod 可能有多个容器)
  • NAMESPACE —— K8s namespace(不是 Linux ns)

常用过滤

crictl ps -a                                     # 含已退出
crictl ps -a --name nginx                        # 按名字
crictl ps --state Exited                         # 按状态
crictl ps -a --label io.kubernetes.pod.name=nginx-abc   # 按 K8s label

# 简化输出(脚本用)
crictl ps -q                                     # 只输出 ID
crictl ps -q --name nginx | head -1              # 拿第一个 nginx 容器 ID

crictl pods —— 看 Pod sandbox

每个 K8s pod 在 CRI 层是一个 sandbox(pause 容器 + 一组应用容器)。

$ crictl pods
POD ID        CREATED         STATE   NAME              NAMESPACE
xyz789...     5 minutes ago   Ready   nginx-abc         default
...

crictl pods 列 sandbox,crictl ps 列其中的具体容器。


排查 Pod 起不来的真实方法

K8s pod 显示 ContainerCreating 或 CrashLoopBackOff 时 —— 节点上发生了什么?

# 1. 在 kubectl 那边看
kubectl describe pod my-pod
# 找出 Pod 调度到了哪个节点:Node: m4

# 2. 登节点
ssh m4

# 3. 看真实容器状态
crictl ps -a | grep my-pod
# CONTAINER  IMAGE  CREATED  STATE  NAME
# abc...     nginx  ...      Exited  nginx                    ← 退出了!
# def...     pause  ...      Running ...sandbox...

# 4. 看那个 Exited 容器的日志
crictl logs abc...
# 看到容器 panic / 启动失败

# 5. 看为啥 Exited
crictl inspect abc... | jq '.status'
# {
#   "exitCode": 1,
#   "reason": "Error",
#   "message": "configmap mounting failed: ...",
#   "startedAt": "...",
#   "finishedAt": "..."
# }

看 kubelet 怎么管这个 pod 的

journalctl -u kubelet --since "10 min ago" | grep my-pod
# 显示 pod sync 失败 / image pull 失败 / cgroup 创建失败 等具体原因

镜像管理:images / pull / rmi

crictl images                                    # 列所有镜像
crictl images | grep nginx
crictl images --quiet                            # 只 ID

crictl pull nginx:1.25                           # 手动拉
crictl pull --auth user:pass private-registry.com/nginx:1.25   # 带认证

crictl rmi nginx:1.21                            # 删一个镜像
crictl rmi --prune                               # 删所有没被容器引用的镜像(**节点磁盘满救命**)

"ImagePullBackOff" 排查

kubectl describe pod my-pod | grep -A 10 Events
# Failed to pull image "private.example.com/myapp:v1": rpc error: code = Unknown desc = ...

# 登节点手动拉
ssh m4
crictl pull private.example.com/myapp:v1
# 看具体错:DNS 失败 / 401 / TLS / ...

常见原因和修法:

错误原因修
connection refused / DNS节点 DNS 配错/etc/resolv.conf
401 Unauthorized没配 imagePullSecret创建 secret + pod spec 引用
x509: certificate signed by unknown私有 registry 自签 certcontainerd 配置加 ca
manifest unknowntag 错看 registry 列表

私有 registry 配 containerd(Day7 必会):

# /etc/containerd/config.toml
[plugins."io.containerd.grpc.v1.cri".registry.configs."private.example.com".auth]
  username = "user"
  password = "pass"

改完 systemctl restart containerd。


crictl logs 和 kubectl logs 的区别

维度kubectl logscrictl logs
来源apiserver → kubelet → 容器 stdout节点本地
需要apiserver 可用只需 runtime 可用
--previous支持(上次崩溃日志)不直接支持,要找上一个 container ID
-f 跟随支持支持
-c 选容器选 K8s pod 内多容器直接指定 container ID
crictl logs abc...                       # 整体
crictl logs -f abc...                    # 跟随
crictl logs --tail=100 abc...
crictl logs --since=10m abc...

kubectl logs 不工作时 crictl logs 是替代方案:apiserver 挂了、kubelet 重启中、网络隔离。


crictl exec —— 进容器

crictl exec -it abc... sh
crictl exec abc... ls /var/log

和 kubectl exec 等价,但不经过 apiserver。


crictl stats —— 实时资源

crictl stats
# CONTAINER  CPU %   MEM        DISK   INODES
# abc123     5.2%    120MB      1.5MB  234
# def456     0.3%    50MB       0.5MB  102

crictl stats -a                          # 含已停止

看节点上真实的容器资源。kubectl top 依赖 metrics-server,crictl stats 直接问 runtime。


crictl info —— Runtime 健康

$ crictl info
{
  "status": {
    "conditions": [
      {"type": "RuntimeReady", "status": true, "reason": "RuntimeReady"},
      {"type": "NetworkReady", "status": true, "reason": "NetworkReady"}
    ]
  },
  "cniconfig": { ... },
  "config": { ... }
}

排查节点 NotReady:

crictl info | jq '.status.conditions'
# 哪个 condition false 就是哪里坏了

NetworkReady=false —— CNI 没起来。 RuntimeReady=false —— containerd 本身有问题。


训练营节点排错套路

Pod 起不来 / 节点 NotReady 排错链

# 1. 节点状态
kubectl get nodes
kubectl describe node m4 | tail -30

# 2. 登节点
ssh m4

# 3. runtime 健康
crictl info | jq '.status.conditions'
systemctl status containerd

# 4. 当前容器
crictl ps -a | head

# 5. 看具体崩了的
crictl logs <container-id>
crictl inspect <container-id> | jq '.status'

# 6. kubelet 日志
journalctl -u kubelet --since "5 min ago"

# 7. 磁盘 / 内存
df -h
free -h

磁盘满了的快速救援

# 节点磁盘报警
df -h /var/lib/containerd

# 清没引用的镜像
crictl rmi --prune
# 通常能清几个 GB

# 清 containerd 缓存(小心,要重启)
ctr -n k8s.io content prune                  # 用 ctr 不是 crictl

# journal 也清
journalctl --vacuum-size=200M

crictl vs ctr 的区别

容器运行时两个命令行工具容易混:

工具走的接口用途
crictlCRI(K8s 标准接口)K8s 视角的容器、镜像操作
ctrcontainerd 原生 APIcontainerd 内部细节

例子:

crictl images                            # 只显示 K8s 用的镜像(k8s.io namespace)
ctr images list                          # 显示**所有** containerd 镜像(含其它 namespace)

ctr -n k8s.io images list                # 等价 crictl images
ctr -n moby images list                  # 看其它(如 docker 兼容层)

99% 场景用 crictl。ctr 用在 containerd 自身排错。


常见踩坑

坑 1:no runtime endpoint configured

$ crictl ps
FATA[0000] no runtime endpoint configured

/etc/crictl.yaml 没配。见上面"配置"段。

坑 2:用旧版 crictl 配新 containerd

crictl --version
# crictl version 1.21    ← 太老

crictl 版本最好和 K8s minor 版本一致(K8s 1.28 → crictl 1.28)。

VERSION=v1.28.0
curl -L https://github.com/kubernetes-sigs/cri-tools/releases/download/$VERSION/crictl-$VERSION-linux-amd64.tar.gz \
  | tar -xz -C /usr/local/bin

坑 3:crictl ps 没看到 pod 容器

kubectl get pods    # 显示 nginx Running
ssh m4 'crictl ps | grep nginx'    # 找不到

可能 pod 在别的节点上跑。kubectl get pods -o wide 看 NODE 列。

或者节点上 runtime 出问题、Pod 还显示 Running 但实际没跑。这种"幽灵 Pod"是 kubelet bug,需要 restart kubelet。

坑 4:crictl 删容器但 kubelet 立刻拉起

crictl stop abc...
crictl rm abc...
crictl ps    # 几秒后又有一个新的

这是正常的——K8s 的 desired state 是要这个 pod 跑着,kubelet 看到容器没了会拉起新的。要真停:

kubectl delete pod my-pod -n my-ns
# 或者把 deployment 缩到 0
kubectl scale deploy nginx --replicas=0

直接 crictl 操作只在调试时用,不能"代替 kubectl"管 K8s 状态。

坑 5:root 才能跑 crictl

$ crictl ps
FATA[0000] connect failed: ... permission denied

containerd.sock 默认 root only。用 sudo 或者 ssh root。

把用户加到组也行:

chgrp myuser /run/containerd/containerd.sock        # 不推荐(生产)

坑 6:crictl logs --previous 不存在

kubectl logs --previous 看上次挂的日志,但 crictl logs 不支持。

替代:

crictl ps -a --name my-container             # 看所有同名容器(含已 Exited)
# 拿到上一个的 container ID
crictl logs <previous-id>

坑 7:镜像名带 / 让 grep 麻烦

crictl images | grep "registry.k8s.io/etcd"
# 因为 / 在某些 shell 里要转义

OK 一般 grep 不需要转义 /,但写 sed 时要。


关联命令

  • kubectl —— 集群视角,crictl 是节点视角
  • kubeadm —— kubeadm 不直接用 crictl,但安装/排错时常配合
  • systemctl —— systemctl status containerd / restart containerd
  • journalctl —— journalctl -u containerd 看 runtime 日志
  • ctr —— containerd 原生 CLI,看 namespace 细节用
  • nerdctl —— containerd 的"docker-like" CLI(更易用,适合本地测试)
在 GitHub 上编辑此页