王智刚

CD-Tools

Misc 更新 2024年3月31日 3 分钟
目录

一个极简的 CD 工具

image-20230724203649494

是什么

K8S api 进行封装,借助 FRP 对封装后的接口进行公网暴露,同时使用 Token 进行身份验证,配合CI Pipeline最终实现代码的自动发布上线

graph LR A[前端创建Token] ---> B[复制命令] B ---> C[CI集成]

使用时,只需要在前端选择对应的Deployment,点击创建按钮,然后复制对应的命令即可。得到的命令是一个curl语句,可以和任意的系统进行集成。如果和CI进行集成,那么当代码构建完之后就能实现自动的发布更新。

前端

image-20230906165707754

Curl

image-20230724160559170

CI 集成

image-20230724161238982

为什么

入学之后组里想探索一下新的方向,做一些平台之类的东西;因此搭建了 K8S,在此之上进行开发。

image-20230724171025296

随着开发的模块越来越多,每天的频繁发版上线成了一件非常折磨人的事情:每次都需要 本地构建镜像 -> 上传docker hub -> 登录 rancher -> 修改镜像Tag,非常的繁琐,某些时间每天会有接近20+次的上线,如果完全依靠人工来做会做到崩溃。

因此搭建了一个 CD 系统,借助 Azure Devops 完成 CI 部分;使用 webhook+K8S api;写完代码 Push 至仓库后自动开始构建自动发布,省去所有人工步骤

为什么不使用开源的方案

在之前实习的时候做过一段时间的 CICD,因此最初遇到这个问题时想的同样是使用开源方案来解决。但我们的代码托管在 Github 等地方,我们希望直接使用这些服务商的 CI 能力而不是在本地单独搭建一套 CI 系统,因此像Jenkins这类工具就显得太重了。

我们的诉求很简单:当 CI 系统构建出来镜像之后以某种方式通知到 K8S 即可

HelmArgoCD 都可以解决这个问题:

  • Helm 可以和 CI 集成,当构建完产物后通过update来更新镜像即可,然而我们的 K8S 是不能直接外网访问的,这样 Helm 就无能为力了。
  • ArgoCD 可以完美的解决这个问题,它会通过监听某个仓库的变化并将变化应用到集群;但是这种方案需要单独维护一个或多个仓库,同时需要手动/自动的更新这些仓库的内容,学习成本太高&和 CI 集成的难度比较大

因此最后没有选择这些方案,自己简单实现了一下。

如何实现

image-20230724203649494

FRP 实现内网穿透

在构建 Docker 镜像时,直接将frp的客户端打包进去,然后在后端的init函数中拉起。

func init() {
......
// 开一个协程拉起
if runtime.GOOS != "windows" {
go startFrp()
}
}

安全起见,FRP 的配置通过环境变量注入

后端

使用 Go 实现,为了适配不同的数据库,抽象出了一些接口。

在修改Jaeger时学习到了这种设计模式,于是就应用了一下。

type Factory interface {
Initialize() error
CreateReader() (Reader, error)
CreateWriter() (Writer, error)
}
type Reader interface {
Get(key string) (KV, error)
}
type Writer interface {
Set(kv KV) error
Remove(key string) error
}

进程内缓存,当 Token 不存在时先去数据库里查,查询到更新至缓存中。

前端

使用angular实现

使用效果

image-20230724205140993

平均每月 600-800 分钟的构建时长,大约100次左右的发布,除网络问题外无任何异常。

仅 2-3 月里自动完成了约500次发布,4 月份消耗了 1800 分钟的构建时长,平均每天 10 次发布,成功率100%,极大的减少了手动发布的痛苦。

202311191912862

image-20230724160836094

意外收获

目前使用 Azure Devops 作为代码托管和 CI,Azure 的 Agent 可以无视 GFW,因此在构建镜像的时候非常丝滑;同时,我们使用阿里云的 ACR 作为镜像中心,Azure 也可以很顺畅的将镜像推至 ACR 中。

一些缺点

并发限制

免费的 CI Pipeline 有并发限制,如果出现多个任务,需要排队;但我们团队只有两个人,这个问题可以忽略不计。

构建速度

虽然不存在网络的问题,但是因为构建镜像的 Agent 是随机的,因此无法将一些可以缓存的东西缓存下来,每次构建都是全新的,平均构建一个镜像需要 3-5 分钟,相比本地要慢一下;但是网络优势又弥补了这个缺点。


适合自己的才是最好的!