十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

containerd离线部署实战:cri-containerd包安装与Kubernetes节点配置

containerd离线部署实战:cri-containerd包安装与Kubernetes节点配置 简介面向容器运维及 Kubernetes 集群管理人员这个压缩包提供容器运行时 containerd 1.7.23 在 Linux AMD64 架构下的完整运行组件。该运行时是云原生计算基金会孵化的核心项目也是 Kubernetes 的容器运行时接口标准实现之一负责镜像拉取、存储管理以及容器全生命周期调度适合在内网或离线环境部署也便于对底层运行时进行精细化控制。资源包共包含 19 个文件压缩后约 101.22MB主要涵盖系统服务管理配置、配置模板、环境变量脚本以及容器运行时主程序、命令行工具、底层进程管理等多个可执行组件能够支撑容器启停、日常调试与压力测试。当前已有 261 人学习下载。包内还提供了版本弃用说明提醒升级路径与迁移注意点目录结构按系统标准布局组织安装时能快速接入现有环境减少手动配置时间。对于需要锁定容器运行时版本、自建 Kubernetes 节点或优化底层架构的工程师这套资源具有较强的实战参考价值。 在干净的内网环境里交付 Kubernetes 节点是我这些年绕不过去的一道坎。节点装好了系统、配好了 IP接着就是要给它准备一个能跑容器的运行时。yum/apt 源在内网基本指望不上手动编译又浪费时间这时候 containerd 官方发布页上的cri-containerd-1.7.23-linux-amd64.tar这类离线包真的是既省事又稳妥的交付形态。这个包不是单薄的二进制而是把 containerd 主程序、CRI 插件、crictl/ctr 客户端、systemd 服务配置甚至基础 CNI 插件全部打在一起的标准化组件包。这篇文章我就从离线部署的实际场景出发把这个 tar 包从解包到上线运行的完整链路拆开讲清楚包括安装步骤、几个我踩过的坑、镜像离线导入和后续升级建议给正在做集群交付、内网部署或者自建测试环境的运维一个可以照做的参考。1. 认识这个安装包CRI、containerd 与离线交付的关系1.1 为什么 Kubernetes 节点现在都在用 containerd很多从 Docker 时代转过来的朋友刚开始会对cri-containerd这个名字有点困惑。它前面这个cri-前缀其实是 Container Runtime Interface 的意思。Kubernetes 的 kubelet 本身不能直接创建容器它需要调用一个符合 CRI 规范的运行时来“代劳”。Docker 早期是通过 dockershim 这个中间层接入 Kubernetes 的但自从 Kubernetes 1.24 版本正式移除 dockershim 之后原本依赖 Docker 的节点就都必须切换到更直接的容器运行时了。containerd 就是这个位置上最主流的选项。它本身不依赖 Docker而是作为一个独立的容器运行时守护进程通过内置的 CRI 插件直接和 kubelet 通信。早期 containerd 的 CRI 功能还是独立组件cri-containerd后来合并进了 containerd 主程序所以现在你看到的这种cri-containerd-1.7.23-linux-amd64.tar命名其实沿用了那个历史习惯。真正用起来的时候很多发行版配置里已经把 CRI 插件内置进去了。1.2 1.7.23 这个版本在 containerd 序列里的位置containerd 的 1.7 分支是一个相当稳的长期维护版本1.7.23 是这个分支后面的一个小补丁版本修复了不少上游问题兼容常见 Kubernetes 版本。对大多数离线集群来说只要不是特别老的 Kubernetes 版本拿 1.7.x 系列的包做运行时基本不会踩坑。选择离线交付的 tar 包还有一个很现实的原因企业内网服务器通常没有直接访问外网包源的权限就算能访问几十个节点的 yum/apt 源同步和依赖解析也很浪费时间。而 containerd 这种 tar 形态的发布包解压后所有二进制都已经齐了不依赖包管理器不需要额外解析依赖非常适合在离线环境里做标准化交付。1.3 这个包解决了什么问题你把这个包丢到一台刚装好系统的干净服务器上只需要解压、改配置、启动服务节点就拥有了一个可以被 Kubernetes 调度的容器运行时。它省掉了你单独安装 containerd、runc、crictl、CNI 插件再手工写 systemd unit 文件的一堆重复工作。所以这个包的定位很明确它就是离线环境里初始化容器运行时的“全家桶”。2. 动手之前先核对包内容和完整性2.1 解包前不要省略校验我见过不少同事拿到 tar 包就直接tar -xzf结果装到一半发现二进制被截断或者损坏。离线交付场景下包在传输过程中可能经过优盘、网盘、各种内网文件服务器完整性没法保证。所以第一步一定是先做校验。sha256sum cri-containerd-1.7.23-linux-amd64.tar拿到一串哈希值之后去 containerd 发布页面核对对应的 sha256sum 列表。如果包是.tar.gz格式文件名就是cri-containerd-cni-1.7.23-linux-amd64.tar.gz校验值对上之后再操作。这一步几分钟的事别跳。2.2 用 tar 命令快速看清包内结构在解压之前你可以先用tar -tzvf了解包内都有哪些路径避免解出来之后覆盖了不想要的东西。tar -tzvf cri-containerd-1.7.23-linux-amd64.tar | head -30我习惯重点看几个路径路径组件说明usr/local/bin/containerdcontainerd 守护进程核心二进制usr/local/bin/containerd-shim-runc-v2shim 进程每个容器一个 shim负责容器生命周期usr/local/bin/runcOCI runtime底层创建容器的执行者部分包会带usr/local/bin/crictlCRI 客户端用于 Kubernetes 场景调试的 CLIusr/local/bin/ctrcontainerd 原生客户端管理 containerd 自己的镜像与命名空间etc/systemd/system/containerd.servicesystemd unit开机自启动服务定义etc/crictl.yamlcrictl 配置文件指定 CRI endpointetc/containerd/config.tomlcontainerd 主配置默认模板安装后需要调整opt/cni/bin/内置 CNI 插件bridge、host-local、portmap 等基础插件有一种情况要特别注意有的官方发布包并不把 runc 打进 tar 里而是要求你另外准备。解压之前先确认一下usr/local/bin/下有没有 runc如果没有安装完 containerd 之后没 runc 是起不了容器的后面我会专门讲这个坑。2.3 区分 amd64 和 arm64 的架构陷阱包名里的linux-amd64说明它面向的是 x86_64 架构。但在实际交付现场偶尔会遇到一台 aarch64 架构的机器有人不管三七二十一把 amd64 的包传上去解压启动的时候直接报exec format error。这里教大家一个先手判断uname -m如果输出是x86_64就用 amd64 包如果输出是aarch64就得去找cri-containerd-1.7.23-linux-arm64.tar这类对应架构的包。别小看这一步我在现场见过的架构踩坑十个里至少有四个是因为uname -m都没跑就直接装了。3. 安装与启动从 tar 包到可用运行时3.1 按绝对路径解压不要图省事乱改目录这个包内所有路径都是相对根目录的所以解压时直接指定-C /让 usr、etc、opt 落到系统对应位置。tar -C / -xzf cri-containerd-1.7.23-linux-amd64.tar如果文件就是未压缩的.tar把-xzf改成-xf就行。解压完成之后先确认关键文件都在ls -l /usr/local/bin/containerd ls -l /etc/containerd/config.toml ls -l /etc/systemd/system/containerd.service我在生产环境里见过有人习惯先把包解压到/tmp再手工复制结果漏了etc下的配置。直接用-C /解压路径最不容易出错这是官方包的默认设计意图。3.2 启动前必须修改的三处配置把包解压完直接systemctl start containerd其实也能起来但用默认配置挂到 Kubernetes 节点上会有问题。重点改三个地方。先备份默认配置cp /etc/containerd/config.toml /etc/containerd/config.toml.bak第一处确认 CRI 插件没有被禁掉。打开config.toml看disabled_plugins这个位置确保列表里没有io.containerd.grpc.v1.cri。如果 disabled 了kubelet 根本连不上 CRI后面全是白忙活。第二处最重要也最容易忽略systemd_cgroup参数。Kubernetes 节点上的 kubelet 默认使用 systemd cgroup drivercontainerd 也必须用 systemd 模式两边对齐才不会出现资源泄漏和 Pod 反复重启。[plugins.io.containerd.grpc.v1.cri.containerd.runtimes.runc.options] SystemdCgroup true第三处离线环境下的sandbox_image。默认的 pause 镜像地址指向外网仓库离线节点拉不下来Pod 创建就会一直卡在 ContainerCreating 状态。把它改成内网镜像仓库里已有的 pause 镜像地址。sandbox_image registry.example.com/pause:3.9如果你没有现成的内网仓库至少要把这个字段记下来后面镜像导入的时候会再次用到。3.3 启动服务和基础验证配置改完之后加载 systemd 配置并启动systemctl daemon-reload systemctl enable --now containerd systemctl status containerd --no-pager看到active (running)之后再用两个命令确认 CRI 端点可用。ctr version crictl version crictl infocrictl info能看到 containerd 是否正常响应了 CRI 接口这是 kubelet 后续能调度 Pod 的基础。如果这块不通问题大概率出在 CRI 插件没有启用回 3.2 再看一眼。4. 复盘几个常见故障节点老是 NotReady 的根因4.1 sandbox 镜像拉不下来Pod 一直 ContainerCreating这个故障在离线集群里出现的频率极高。现象很典型节点加入集群后kubelet 状态正常但创建 Pod 时一直处于 ContainerCreatingcrictl ps -a能看到 sandbox 容器反复创建又销毁。排查的时候直接看 kubelet 日志里的关键词基本都会落在ErrImagePull或ImagePullBackOff上。原因就是config.toml里的sandbox_image指向了外网地址离线节点拉取失败。我当时处理的办法是先把sandbox_image改成内网 registry 里已有的 pause 镜像地址然后systemctl restart containerd最后再重新调度一次 Pod。核心思路是让所有流量都在内网闭环不要让节点产生任何外网访问依赖。4.2 cgroup driver 不一致kubelet 反复重启另一个高频现场是 kubelet 起来之后反复 crash错误日志会提示 M kubelet cgroup driver 和容器运行时的 cgroup driver 不一致。这种情况基本就是SystemdCgroup没有打开或者打开了但 kubelet 那边用的是 cgroupfs两边对不上。处理方式前面已经提到了在 containerd 配置里显式设置SystemdCgroup true并且确认 kubelet 参数--cgroup-driversystemd。这两个值必须一致没有第二种协商空间。4.3 runc 缺失或版本过旧如果你的包解压后没有 runc 二进制或者机器上本身存在一个旧版 runcPod 启动时会报类似failed to load oci spec或者runc not found的错误。我的习惯是解压后立刻执行ls -l /usr/local/bin/runc runc --version如果不存在就去 containerd 发布页或者 runc 官方仓库拿对应架构的 runc 放进/usr/local/bin并给可执行权限。这一步尽量在离线环境出发前解决否则到了现场再转包非常被动。另外还有一个跟内核相关的点新版 runc 对内核特性有一些要求如果用很老的 CentOS 7 内核overlayfs 可能不可用containerd 会回退到其他快照器。遇到这种情况可以临时把快照器改成native试验一下但更稳妥的方案仍然是升级内核。4.4 CNI 插件目录冲突内置插件和 Calico 并存的问题cri-containerd包默认会在/opt/cni/bin下放一套基础 CNI 插件包括 bridge、host-local、portmap 这类。但生产集群里真正让 Pod 互通网络的往往是 Calico、Cilium 这类第三方 CNI。它们安装时通常会自己重新下载或复制二进制到/opt/cni/bin如果两边插件版本不一致或者你手工往这个目录里放文件时不小心覆盖了 Calico 的可执行文件网络插件就会出状况。我在交付生产环境时如果确定会使用 Calico一般不会依赖包内自带的 CNI 插件而是交给 Calico 的安装方式去管理。哪怕 tar 包解压后/opt/cni/bin里有文件也不用主动去执行它们把这个目录留给正式的 CNI 插件使用。5. 离线镜像导入与后续升级维护5.1 用 ctr 导入镜像时命名空间这个坑必须避开运行时装好之后离线环境还得把应用镜像塞进去。常见做法是把镜像打成 tar 包比如用docker save或者skopeo copy。到了目标机器上很多人下意识用docker load但那台机器根本没有 docker正确工具是 containerd 自带的ctr。这里有一个非常关键的细节命令要加上-n k8s.io参数。ctr -n k8s.io images import app-images.tar原因在于 containerd 是多命名空间的。kubelet 通过 CRI 操作镜像时默认访问的是k8s.io这个命名空间。如果你不加-n k8s.io镜像会被导入到默认的default命名空间里kubelet 看不见Pod 调度起来照样拉不到镜像。我第一次在这个地方卡了很久因为ctr images list明明能看到镜像kubelet 却始终报image not found后来才意识到是命名空间的问题。这个经历让我后来对离线导入格外敏感。5.2 内网镜像仓库与 mirror 映射如果你内网里已经有 Harbor 或其他 registry可以把应用镜像全部推到内网仓库然后在 containerd 侧做 mirror 配置让节点把对外网的拉取请求重定向到内网仓库。containerd 1.7 使用config.toml里的[plugins.io.containerd.grpc.v1.cri.registry.mirrors]或者更现代的hosts.toml方式来定义 endpoint。以 Harbor 地址registry.example.com为例可以在 CRI 插件的 registry 配置里把你的内网仓库地址放在最前面这样当 kubelet 拉镜像时containerd 会优先走内网拉取路径全程离线。我的建议是内网集群里尽量统一镜像名称和 tag 规范把sandbox_image、应用镜像、基础中间件镜像全部放在同一个仓库目录下节点只需维护这一份 endpoint 配置后续加节点会非常省心。5.3 补丁版本升级的正确姿势containerd 1.7.x 偶发小版本升级时不需要卸载重装。我的操作步骤是systemctl stop containerd tar -C / -xzf cri-containerd-1.7.23-linux-amd64.tar systemctl daemon-reload systemctl start containerd升级前最好把现有/usr/local/bin/containerd备份一份防止新版本出现兼容性问题时能快速回滚。同时对比一下新旧两版的config.toml因为 containerd 升级后配置格式可能有细微调整直接沿用旧配置不一定安全。我在升级后一般会立刻跑一遍crictl run或者拉起一个测试 Pod确认节点从 kubelet 视角完全正常再放量到集群其他节点。5.4 最后分享一个小技巧离线节点装完 containerd 之后我会把config.toml和crictl.yaml的修改记录保存成一份 changelog连同当前版本号一起写到节点本地文件里比如/etc/containerd/version-info。这样后续运维接手节点时不需要重新翻历史命令就能知道这台机器的容器运行时是怎么装的、改了哪些参数。这个习惯帮我省掉了很多半夜排查故障的时间也算是个意外的收获。本文还有配套的精品资源点击获取
返回列表