资讯动态

cri-containerd离线安装包详解:从kubelet接入到容器运行时避坑指南

发布时间:2026/10/15 11:37:30 来源:尧图企业网站定制
简介这份资源提供的是 cri-containerd-1.7.23-linux-amd64.tar.gz 压缩包面向需要在 Linux 系统上部署和管理容器运行时的运维、开发及 Kubernetes 集群管理人员。Containerd 作为 CNCF 旗下的容器运行时是 Kubernetes CRI 的标准实现之一负责镜像拉取、存储及容器生命周期管理该版本针对 AMD64 架构优化适合作为节点运行时组件使用。压缩包共 19 个文件包含 yaml 配置、systemd service 服务文件、containerd 及 crictl 等二进制工具、runc 与 containerd-shim 运行组件、环境脚本及弃用说明文档基本覆盖离线安装与启动所需的核心内容整体约 101.22MB。资源中附带 cri-containerd.DEPRECATED.txt提示旧版集成方式可能已弃用使用时应关注官方迁移指引。目前已有 261 人学习下载适合需要进行离线部署或版本固定的容器环境搭建场景。1. 为什么你的 K8s 节点需要直接下载这个 cri-containerd 安装包做过 Kubernetes 集群初始化的人大概率都有过这样的经历用文档里的脚本装完 containerdkubelet 那边却一直报容器运行时没连上又或者系统自带的 containerd 版本太旧根本认不出新版 kubelet 发出的 CRI v1 请求。这时候最省事的做法不是去折腾发行版自带的包而是直接下载官方发布的cri-containerd-1.7.23-linux-amd64.tar这类捆绑包。这个包里不只是 containerd 本身还带了 CRI 插件、ctr、crictl 以及配套的 systemd 单元文件解压就能用。它解决的问题很明确让你在裸机环境里快速搞出一个符合 Kubernetes 接入要求的运行时不依赖 docker也不依赖操作系统自带的旧版本。适合谁用负责集群节点初始化、或者被运行时版本问题折磨过的运维和开发拿这个包能省掉不少麻烦。下载资源本身是一个 tar 归档直接面向 Linux amd64 平台。很多人一看到这种发行物第一反应是“这不就是个压缩包嘛解压不就行了”——真上手会发现目录结构、配置文件、容器运行时权限这几样东西哪一步没搞对后面 kubelet 就给你颜色看。下面这几章我会从最基础的安装落地开始一步步讲到配置改写、启动验证、避坑排查再到接进 kubelet 的完整套路。2. 安装前置检查与二进制落位先把环境摸清再解压2.1 系统环境检查与内核参数确认拿到这个 tar 包以后先别急着解压。我一般会在节点上先确认三件事操作系统架构是不是 amd64内核版本够不够新建议 4.x 以上以及有没有残留的 docker 或者旧版 containerd 在占用端口。前两项直接关系到该包能不能跑起来第三项则关系到会不会出现“端口被占”“socket 冲突”之类的玄学故障。# 检查架构必须输出 x86_64 uname -m # 查看内核版本低于 4.x 的话建议先升级内核 uname -r # 检查是否有旧的 containerd/docker 在运行 systemctl status containerd docker 2/dev/null || echo no old runtime detected # 确认 cgroup 挂载方式systemd 环境下一般输出 cgroup2 stat -fc %T /sys/fs/cgroup/这几条命令是我每次都会先跑的。第一组命令里uname -m的输出必须是x86_64对应 amd64 架构如果你的节点是 arm64这个包就没法用得换arm64版本。内核版本这块老内核在高版本 containerd 上会遇到 mount 传播和网络命名空间的问题踩过坑的人都懂。systemctl status是看有没有老运行时在抢占资源如果之前装过 docker里面自带的 containerd 往往会占着/var/run/docker/containerd和 2375 端口不清理干净新装的 containerd 会被搞得很被动。cgroup那一步则是为了确认后面配置 cgroup driver 时该写 systemd 还是 cgroupfs。2.2 解压归档与二进制落位检查没问题后再把 tar 包解压到根目录。这里注意这个归档内部是直接按/usr/local/bin、/etc/containerd、/usr/local/lib/systemd/system这种绝对路径组织的所以解压目标必须是/不能自作聪明解压到某个临时目录然后手动复制那样很容易漏掉目录层级。# 解压到系统根目录自动落位所有二进制和配置文件 tar -C /usr/local -xzf cri-containerd-1.7.23-linux-amd64.tar # 确认二进制文件已就位 ls -l /usr/local/bin/containerd /usr/local/bin/containerd-shim-runc-v2 /usr/local/bin/ctr /usr/local/bin/crictl这里关键点在-C /usr/local它指了解压的根目标归档内部自带bin/、etc/、lib/systemd/system等路径前缀解压以后会自然落到/usr/local/bin、/etc/containerd、/usr/local/lib/systemd/system。为什么不直接tar -xzf解到/根目录为了安全我习惯限制在/usr/local下面这套包的所有产物本来就在这个前缀里不会扩散到别的目录回退卸载也干净。落位完成后检查一下ls -l输出。正常情况下应能看到 containerd、containerd-shim-runc-v2、ctr、crictl 四个主要二进制。crictl 这个工具在有些发布里要单独装这个包里直接带好了后面调试会很省事。另外注意看权限位要有x执行权限如果是从 Windows 上传到服务器的包有时候权限会掉需要chmod x /usr/local/bin/*补一下。3. 生成与改写 config.tomlcgroup driver 和 sandbox_image 必须动刀3.1 生成默认配置并理解关键段containerd 安装好以后不会自动生成配置文件先用containerd config default生成一份默认配置再在此基础上改两处关键内容。默认配置会输出到 stdout不要直接拿来就用因为它里面的 CRI 插件配置是按通用场景给的直接用的后果通常是 kubelet 能连上 containerd但创建 Pod 沙箱时被镜像拉取卡死。# 生成默认配置并放到指定位置 containerd config default /etc/containerd/config.toml # 检查配置中 CRI 插件段落是否存在 grep -n cri /etc/containerd/config.toml | head -20这里containerd config default会输出一份完整的 TOML 配置重定向到/etc/containerd/config.toml后containerd 启动时就能读到了。配置结构上最关键的段落是[plugins.io.containerd.grpc.v1.cri]它控制的是 CRI 相关的行为——包括 sandbox 镜像、cgroup driver、CNI 配置路径。grep 出来的内容主要是为了确认这段存在如果输出为空说明你装的 containerd 版本里 CRI 插件被裁剪了但 1.7 版本一般不会出现这种情况。3.2 改写 systemd cgroup driver 和 sandbox 镜像默认配置里有几个值是必须改的SystemdCgroup默认是 false而我们的节点几乎都是 systemd 管理 cgroup 的sandbox_image默认指向registry.k8s.io/pause:3.9或者更老的名字在部分地区可能拉不通还有镜像加速器配置也是空的。这三处不改后面 kubelet 创建 Pod 时会出现沙箱一直 ContainerCreating 的问题。# 把 SystemdCgroup 设为 true并用 containerd 镜像加速器替换原值 sed -i s/SystemdCgroup false/SystemdCgroup true/ /etc/containerd/config.toml # 替换 sandbox 镜像地址set 成实际可拉取的地址以你环境能拉到的 registry 为准 sed -i s#sandbox_image registry.k8s.io/pause:3.9#sandbox_image your.registry.example.com/pause:3.9# /etc/containerd/config.toml # 追加镜像加速器配置可选但强烈建议。这里说明一下SystemdCgroup true让 containerd 的容器配置直接走 systemd 的 cgroup 管理与 kubelet 的--cgroup-driversystemd保持一致。如果你 node 上 kubelet 用了 systemd而 containerd 这边是 false那后续 Pod 会偶发报 cgroup 相关错误重启后部分容器起不来的情况也见过。sandbox_image是 Pod 沙箱的基础镜像如果拉不到整个 Pod 都创建不出来。替换成你环境里能访问的镜像仓库地址比如自建的 Harbor 或云厂商镜像仓库保证节点能拉到即可。镜像加速器那段改的是[plugins.io.containerd.grpc.v1.cri.registry.mirrors.docker.io]下的 endpoint不加的话docker hub 上的镜像拉取速度会非常感人。这里还有一个容易忽略的点改完后一定要重新加载配置。containerd 不支持热加载配置必须重启服务不然你以为改好了实际运行的还是旧的。# 重新加载 systemd 配置并重启 containerd systemctl daemon-reload systemctl restart containerdsystemctl daemon-reload是为了让新安装的 systemd unit 文件生效这个包自带 containerd.service 和 containerd.socket 两份 unit不重载的话 systemctl 可能找不到服务。重启 containerd 后可以用systemctl status containerd确认它是 active 状态这一步做到位后面接入 kubelet 才有底气。4. 启动验证与镜像拉取ctr 和 crictl 不能混用4.1 用 ctr 验证 containerd 进程本身containerd 是一个独立运行的 daemon在往里放容器之前先确认它自己的 API 活着。ctr 是 containerd 自带的客户端走的不是 CRI 接口而是 containerd 的原生 API所以它主要用于验证 containerd 本身是否健康不能用来验证 CRI 插件状态。# 查看 containerd 版本信息能输出即说明 daemon 已正常启动 ctr version # 查看当前 containerd 里的 namespace ctr namespaces listctr version如果能正常输出版本号说明 containerd 进程在跑并且原生 gRPC socket默认/run/containerd/containerd.sock可以被访问。ctr namespaces list是为了确认 containerd 工作正常、并且能看到 namespace 列表K8s 的 Pod 沙箱会落在k8s.io这个 namespace 下后期排查可以到这里面找容器。这里有个很多新手会懵的地方ctr看不到 kubelet 创建出来的容器对的因为 ctr 默认连的是/run/containerd/containerd.sock而 CRI 插件的流量走的是同一个 socket 但不同的服务crictl 才走 CRI 地址。如果你用 ctr 去看 K8s 的容器会发现很多看不见这不是故障是接口不同。4.2 用 crictl 验证 CRI 插件并拉取测试镜像真正贴近 kubelet 视角的客户端是 crictl。它会走 CRI 接口和 kubelet 使用的路径一致可以查看 kubelet 视角的容器、镜像和 PodSandbox 状态。先给它指定 endpoint再执行探测命令。# 告诉 crictl 走哪个 CRI socket默认是这个旧版本可能需要手动指定 crictl config --set runtime-endpointunix:///run/containerd/containerd.sock crictl config --set image-endpointunix:///run/containerd/containerd.sock # 查看 CRI 插件返回的运行时版本 crictl version # 拉取一个最小的测试镜像按你环境能访问的 registry 来 crictl pull your.registry.example.com/library/nginx:1.27-alpine # 查看已拉取的镜像列表确认镜像已落地 crictl images设置 runtime-endpoint 和 image-endpoint 是为了确保 crictl 连到 containerd 的 CRI 服务而不是其他运行时如果你之前机器上装过其他 CRI 工具这一步尤其重要。crictl version会同时返回了 containerd 的版本和 CRI 插件的版本如果这里报 “unknown service runtime” 之类错误基本可以判定 containerd 里的 CRI 插件没启用要去 config.toml 检查 cri 插件段落。crictl pull是测试整个镜像链路是否通畅从仓库认证、镜像拉取、解压到本地存储。拉取成功后crictl images能看到镜像的IMAGE ID、SIZE和CREATED信息。到这一步containerd 本身和 CRI 插件链路都验证过了接下来才是 kubelet 接入的事。5. 安装与调试避坑三条真实踩坑记录5.1 现象kubelet 报找不到运行时 socketcontainerd 却显示 active在某台新节点上装完这个包后systemctl status containerd明明是 active但 kubelet 起不来日志里反复报failed to connect to /run/containerd/containerd.sock。 原因是 containerd.socket 这个 systemd 单元没有被激活/run/containerd/containerd.sock文件根本不存在kubelet 起来得太早或者 containerd 进程虽然活着但并没有监听这个路径。解决方法是确认 containerd 确实使用了正确的 socket 路径启动并手动把 containerd.socket 启用起来# 确认 containerd 是否在通过 systemd socket 激活 systemctl status containerd.socket # 如果没有启用则启动它让 socket 文件被创建 systemctl enable --now containerd.socket # 再检查 socket 文件是否真实存在 ls -l /run/containerd/containerd.sockcontainerd.socket是 systemd socket 激活机制的产物containerd 配套的 unit 文件里有Socketscontainerd.socket这句配置如果 socket 单元没起来即使 containerd daemon 在运行kubelet 也可能连不上。这个故障最容易发生在你手工启动过 containerd、而不是通过 systemctl 启动的情况那种情况下 containerd 自己会创建 socket但路径可能被 systemd 的私有临时目录影响。从那以后我每次装完都强制走一遍 socket 检查不偷懒。5.2 现象crictl pull 一直卡住最后报超时一台新节点crictl pull 镜像进度走到 1% 就再也不动了等了几分钟报context deadline exceeded。 原因是镜像仓库域名解析和网络路径有问题以及没有配置镜像加速器。我一开始只改了 sandbox_image 和 SystemdCgroup没有管 mirrors 配置结果 docker hub 的镜像根本拉不动。解决方法是把 docker.io 仓库的 mirror 端到到可用地址在 config.toml 里加 mirrors 段落然后重启 containerd。# 在 /etc/containerd/config.toml 中加入或修改如下段落注意域名换成你自己的可用仓库 [plugins.io.containerd.grpc.v1.cri.registry.mirrors.docker.io] endpoint [https://your.mirror.example.com, https://registry-1.docker.io]配置解释mirrors.docker.io是告诉 containerd凡是请求 docker.io 前缀的镜像先走 endpoint 列表里的地址依次尝试。第一个是你的内网或云厂商加速器第二个是 docker 官方仓库containerd 会按顺序尝试第一个不通会自动切换下一个。如果你所在网络连 docker.io 基本不可用那第一个地址必须可靠否则仍然会卡住。改完配置别忘了systemctl restart containerd。这类问题高发不是单一节点凡是新环境我都默认先做镜像加速配置再测拉取能省掉一大堆看超时日志的时间。5.3 现象kubelet 起来了但新 Pod 的 Sandbox 一直创建失败集群里新增了一个节点加入后上面的 Pod 调度过去状态一直是 ContainerCreatingcrictl pods看到 sandbox 创建报错日志提示failed to get sandbox image或者failed to pull pause image。 原因是我当时把 sandbox_image 替换成了your.registry.example.com/pause:3.9但实际上这个仓库里压根没有存这个镜像连名字都不对。解决方法是先去仓库确认 pause 镜像真实存在且 tag 正确再修改配置。# 先手动拉取一次 sandbox 镜像验证仓库里真实存在 crictl pull your.registry.example.com/pause:3.9 # 拉取成功后再搜一下配置确认已改对 grep sandbox_image /etc/containerd/config.toml这个问题的根本点是sandbox_image 必须保证节点能拉到且版本要和 kubelet 兼容。如果仓库确实没有这个镜像要么上传一个要么换成官方 registry.k8s.io 或者其他可用源。我自己第一次配这个时就是随手写了个名字进去没有先验证仓库里是否存在结果 kubelet 那边创建 sandbox 时一直卡在镜像拉取。从那以后我习惯先把 sandbox 镜像手动拉一遍再重启 containerd最后用crictl pods确认节点上的 sandbox 能正常起来。这个动作虽然简单但能提前暴露仓库镜像缺失、认证失败、tag 不存在等问题省得 kubelet 在那边反复重试。6. 把 containerd 接进 kubelet一条命令级别的验证链路6.1 确认 kubelet 的运行时参数containerd 装好、验证完最后一步是让 kubelet 认它。以 kubeadm 方式初始化或者 join 节点时主要靠 kubelet 的运行时端点参数来指定这里直接给出常用的配置方式。不同发行版、不同 kubeadm 版本参数会有一点差异但 CRI 端点路径基本不变。# 查看当前 kubelet 的运行时参数 cat /var/lib/kubelet/kubeadm-flags.env # 期望输出里包含如下内容缺什么就补什么 # KUBELET_KUBEADM_ARGS--container-runtime-endpointunix:///run/containerd/containerd.sock --pod-infra-container-imageyour.registry.example.com/pause:3.9KUBELET_KUBEADM_ARGS这个文件是 kubeadm 生成 kubelet 启动参数的地方。如果你的环境是手工二进制部署的 kubelet那就在 systemd unit 里加对应参数思路一样。这里有一个容易被忽略的点--pod-infra-container-image这个参数需要和 containerd 配置里的 sandbox_image 保持一致如果两者不一致kubelet 会尝试按自己的参数拉镜像containerd 里配置的 sandbox_image 就变成摆设了结果还是可能卡在拉取失败。我一般会让这两个值保持完全一致并在巡检时用 grep 同时查这两处grep -E sandbox_image|pod-infra-container-image /etc/containerd/config.toml /var/lib/kubelet/kubeadm-flags.env这样一行命令同时把 containerd 和 kubelet 两边的沙箱镜像配置拉出来对齐一眼就能看出有没有偏差。实际配置时你会遇到 kubelet 版本和 containerd 版本各说各话的情况比如新版 kubelet 默认还要传--runtime-cgroups/systemd/system.slice这类参数这些都按你实际的部署方式来补。6.2 验证整个链路从镜像到 Pod 沙箱全部配置完成后不能只看 containerd 活着就收工。我习惯做一轮从镜像到 Pod 沙箱的端到端检查确认调度、拉取、沙箱创建的整条链路是通的。这一步能直接发现那些“单个组件健康但整体不工作”的问题。# 查看 kubelet 是否已经连上 containerd无报错即正常 crictl nodes 2/dev/null || crictl pods # 查看当前节点上的镜像数量能列出 K8s 系统组件镜像即基本正常 crictl images | wc -l # 手动创建一个 PodSandbox 测试可选不建议在已有集群里乱试 crictl runp pause.yamlcrictl nodes在新版本 crictl 里可以看到节点列表老版本没有这个子命令就换用crictl pods有输出即说明 kubelet 到 containerd 的链路是通的。crictl images数量是一个直观的参考正常节点上会有 kube-apiserver、kube-proxy、pause 这些镜像。crictl runp这条命令只建议在测试节点上手动创建一个 sandbox验证系统组件和网络插件都没有问题在已有业务集群节点上执行要格外小心搞不好就把 pod 网络搞乱了。我自己的习惯是每一次新节点装完这个包固定走一套四步验证检查 socket 文件是否创建、crictl version 是否正常返回、crictl pull 最小镜像是否能拉到、kubelet 日志里是否还有 CRI 连接报错。四步全部通过才算真正装好。这套流程跑得多了你会发现大部分问题出在前面那三个环节kubelet 本身的接入反而不容易出幺蛾子。希望这篇拆解能让你拿到这个包以后少走几步弯路尤其是那些刚开始把 CRuntime 从 docker 切换到 containerd 的节点照着这个顺序做一遍基本能把隐藏的坑先趟平。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑