kubelet版本升级引起的容器重启机制与参考解决方案

本文涉及的产品
容器服务 Serverless 版 ACK Serverless,317元额度 多规格
容器镜像服务 ACR,镜像仓库100个 不限时长
容器服务 Serverless 版 ACK Serverless,952元额度 多规格
简介: 背景 k8s能够帮助我们的服务实现服务高可用,其提供的副本机制能够有效的保证运行实例的副本数,从而当某个实例异常后服务可以重新被自动唤起,但在我们的生产环境中,某些特殊的服务(如广告资金服务或计费服务)因服务重启期间而导致的业务中断,对业务请求的延时响应也是不可忽略的问题;而在kubelet的部分版本升级中,也可能会因版本的升级进而导致已经运行的容器服务发生重启;而在特殊的生产环境中类似的操作直接引起的服务重启是需要我们尽可能去规避的; 此篇内容即是对kubelet版本升级与container自动重启这一关联过程原因分析以及供参考方案的简单介绍。

背景


k8s能够帮助我们的服务实现服务高可用,其提供的副本机制能够有效的保证运行实例的副本数,从而当某个实例异常后服务可以重新被自动唤起,但在我们的生产环境中,某些特殊的服务(如广告资金服务或计费服务)因服务重启期间而导致的业务中断,对业务请求的延时响应也是不可忽略的问题;而在kubelet的部分版本升级中,也可能会因版本的升级进而导致已经运行的容器服务发生重启;而在特殊的生产环境中类似的操作直接引起的服务重启是需要我们尽可能去规避的;

此篇内容即是对kubelet版本升级与container自动重启这一关联过程原因分析以及供参考方案的简单介绍。

环境基本信息:

操作系统: CentOS 7

kubelet当前版本:1.7.4

目标kubelet版本:1.9.1

现象

当前kubelet版本1.7.4中已持续运行一些容器服务,在对kubelet版本升级1.9.1后,所升级机器上已持续运行多天的container服务出现自动重启,重启之后继续提供服务

原因

因为container的自动重启发生在kubelet版本升级后,所以需要沿kubelet启动后的接口函数调用链进行定位,以确认container重启的根本原因.

总体调用链关系图:(右下角computePodActions() 函数中containerChanged()函数即为决定container服务是否重启的判断逻辑)

高清无码图下载(https://pan.baidu.com/s/1dtMmbO

链路跟踪过程:(整体kubelet调用关系比较复杂,后面仅针对问题的场景关键链路进行分析)

@kubernetes-1.9.1/cmd/kubelet/kubelet.go @表示所处的源码文件,后面意义相同)

启动kubelet main()入口,风格上保持主入口代码最小化的设计风格

功能上仅是读取config初始化配置结构后调用真正的server中的Run()

@kubernetes-1.9.1/cmd/kubelet/app/server.go

判断启动模式,同时初始化证书相关和心跳等,以及进行健康度的检查

RunKubelet中启动协程,进入真正的更新处理流程kubelet中的Run主体

@kubernetes-1.9.1/pkg/kubelet­/kubelet.go

与场景现象相关的逻辑处理主入口,依次进行非依赖模块初始化initializeModules(“internal modules that do not require the container runtime to be up”),以及使用kubeClient与APIserver 同步node状态信息和本地网络状态及容器网络状态的检查

statusprobepleg作用如下图示,可参照如上整体的调用链路简图

@kubernetes-1.9.1/pkg/kubelet/kubelet.go

syncLoop(),处理变化的主循环逻辑,监听3种来源的管道:file, apiserver, http;

只要有消息就会进行处理(监听的也是updates消息队列)

在syncLoopIteration迭代过程中,会根据不同的类型(config\pleg\sync…)进行相应的处理,处理是通过调用对应的Handle*()函数实现的

在各自的处理函数中,针对所有的类别,本质都是调用dispatchWork,只是传入的参数分别为不同的类别而已;如果pod已是终止状态了,则需要同时调用statusManager.TerminatePod(pod) 来通知apiserver状态的更新;

在dispatchWork函数中,会调用具体执行单元worker中UpdatePod函数,此时已将变化封装的信息交由执行单元worker。

@kubernetes-1.9.1/pkg/kubelet/pod_workers.go

在UpdatePod中,主要是启动持续处理逻辑managePodLoop(),此函数只运行一次,执行后会启动一个循环来处理syncPodFn指向函数。如果希望退出循环则如下2个函数被调用时会中止这个循环:ForgetWorker()与 ForgetNonExistingPodWorkers();控制这2个函数是否被调用则依赖于housekeepingCh 消息队列的处理。

managePodLoop会调用syncPodFn函数

syncPodFn指向kubelet.go中的syncPod处理函数。

@kubernetes-1.9.1/pkg/kubelet/kubelet.go

对于status, mkdir与volume简述如下

最后调用容器运行时的SyncPod函数,以便对POD中容器进行操作。

@ kubernetes-1.9.1/pkg/kubelet/container/runtime.go

containerRuntime.SyncPod进而调用

@ kubernetes-1.9.1/pkg/kubelet/kuberuntime/kuberuntime_manager.go

调用computePodActions()判断哪些container发生了变化,以便后面对变化的container进行处理(如重启等)

在computePodAction()中会对POD中运行的container进行判断,以此为基础来决定后面是否对这个运行的container进行重启(即决定是否重启container的入口判断逻辑)

检查运行时container与pod.spec中是否Hash一致,如果发生变化,则在changes结构中ContainersToStart 加入这个container,以便统一对ContainersToStart数组中的容器进行重启

@ kubernetes-1.9.1/pkg/kubelet/container/helpers.go

container进行深层次HASH计算

@ kubernetes-1.9.1/pkg/util/hash/hash.go

使用spewcontainer对象元素进行字符拼接(github.com/davecgh/go-spew/spew

由此可见,在版本升级启动后,定时触发的containerChanged()函数对container结构元素进行了内容上的HASH比对校验,从而将变化的container加入到ContainersToStart列表。

syncPodFnDeepHashObject链路如下所示:

由于DeepHashObject是对container结构的序列化进行HASH计算,所以对比升级前后版本Container结构不难发现,成员增了VolumeDevices等新成员。

所以在对container进行HASH计算时出现了新旧版本计算HASH值的不一致进而引起重启container服务。

方案

由于重启container是基于container HASH值的比较来判定的,所以可以将kubelet版本信息与启动时间记录并持久化,当container变化后计算HASH的时候,参考持久化的信息辅助决定是否忽略重启的条件。基本参考方案示例流图如下

更新源代码的补丁文件@ https://github.com/cloudusers/UpdateKubeletVersionIgnoreContainerRestart

适用场景及注意事项

适用于在kubelet版本升级情况下,container服务持续运行不希望重启的业务场景;同时因对源码的改动也引入了如下的注意事项或复杂点:

1)版本升级前对比不同版本container结构的变化情况以便了解是否升级对容器HASH计算产生影响;

2)目前采用的记录并缓存kubelet版本及启动时间信息至checkpoint持久化本地文件,所以版本升级前文件的损坏可能使得容器服务依旧会重新启动(因checkpoint内容较少,可以临时手动生成);

3)在每次版本升级前需要对新版本进行源码更新重新编译生成二进制执行文件,过程稍显复杂。

综上所述,简单介绍了自kubelet启动至container服务重启的链路调用关系,同时确认版本升级后引起容器重启的判断条件及处理逻辑,以及提供可参考的避免因版本升级引起重启容器的解决方案;

另一方面简单说明了源码修改后所适用的场景及注意事项。因目前还处在研发阶段,但是我们可以发现,通过规避容器服务因版本升级导致的重启可以解决生产环境中的关键业务无服务中断的问题。

本文转自kubernetes中文社区-kubelet版本升级引起的容器重启机制与参考解决方案

相关实践学习
巧用云服务器ECS制作节日贺卡
本场景带您体验如何在一台CentOS 7操作系统的ECS实例上,通过搭建web服务器,上传源码到web容器,制作节日贺卡网页。
容器应用与集群管理
欢迎来到《容器应用与集群管理》课程,本课程是“云原生容器Clouder认证“系列中的第二阶段。课程将向您介绍与容器集群相关的概念和技术,这些概念和技术可以帮助您了解阿里云容器服务ACK/ACK Serverless的使用。同时,本课程也会向您介绍可以采取的工具、方法和可操作步骤,以帮助您了解如何基于容器服务ACK Serverless构建和管理企业级应用。 学习完本课程后,您将能够: 掌握容器集群、容器编排的基本概念 掌握Kubernetes的基础概念及核心思想 掌握阿里云容器服务ACK/ACK Serverless概念及使用方法 基于容器服务ACK Serverless搭建和管理企业级网站应用
相关文章
|
13天前
|
关系型数据库 MySQL API
|
3月前
|
Kubernetes 开发者 容器
"Kubernetes的生死抉择:揭秘Pod容器重启策略如何决定应用命运的惊天大戏"
【8月更文挑战第20天】Kubernetes (k8s) 是一个强大的容器编排平台,其中Pod是最小的运行单元。Pod的重启策略确保服务连续性,主要有Always(总是重启)、OnFailure(失败时重启)和Never(从不重启)。默认策略为Always。根据不同场景,如Web服务、批处理作业或一次性任务,可以选择合适的策略。K8s还支持健康检查等高级机制来控制容器重启。合理配置这些策略对维护应用稳定性至关重要。
147 4
|
29天前
|
Ubuntu 安全 Linux
|
14天前
|
Docker 容器
docker 容器重启
【10月更文挑战第30天】docker 容器重启
17 0
|
3月前
|
Docker 容器
Docker启动的容器如何做到自动重启?
【8月更文挑战第19天】Docker启动的容器如何做到自动重启?
309 1
|
3月前
|
网络协议 Linux 网络安全
遇到Docker容器网络隔断?揭秘六种超级实用解决方案,轻松让Docker容器畅游互联网!
【8月更文挑战第18天】Docker容器内网络不通是开发者常遇问题,可能因网络配置错、Docker服务异常或防火墙阻碍等原因引起。本文提供六种解决策略:确认Docker服务运行状态、重启Docker服务、检查与自定义Docker网络设置、验证宿主机网络连接、临时禁用宿主机IPv6及检查防火墙规则。通过这些步骤,多数网络问题可得以解决,确保容器正常联网。
938 1
|
3月前
|
弹性计算 运维 Kubernetes
容器化管理云上应用解决方案评测
容器化管理云上应用解决方案评测
57 10
|
3月前
|
运维 Kubernetes 开发者
容器化管理云上应用解决方案评测
容器化管理云上应用解决方案评测
56 2
|
3月前
|
存储 运维 Kubernetes
容器化管理云上应用解决方案评测
在企业上云进程中,容器化应用托管已成为主流。阿里云容器服务Kubernetes版(ACK)凭借一键部署、自动扩展及高效管理容器化应用的能力脱颖而出。本体验分享了使用ACK快速部署应用的过程,从选择实例规格到查看服务运行状态,再到清理资源。技术细节覆盖容器化基础与Kubernetes核心组件,但高级配置如网络策略方面略显不足。文档资源丰富但部分高级功能指引不够详尽。代码示例实用,有助于快速启动部署。容器化托管的优势在于提升资源利用率、加速部署与迭代,是企业云转型的重要工具。总体而言,ACK提供了强大且便捷的容器服务体验,未来有望进一步完善以提供更佳服务。
91 0
|
4月前
|
存储 Kubernetes 负载均衡
容器化管理云上应用解决方案评测
整体而言,该方案为用户提供了清晰、详细且有用的部署指导。通过进一步增强初学者的引导和文档内容,可以更加提升用户的满意度和实施效率。