使用 Spot 实例打造低成本高性能无限并发的 Gitlab Runner
2022-11-04当项目中存在一些大型编译项目时,由于机器性能不足,导致研发花费大量时间等待构建,浪费生命,本文带你了解 DeepFlow 如何使用阿里云 ECI Spot 弹性实例打造低成本高性能无限并发的 Gitlab Runner。
0x0: 背景
一般使用 Gitlab CI 都是创建一台虚拟机,注册为 Gitlab Runner。我们项目中的 deepflow-agent 使用 Rust 编写,对编译机性能要求非常高,在多人同时提交代码时虚拟机经常卡顿,造成所有开发等待编译,浪费时间浪费生命。
发现这个问题后,我们开始寻找新的 CI 构建方案,最终采用了阿里云 ACK + ECI + Spot 实例
的方式,实现低成本高性能无限资源池的 Gitlab Runner。
在我们内部企业版 deepflow-agent 及 deepflow-server 项目的 CI 中,半年时间构建了 6531 次 Pipeline,可以看到 8 月份总计跑了 1176 次 CI,单月 ECI 成本为 130.31 元,对比原来需要给 Rust 编译准备一台 32C64G 包月计费虚拟机(ecs.c7.8xlarge),成本下降到了 1/20
。
CI/CD 构建次数:
CI构建记录分析
ECI 成本分析:
ECI成本分析
原单台虚拟机成本:
虚拟机成本
0x1: 阿里云 ECI 基本概念
通过基础设施集群中的虚拟节点,在阿里云的超大资源池中直接创建 Pod 资源,Kubernetes 不再需要直接负责单个 Pod 的放置、启动等工作,也不再需要关心底层虚拟机的资源情况,无需自行准备计算节点。通常用于高性能计算,离线备份计算,CI 等临时需要高规格资源场景。
限制:基于 Kubernetes 社区的 Virtual Kubelet 技术,ECI 通过虚拟节点与 Kubernetes 实现无缝对接,因此 ECI 实例并不会运行在一个集中式的真实节点上,而是打散分布在整个阿里云的资源池中。基于公有云的安全性和虚拟节点本身带来的限制,ECI 目前还不支持 Kubernetes 中 HostPath、DaemonSet 等功能。
阿里云上有两种 K8s 集群类型,ASK 及 ACK:
- ASK:该集群中创建的所有 Pod 直接使用 ECI 调度
- ACK:部署虚拟节点,通过添加特定 Label 调度 Pod 到 ECI
阿里云 ASK、ACK 对比
ACK 使用 ECI 调度:由于我们本身基础架构使用的阿里云 ACK 集群,固选择在 ACK 中部署虚拟节点的方式使用 ECI,使用流程:
- 部署虚拟节点
- 调度Pod到虚拟节点
ACK + ECI 混合集群
部署虚拟节点
简单测试一下创建 ECI 实例:
1 | kubectl run deepflow-test --image ubuntu:latest -l alibabacloud.com/eci=true --annotations=k8s.aliyun.com/eci-use-specs="2-4Gi" -n dev-ci-cd |
实例资源配置:可选择多种方式创建实例:
- 指定 vCPU 和内存,会自动匹配对应的 ECS 资源规格
- 指定 ECS 规格,可选择计算型,内存型,高主频等规格
- 创建 GPU 实例,可选择带 GPU 类型
- 创建 AMD 实例,可选择处理器为 AMD EPYCTM ROME 的实例
Spot 抢占式实例:一种价格极低的抢占式实例,价格非常便宜但不保证长时间的可用性,适合临时测试业务或 CI 使用。按秒计费,计费规则为每小时价格/3600秒。
常用规格参考
规格 | 大小 | 原价格/小时 | spot 价格/小时 |
---|---|---|---|
ecs.c5.large | 2C4G | 0.62 | 0.062 |
ecs.c6.large | 2C4G | 0.39 | 0.078 |
ecs.g6.2xlarge | 8C32G | 2.0 | 0.4-0.84 |
ecs.g6.4xlarge | 16C64G | 4.0 | 0.8-1.44-4.0 |
annotations 参考
可使用 kubernetes 中 pod annotations 调整 ECI 参数,其中 ECI 支持的所有 Annotation,详细说明参考官方文档: ECI Pod Annotation
1 | annotations: |
查询当前 spot 实例价格
两种方式,命令行工具或 API 查询,推荐 cli 工具,具体参数详见阿里云cli工具使用说明
1 | # aliyun-cli |
也可使用 API 方式
1 | # API 文档 |
0x2: Gitlab CI 配置
第一步 创建命名空间
创建命名空间 dev-eci
,并打上 alibabacloud.com/eci=true
LABEL,在此命名空间下创建的 Pod 将默认调度至 ECI 虚拟节点。
1 | kubectl create ns dev-eci |
第二步 注册 Kubernetes 类型 Runner
我们在 dev-eci
命名空间下注册一个名为 kubernetes-eci 的 Runner, 使用该 runner 的 CI 将自动在 dev-eci
命名空间使用 ECI 创建 CI POD。详细说明可查看官方文档 The Kubernetes executor for GitLab Runner
1 | helm repo add gitlab https://charts.gitlab.io |
values-custom.yaml 自定义配置参考
- 指定 namespace
- 如果访问 gitlab 官方仓库网络不好,可以将 gitlab-runner-helper:x86_64-f761588f 镜像传到国内公网仓库
- 指定 pod_annotations_overwrite_allowed ,方可在 ci 中通过变量控制 ECI 实例参数,详细注解列表可参考 Overwriting pod annotations
- 指定挂载 pvc(所有 CI Pod 可共享该目录,可以用来放置缓存目录)
1 | # values-custom.yaml |
Gitlab-Runner
第三步 配置 Gitlab CI
有关 ECI 与 Gitab CI 的结合,没有太多网络资料参考,如有疑问可扫描下方二维码加入 DeepFlow 开源交流群共同交流。
以构建 deepflow-agent-x86 为例,参考 CI 配置如下:
1 | # .gitlab-ci.yml |
第四步 Push 代码
此时已完成 Runner 注册,可提交代码触发 CI Pipeline,查看 CI 执行流程。
build-agent-ci
0x4: 遇到的问题
spot 实例资源不足导致无法启动
阿里云当前可用区的 Spot 资源不足,导致无法启动实例
资源不足
1 | 14:51 Message: The instanceTypes are out of usage.. |
解决办法
- 通过增加交换机的方式增加可用区,详细说明参考官方文档:配置 ECI Profile 中的 vSwitchIds
- 调整实例规格类型,使用剩余资源较多的类型,详细说明参考官方文档:优化库存之多可用区多规格创建 Pod
0x5: 使用 ECI 后的改变
目前我们 DeepFlow 的主要 CI 都已切换到 ECI 的 Runner 上,达到了之前所有的预期:
- 性能:每人每次 Push 后都将独立使用一台高性能机器编译,无需等待他人,不受其他编译任务影响
- 成本:对比原来需要给 Rust 编译准备一台 32C64G 包月计费虚拟机(ecs.c7.8xlarge),成本仅为虚拟机的 1/20,极大的降低了成本
- 灵活性:可将任意 CI 或负载弹性扩容至 ECI 集群
- 实例维护成本:无任何维护成本,无需维护虚拟机
0x6: 什么是 DeepFlow
DeepFlow 是云杉网络开发的一款可观测性产品,旨在为复杂的云基础设施及云原生应用提供深度可观测性。DeepFlow 基于 eBPF 实现了应用性能指标、分布式追踪、持续性能剖析等观测信号的零侵扰(Zero Code
)采集,并结合智能标签(SmartEncoding
)技术实现了所有观测信号的全栈(Full Stack
)关联和高效存取。使用 DeepFlow,可以让云原生应用自动具有深度可观测性,从而消除开发者不断插桩的沉重负担,并为 DevOps/SRE 团队提供从代码到基础设施的监控及诊断能力。
GitHub 地址:https://github.com/deepflowio/deepflow
访问 DeepFlow Demo,体验高度自动化的可观测性新时代。