Containerd 的 Bug 导致容器被重建!如何避免?

傅秋芳
• 阅读 810
作者简介
邓宇星,SUSE Rancher 中国区软件架构师,6 年云原生领域经验,参与 Rancher 1.x 到 Rancher 2.x 版本迭代,目前负责 Rancher For openEuler(RFO) 项目开发。

最近我们关注到一个关于 containerd 运行时的 issue,该问题在 containerd v1.6.9/v1.5.15 被引入。出现的问题是,当 containerd 重启后,在其中运行的 Pod 元数据中关于网络相关的数据(如 pod ip)丢失,核心原因在于部分数据没有落盘。  

受影响的版本:

  • v1.6.9 ~ v1.6.14,问题在 v1.6.15 版本中被修复。
  • v1.5.15 ~ v1.5.16,问题在 v1.5.17 版本中被修复。

通过以下步骤,可以快速重现该问题,并验证该问题的修复情况。

本文使用 rke2 为例进行演示,版本为 rke2 v1.24.9+rke2r1,该版本使用了 k3s-containerd v1.6.12-k3s1,受该 containerd 问题影响。

在 containerd 的默认行为中,重启 containerd 服务不会影响正在运行的业务容器,并在启动容器时,通过将容器父进程绑定 Pid 1 的方式进行体现。即使使用 systemctl 对服务进行重启,也不会影响到已经在运行的容器状态。

问题重现

# 配置rke2使用国内镜像仓库下载镜像
mkdir -p /etc/rancher/rke2
echo "system-default-registry: registry.cn-hangzhou.aliyuncs.com" > /etc/rancher/rke2/config.yaml
# 使用命令安装 rke2,以下命令使用了我们在国内维护的 rke2 安装镜像脚本,会从aliyun OSS下载RKE2资源
curl -sfL https://rancher-mirror.oss-cn-beijing.aliyuncs.com/rke2/install.sh | INSTALL_RKE2_MIRROR=cn INSTALL_RKE2_VERSION=v1.24.9+rke2r1 sh -
# [INFO]  using v1.24.9-rke2r1 as release
# [INFO]  downloading checksums at https://rancher-mirror.rancher.cn/rke2/releases/download/v1.24.9-rke2r1/sha256sum-amd64.txt
# [INFO]  downloading tarball at https://rancher-mirror.rancher.cn/rke2/releases/download/v1.24.9-rke2r1/rke2.linux-amd64.tar.gz
# [INFO]  verifying tarball
# [INFO]  unpacking tarball file to /usr/local

# 启动 rke2 服务,并等待服务启动成功
systemctl start rke2-server

# 配置 rke2 相关的 PATH 路径以及 kube-config 路径
export KUBECONFIG=/etc/rancher/rke2/rke2.yaml
export PATH=/var/lib/rancher/rke2/bin:$PATH

# 使用 kubectl 查询当前集群状态
kubectl get po -A | grep rke2-metrics-server-5b987d776b-gqxv9

# kube-system   rke2-metrics-server-5b987d776b-gqxv9                    1/1     Running     0          15m

至此,rke2 单节点服务启动完成,但我们的目标是 containerd,接下来继续操作:

# 配置 containerd 相关环境变量
export CRI_CONFIG_FILE=/var/lib/rancher/rke2/agent/etc/containerd/config.toml CONTAINER_RUNTIME_ENDPOINT=unix:///var/run/k3s/containerd/containerd.sock
# 使用 crictl 查询pods以及container信息
crictl pods | grep rke2-metrics-server

# bfad445917423       18 minutes ago      Ready               rke2-metrics-server-5b987d776b-gqxv9                    kube-system         0                   (default)

crictl ps | grep rke2-metrics-server

# db5d6392a310e       f6dc23a68f5fb       18 minutes ago      Running             metrics-server                  0                   bfad445917423       rke2-metrics-server-5b987d776b-gqxv9

我们以 metrics-server 的 pod 为例,查询 pod 详情中的网络部分内容,并对 containerd 进行重启,对问题进行重现:

# 查询 metrics-server pod的详情
crictl inspectp bfad445917423 | jq .status.network

# {
#   "additionalIps": [],
#   "ip": "10.42.0.6"
# }

# 停止rke2-server服务并单独启动containerd,避免kubelet影响重现结果
systemctl stop rke2-server
# 单独启动 containerd
containerd -c /var/lib/rancher/rke2/agent/etc/containerd/config.toml -a /run/k3s/containerd/containerd.sock --state /run/k3s/containerd --root /var/lib/rancher/rke2/agent/containerd

通过新的 terminal,使用 crictl 查询 containerd 运行状态

crictl pods | grep rke2-metrics-server

# bfad445917423       24 minutes ago      Ready               rke2-metrics-server-5b987d776b-gqxv9                    kube-system         0                   (default)

# 再次查询metrics-server pod详情
crictl inspectp bfad445917423 | jq .status.network

# {
#   "additionalIps": [],
#   "ip": ""
# }

从最后的返回结果可以看出,containerd 重启后容器的 IP 丢失。

问题影响

通过在上述例子中重启 rke2-server 可以看到,由于 ip 信息丢失,导致了业务容器被重建,带来了业务中断的风险。

# 在中断 containerd进程后,重启rke2-server进程(以下数据为重新验证后的数据)
systemctl restart rke2-server
kubectl get po -A |grep rke2-metrics-server-5b987d776b-8vg69

# kube-system   rke2-metrics-server-5b987d776b-8vg69                    1/1     Running     2 (115s ago)   23m

crictl pods | grep rke2-metrics-server

# caba6d8d15823       41 seconds ago      Ready               rke2-metrics-server-5b987d776b-8vg69                    kube-system         1                   (default)
# 2dec6a11fd36f       22 minutes ago      NotReady            rke2-metrics-server-5b987d776b-8vg69                    kube-system         0                   (default)

可以看到,在 rke2-server 重启后,使用了 cni 的 pod 发生了重启,在 crictl pods 返回中可以看到重新创建的 pods。

问题修复验证

下载新版本 containerd,这次验证使用 k3s-containerd v1.6.14+k3s1。该版本为 Rancher 在 containerd v1.6.15 发布前紧急发布的修复补丁版本。

# 拉取新镜像
docker pull rancher/hardened-containerd:v1.6.14-k3s1-build20230105
mkdir container-new
cd container-new
# 从镜像中获取新版本containerd
docker run --rm -it -v ${PWD}:/output rancher/hardened-containerd:v1.6.14-k3s1-build20230105 cp -r /usr/local/bin /output
./output/bin/containerd --version
# containerd github.com/k3s-io/containerd v1.6.14-k3s1 6f9c63d571f5026e85a0768f0f2ef03d1c8dbc6e

# 关闭当前运行的容器
pkill -f /var/lib/rancher/rke2/data/v1.24.9-rke2r1-d4d8faf800d0/bin/containerd-shim-runc-v2
# 替换containerd binary版本
cp ./bin/* /var/lib/rancher/rke2/bin
/var/lib/rancher/rke2/bin/containerd --version
# containerd github.com/k3s-io/containerd v1.6.14-k3s1 6f9c63d571f5026e85a0768f0f2ef03d1c8dbc6e

# 启动 rke2
systemctl start rke2-server
# 此时使用 crictl 查询新的 metrics-server pod
crictl pods | grep " Ready" |grep metrics-server
# ad8b101f819df       3 minutes ago       Ready               rke2-metrics-server-5b987d776b-gqxv9                    kube-system         1                   (default)

# 停止 rke2 并使用命令行启动 containerd
systemctl stop rke2-server
containerd -c /var/lib/rancher/rke2/agent/etc/containerd/config.toml -a /run/k3s/containerd/containerd.sock --state /run/k3s/containerd --root /var/lib/rancher/rke2/agent/containerd

通过新的 terminal,使用 crictl 查询 containerd 运行状态

crictl inspectp ad8b101f819df | jq .status.network
# {
#   "additionalIps": [],
#   "ip": "10.42.0.13"
# }

可以看到 containerd 重启后,pod ip 没有丢失。

RKE2 与 RFO

RKE2 以下版本受该 issue 影响:

  • v1.23.15+rke2r1
  • v1.24.9+rke2r1
  • v1.25.5+rke2r1
  • v1.26.0+rke2r1

该 issue 在 2022 年 12 月 20 日被提交,RKE2 团队在 2023 年 1 月 6 日紧急合并了 containerd 中修复该 issue 的 commit,发布了 k3s-containerd v1.6.14+k3s1 版本,并发布了新的 rke2 rc 版本进行测试验证。  

最终在 1 月 11 日,RKE2 团队发布以下已经修复 containerd 问题的版本:

  • v1.23.16+rke2r1
  • v1.24.9+rke2r2
  • v1.25.5+rke2r2
  • v1.26.0+rke2r2

RFO 是 Rancher For openEuler 的缩写,顾名思义,目的在于面向 openEuler 打造 Rancher 基础平台。  

由于 RFO 版本发布周期在 RKE2 之后,RFO 并没有受到该 issue 影响,并在近期发布了以下版本:

  • v1.23.16+rfor1
  • v1.24.9+rfor1
  • v1.24.10+rfor1
  • v1.25.5+rfor1
  • v1.25.6+rfor1
  • v1.26.0+rfor1
  • v1.26.1+rfor1

写在最后

由于操作系统的软件包发布存在一定的时间延后性,在大部分情况下都无法及时修复软件出现的问题。像 CVE、功能缺陷等问题都比较紧急,等待操作系统供应商提供修复版本将是一个漫长的过程,甚至有时候由于一些限制,操作系统提供商无法提供新版本的软件包,这会给系统运行带来不确定因素。

在这种情况下,将软件自身依赖的组件打包到自己的 rootfs 中进行分发,能更好地对其进行管理和升级,避免给系统运行带来风险以及潜在的损失。

关于 RFO 的项目说明和部署使用,请点击《Rancher RFO 正式 GA》

点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
Easter79 Easter79
3年前
swap空间的增减方法
(1)增大swap空间去激活swap交换区:swapoff v /dev/vg00/lvswap扩展交换lv:lvextend L 10G /dev/vg00/lvswap重新生成swap交换区:mkswap /dev/vg00/lvswap激活新生成的交换区:swapon v /dev/vg00/lvswap
待兔 待兔
1年前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Stella981 Stella981
3年前
KVM调整cpu和内存
一.修改kvm虚拟机的配置1、virsheditcentos7找到“memory”和“vcpu”标签,将<namecentos7</name<uuid2220a6d1a36a4fbb8523e078b3dfe795</uuid
Easter79 Easter79
3年前
Twitter的分布式自增ID算法snowflake (Java版)
概述分布式系统中,有一些需要使用全局唯一ID的场景,这种时候为了防止ID冲突可以使用36位的UUID,但是UUID有一些缺点,首先他相对比较长,另外UUID一般是无序的。有些时候我们希望能使用一种简单一些的ID,并且希望ID能够按照时间有序生成。而twitter的snowflake解决了这种需求,最初Twitter把存储系统从MySQL迁移
Wesley13 Wesley13
3年前
mysql设置时区
mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0
Wesley13 Wesley13
3年前
Java 9版本之后Base64Encoder和Base64Decoder无法继续使用解决办法
<divclass"htmledit\_views"id"content\_views"<p在项目开发过程中,因为重装系统,安装了Java10版本,发现sun.misc.Base64Encoder和sun.misc.Base64Decoder无法使用。</p<p<br</p<p<strong原因:</strong</p<p查看
Stella981 Stella981
3年前
Docker 部署SpringBoot项目不香吗?
  公众号改版后文章乱序推荐,希望你可以点击上方“Java进阶架构师”,点击右上角,将我们设为★“星标”!这样才不会错过每日进阶架构文章呀。  !(http://dingyue.ws.126.net/2020/0920/b00fbfc7j00qgy5xy002kd200qo00hsg00it00cj.jpg)  2
Python进阶者 Python进阶者
1年前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这
美凌格栋栋酱 美凌格栋栋酱
5个月前
Oracle 分组与拼接字符串同时使用
SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(