news 2026/10/15 11:36:22

cri-containerd 1.7.23离线部署与K8s节点排障实战

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
cri-containerd 1.7.23离线部署与K8s节点排障实战

简介:containerd 1.7.23 的 Linux AMD64 CRI 运行时安装包,面向需要部署或维护 Kubernetes 节点、容器平台的运维工程师与 DevOps 人员,解决在 x86_64 服务器上快速获取标准容器运行时、并完成初始配置的问题,适合离线或内网环境直接分发使用。压缩包约 101MB,共 19 个文件,内含 containerd 主程序、runc、containerd-shim 系列二进制,以及 crictl、ctr、critest 等客户端与测试工具;同时提供 systemd service 模板、crictl.yaml、环境变量与部署脚本,yaml 配置和 sh 脚本基本串起了从启动、配置到验证的完整流程。文件中 cri-containerd.DEPRECATED.txt 提示该版本对应旧式 CRI 插件承载方式,实施时可留意后续迁移信息。已有 261 人学习下载,适合需要手工搭建 CRI 运行时、排查安装细节或理解 containerd 工具链的实践者参考。

1. 一个 tar 包解决节点运行时:cri-containerd 1.7.23 到底帮你装了什么

第一次在内部机房里面对一堆还没加入 Kubernetes 集群的 Linux 节点时,我手里只有一个包:cri-containerd-1.7.23-linux-amd64.tar。当时最怕的不是没网,而是对 containerd 运行时的理解停留在「听说过、没搭过」的状态。这个包把 containerd 服务端、CRI 实现、命令行工具 crictl/ctr、systemd 服务单元和一份默认配置文件打包在一起,解压到对应目录,节点运行时就算落地了。它适合三类人:要在离线环境交付容器平台的人、不想在节点上装 docker 的运维,以及被 containerd 版本号和配置键名绕晕的排障者。这篇按我踩过的顺序,从包结构讲到 kubelet 对接,再给五个典型故障的现场排查方法。

2. 解开包先看清单:cri-containerd、containerd 与 docker 的区别

网上有人说 containerd 和 cri-containerd 是一回事,有人说不是,其实两者都对,关键是看哪个 tar 包。普通 containerd release 包没有为 kubelet 准备 CRI 插件的默认配置;cri-containerd 包则默认启用 CRI 插件,把 sandbox 镜像、crictl 客户端、systemd 单元都配成一套容器运行时。之所以容易混,是因为 containerd 从 1.x 起就把 CRI 插件做成了内置插件,只是官方分发的包形态不同,使用姿势就差很远。

2.1 三个名字,一张对照表

我在本地把三种形态拉通跑过一次后,整理了下面这张表,后续排查时基本先靠它定位问题:

形态CRI 插件配置客户端工具使用场景
containerd 官方 release默认不启用,需手动改 config.tomlctr通用容器管理、嵌入上层系统
cri-containerd release自带 CRI 配置,开箱供 kubelet 使用ctr + crictlKubernetes 节点运行时
docker 内置 containerd由 docker 引擎接管,不对外暴露docker CLI依赖 docker 生态的存量环境

普通 containerd 包和 cri-containerd 包在二进制层面基本同源,差异集中在配置文件、服务单元和附带工具上。docker 里的 containerd 则更像一个被嵌在引擎内部的执行部件,虽然也承担容器生命周期管理,但不会把 CRI socket 暴露给 kubelet。

选型时记住一条经验:只要节点要跑 kubelet,优先用 cri-containerd 形态的包,不要在普通 containerd 包上自己折腾 CRI 开关,浪费时间还会翻车。

2.2 解开 tar 后先看布局,别急着解压

拿到包后我习惯先扫一眼内容清单,而不是直接解压到根目录。这一步能帮你确认包里有没有预期中的 etc/ 配置和 systemd 单元,也能避免把旧环境里的同名文件覆盖掉之后才后悔。

tar -tf cri-containerd-1.7.23-linux-amd64.tar | head -40

这段里的-t表示只列出归档内的文件名,不实际展开文件;-f指定要读取的 tar 包路径;head -40用来控制输出行数,避免文件列表太长刷屏。看到的结果一般是 bin/、etc/containerd/、lib/systemd/system/ 这几类目录,关键产物包括:

tar -tf cri-containerd-1.7.23-linux-amd64.tar | grep -E "bin/|config.toml|containerd.service"

grep -E按正则匹配过滤文件名。我一般会专门确认三样东西:containerd 主程序、config.toml 是否存在、containerd.service 单元是否在包里。如果 unit 文件缺失,后面就要自己手写 systemd 配置,可用性会差不少。

实际资源以压缩包内清单为准,拿到手先扫一遍再操作,这是最稳的流程。

2.3 版本怎么选:1.7.23 处在什么位置

1.7 是 containerd 社区明确维护的稳定分支,1.7.23 属于这条线上的补丁版本。相比 1.6,1.7 在 CRI 日志采集、Sandbox 生命周期管理、NRI 机制上都有变化。如果所在集群版本落在 1.24 到 1.29 这个区间,1.7.x 基本是默认选项。

离线环境里更要注意校验:下载后先用 sha256sum 和官方校验值对一遍,避免拿到同名但不同的文件。我就遇到过文件同名拷贝错位的情况,启动后 shim 全部报错,查了半天才发现是包不对。

还有一个容易忽略的点:crictl 和 containerd 的版本不要差太多。crictl 太老时请求新版本 containerd 的数据结构,crictl ps会返回解析失败或字段缺失,那时你会误以为是运行时坏了,实际只是客户端和服务端版本不匹配。

3. 从 tar 到 systemd:解压路径、默认配置与启动参数一次讲清

这一章是整个部署的动手环节。顺序看起来简单,但解压目录、配置生成方式、服务启动参数之间是有依赖关系的,顺序错了后面会反复返工。

3.1 解压到约定目录,并检查 PATH

cri-containerd 包里文件的默认落位通常是 /usr/local 下,所以解压时把归档内容释放到 /usr/local 根目录即可。注意是解压到目录本身,不是新建一个子目录:

tar -C /usr/local -xzf cri-containerd-1.7.23-linux-amd64.tar

-C指定先切换目标目录再展开,保证 bin/ 里的工具落到 /usr/local/bin,配置文件落到 /etc/containerd,服务单元落到 /lib/systemd/system。解压后先确认关键二进制是否存在:

ls -l /usr/local/bin/containerd /usr/local/bin/ctr /usr/local/bin/crictl

如果提示 No such file,优先检查 PATH 或包内结构。对于 runc,部分包只带 containerd-shim-runc-v2,不带 runc 本身;如果解压后没找到 runc,需要单独准备并放到 /usr/local/sbin。这里有个常见的认知误区:containerd 只是管理者和分发者,真正创建容器进程的是 runc,shim 会去找它。没有 runc 时,拉取镜像没问题,一启动容器就失败。

3.2 生成默认配置,并留好后悔药

装完二进制后不要直接启动,先把默认配置生成出来:

mkdir -p /etc/containerd containerd config default > /etc/containerd/config.toml

config default子命令把内置默认值打印到标准输出,重定向后写入文件。执行前如果有旧配置,先备份,这一步是后悔药:

cp /etc/containerd/config.toml /etc/containerd/config.toml.bak

新生成的配置里有一项对 kubelet 至关重要:cgroup 驱动。很多集群默认要求运行时使用 systemd cgroup 驱动,和 kubelet 保持一致。在 config.toml 里搜一下:

grep -n "SystemdCgroup" /etc/containerd/config.toml

结果一般在[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options]下面。默认通常是 false,如果集群 kubelet 声明了--cgroup-driver=systemd,这里就要改成 true。别光改 kubelet 不动 containerd,两边不一致,节点会反复 NotReady,后面避坑章会专门讲。

3.3 用 systemd 拉起服务,并确认状态

包里的 containerd.service 单元会声明启动命令和几个关键路径。启用服务:

systemctl daemon-reload systemctl enable --now containerd

daemon-reload让 systemd 重新扫描单元文件,enable --now合并了开机自启和立即启动。启动后立刻看状态:

systemctl status containerd --no-pager -l

--no-pager避免进入 less 分页,-l显示完整日志。看到 active (running) 再往下走。如果启动失败,常见症状是二进制路径不对或配置文件语法错误,用journalctl -u containerd看详细报错。

3.4 内核网络参数与两端版本验证

容器节点还需要确认内核参数,否则 Pod 网络容易出问题。常见配置如下:

cat <<EOF | tee /etc/sysctl.d/99-kubernetes-cri.conf net.bridge.bridge-nf-call-iptables = 1 net.ipv4.ip_forward = 1 EOF sysctl --system

tee把内容写入 sysctl 配置目录,sysctl --system重新加载全部配置。bridge-nf-call-iptables 保证 bridge 上的流量能被 iptables 规则过滤,ip_forward 开启 IPv4 转发。两者缺失会让跨节点 Pod 通信变黑匣子。

最后做一次版本级检查:

ctr version crictl version --runtime-endpoint unix:///run/containerd/containerd.sock

ctr version 验证服务端可用,crictl version 显式指定 endpoint,避免依赖默认值。这两条都能过,说明运行时基础环境已经准备好了。

4. 接通 kubelet 和私有仓库:config.toml 里真正要改的几处参数

服务起来只是第一步,真正决定集群能否稳定的,是 config.toml 里的几个关键参数。这章讲四处:CRI socket、cgroup 驱动、sandbox 镜像、私有镜像仓库凭证。

4.1 CRI socket 与 kubelet 对接

kubelet 通过 gRPC 和 containerd 的 CRI 插件通信,socket 路径是硬约定。containerd 默认监听unix:///run/containerd/containerd.sock。使用 kubeadm 加入集群时,显式指定:

kubeadm join 192.168.1.10:6443 \ --token xxxxx \ --discovery-token-ca-cert-hash sha256:xxxxx \ --cri-socket unix:///run/containerd/containerd.sock

--cri-socket告诉 kubelet 去哪找 CRI 实现。1.24 以后 kubelet 默认也会尝试 containerd,但显式传参更稳,避免 kubelet 先探测到别的 socket 类型报错。

还有一个容易忽略的地方:kubelet 的 cgroup 驱动。kubelet 配置里如果是 systemd 驱动,config.toml 的 SystemdCgroup 必须等于 true。我的判断标准很简单:集群初始化用 kubeadm 默认参数,就把 SystemdCgroup 打开;用云平台脚本初始化,先看对方要求,再决定是否改。

4.2 sandbox 镜像:网络栈的底座

每个 Pod 都会先启动一个 sandbox 容器,镜像由sandbox_image指定。在 config.toml 里定位:

grep -n "sandbox_image" /etc/containerd/config.toml

默认值通常是 registry.k8s.io/pause 某个版本。如果集群访问不了默认仓库,这个镜像拉不下来,节点就会一直 Ready 不了。处理方式是把 sandbox_image 换成内网镜像地址。改完后重启 containerd:

systemctl restart containerd

注意:改 sandbox_image 要同时确认 kubelet 不会覆盖它。kubelet 没有直接控制 sandbox 镜像的参数,真正生效的是 containerd 配置,所以这里以 config.toml 为准。

4.3 私有镜像仓库:hosts.toml 与证书配置

生产环境几乎不可能只用 docker hub,私有仓库是必选项。containerd 1.7 推荐用config_path配合 hosts.toml 管理。

先在 config.toml 中查找 cri registry 配置:

grep -n "config_path" /etc/containerd/config.toml

如果为空,在[plugins."io.containerd.grpc.v1.cri".registry]下补充:

config_path = "/etc/containerd/certs.d"

然后按仓库主机名建目录,比如内部仓库地址是 registry.internal,就建:

mkdir -p /etc/containerd/certs.d/registry.internal

该目录下创建一个 hosts.toml:

# /etc/containerd/certs.d/registry.internal/hosts.toml server = "https://registry.internal" [host."https://registry.internal"] ca = "/etc/containerd/certs/registry.internal.crt"

server是默认镜像端点;host分节配置具体访问方式;ca指向自签名证书文件。containerd 会优先读取 hosts.toml 而不是老的 registry.mirrors 配置。对于明文 HTTP 的内网测试环境,可以临时用insecure_skip_verify = true,但生产环境应换成正式证书。

配好后不用重启服务,用 crictl 拉一次镜像验证:

crictl pull registry.internal/ns/app:latest --runtime-endpoint unix:///run/containerd/containerd.sock

能成功说明解析和证书链路正常。

4.4 快照器:overlayfs 的确认

containerd 默认使用 overlayfs 快照器,节点需要内核支持。检查方法:

cat /proc/filesystems | grep overlay

如果输出里没有 overlay,需要先确认内核模块加载:

modprobe overlay

modprobe动态加载模块,cat /proc/filesystems验证。内核不支持 overlayfs 时,containerd 会回退到其他快照器,但性能差异明显,Pod 启动和镜像层写入都会变慢。在准备阶段就把这个确认掉,能省去后面一堆玄学性能问题。

5. 避坑手册:五个把节点搞 NotReady 的现场问题

这章是实战中踩过的坑。每个问题按「现象 → 原因 → 解决」的顺序写,对应节点加入集群前后最容易翻车的几个位置。

5.1 先建立排查思路

节点 NotReady 时,我一般按三步走:先看 containerd 服务状态,再查 kubelet 日志,最后用 crictl 看实际容器情况。不要一上来就改配置,先收集现场,否则会把问题改复杂。

systemctl status containerd --no-pager -l journalctl -u kubelet --no-pager -n 50 crictl ps --runtime-endpoint unix:///run/containerd/containerd.sock

journalctl -n 50只看最近 50 行,crictl ps看容器列表。如果 crictl 报连接失败,问题大概率在 socket 路径或服务没起来;如果 kubelet 报 runc 错误,多半是运行时配置问题。

5.2 五个高频坑

坑一:kubelet 连接 containerd 超时

现象是 kubelet 日志反复出现Failed to connect containerd,节点状态 NotReady。原因通常不是 containerd 挂了,而是 kubelet 用了错误的 socket 地址。解决:显式指定 cri-socket,并确认/run/containerd/containerd.sock文件存在。如果 socket 文件不存在,检查 containerd 是否真的在运行、是否改了监听地址。

坑二:cgroup 驱动不一致

现象是 Pod 调度后一直 ContainerCreating,kubelet 报failed to set cgroup或 cgroup 相关权限错误。原因就是 SystemdCgroup 和 kubelet cgroup 驱动不一致。解决:把 config.toml 中的 SystemdCgroup 改成与 kubelet 一致,重启 containerd。这个坑最隐蔽,因为服务状态看起来正常,报错却指向资源隔离。

坑三:sandbox 镜像拉不下来

现象是节点加入集群后持续 NotReady,crictl ps 看到沙箱容器一直重启或不存在。原因是 sandbox_image 指向的仓库在当前网络环境不可达。解决:改成内网镜像地址,重启 containerd,再观察 sandbox 容器状态。改完后建议顺手执行crictl pull验证镜像可访问。

坑四:私有仓库 x509 证书报错

现象是 crictl pull 内网镜像失败,报x509: certificate signed by unknown authority。原因是 containerd 不信任系统根证书目录,它走的是 hosts.toml 里配置的 ca。解决:确认 hosts.toml 的 ca 路径正确,证书文件有读取权限;临时内网环境可以insecure_skip_verify = true,但要用注释标出,方便后面切正式证书。

坑五:runc 缺失导致容器起不来

现象是拉镜像成功,但创建容器时报shim: exec: "runc": executable file not found。原因是包只带了 containerd-shim-runc-v2,没有 runc 主程序。解决:单独下载匹配版本的 runc,放到 /usr/local/sbin,chmod +x,重启 containerd,再跑一次容器创建。判断方法很简单:which runc和runc --version能过,基本就没事。

6. 验证与调优:用 crictl 确认节点状态,并安全升级

6.1 端到端验证

节点接入集群后,我习惯用 crictl 做一次完整检查,而不是只盯 kubelet 状态:

crictl version --runtime-endpoint unix:///run/containerd/containerd.sock crictl pods --runtime-endpoint unix:///run/containerd/containerd.sock crictl images --runtime-endpoint unix:///run/containerd/containerd.sock

crictl pods列出 Pod 沙箱,没有异常退出说明 CRI 链路正常;crictl images确认镜像列表。两条都正常,再执行kubectl get node看节点状态。crictl 是一条很直接的验证路径,它绕过了 kubelet 的日志噪声,直接看运行时视角。

日常排查可以把 endpoint 写进/etc/crictl.yaml:

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

之后执行 crictl 就不用每次带--runtime-endpoint参数了。这个文件对后续所有 crictl 检查都生效,省事不少。

6.2 升级与调优

从 1.7.23 升级到后续补丁版本时,我一般按固定顺序走:先停服务,备份 config.toml 和 containerd 数据目录,再解压新包,然后对比新旧配置差异,最后启动服务验证。最忌讳直接覆盖配置,旧版 config.toml 里可能保存了私有仓库证书路径,升级后再丢就麻烦。

调优方面,最常见的是镜像拉取并发限制。如果节点上批量启动 Pod 时镜像拉取很慢,可以在 config.toml 顶层找 max_concurrent_downloads 相关参数,适当加大并发数。这个参数在不同小版本里的具体键名不完全一致,我一般会在升级后先 diff 一次默认配置和当前配置再调。空余资源允许时,还可以把 pull 超时时间调大,避免大镜像在慢速网络下拉取超时。

从那以后,我每次装完 containerd 都强制走一遍 crictl info、crictl pods、crictl images 三连检查,确认运行时视角正常后才让节点加入集群。希望帮到你。

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

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

DeepSeek模型硬件配置:显存-精度-并行的三角博弈

简介&#xff1a;本资源是一份面向深度学习研究者与工程开发者的DeepSeek大语言模型硬件选型指南&#xff0c;聚焦不同参数规模模型&#xff08;1B/3B精简版、7B/13B基础版、33B/70B大型版及100B超大规模集群&#xff09;的实操级硬件配置要求与性能优化建议&#xff0c;解决模…

作者头像 李华
网站建设 2026/10/15 11:34:44

Matlab实现电气热综合能源系统二阶锥优化模型

1. 项目背景与核心价值 综合能源系统优化是当前能源领域的前沿研究方向&#xff0c;它打破了传统电力、燃气、热力系统单独规划运行的局限。我在参与某工业园区能源系统改造项目时&#xff0c;深刻体会到多能互补协同优化的必要性——单纯优化电网可能导致气网压力激增&#xf…

作者头像 李华
网站建设 2026/10/15 11:33:20

微信小程序最小可运行闭环:从初始化到真机验证

简介&#xff1a;本资源是一套完整的微信小程序开发实战代码包&#xff0c;面向前端初学者及小程序入门开发者&#xff0c;帮助快速掌握小程序基础架构、页面逻辑与接口调用等核心开发流程。压缩包共106个文件&#xff0c;涵盖22个JS文件&#xff08;实现页面交互与API请求&…

作者头像 李华
网站建设 2026/10/15 11:33:11

Java常量池深度解析:从内存模型到字符串比较的避坑指南

1. 从一个诡异的现象说起&#xff1a;为什么两个"相等"的字符串却不相等刚入行那会儿&#xff0c;我写过一段至今想起来都脸红的代码。当时在做一个用户标签匹配的功能&#xff0c;逻辑很简单&#xff1a;从数据库里读出一个标签字符串&#xff0c;跟代码里写死的常量…

作者头像 李华