
生产环境升级 Kubernetes最容易出问题的地方通常不是“二进制能不能替换成功”而是升级后 kubelet 能不能继续通过 CRI 正常调用 containerd。很多事故的现场都很像节点重启后看起来还在containerd服务也显示 running但 Pod 卡在ContainerCreating节点变成NotReady或者业务镜像突然拉不下来。这个时候再回头查 CRI endpoint、cgroup driver、pause 镜像、Harbor 证书已经是在业务窗口里抢时间。这篇按生产升级检查手册来写不写新闻解读。目标是回答一个很具体的问题升级 Kubernetes 1.36 containerd 2.3 前节点上到底要检查哪些文件、命令、字段和回滚条件版本边界本文按 2026-07-01 写作时核对的官方信息讨论Kubernetes 1.36 当前维护分支的最新补丁版本为 1.36.2containerd 2.3 当前已有 2.3.2 补丁版本。生产操作前仍要以官方 release notes、版本偏差策略和发行版包源为准不要只按文章里的版本号直接全量升级。1. 升级风险从哪里来Kubernetes 节点上的运行时链路可以简化成API Server - kubelet - CRI endpoint - containerd - runc - Pod升级 Kubernetes 或 containerd 时真正要保护的是这条链路连续不断。常见风险主要来自 5 类风险点典型现象先看哪里kubelet 与运行时断连节点NotReadyPod 无法创建crictl info、kubelet 日志CRI endpoint 配错crictl报连接失败/etc/crictl.yaml、kubelet 启动参数cgroup driver 不一致Pod 启动异常资源统计异常/var/lib/kubelet/config.yaml、containerd config dumppause 镜像或私有仓库不可达Pod 卡在ContainerCreating或ImagePullBackOffsandbox_image、certs.d、Pod Events升级没有灰度和回滚问题从单节点扩散到整组节点Drain、验证、回滚窗口升级前先做一个判断如果你现在不能解释节点上 kubelet 连到哪个 containerd socket也不能说清SystemdCgroup和sandbox_image在哪里那就先不要动生产批量升级。2. 版本兼容关系不要只看 Kubernetes 和 containerd 两个数字生产升级至少要记录 5 个维度Kubernetes 控制面、kubelet、containerd、CNI、操作系统内核。只看kubeadm upgrade plan不够它不会替你判断私有仓库证书、节点 cgroup、containerd 配置是否都适合这次升级。先把 Kubernetes 自身的版本偏差规则压实组件Kubernetes 1.36 升级时的关键限制升级前判断kube-apiserverHA 集群里新旧 apiserver 最多相差 1 个 minor控制面不要跨 minor 跳升kubelet不能比 kube-apiserver 新最多可比 kube-apiserver 旧 3 个 minor目标 apiserver 为 1.36 时kubelet 可为 1.36、1.35、1.34、1.33kube-proxy不能比 kube-apiserver 新最多可旧 3 个 minor和节点 kubelet 版本一起看kubectl支持与 kube-apiserver 前后相差 1 个 minor运维机 kubectl 不要长期落后这里的重点不是背规则而是确定升级顺序控制面先按规则进入 1.36再逐批处理 kubelet 和节点运行时。对 kubelet 做 minor 版本升级前应先 drain 对应节点不要在承载业务 Pod 的节点上原地硬升。建议先建一张盘点表节点角色kubeletcontainerdCNIOS / Kernel业务风险node-aworker1.35.x2.2.xCalico/Cilium 版本Ubuntu/RHEL kernel低流量node-bGPU worker1.35.x2.2.xCalico/Cilium 版本GPU 驱动依赖内核高风险检查 kubelet 版本kubelet --version用途确认节点实际运行的 kubelet 版本。 判断标准输出版本要和升级计划一致如果节点版本散乱先把节点分组不要混在一个批次升级。检查 containerd 版本containerd --version用途确认节点运行时版本。 判断标准确认当前版本、目标版本、发行版包源是否匹配如果生产节点来自不同 OS 镜像必须逐类验证。检查节点汇报的运行时版本kubectl get nodes -o wide用途从控制面视角确认每个节点的CONTAINER-RUNTIME。 判断标准目标节点应显示预期运行时例如containerd://2.3.x如果控制面看到的版本和节点本机不一致先查 kubelet 汇报和服务重启状态。3. 升级前先备份配置文件比命令更值钱升级涉及/etc/containerd/config.toml、/var/lib/kubelet/config.yaml、systemd drop-in、registry 证书和认证配置时必须先备份。不要相信“配置很简单我记得住”。建议在每台节点上执行sudo mkdir -p /root/k8s-runtime-backup/$(date %F)用途创建当天备份目录。 判断标准目录创建成功后续备份都放到同一个日期目录里。sudo cp -a /etc/containerd /root/k8s-runtime-backup/$(date %F)/containerd用途备份 containerd 主配置、certs.d、registry hosts 配置。 判断标准备份目录里能看到config.toml和证书、hosts 文件如果目录不存在记录当前节点是否使用默认配置。sudo cp -a /var/lib/kubelet/config.yaml /root/k8s-runtime-backup/$(date %F)/kubelet-config.yaml用途备份 kubelet 配置。 判断标准文件存在且可读重点字段包括cgroupDriver、clusterDNS、containerLogMaxSize等。sudo systemctl cat kubelet /root/k8s-runtime-backup/$(date %F)/kubelet-systemd.txt sudo systemctl cat containerd /root/k8s-runtime-backup/$(date %F)/containerd-systemd.txt用途备份 systemd unit 和 drop-in。 判断标准能看到 kubelet 的启动参数来源如果这里有--container-runtime-endpoint后面要和/etc/crictl.yaml对齐。4. CRI 插件与 endpoint 检查升级 containerd 后kubelet 能不能正常工作关键是 CRI service 是否可用、endpoint 是否一致。检查 crictl 配置cat /etc/crictl.yaml用途确认crictl连接哪个 runtime endpoint。 判断标准生产 containerd 节点通常应看到类似runtime-endpoint: unix:///run/containerd/containerd.sock image-endpoint: unix:///run/containerd/containerd.sock timeout: 10 debug: false如果 endpoint 指向旧 Docker socket、CRI-O socket 或不存在的路径crictl info会误导你。检查 socket 是否存在ls -l /run/containerd/containerd.sock用途确认 containerd socket 文件存在。 判断标准文件存在且服务运行如果不存在先查systemctl status containerd不要继续看 Pod 业务日志。检查 CRI 连通性sudo crictl info用途验证 CRI service 能否正常响应。 判断标准能输出 runtime、config、runtimes 等信息如果报connection refused、context deadline exceeded、unknown service runtime.v1.RuntimeService优先查 endpoint、CRI 插件和 containerd 日志。检查 containerd 配置中的 CRI 插件sudo containerd config dump | grep -n io.containerd -A 120用途查看 CRI 插件配置段。 判断标准CRI 插件不能被禁用如果/etc/containerd/config.toml的disabled_plugins里出现crikubelet 无法通过 CRI 管理 Pod。containerd 1.x 常见路径是plugins.io.containerd.grpc.v1.cricontainerd 2.x 会出现plugins.io.containerd.cri.v1.runtime等新路径排查时不要只 grep 旧路径。5. kubelet、cgroup 与 containerd runtime 配置cgroup 配置不一致是升级后很容易变成“节点偶发异常”的坑。新集群通常建议 kubelet 使用systemdcgroup drivercontainerd 的 runc options 里也要对应启用SystemdCgroup。检查 kubelet cgroup drivergrep -n cgroupDriver /var/lib/kubelet/config.yaml用途确认 kubelet 使用哪个 cgroup driver。 判断标准如果输出cgroupDriver: systemdcontainerd 侧也应使用 systemd cgroup如果为空要结合 kubelet 版本和启动参数确认默认行为。检查 containerd 的 SystemdCgroupsudo containerd config dump | grep -n SystemdCgroup -A 5 -B 5用途确认 runc runtime options。 判断标准生产 Kubernetes 节点常见目标是SystemdCgroup true如果 kubelet 是systemdcontainerd 却是 false升级前先评估并灰度修正。containerd 2.x 的 runc 配置路径通常在[plugins.io.containerd.cri.v1.runtime.containerd.runtimes.runc] runtime_type io.containerd.runc.v2 [plugins.io.containerd.cri.v1.runtime.containerd.runtimes.runc.options] SystemdCgroup true如果你的配置仍是 1.x 风格路径先确认发行版是否做了兼容迁移不要直接复制线上旧配置覆盖新版本默认配置。检查系统是 cgroup v1 还是 v2stat -fc %T /sys/fs/cgroup用途确认系统 cgroup 文件系统类型。 判断标准cgroup2fs表示 cgroup v2tmpfs常见于 cgroup v1。OS 升级或内核变更时这个结果可能影响 kubelet 和运行时行为。6. 镜像仓库、pause 镜像和 sandbox_image很多升级事故不是 containerd 起不来而是升级后新 Pod 的 sandbox 或业务镜像拉不下来。检查 pause 镜像sudo containerd config dump | grep -n sandbox_image用途确认 Pod sandbox 使用的 pause 镜像。 判断标准镜像地址应在当前网络环境可拉取国内环境、离线环境、私有仓库环境尤其要提前验证。旧配置里常见plugins.io.containerd.grpc.v1.cri.sandbox_image升级到 containerd 2.x 时要结合containerd config dump的实际输出确认字段是否仍然生效。验证 sandbox 镜像能拉取sudo crictl pull pause-image用途从 CRI 视角验证镜像拉取。 判断标准能成功 pull如果失败看错误是x509、401、403、not found还是timeout不要只写“网络问题”。检查 registry 配置目录sudo find /etc/containerd/certs.d -maxdepth 3 -type f -name hosts.toml -print用途确认 containerd 是否使用certs.d/registry/hosts.toml管理 mirror、TLS、认证入口。 判断标准私有仓库域名应有对应目录如果 Harbor 使用自签证书还要确认 CA 文件路径和域名 SAN。7. 关键命令速查正文仍保留准确命令避免图片压缩影响阅读检查目标命令看什么异常时下一步kubelet 版本kubelet --version是否符合升级批次先分组不要混升containerd 版本containerd --version当前和目标版本核对包源和回滚包节点运行时kubectl get nodes -o wideCONTAINER-RUNTIME查 kubelet 汇报状态CRI 连通crictl info是否能输出 runtime 信息查 endpoint 和 containerd 日志crictl endpointcat /etc/crictl.yamlruntime-endpoint改成正确 socket 后重测containerd 配置containerd config dumpCRI、sandbox、runtime、registry先备份再调整kubelet 服务systemctl status kubeletactive、失败原因查journalctl -u kubeletcontainerd 服务systemctl status containerdactive、启动错误查journalctl -u containerdkubelet 日志journalctl -u kubelet -n 200 --no-pagerruntime、PLEG、cgroup、image 关键词顺着关键词下钻containerd 日志journalctl -u containerd -n 200 --no-pagerCRI、registry、snapshot、sandbox 错误对应查配置和镜像仓库8. 灰度升级流程和回滚条件不要直接滚全量节点。推荐顺序选 1 台非核心 worker 节点cordon防止新 Pod 调度drain迁移可迁移工作负载备份配置升级 kubelet/containerd重启服务验证 CRI、Pod sandbox、业务镜像、DaemonSet放开少量业务观察 30-60 分钟后再进入下一批。节点灰度命令kubectl cordon node-name用途暂停新 Pod 调度到该节点。 判断标准kubectl get nodes中节点出现SchedulingDisabled。kubectl drain node-name --ignore-daemonsets --delete-emptydir-data用途迁移普通 Pod为节点升级腾出窗口。 判断标准业务 Pod 能在其他节点恢复如果有 PDB 阻塞不要强拆核心业务先调整升级批次。升级后验证sudo systemctl restart containerd kubelet sudo crictl info kubectl describe node node-name kubectl get pods -A -o wide --field-selector spec.nodeNamenode-name用途确认服务、CRI、节点状态和 Pod 状态连续恢复。 判断标准crictl info正常、节点 Ready、核心 DaemonSet 正常、新建测试 Pod 能拉镜像并进入 Running。回滚条件建议写死不要临场争论条件处理containerd 启动失败还原/etc/containerd备份回滚包版本重启服务crictl info无法连接回滚 endpoint/config检查 CRI 插件和 socket节点持续 NotReady暂停批次查 kubelet 日志和 Node ConditionsDaemonSet 无法恢复暂停放量确认 CNI、日志采集、监控 agent核心业务 Pod 无法 Running立即停止升级按业务回滚预案处理解除调度kubectl uncordon node-name用途验证通过后允许新 Pod 调度。 判断标准节点不再显示SchedulingDisabled新 Pod 可以正常落到该节点。9. 常见故障与判断路径故障一升级后节点 NotReady先看 Node Conditionskubectl describe node node-name关注Ready、MemoryPressure、DiskPressure、PIDPressure、NetworkUnavailable。如果Ready是False或Unknown继续看 kubelet 日志journalctl -u kubelet -n 200 --no-pager重点搜container runtime、PLEG、cgroup、failed to run Kubelet、node not found。故障二Pod 卡在 ContainerCreating先看 Pod Eventskubectl describe pod pod-name -n namespace如果看到FailedCreatePodSandBox优先查 pause 镜像、CNI、CRI。继续执行sudo crictl pods sudo crictl ps -a sudo journalctl -u containerd -n 200 --no-pager判断标准如果 sandbox 没创建出来问题还没到业务容器不要先查应用日志。故障三镜像拉取失败先区分错误类型错误关键词常见原因下一步x509CA、证书链、域名 SAN查/etc/containerd/certs.d/registry/hosts.toml和 CA 文件401未认证查 imagePullSecret 或节点侧认证403认证成功但无权限查 Harbor project 权限not found镜像名、tag、项目路径错误核对镜像完整地址timeout网络、DNS、mirror 不通查 DNS、代理、mirror endpoint10. 一页式 checklist阶段检查项通过标准版本kubelet/containerd/CNI/OS 已盘点每类节点有清单和升级批次备份containerd、kubelet、systemd drop-in 已备份可以从备份恢复原配置CRIcrictl info正常endpoint 指向 containerd socketcgroupkubelet 与 containerd 配置一致cgroupDriver与SystemdCgroup不冲突镜像pause 镜像和业务仓库可拉取crictl pull验证通过服务kubelet/containerd 重启后正常systemd active无关键错误灰度先非核心节点Drain、验证、观察完成回滚包版本、配置、业务窗口明确达到条件立即停止放量11. 总结Kubernetes containerd 的生产升级核心不是“把版本升上去”而是升级前把节点运行时链路查清楚kubelet - CRI endpoint - containerd - runtime - Pod sandbox - 镜像仓库只要这条链路里有一个点没确认升级就可能从计划内维护变成现场排障。我的建议是先做版本盘点和配置备份再检查 CRI、cgroup、镜像仓库最后只从低风险节点灰度开始。下一篇会继续落到工具层crictl 实战指南没有 docker 命令后Kubernetes 节点该怎么排障参考资料Kubernetes Releases: Releases | KubernetesKubernetes Version Skew Policy: Version Skew Policy | KubernetesKubernetes Container Runtimes: Container Runtimes | Kubernetescontainerd GitHub Releases: Releases · containerd/containerd · GitHubcontainerd CRI 配置文档: containerd/docs/cri/config.md at main · containerd/containerd · GitHub