OpenKruise :SidecarSet 助力 Mesh 容器热升级

网友投稿 191 2022-11-08

OpenKruise :SidecarSet 助力 Mesh 容器热升级

前言

​OpenKruise 是阿里云开源的云原生应用自动化管理套件,也是当前托管在 Cloud Native Computing Foundation ( CNCF ) 下的 Sandbox 项目。它来自阿里巴巴多年来容器化、云原生的技术沉淀,是阿里内部生产环境大规模应用的基于 Kubernetes 之上的标准扩展组件,也是紧贴上游社区标准、适应互联网规模化场景的技术理念与最佳实践。​OpenKruise 在 2021.5.20 发布了最新的 v0.9.0版本( ChangeLog ),上一篇文章我们介绍了新增 Pod 重启、删除防护等重磅功能,今天向大家介绍另一个核心特性,即 SidecarSet 基于上一个版本扩展了特别针对 Service Mesh 场景的支持。​

背景:如何独立升级 Mesh 容器

​SidecarSet 是 Kruise 提供的独立管理 Sidecar 容器的 workload。用户通过 SidecarSet 能够便利的完成对 Sidecar 容器的自动注入和独立升级,详情请参考:OpenKruise 官网​

阿里巴巴集团内部拥有上万的 Pod 都是基于 Service Mesh 来实现相互间的通信,由于 Mesh 容器升级会导致业务 Pod 的不可用,因而 Mesh 容器的升级将会极大阻碍 Service Mesh 的迭代。针对这种场景,我们同集团内部的 Service Mesh 团队一起合作实现了 Mesh 容器的热升级能力。本文将重点介绍在实现 mesh 容器热升级能力的过程中 SidecarSet 是扮演了怎样的重要角色。​

SidecarSet 助力 Mesh 容器无损热升级

Mesh 容器不能像日志采集类容器直接原地升级,其原因在于:Mesh 容器必须要不间断地对外提供服务,而独立升级方式会导致 Mesh 服务存在一段不可用时间。虽然社区中已有一些知名的 Mesh 服务如 Envoy 、Mosn 等默认能够提供平滑升级的能力,但是这些升级方式无法与云原生进行恰当地结合,且 kubernetes 本身也缺乏对此类 Sidecar 容器的升级方案。​

OpenKruise SidecarSet 为此类 Mesh 容器提供了 Sidecar 热升级机制,能够通过云原生的方式助力 Mesh 容器实现无损热升级。

apiVersion: apps.kruise.io/v1alpha1 kind: SidecarSet metadata: name: hotupgrade-sidecarset spec: selector: matchLabels: app: hotupgrade containers: - name: sidecar image: openkruise/hotupgrade-sample:sidecarv1 imagePullPolicy: Always lifecycle: postStart: exec: command: - /bin/sh - /migrate.sh upgradeStrategy: upgradeType: HotUpgrade hotUpgradeEmptyImage: openkruise/hotupgrade-sample:empty

upgradeType : HotUpgrade 代表该 sidecar 容器的类型是 Hot upgrade ,即热升级方案。 HotUpgradeEmptyImage : 当热升级 Sidecar 容器时,业务须要提供一个 empty 容器用于热升级过程中的容器切换。Empty 容器同 Sidecar 容器具有相同的配置(镜像地址除外),例如 command , lifecycle , probe 等。

SidecarSet 热升级机制主要包含注入热升级 Sidecar 容器和 Mesh 容器平滑升级两个过程。​

注入热升级 Sidecar 容器

针对热升级类型的 Sidecar 容器,在 Pod 创建时 SidecarSet Webhook 将会注入两个容器:​

{Sidecar.name} -1: 如下图所示 envoy -1,这个容器代表正在实际工作的 sidecar 容器,例如:envoy :1.16.0​ {Sidecar.name} -2: 如下图所示 envoy-2,这个容器是业务提供的 HotUpgradeEmptyImage 容器,例如:empty :1.0

上述 Empty 容器在 Mesh 容器运行过程中,并没有做任何实际的工作。​

Mesh 容器平滑升级

热升级流程主要分为一下三个步骤:​

Upgrade: 将 Empty 容器替换为最新版本的 Sidecar 容器,例如:envoy-2.Image = envoy:1.17.0 Migration : 执行 Sidecar 容器的 PostStartHook 脚本,完成 mesh 服务的平滑升级 Reset: Mesh 服务平滑升级后,将老版本 Sidecar 容器替换为 Empty 容器,例如:envoy-1.Image = empty : 1.0

Migration 核心逻辑

SidecarSet 热升级机制不仅完成了 Mesh 容器的切换,并且提供了新老版本的协调机制( PostStartHook ),但是至此还只是万里长征的第一步,Mesh 容器同时还需要提供 PostSartHook 脚本来完成 Mesh 服务自身的平滑升级(上述 Migration 过程),如:Envoy 热重启、Mosn 无损重启。​

热升级 Migration Demo

不同 Mesh 容器对外提供的服务以及内部实现逻辑各有差异,进而具体的 Migration也有所不同,上述逻辑只是对其中一些要点做了一些总结,希望能对有需要的各位有所裨益,同时在 Github 上面我们也提供了一个热升级 Migration Demo 以供参考,下面将对其中的一些关键代码进行介绍。​

1. 协商机制​

Mesh 容器启动逻辑首先就需要判断第一次启动还是热升级平滑迁移过程,为了减少Mesh 容器沟通成本,Kruise 在两个 sidecar 容器中注入了两个环境变量 SIDECARSET_VERSION 和 SIDECARSET_VERSION_ALT ,通过判断两个环境变量的值来判断是否是热升级过程以及当前 sidecar 容器是新版本还是老版本。​

// return two parameters: // 1. (bool) indicates whether it is hot upgrade process // 2. (bool ) when isHotUpgrading=true, the current sidecar is newer or older func isHotUpgradeProcess() (bool, bool) { // 当前sidecar容器的版本 version := os.Getenv("SIDECARSET_VERSION") // 对端sidecar容器的版本 versionAlt := os.Getenv("SIDECARSET_VERSION_ALT") // 当对端sidecar容器version是"0"时,表明当前没有在热升级过程 if versionAlt == "0" { return false, false } // 在热升级过程中 versionInt, _ := strconv.Atoi(version) versionAltInt, _ := strconv.Atoi(versionAlt) // version是单调递增的int类型,新版本的version值会更大 return true, versionInt > versionAltInt }

2. ListenFD 迁移​

通过 Unix Domain Socket 实现 ListenFD 在不同容器间的迁移,此步同样也是热升级中非常关键的一步,代码示例如下:​

// 为了代码的简洁,所有的失败都将不捕获 /* 老版本sidecar通过Unix Domain Socket迁移ListenFD到新版本sidecar */ // tcpLn *net.TCPListener f, _ := tcpLn.File() fdnum := f.Fd() data := syscall.UnixRights(int(fdnum)) // 与新版本sidecar容器通过 Unix Domain Socket建立链接 raddr, _ := net.ResolveUnixAddr("unix", "/dev/shm/migrate.sock") uds, _ := net.DialUnix("unix", nil, raddr) // 通过UDS,发送ListenFD到新版本sidecar容器 uds.WriteMsgUnix(nil, data, nil) // 停止接收新的request,并且开始排水阶段,例如:GOAWAY tcpLn.Close() /* 新版本sidecar接收ListenFD,并且开始对外服务 */ // 监听 UDS addr, _ := net.ResolveUnixAddr("unix", "/dev/shm/migrate.sock") unixLn, _ := net.ListenUnix("unix", addr) conn, _ := unixLn.AcceptUnix() buf := make([]byte, 32) oob := make([]byte, 32) // 接收 ListenFD _, oobn, _, _, _ := conn.ReadMsgUnix(buf, oob) scms, _ := syscall.ParseSocketControlMessage(oob[:oobn]) if len(scms) > 0 { // 解析FD,并转化为 *net.TCPListener fds, _ := syscall.ParseUnixRights(&(scms[0])) f := os.NewFile(uintptr(fds[0]), "") ln, _ := net.FileListener(f) tcpLn, _ := ln.(*net.TCPListener) // 基于接收到的Listener开始对外提供服务,以http服务为例 serveMux) }

已知 Mesh 容器热升级案例

阿里云服务网格( Alibaba Cloud Service Mesh,简称 ASM)提供了一个全托管式的服务网格平台,兼容社区 Istio 开源服务网格。当前,基于 OpenKruise SidecarSet 的热升级能力,ASM 实现了数据平面 Sidecar 热升级能力( Beta ),用户可以在应用无感的情况下完成服务网格的数据平面版本升级,正式版也将于近期上线。除热升级能力外,ASM 还支持配置诊断、操作审计、访问日志、监控、服务注册接入等能力,全方位提升服务网格使用体验,欢迎您前往试用。

总结​云原生中 Mesh 容器的热升级一直都是迫切却又棘手的问题,本文中的方案也只是阿里巴巴集团在此问题上的一次探索,在反馈社区的同时也希望能够抛砖引玉,引发各位对此中场景的思考。同时,我们也欢迎更多的同学参与到 OpenKruise 社区来,共同建设一个场景更加丰富、完善的 K8s 应用管理、交付扩展能力,能够面向更加规模化、复杂化、极致性能的场景。​

热升级Migration Demo:https://github.com/openkruise/samples Github:https://github.com/openkruise/kruise Official:https://openkruise.io/

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:瑞萨电子通过RZ / T1解决方案支持HIPERFACE DSL®数字编码器接口
下一篇:一篇文章带你搞懂 etcd 3.5 的核心特性
相关文章

 发表评论

暂时没有评论,来抢沙发吧~