使用 Spot 实例打造低成本高性能无限并发的 Gitlab Runner

当项目中存在一些大型编译项目时,由于机器性能不足,导致研发花费大量时间等待构建,浪费生命,本文带你了解 DeepFlow 如何使用阿里云 ECI Spot 弹性实例打造低成本高性能无限并发的 Gitlab Runner。

01

背景

一般使用 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 构建次数:

使用 Spot 实例打造低成本高性能无限并发的 Gitlab Runner
CI构建记录分析

ECI 成本分析:

使用 Spot 实例打造低成本高性能无限并发的 Gitlab Runner
ECI成本分析

原单台虚拟机成本:

使用 Spot 实例打造低成本高性能无限并发的 Gitlab Runner
虚拟机成本

02

阿里云 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
使用 Spot 实例打造低成本高性能无限并发的 Gitlab Runner
阿里云 ASK、ACK 对比

ACK 使用 ECI 调度:由于我们本身基础架构使用的阿里云 ACK 集群,固选择在 ACK 中部署虚拟节点的方式使用 ECI,使用流程:

  1. 部署虚拟节点
  2. 调度Pod到虚拟节点

使用 Spot 实例打造低成本高性能无限并发的 Gitlab Runner
ACK + ECI 混合集群
使用 Spot 实例打造低成本高性能无限并发的 Gitlab Runner
部署虚拟节点

简单测试一下创建 ECI 实例:

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:
 k8s.aliyun.com/eci-use-specs : "ecs.c5.large" # 根据需要替换ECS实例规格
 k8s.aliyun.com/eci-spot-strategy: "SpotWithPriceLimit" # 采用自定义设置价格上限的策略或 SpotAsPriceGo 系统自动出价,跟随当前市场实际价格。
 k8s.aliyun.com/eci-spot-price-limit: "0.250" # 设置每小时价格上限
 k8s.aliyun.com/eci-spot-duration: "2" # 设置保护期

查询当前 spot 实例价格

两种方式,命令行工具或 API 查询,推荐 cli 工具,具体参数详见阿里云cli工具使用说明[2]

# aliyun-cli
aliyun ecs DescribeSpotPriceHistory --InstanceType=ecs.c5.large --NetworkType=vpc --output cols=InstanceTypeOriginPrice,SpotPrice,ZoneId rows=SpotPrices.SpotPriceType[]
## 注意:zsh shell 中 [] 需要用  转义,e.g. []

也可使用 API 方式

# API 文档
https://next.api.aliyun.com/api/Ecs/2014-05-26/DescribeSpotPriceHistory?lang=GO&params{%22NetworkType%22:%22vpc%22,%22ZoneId%22:%22cn-beijing-h%22,%22RegionId%22:%22cn-beijing%22%22InstanceType%22:%22ecs.c5.large%22}&tab=DEMO

03

Gitlab CI 配置

第一步 创建命名空间

创建命名空间 dev-eci,并打上 alibabacloud.com/eci=true LABEL,在此命名空间下创建的 Pod 将默认调度至 ECI 虚拟节点。

kubectl create ns dev-eci
kubectl label ns dev-eci alibabacloud.com/eci=true

第二步 注册 Kubernetes 类型 Runner

我们在 dev-eci 命名空间下注册一个名为 kubernetes-eci 的 Runner, 使用该 runner 的 CI 将自动在 dev-eci 命名空间使用 ECI 创建 CI POD。详细说明可查看官方文档 The Kubernetes executor for GitLab Runner[3]

helm repo add gitlab https://charts.gitlab.io

# For Helm 3
helm install --namespace dev-eci gitlab-runner -f values-custom.yaml gitlab/gitlab-runner

# 按提示输入 gitlab url 及 token

values-custom.yaml 自定义配置参考

  • 指定 namespace
  • 如果访问 gitlab 官方仓库网络不好,可以将 gitlab-runner-helper:x86_64-f761588f 镜像传到国内公网仓库
  • 指定 pod_annotations_overwrite_allowed ,方可在 ci 中通过变量控制 ECI 实例参数,详细注解列表可参考 Overwriting pod annotations[4]
  • 指定挂载 pvc(所有 CI Pod 可共享该目录,可以用来放置缓存目录)
# values-custom.yaml
runners:
  # runner configuration, where the multi line strings is evaluated as
  # template so you can specify helm values inside of it.
  #
  # tpl: https://helm.sh/docs/howto/charts_tips_and_tricks/#using-the-tpl-function
  # runner configuration: https://docs.gitlab.com/runner/configuration/advanced-configuration.html
    [[runners]]
      [runners.kubernetes]
        namespace = "dev-eci"
        image = "ubuntu:16.04"
        ## 可选,如果网络无法拉取官方镜像,可自行同步至内网仓库
        # helper_image = "dfcloud-image-registry.cn-beijing.cr.aliyuncs.com/deepflowcloud/gitlab-runner-helper:x86_64-f761588f"
        pod_annotations = ""
        pod_annotations_overwrite_allowed = "k8s.aliyun.com.*"
        poll_timeout = 3600
        privileged = false
        ## 可选
        [[runners.kubernetes.volumes.pvc]]
          name = "rust-cache"
          mount_path = "/root/.cache/"
使用 Spot 实例打造低成本高性能无限并发的 Gitlab Runner
Gitlab-Runner

第三步 配置 Gitlab CI

有关 ECI 与 Gitab CI 的结合,没有太多网络资料参考,如有疑问可扫描下方二维码加入 DeepFlow 开源交流群共同交流。

以构建 deepflow-agent-x86 为例,参考 CI 配置如下:

# .gitlab-ci.yml
.common_rules:
  ci_script:
  - changes:
    - .gitlab-ci.yml
  agent_verify_rules:
  - if: $CI_PIPELINE_SOURCE == "merge_request_event"
    changes:
    - agent/**/*
  - if: '$CI_COMMIT_BRANCH && $CI_OPEN_MERGE_REQUESTS'
    when: never
  agent_package_rules:
  - if: $CI_COMMIT_BRANCH =~ /^feature-/  || $CI_COMMIT_REF_NAME == "main"
    changes:
    - agent/**/*
  - if: $CI_PIPELINE_SOURCE == "schedule"

variables:
  ALIYUN_REGISTRY: 镜像仓库地址
  DEPLOY_IMAGE: 镜像仓库地址/deepflow-agent
  GO_IMAGE: 镜像仓库地址/golang:1.18.0-protobuf-3.6.1-tmpl-docker-0.7
  RUST_IMAGE: 镜像仓库地址/public/rust-build:1.14
  # 可指定多个实例类型,至多 5 个。
  KUBERNETES_POD_ANNOTATIONS_1: "k8s.aliyun.com/eci-use-specs=ecs.c6.2xlarge,ecs.c5.2xlarge,ecs.c7.3xlarge,ecs.g6.2xlarge,ecs.c6e.2xlarge"
  # 配置 Spot 实例保护期为一小时,防止 CI 运行时突然中断。超过2小时将只能使用部分指定机型,详情看文档。
  # https://help.aliyun.com/document_detail/451259.html
  KUBERNETES_POD_ANNOTATIONS_2: "k8s.aliyun.com/eci-spot-duration=1"
  # 配置 Spot 实例自动出价,跟随当前市场实际价格。
  KUBERNETES_POD_ANNOTATIONS_3: "k8s.aliyun.com/eci-spot-strategy=SpotAsPriceGo"
  # 启用镜像缓存,加速镜像拉取速度。
  KUBERNETES_POD_ANNOTATIONS_4: "k8s.aliyun.com/eci-image-cache=true"
  # 是否开启镜像缓存复用。开启后,新创建的镜像缓存可以复用已有镜像缓存的镜像层,加快镜像缓存的制作速度。
  # https://help.aliyun.com/document_detail/311475.html?spm=a2c4g.11186623.0.0.24ba9f3c6sFiO6
  KUBERNETES_POD_ANNOTATIONS_5: "k8s.aliyun.com/imc-enable-reuse=true"
  # [可选]镜像缓存时间,过期自动删除,超过1G的镜像尽量不删除,不然每次拉取很慢。
  # KUBERNETES_POD_ANNOTATIONS_7: "k8s.aliyun.com/imc-retention-days=7"

stages:
  - verify
  - build_agent
  - package

verify-agent-x64:
  stage: verify
  retry: 1
  tags:
    - kubernetes-eci
  image: $RUST_IMAGE
  script:
    - source /opt/rh/devtoolset-8/enable
    - cd agent
    - cargo check
    - cargo fmt --all -- --check
  rules:
  - !reference [.common_rules, ci_script]
  - !reference [.common_rules, agent_verify_rules]

binary-agent-x64:
  stage: build_agent
  tags:
    - kubernetes-eci
  image: $RUST_IMAGE
  timeout: 30 minutes
  script:
    - cd agent
    - cargo build --release --target=x86_64-unknown-linux-musl
    - cargo build --release --bin deepflow-agent-ctl --target=x86_64-unknown-linux-musl
    - ls -alh target/x86_64-unknown-linux-musl/release
    - mkdir -p x86_64/output
    - cp target/x86_64-unknown-linux-musl/release/{deepflow-agent,deepflow-agent-ctl} x86_64/output/
    - DEP_PATH=$(cargo metadata | jq -r '.packages[] | select(.name=="deepflow-agent" and .source!=null) | .manifest_path' | xargs -i dirname {})
    - cp $DEP_PATH/src/ebpf/{libtrace.a,deepflow-ebpfctl} x86_64/output/
  rules:
  - !reference [.common_rules, ci_script]
  - !reference [.common_rules, agent_package_rules]
  artifacts:
      paths:
        - agent/x86_64/output/deepflow-agent
        - agent/x86_64/output/deepflow-agent-ctl
        - agent/x86_64/output/libtrace.a
        - agent/x86_64/output/deepflow-ebpfctl

docker-agent-x64:
  stage: package
  tags:
    - rust
  script:
    - cd agent
    - cp x86_64/output/{deepflow-agent,deepflow-agent-ctl,deepflow-ebpfctl} docker/
    - cd docker
    # e.g. deepflow-agnet:latest
    - docker build --pull -t  $DEPLOY_IMAGE:latest .
    - docker push $DEPLOY_IMAGE:latest
  rules:
  - !reference [.common_rules, ci_script]
  - !reference [.common_rules, agent_package_rules]

第四步 Push 代码

此时已完成 Runner 注册,可提交代码触发 CI Pipeline,查看 CI 执行流程。

使用 Spot 实例打造低成本高性能无限并发的 Gitlab Runner
build-agent-ci

05

遇到的问题

spot 实例资源不足导致无法启动

阿里云当前可用区的 Spot 资源不足,导致无法启动实例

使用 Spot 实例打造低成本高性能无限并发的 Gitlab Runner
资源不足
14:51 Message: The instanceTypes are out of usage..
We recommend that you use the create multi-zone function to avoid insufficient inventory.
For more information, see https://help.aliyun.com/document_detail/157290.html
...

解决办法

  • 通过增加交换机的方式增加可用区,详细说明参考官方文档:配置 ECI Profile 中的 vSwitchIds[5]
  • 调整实例规格类型,使用剩余资源较多的类型,详细说明参考官方文档:优化库存之多可用区多规格创建 Pod[6]

06

使用 ECI 后的改变

目前我们 DeepFlow 的主要 CI 都已切换到 ECI 的 Runner 上,达到了之前所有的预期:

  • 性能:每人每次 Push 后都将独立使用一台高性能机器编译,无需等待他人,不受其他编译任务影响
  • 成本:对比原来需要给 Rust 编译准备一台 32C64G 包月计费虚拟机(ecs.c7.8xlarge),成本仅为虚拟机的 1/20,极大的降低了成本
  • 灵活性:可将任意 CI 或负载弹性扩容至 ECI 集群
  • 实例维护成本:无任何维护成本,无需维护虚拟机

07

什么是 DeepFlow

DeepFlow[7] 是一款开源的高度自动化的可观测性平台,是为云原生应用开发者建设可观测性能力而量身打造的全栈、全链路、高性能数据引擎。DeepFlow 使用 eBPF、WASM、OpenTelemetry 等新技术,创新的实现了 AutoTracing、AutoMetrics、AutoTagging、SmartEncoding 等核心机制,帮助开发者提升埋点插码的自动化水平,降低可观测性平台的运维复杂度。利用 DeepFlow 的可编程能力和开放接口,开发者可以快速将其融入到自己的可观测性技术栈中。

GitHub 地址:https://github.com/deepflowys/deepflow

访问 DeepFlow Demo[8],体验高度自动化的可观测性新时代。

08

参考文档

  • 通过部署ACK虚拟节点组件创建ECI Pod[9]
  • ECI 容器实例规格[10]
  • ECS实例规格[11]
  • 创建抢占式实例[12]
  • ECI地域和可用区[13]
  • Pod 注释列表[14]
  • ECI 弹性容器实例控制台[15]
  • The Kubernetes executor for GitLab Runner[16]
  • .gitlab-ci.yml 参考[17]

参考资料

[1]

ECI Pod Annotation: https://help.aliyun.com/document_detail/144561.htm?spm=a2c4g.11186623.0.0.41ba79aa4ilTpY#topic-1860148

[2]

阿里云cli工具使用说明: https://help.aliyun.com/document_detail/122111.html

[3]

The Kubernetes executor for GitLab Runner: https://docs.gitlab.com/runner/executors/kubernetes.html

[4]

Overwriting pod annotations: https://docs.gitlab.com/runner/executors/kubernetes.html#overwriting-pod-annotations

[5]

配置 ECI Profile 中的 vSwitchIds: https://help.aliyun.com/document_detail/209123.html

[6]

优化库存之多可用区多规格创建 Pod: https://help.aliyun.com/document_detail/451206.html

[7]

DeepFlow: https://github.com/deepflowys/deepflow

[8]

DeepFlow Demo: https://deepflow.yunshan.net/docs/zh/install/overview/

[9]

通过部署ACK虚拟节点组件创建ECI Pod: https://help.aliyun.com/document_detail/118970.htm?spm=a2c4g.11186623.0.0.342a2981obpey9#section-9ec-223-45i

[10]

ECI 容器实例规格: https://help.aliyun.com/document_detail/114662.html

[11]

ECS实例规格: https://help.aliyun.com/document_detail/25378.html

[12]

创建抢占式实例: https://help.aliyun.com/document_detail/157759.htm?spm=a2c4g.11186623.0.0.325031c9S2mMjH#topic-2445170

[13]

ECI地域和可用区: https://help.aliyun.com/document_detail/89155.htm?spm=a2c4g.11186623.0.0.6fa43bebxDb7eu#topic-1860084

[14]

Pod 注释列表: https://help.aliyun.com/document_detail/144561.htm?spm=a2c4g.11186623.0.0.3ddb413aC52NTo#topic-1860148

[15]

ECI 弹性容器实例控制台: https://eci.console.aliyun.com/?spm=5176.2020520101.categories-n-products.deci.217b4df5nffIp9#/eci/cn-beijing/list

[16]

The Kubernetes executor for GitLab Runner: https://docs.gitlab.com/runner/executors/kubernetes.html#overwriting-pod-annotations

[17]

.gitlab-ci.yml 参考: https://docs.gitlab.com/ee/ci/yaml/

加入DeepFlow开源社区
体验高度自动化的可观测性新时代




官网链接

https://deepflow.yunshan.net/community.html


GitHub 地址

https://github.com/deepflowys/deepflow


访问 DeepFlow 文档

https://deepflow.yunshan.net/docs/about/overview/

往期推荐:





DeepFlow 使用 Spot 实例加速 GitHub Action 的探索


DeepFlow 入选 CNCF 云原生全景图和 eBPF 全景图


DeepFlow v6.1.1重大更新 应用性能监控能力极大增强 开源社区同步发布

关于 DeepFlow


DeepFlow 是云杉网络开源的一款高度自动化的可观测性平台,是为云原生应用开发者建设可观测性能力而量身打造的全栈、全链路、高性能数据引擎。DeepFlow 使用 eBPF、WASM、OpenTelemetry 等新技术,创新的实现了 AutoTracing、AutoMetrics、AutoTagging、SmartEncoding 等核心机制,帮助开发者提升埋点插码的自动化水平,降低可观测性平台的运维复杂度。利用 DeepFlow 的可编程能力和开放接口,开发者可以快速将其融入到自己的可观测性技术栈中。


DeepFlow 企业版自2016年起已在中国移动、中国联通、中国电信、国家电网、招商银行、民生银行、光大银行、中国人保财险、平安科技、兴业数金、国泰君安、海通证券、上汽集团、深航货运、东方明珠、中保信等超过50家企业级数据中心落地部署,帮助客户构建多维度、一体化的可观测性平台。




使用 Spot 实例打造低成本高性能无限并发的 Gitlab Runner

点击【阅读原文】观看完整博客

0 0 投票数
文章评分

本文为从大数据到人工智能博主「jellyfin」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。

原文链接:https://lrting.top/backend/13434/

(0)
上一篇 2023-06-11 01:49
下一篇 2023-06-11 01:58

相关推荐

订阅评论
提醒
guest

0 评论
内联反馈
查看所有评论
0
希望看到您的想法,请您发表评论x