zl程序教程

您现在的位置是:首页 >  工具

当前栏目

Helm Chart在云拨测中的应用

应用 Helm Chart
2023-06-13 09:15:31 时间

背景

云拨测由于业务特性在国内和国外多个机房维护了大量的拨测节点,这些拨测节点以边缘节点(腾讯云ECM节点)的方式加入到TKE边缘集群进行统一管理与调度,拨测Agent(拨测执行器)以Pod的形式跑在边缘节点服务器上。由于拨测节点具有地域与运营商属性,因此拨测Agent在发布时Pod必须创建在对应的地域和运营商节点上,比如广州电信的拨测Agent需要跑在广州电信的拨测节点上。与此同时,由于发布的地域又比较多,因此云拨测使用Helm来做发布的编排与管理。

1. 为什么选择Helm

Helm是K8S包管理工具。我们知道K8S的资源都能描述成一个yaml文件,通过yaml文件可以定义Service、ConfigMap、Deployment、Ingress等。有了这些yaml文件后通过与Kube API Server进行交互,比如使用kubectl apply这些yaml文件,就能在K8S上创建我们需要的资源。

但这里的yaml文件是零散的,缺乏一个版本管理。其次,我们创建一个K8S微服务,可能要apply多次,甚至资源的创建可能是有先后依赖顺序的。比如一个微服务配置放到ConfigMap中,那么需要先创建ConfigMap,然后才能创建Deployment,否则Pod可能起不来。除此之外,如果发布出了问题,这种手工式的操作回退也是个麻烦。

Helm恰好适合解决这些问题,它的包管理方式称之为chart,chart可以认为是yaml文件的集合。当使用Helm来创建K8S资源时,它会根据这些yaml文件的依赖关系先后创建资源。同时每一次发布都会维护一个版本号(版本信息写入到K8S集群的Secret中),因此在出现问题时可以很方便回退。

但笔者使用最多的是Helm的模板变量功能,它支持在yaml文件里定义变量,然后通过维护一个values.yaml文件,用于对变量值的替换。甚至还可以通过Helm命令--set的方式传入参数修改yaml文件变量的值。这个功能十分有用,像云拨测的节点比较多,节点上的拨测Agent需要打入地域和运营商环境变量,那么在发布时我们通过--set的方式来传参修改,最终只需要维护一份yaml文件却能适配所有的节点。

使用values.yaml与使用helm命令替换变量值

2. 拨测节点管理与初始化

为了方便使用Helm来做发布,我们需要对拨测节点进行管理和初始化工作。

2.1 节点编码

每个云拨测节点都会分配一个地域和运营商编码,两者组合能确定一种类型的节点,我们称之为节点编码。节点编码由大洲、国家、城市、运营商编码组合而成,以广州联通的节点为例:

节点编码

大洲编码占一位,紧接着是国家编码,占三位,后面是城市编码占三位,大洲、国家、城市编码组合构成地域编码,运营商编码也占用三位。

2.3 Label标签与nodeSelector调度

2.因为拨测Agent在发布时需要调度到同地域同运营商的节点上,因此这里使用K8S的nodeSelector调度能力,需要给拨测节点打上地域和运营商属性标签

节点Label

同时在拨测Agent Pod的yaml文件里也加上nodeSelector调度配置,Label标签跟节点标签一致,那么K8S就能根据这里的Label Match把Pod调度到对应的节点上。

基于nodeSelector调度

2.3 初始化容器的使用

在使用Helm发布的过程中,我们还配合使用K8S的初始化容器(init container)来完成Pod的初始化工作。这里一个场景是拨测Agent需要获取所在节点的外网IP,但Helm部署时根据nodeSelector标签调度,只能调度到一组相同的节点(比如广州联通),到不了具体的节点,因此这里使用初始化容器来完成最后的初始化工作。

初始化容器会比业务Pod先启动,启动后通过kube API从所在节点Label获取到外网IP,然后写入一个文件,该文件也会被Agent Pod所挂载,Agent Pod起来后从该文件读取外网IP Label,再注入到自身的环境变量中,进而完成了自身的初始化。

init container

3. 与流水线整合

以上这些做完后我们把Helm发布整合到了Coding流水线上,只需要选择需要发布的城市(支持多选)和运营商,就能把拨测Agent发布到对应的节点上。

coding流水线

流水线运行时,会执行我们定义的脚本,脚本会从我们的节点库表获取需要发布地域的节点编码,通过--set的方式传入参数至Helm命令,Helm执行时会通过变量替换的方式修改Helm chart的yaml文件。这里我们主要是修改Pod yaml文件里的Label和nodeSelector,最终K8S会把Pod调度到对应的节点上。之后Agent Pod起来,在这之前,初始化容器已完成初始化,整体发布流程结束。

Helm命令

发布流水线