news 2026/9/9 4:23:13

cri-containerd 1.7.23 安装配置与 Kubernetes 对接实战指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
cri-containerd 1.7.23 安装配置与 Kubernetes 对接实战指南

简介:面向 Linux AMD64 架构的 containerd 1.7.23 CRI 集成压缩包,定位为 Kubernetes 节点容器运行时组件,适用于需要在离线环境部署、升级或替换 CRI 运行时的运维与集群管理人员。包内共 19 个文件、101.22MB,以 containerd、crictl、ctr、containerd-shim-runc-v1/v2 及 runc 等可执行文件为核心,同时提供 systemd service 模板、yaml 声明式配置和 env/sh 辅助脚本,可支撑服务托管、命令行调试、自动化初始化和离线安装等场景。尤其适合将节点接入 Kubernetes 前完成 containerd 基础调优,或在内网环境通过离线安装包统一各节点运行时版本。随包附带的弃用说明标记了当前版本后续迁移方向,便于使用者在生产环境规划升级路径。已有 261 人学习下载,读者可结合目录结构理解 CRI 插件的组成,并通过 crictl、ctr 等工具掌握镜像管理和排错方法;对于需要维护多节点 Kubernetes 集群的工程师,也能借助其中的配置模板统一运行时参数,为容器平台维护打牢基础。 接手新节点时看到cri-containerd-1.7.23-linux-amd64.tar这种安装包,很多人第一反应是“这不就是个 tar 包嘛,解压就行”,但真到了生产环境配置 kubelet、对接网络插件的时候,各种问题才冒出来。我在这上面踩过不少坑,所以今天把针对这个包的完整安装、配置、验证和排障过程梳理一遍,给做 Kubernetes 运维的朋友一个可直接参考的流程。这篇内容适合刚接触 containerd 的入门者,也适合已经在用 docker 运行时、准备切换到 containerd 的集群运维,按步骤走基本能避开 90% 的常见问题。

1. 安装前先搞懂:这个 cri-containerd 包里到底装了什么

1.1 它和 containerd、CRI 是什么关系

先说背景。Kubernetes 从 1.24 版本开始默认使用 containerd 作为容器运行时,这在业界已经是标准做法。但 Kubernetes 本身不会直接调用 containerd,而是通过 CRI(Container Runtime Interface)这套接口来统一管理容器生命周期。cri-containerd这个名称里的cri前缀,指的就是 containerd 中负责实现 CRI 插件的部分。在 containerd 1.0 时代,CRI 插件还是一个独立的二进制,叫cri-containerd,部署时要单独拉起进程;后来插件直接内置到了 containerd 主进程里,现在的 tar 包里已经看不到那个独立二进制了,所以看到一个包名带着cri-前缀,意味着这是官方专门为 Kubernetes 场景打好的发布包,里面包含了 containerd 主程序、shim 进程、crictlctr命令行工具,还会带上基础的 CNI 网络插件。

很多刚接触的人会把crictlctr搞混。简单说,ctr是 containerd 自己的调试工具,直接操作 containerd API,但它不认识 Kubernetes 那一套装镜像、起沙箱的流程;而crictl是 CRI 兼容的客户端,它通过 CRI 插件的 socket 和 containerd 通信,Kubernetes 也是走这条路。所以日常排查集群里 Pod 的容器状态,用crictl更贴近真实场景,ctr只适合做底层调试和离线镜像导入。

1.2 版本号和 linux-amd64 为什么必须看仔细

1.7.23是 containerd 1.x 系列的一个稳定版本。1.x 是当前生产环境最成熟的主线版本,1.7 又是 1.x 里的长期维护分支,所以选 1.7.x 作为集群运行时版本是稳妥的做法。有一点要提前知道:containerd 2.x 版本已经在推进,配置格式和默认行为会有变化,等未来要升级时,config.toml里的version字段、插件路径这些都得重新核对,不能想当然直接沿用 1.7 的配置。

linux-amd64指的是为 Linux 操作系统、x86_64 架构编译的二进制包。如果服务器不是这个架构,比如 ARM 架构的国产化服务器,那就得下linux-arm64版本。判断架构用一条命令:uname -m,输出是x86_64就用 amd64 包,输出是aarch64就用 arm64 包。选错架构的后果很直接:二进制要么报Exec format error,要么直接段错误,根本起不来。另外要注意,这个 tar 包是 gzip 压缩的,虽然文件名尾部是.tar,实际能用tar -zxvf解压,这和常见命名习惯略有差别,别到时候卡在解压这一关。

2. 完整安装流程:从 tar 解压到 systemd 服务启动

2.1 解压的正确姿势和目录结构

下载安装包之后,我习惯先在临时目录解压,看清楚文件结构再安装到系统目录,而不是直接一把tar -zxvf解到根目录覆盖。这样能避免不小心覆盖掉系统里已有的同名配置,尤其在服务器上已经装过旧版本 containerd 的情况下,先看再动非常重要。

mkdir -p /tmp/cri-pkg tar -zxvf cri-containerd-1.7.23-linux-amd64.tar -C /tmp/cri-pkg tree /tmp/cri-pkg

解压后的典型结构大致是:

usr/local/bin/ ├── containerd ├── containerd-shim ├── containerd-shim-runc-v2 ├── crictl └── ctr etc/containerd/ └── config.toml etc/cni/net.d/ opt/cni/bin/

不同小版本的发布包目录可能有些微调,但核心就两块:一是二进制文件,二是配置文件。确认结构没问题后,再把内容放到对应系统目录:

cp -r /tmp/cri-pkg/usr/local/bin/* /usr/local/bin/ mkdir -p /etc/containerd cp /tmp/cri-pkg/etc/containerd/config.toml /etc/containerd/config.toml

二进制放到/usr/local/bin而不是/usr/bin,主要是为了和发行版自带的包管理路径区分开。containerd主进程、containerd-shim-runc-v2这个 shim 进程、crictlctr这五个文件必须齐全,缺了 shim 会导致启动容器时直接报 OCI 相关错误。CNI 插件目录可以后续按网络方案再补充,但如果包里有opt/cni/bin,也建议一起放到/opt/cni/bin,后面配置容器网络时会省很多事。

2.2 如何正确配置 systemd 托管

containerd 通常以 systemd 服务方式运行,方便开机自启和崩溃恢复。不要自己搞个nohup后台启动就算完事,生产环境必须用服务管理器。这里我直接给出一个经过实践验证的 unit 文件内容,存到/etc/systemd/system/containerd.service

[Unit] Description=containerd container runtime Documentation=https://containerd.io After=network.target local-fs.target [Service] ExecStartPre=-/sbin/modprobe overlay ExecStart=/usr/local/bin/containerd Type=notify Delegate=yes KillMode=process Restart=always RestartSec=5 LimitNOFILE=1048576 LimitNPROC=infinity LimitCORE=infinity TasksMax=infinity OOMScoreAdjust=-999 [Install] WantedBy=multi-user.target

这个配置里有几个关键点值得细说。ExecStartPre=-/sbin/modprobe overlay是提前加载 overlay 内核模块,overlayfs 是 containerd 默认的存储驱动,缺了它容器镜像层没法正常工作,前面那个减号表示即使模块已存在、命令以非零状态退出也不影响服务启动。Type=notify让 containerd 自己通过 sd_notify 通知 systemd 启动完成,而不是靠超时硬等。Delegate=yes非常关键,它把 cgroup 子树的控制权完全委托给 containerd,这样 kubelet 和容器才能正确管理 CPU、内存等资源限制。KillMode=process保证 systemd 停止服务时只杀 containerd 主进程,不会误杀正在运行的容器进程。

配置写好后按顺序执行:

systemctl daemon-reload systemctl enable --now containerd systemctl status containerd

启动后先看状态是否active (running),再确认 socket 文件是否生成。默认情况下 containerd 会监听/run/containerd/containerd.sock,这个 socket 就是 kubelet 和 crictl 的接入点。如果服务起不来,立刻用journalctl -u containerd -n 50看日志,定位速度比瞎猜快得多。

3. 关键配置与镜像管理:让集群真正跑起来

3.1 config.toml 里必须改的几个参数

containerd 的默认配置文件可以直接用它自己生成的标准版本,再针对 Kubernetes 场景做修改。用containerd config default > /etc/containerd/config.toml重新生成一份是最稳妥的,不会出现缺字段、格式过时的问题。生成后重点关注 CRI 插件这一段。

config.toml是 TOML 格式,核心配置结构大致是这样的:

version = 2 root = "/var/lib/containerd" state = "/run/containerd" [plugins."io.containerd.grpc.v1.cri"] sandbox_image = "registry.aliyuncs.com/google_containers/pause:3.9" [plugins."io.containerd.grpc.v1.cri".containerd] default_runtime_name = "runc" [plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc] runtime_type = "io.containerd.runc.v2" [plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options] SystemdCgroup = true

第一个必须改的是sandbox_image。默认值指向registry.k8s.io/pause:3.9,但很多网络环境访问这个地址非常慢甚至超时。我常用的替代方案是registry.aliyuncs.com/google_containers/pause:3.9,这个 pause 镜像就是每个 Pod 的“沙箱”容器,它不承载业务,只负责维持 Pod 的网络命名空间,版本最好和集群期望一致,否则会出现沙箱反复重建的问题。

第二个必须关注的是SystemdCgroup。如果 kubelet 的 cgroup 驱动是systemd(kubeadm 默认推荐这个值),那这里必须设为true;如果设成false,kubelet 启动后要么报 cgroup driver 不匹配,要么节点状态异常。这个参数的位置在不同版本里略有变化,1.7 版本里放在 runc runtime 的 options 下面,核对配置时别找错地方。改完配置后执行systemctl restart containerd,重启后立刻journalctl -u containerd确认没有报错。

3.2 离线环境的镜像导入操作

很多生产环境是内网隔离的,没法直接拉公网镜像,这就绕不开离线镜像导入。常见做法是先在能联网的机器上用 Docker 把镜像打成 tar 包,再带到内网导入 containerd。注意这里导入的命名空间必须是k8s.io,因为 CRI 插件只从k8s.io这个命名空间读取镜像,如果你用ctr images import时不指定命名空间,镜像是导入了,但 kubelet 就是看不到。

docker save my-app:1.0 -o my-app-1.0.tar # 在目标节点上执行 ctr -n=k8s.io images import my-app-1.0.tar ctr -n=k8s.io images list

如果后续还要给镜像打 tag,用ctr -n=k8s.io images tag即可。还有一种更省事的做法,是把整个sandbox_image对应的 pause 镜像也打成 tar 离线导入,这样内网节点从启动到就绪完全不需要外网。曾遇到一个客户环境,所有节点都没外网,我提前把 pause、flannel、coredns 等基础镜像全部离线导入,集群初始化一气呵成,这个习惯建议运维同学都保留下来。

3.3 kubelet 怎么和 containerd 对接

如果节点是 kubeadm 初始化或加入集群的,kubelet 默认就会走 containerd,因为 v1.24 之后--container-runtime参数默认值就是remote--container-runtime-endpoint默认是unix:///run/containerd/containerd.sock。但手动部署 kubelet 时,一定要在启动参数里显式指定这两个参数,不然 kubelet 会尝试用 docker socket,导致节点一直 NotReady。

--container-runtime=remote --container-runtime-endpoint=unix:///run/containerd/containerd.sock

为了日常排查方便,建议同时配置/etc/crictl.yaml

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

这个文件配好后,crictl pscrictl images等命令不用反复带--runtime-endpoint参数,效率高很多。

4. 高频踩坑记录与排查方法

4.1 常见错误速查表

我在实际环境里把这些典型的故障现象和对应解法整理了一下,按出现频率排的:

现象根因处理方式
kubelet 报failed to run Kubelet: cgroup driver "cgroupfs" is not supported by systemdcontainerd 的 SystemdCgroup 未开启修改 config.toml 中对应字段为 true,重启 containerd
节点 NotReady,日志出现sandbox image ... not readypause 镜像拉不下来替换 sandbox_image 为可用加速地址,或离线导入 pause 镜像
Pod 创建卡在ContainerCreating,报network plugin is not readyCNI 配置缺失或 CNI 插件文件不存在安装 flannel/calico 的 CNI 插件,确保/opt/cni/bin有对应二进制、/etc/cni/net.d有配置文件
启动容器提示OCI runtime create failed: unable to start container processrunc 或 shim 缺失、版本过旧确认/usr/local/bin/containerd-shim-runc-v2存在,必要时单独安装新版本 runc
执行 containerd 命令报Exec format errorbad CPU type架构选错,下了 amd64 包用在 arm64 机器uname -m确认架构,换成 arm64 版本
Failed to load cni config,containerd 启动失败/etc/cni/net.d下有损坏配置或目录不存在清空该目录或放入正确 conflist 文件
离线导入镜像后 kubelet 仍拉不到导入时没指定k8s.io命名空间ctr -n=k8s.io images import重新导入

这张表基本覆盖了我在不同环境里遇到的所有高频问题,剩下的一些偶发问题大多和网络、DNS 相关,先看journalctl再顺着日志链路排查就好。

4.2 排查流程和避坑经验总结

排查 containerd 相关故障时,我习惯按这个顺序来:先确认进程,再确认 socket,最后看日志和端到端验证。

systemctl status containerd ls -l /run/containerd/containerd.sock journalctl -u containerd --since "5 minutes ago" crictl version crictl ps -a

这几条命令如果都正常,那说明 containerd 层面基本没问题,再把排查重点转到 CNI、镜像拉取或 kubelet 参数上。如果crictl ps能列出沙箱容器但 Pod 网络不通,大概率是 CNI 插件配置与集群网络方案不匹配,可以去/etc/cni/net.d目录检查配置文件内容,确认没有遗留旧版本网络插件生成的文件。

还有几个容易被忽略的细节:修改过config.toml后必须重启 containerd,而不是用systemctl reload,因为 containerd 不支持运行时增量重载所有配置;安装过程用到cp覆盖二进制时,如果旧进程还在运行,最好先停服务再替换文件,避免text file busy或运行中二进制冲突;tar 包解压出来的文件属性一般是正确的,但如果你手动移动过文件,检查一下是否有可执行权限。

在生产环境多节点批量部署时,我曾吃过一个教训:把第一台机器的配置直接scp到所有节点,结果因为版本号、CPU 架构不完全一致,导致部分节点启动异常。后来我养成了在每个节点上都先用uname -mcontainerd --version校验环境的习惯,再决定用哪个安装包、推哪份配置。虽然多花一点时间,但省掉了大量返工。

最后分享一个小技巧:升级 containerd 版本前,先用ctr versioncrictl version记录当前版本,升级完成后对比确认;同时把旧版本的config.toml备份一份放到/etc/containerd/config.toml.bak。有一次我因为手滑把新版默认配置覆盖了旧配置,导致原有镜像加速配置全部丢失,节点拉镜像速度直线下降,还好有备份才能快速回滚。版本升级这种事,宁可慢一点,也要给自己留好退路。

本文还有配套的精品资源,点击获取

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/9 4:22:20

零基础深度学习入门路线图:从数学三块基石到实战项目

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/9 4:22:18

ArmNN源码审计与端侧AI部署:从架构到实战优化

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/9 4:20:52

端侧AI算力选型实战:从需求拆解到主流平台对比

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/9 4:18:49

西门子S7-200 PLC与组态王的全自动洗衣机控制系统设计

先交代一下背景。洗衣机的PLC控制是工控入门阶段非常经典的教学项目,也是实际工程里经常拿来练手的对象。很多朋友学完PLC基础指令之后,最大的困惑是“这些指令连起来到底能干啥”。洗衣机这套案例,恰好把开关量输入、定时器、计数器、状态转…

作者头像 李华
网站建设 2026/9/9 4:17:02

2026年9月扫地机器人选购指南:五大品牌横评与避坑要点

说实话,扫地机器人这个品类发展到2026年,已经不适合用“早买早享受”这种简单逻辑来决策了。原因很简单:产品之间拉开了明显差距,千元级的入门机和六千元级的旗舰机,本质上已经是两种完全不同的家用设备。9月这个节点又…

作者头像 李华