在 Kubernetes 上执行 GitHub Actions 流水线作业

cfc52b65c34ea83ff13cf182443e18f2.gif

作者 | Addo Zhang

来源 | 云原生指北

GitHub Actions 是一个功能强大、“免费” 的 CI(持续集成)工具。

与之前介绍的 Tekton 类似,GitHub Actions 的核心也是 Pipeline as Code 也就是所谓的流水线即代码。二者不同的是,GitHub Actions 本身就是一个 CI 平台,用户可以使用代码来定义流水线并在平台上运行;而 Tekton 本身是一个用于构建 CI/CD 平台的开源框架。

Pipeline as Code,既然与代码扯上了关系。那流水线的定义就可繁可简了,完全看需求。小到一个 GitHub Pages,大到流程复杂的项目都可以使用 GitHub Actions 来构建。

本篇文章不会介绍如何使用 GitHub Actions 的,如果还未用过的同学可以浏览下官方的文档。今天主要来分享下如何在 Kubernetes 上的自托管资源来执行流水线作业。

背 景

在介绍 GitHub Actions 的时候,免费带上了引号,为何?其作为一个 CI 工具,允许用户定义流水线并在平台上运行,需要消耗计算、存储、网络等资源,这些运行流水线的机器称为 Runner。GitHub 为不同类(等)型(级)的用户每月提供了不同的免费额度(额度用完后,每分钟 0.008 美元。),见下图。不同类型的主机,分钟数的消耗倍数也不同:Linux 为 1、macOS 为 10、Windows 为 2。

b6cd662692d882ffe8724d1dcf5ad277.png

拿免费用户来看,每月 2000 分钟看似也不少。比如笔者个人就是拿来构建下博客静态页面,以及几个简单的应用,每个月也用不了太多。但对于企业或者组织来说,尤其是当流水线的触发频繁(每次代码提交触发)、或者项目的单元测试耗时很长(bug 引起的或者项目本身的复杂度所致),积少成多也会变成一笔不小的开支。

那有没有办法使用自己的资源来运行流水线呢?有。GitHub Actions Runner 分为两种:Github 托管的 Runner 和自托管的 Runner。我们可以将自己的资源作为自托管的 Runner 来运行流水线,而且还可以借助 Kubernetes 的能力来管理这些 Runner。

同时,自托管 Runner 也适合那些对 CI 有更高要求的用户,比如更高性能、更多类型的计算资源等等。

准备工作

Kubernetes 集群

我们使用 k3s 快速创建一个单节点的集群。

export INSTALL_K3S_VERSION=v1.22.11+k3s2
curl -sfL https://get.k3s.io | sh -s - --disable traefik --write-kubeconfig-mode 644 --write-kubeconfig ~/.kube/config

使用 Github Actions 构建的项目

这里使用之前做的一个 graalvm+maven 的基础镜像仓库来进行测试:https://github.com/addozhang/docker-graalvm-maven。

GitHub Access Token

参考文档,创建 Access Token。

注意:鉴于本演示的需要,分配完全的 repo 访问权限。

26ffdac8e6bb6dd07d479384f10d1326.png

access token

创建 Runner

GitHub Actions Runner 的程序源码是开源的,GitHub 托管的 Runner 也是使用该程序运行的。

Runner 可以是某个仓库使用,也可以由组织下的所有仓库共享。鉴于这里演示用的项目,我们为上面提到的项目仓库创建 Runner。

Runner 在启动时,会通过 GitHub API 将自己注册到 GitHub Actions;然后不断发送请求到 GitHub 查看是否分配了流水线作业,如有则会执行流水线作业;Runner 停止运行时,需要进行注销的操作。这里的一系列操作,都会用到上面创建的 Access Token。

要在 Kubernetes 上运行,我们要将 Runner 应用以及上面的逻辑打成镜像,并以 Deployment 的方式部署到 Kubernetes 中。然后通过 workflow 作业 webhook 查看排队的作业数来决定是否增加或者减少 Deployment 的副本数。

听起来就有些复杂,但确实是实现的基本方式。这里我们使用一个 Kubernetes controller actions-runner-controller/actions-runner-controller 来实现所有的流程。

actions-runner-controller 提供了三种 CRD:

  • Runner:可以理解为 Pod,该 Runner 只能执行一次作业。

  • RunnerDeployments:可以理解为 Deployment,可以设置要创建的 Runner 数量。Runner 在执行完作业后会销毁,然后 Controller 会创建新的 Runner 等待作业调度。

  • RunnerSets:可以理解为 StatefulSet,也是基于 StatefulSet 来创建 Pod(即 Runner),提供 StatefulSet 的特性。

更多用法,可以参考 actions-runner-controller 官方文档。

部署 Cert Manager

actions-runner-controller 的运行,需要使用 cert-mananger。通过下面的命令来部署:

kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.8.2/cert-manager.yaml

检查 pod 是否成功启动:

kubectl get pods -n cert-managerNAME                                       READY   STATUS    RESTARTS   AGE
cert-manager-66b646d76-7b9fz               1/1     Running   0          18s
cert-manager-cainjector-59dc9659c7-rzlrl   1/1     Running   0          18s
cert-manager-webhook-7d8f555998-6zkqp      1/1     Running   0          18s

启动 Controller

接下来就是启动 controller,本文发布时的最新版本是 v0.25.0。使用下面的命令部署 controller:

kubectl create -f https://github.com/actions-runner-controller/actions-runner-controller/releases/download/v0.25.0/actions-runner-controller.yaml

注:这里使用的 create 而非 apply。使用 apply 会报类似下面的错误:Error from server (Invalid): error when creating "https://github.com/actions-runner-controller/actions-runner-controller/releases/download/v0.25.0/actions-runner-controller.yaml": CustomResourceDefinition.apiextensions.k8s.io "runnerdeployments.actions.summerwind.dev" is invalid: metadata.annotations: Too long: must have at most 262144 bytes

此时,pod 无法启动,还需要为其创建 Secret 来提供 GitHub Access Token:

export GITHUB_TOKEN=<TOKEN_HERE>
kubectl create secret generic controller-manager \-n actions-runner-system \--from-literal=github_token=${GITHUB_TOKEN}

现在可以看到 pod 可以成功运行:

kubectl get pods -n actions-runner-system
NAME                                  READY   STATUS    RESTARTS   AGE
controller-manager-58c598f64d-27xn6   2/2     Running   0          40s

创建 Runner

执行下面的命令,创建一个名为 building-runner 的 Runner CR。

kubectl apply -f - <<EOF
apiVersion: actions.summerwind.dev/v1alpha1
kind: Runner
metadata:name: building-runner
spec:repository: addozhang/docker-graalvm-mavenenv: []
EOF

此时,会发现 controller 创建了一个同名的 pod:

kubectl get pods -l actions-runner="" -n actions-runner-system
NAME              READY   STATUS    RESTARTS   AGE
building-runner   2/2     Running   0          16s

在仓库的 Settings/Actions/Runners 中可以看到同名的 Runner,处于 idle 状态。

1d100c93cfc6e4b6b971907cc218b1e3.png

runner list

假如此时启动流水线作业,会发现作业并没有调度该 Runner 上。这是因为还没有将作业 Runner 的 label 设置为该 runner 的 label:self-hostedLinux、 X64

修改流水线定义,将 runs-on 指定为 [self-hosted, linux, X64]

5eb93daa371edc4212f268b64532bef7.png

custom labels

然后可以查看作业成功调度到该 runner 上运行:

68fab0babafb04bdc25c88f5537d6b67.png

schedule job

现在再去看 pod 的状态,其中的 runner 容器是 Completed

kubectl get pods -l actions-runner="" -n actions-runner-system
NAME              READY   STATUS     RESTARTS   AGE
building-runner   1/2     Running   0          3m53s

此时,再去触发流水线执行,作业会一直等待可用的 runner 来执行:

70461a63963b387bc9a78749e5e7e002.png

queued job

runner 无法重复使用,怎么办?

可重用 Runner

RunnerDeployment 要派上用场了,前面提到可以将 RunnerDeployments 理解为 Deployment,可以设置要创建的 Runner 数量。Runner 在执行完作业后会销毁,然后 Controller 会创建新的 Runner 等待作业调度。

kubectl apply -f - <<EOF
apiVersion: actions.summerwind.dev/v1alpha1
kind: RunnerDeployment
metadata:name: building-runner
spec:template:spec:repository: addozhang/docker-graalvm-mavenenv: []
EOF

使用上面的命令创建 RunnerDeployment 之后,controller 会创建新的 pod(runner)并得到作业的调度;完成作业的执行后,pod building-runner-9k4cj-ml46v 被销毁,新的 pod building-runner-9k4cj-f8twz 被创建并等待作业的调度:

kubectl get events --sort-by='metadata.creationTimestamp'
...
3m7s        Normal    PodCreated                 runner/building-runner-9k4cj-ml46v         Created pod 'building-runner-9k4cj-ml46v'
3m6s        Normal    Scheduled                  pod/building-runner-9k4cj-ml46v            Successfully assigned actions-runner-system/building-runner-9k4cj-ml46v to ubuntu-dev1
3m7s        Normal    RegistrationTokenUpdated   runner/building-runner-9k4cj-ml46v         Successfully update registration token
3m6s        Normal    Pulling                    pod/building-runner-9k4cj-ml46v            Pulling image "summerwind/actions-runner:latest"
3m3s        Normal    Started                    pod/building-runner-9k4cj-ml46v            Started container docker
3m3s        Normal    Pulled                     pod/building-runner-9k4cj-ml46v            Successfully pulled image "summerwind/actions-runner:latest" in 3.06531539s
3m3s        Normal    Created                    pod/building-runner-9k4cj-ml46v            Created container runner
3m3s        Normal    Started                    pod/building-runner-9k4cj-ml46v            Started container runner
3m3s        Normal    Created                    pod/building-runner-9k4cj-ml46v            Created container docker
3m3s        Normal    Pulled                     pod/building-runner-9k4cj-ml46v            Container image "docker:dind" already present on machine
2m6s        Normal    RegistrationTokenUpdated   runner/building-runner-9k4cj-f8twz         Successfully update registration token
2m6s        Normal    PodCreated                 runner/building-runner-9k4cj-f8twz         Created pod 'building-runner-9k4cj-f8twz'
2m5s        Normal    Scheduled                  pod/building-runner-9k4cj-f8twz            Successfully assigned actions-runner-system/building-runner-9k4cj-f8twz to ubuntu-dev1
2m5s        Normal    Pulling                    pod/building-runner-9k4cj-f8twz            Pulling image "summerwind/actions-runner:latest"
2m5s        Normal    Killing                    pod/building-runner-9k4cj-ml46v            Stopping container docker
2m3s        Normal    Pulled                     pod/building-runner-9k4cj-f8twz            Successfully pulled image "summerwind/actions-runner:latest" in 2.50468863s
2m3s        Normal    Created                    pod/building-runner-9k4cj-f8twz            Created container runner
2m3s        Normal    Started                    pod/building-runner-9k4cj-f8twz            Started container runner
2m3s        Normal    Pulled                     pod/building-runner-9k4cj-f8twz            Container image "docker:dind" already present on machine
2m3s        Normal    Created                    pod/building-runner-9k4cj-f8twz            Created container docker
2m3s        Normal    Started                    pod/building-runner-9k4cj-f8twz            Started container docker

前面创建 RunnerDeployment 的时候没有指定副本数,也就是 runner 的数量,controller 只创建了一个 Runner。假设这个 RunnerDeployment 是某个组织下多个项目共用的,多个项目同时执行作业会怎样?

这里我重新运行 3 个已经完成的作业,模拟作业的并发:

curl -X POST -H "Accept: application/vnd.github+json" -H "Authorization: token ${GITHUB_TOKEN}" https://api.github.com/repos/addozhang/docker-graalvm-maven/actions/runs/2643982502/rerun
curl -X POST -H "Accept: application/vnd.github+json" -H "Authorization: token ${GITHUB_TOKEN}" https://api.github.com/repos/addozhang/docker-graalvm-maven/actions/runs/2643982274/rerun
curl -X POST -H "Accept: application/vnd.github+json" -H "Authorization: token ${GITHUB_TOKEN}" https://api.github.com/repos/addozhang/docker-graalvm-maven/actions/runs/2643982274/rerun

或者 push 几个空的提交到仓库(不推荐,会有 commit 历史。测试项目随意):

git commit --allow-empty -m "trigger action"
git push

去 Actions 列表会发现,只有一个作业在运行,其他两个都是 queued 的等待状态。前面的作业执行完成后,后一个作业才会被执行。

不支持并发?既然是类似 Deployment 的方式运行 runner,那是否有类似 HPA(水平 pod 自动扩缩容)的功能?

自动伸缩

actions-runner-controller 在 3 个 Runner 的 CRD 之外,还提供了类似 HPA 的 CRD HorizontalRunnerAutoscaler,简称 HRA。

HRA 可以根据指标 PercentageRunnersBusy 或者 TotalNumberOfQueuedAndInProgressWorkflowRuns来对 runner 进行扩缩容,或者基于 GitHub Events(webhook)来进行扩缩容。这两种都各有优缺点,前者指标是通过 GitHub API 轮训等待的作业数,实现简单,但时效性差;后者基于事件触发时效性更佳,但是实现复杂,需要对外暴露访问端点接收 GitHub Event。

这里为了演示,使用基于指标的方式进行扩缩容。

kubectl apply -f - <<EOF
apiVersion: actions.summerwind.dev/v1alpha1
kind: HorizontalRunnerAutoscaler
metadata:name: building-runner-autoscaler
spec:scaleDownDelaySecondsAfterScaleOut: 30scaleTargetRef:name: building-runnerminReplicas: 1maxReplicas: 5metrics:- type: PercentageRunnersBusyscaleUpThreshold: '0.75'scaleDownThreshold: '0.25'scaleUpFactor: '2'scaleDownFactor: '0.5'
EOF

还是通过 API 触发作业模拟并发执行,由于轮训间隔比较长(默认 1 分钟),自动扩容需要等待一段时间:

kubectl get pods -l actions-runner="" -n actions-runner-system
NAME                          READY   STATUS    RESTARTS   AGE
building-runner-k6jlc-dk7gc   2/2     Running   0          1m34s
building-runner-k6jlc-pbwnz   2/2     Running   0          54s
building-runner-k6jlc-nlptp   2/2     Running   0          54s

总结

GitHub Actions 是个很强大的 CI 工具,结合自托管的 Runner 可以在付出较低成本的基础上有更好的体验。本文也只是从满足需求的出发,对 “Runner on Kubernetes” 进行了探索。对一个工具从会用到用好,还有很长的路要走。但满足当前需求,已是足矣。

有兴趣的同学可以更进一步思考:

  • 如何限制 Runner 运行时的资源占用

  • 持久化如何实现,比如 Maven 构建时的本地库,Nodejs 的 node_mudules 如何避免重复下载

  • 自动扩缩容能否更加高效

75f28af58f7d8b7496fdc301c8f08c3b.gif

往期推荐

Redis 内存优化神技,小内存保存大数据

使用 nginx 轻松管理 kubernetes 资源文件

Redis 内存满了怎么办?这样置才正确!

实战 Kubectl 创建 Deployment 部署应用

84f222504eabe18b72ad0b8e8143f813.gif

点分享

a3f599b16b02a5c6935bb35adab1808e.gif

点收藏

25a180f78be2fa0f3c4e34f5f9012bd7.gif

点点赞

a685424382967acb4a24fb9c3bc52048.gif

点在看

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/511358.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

将信息系学生的计算机文化学,计算机等级考试(国家)-关系数据库操作语言sql(四)...

计算机等级考试(国家)-关系数据库操作语言sql(四) (8页)本资源提供全文预览&#xff0c;点击全文预览即可全文预览,如果喜欢文档就下载吧&#xff0c;查找使用更方便哦&#xff01;10.90 积分关系数据关系数据库库操作操作语语言言SQL(四四)设计题设计题 在SQL Server 2000中&a…

系统困境与软件复杂度,为什么我们的系统会如此复杂

简介&#xff1a;读 A Philosophy of Software Design 有感&#xff0c;软件设计与架构复杂度&#xff0c;你是战术龙卷风吗&#xff1f; 作者 | 聂晓龙&#xff08;率鸽&#xff09; 来源 | 阿里技术公众号 读 A Philosophy of Software Design 有感&#xff0c;软件设计与架…

节省 58% IT 成本,调用函数计算超过 30 亿次,石墨文档的 Serverless 实践

简介&#xff1a;石墨文档使用函数计算搭建文档实时编辑服务&#xff0c;由函数计算的智能调度系统自动分配执行环境&#xff0c;处理多用户同时编写文档带来的峰值负载&#xff0c;函数计算的动态扩缩容能力保障应用的可靠运行。 作者 | 金中茜 对石墨文档来说&#xff0c;“…

剖析 Netty 内部网络实现原理

作者 | 张彦飞allen来源 | 开发内功修炼Netty 是一个在 Java 生态里应用非常广泛的的网络编程工具包&#xff0c;它在 2004 年诞生到现在依然是火的一塌糊涂&#xff0c;光在 github 上就有 30000 多个项目在用它。所以要想更好地掌握网络编程&#xff0c;我想就绕不开 Netty。…

免费体验,阿里云智能LOGO帮你解决设计难题

简介&#xff1a;超实用&#xff01;零基础搞定一个高大上的智能logo设计 新年过后&#xff0c;往往是大家一年中士气最足的时候&#xff0c;散去了年末的疲惫和emo&#xff0c;重燃对新一年的热情和希望。 想创业的朋友们同样意气风发&#xff0c;趁着新年的劲头想大干一场。…

第十一届吴文俊人工智能科学技术奖颁奖盛典召开,66个项目成果摘得中国智能科学技术奖励最高殊荣

7月16日上午&#xff0c;我国智能科学技术最高奖“吴文俊人工智能科学技术奖”颁奖盛典在北京隆重举行&#xff0c;66个获奖项目及个人受到表彰奖励。中国工程院院士、浙江大学教授潘云鹤荣获“吴文俊人工智能最高成就奖”,并颁授荣誉奖牌和100万人民币奖金。欧洲科学院院士、华…

企业拥抱开源之前,必须了解的七件事

简介&#xff1a;新的时代&#xff0c;开源的发展越来越蓬勃&#xff0c;开源和云的关系越来越复杂&#xff0c;耦合度越来越高&#xff0c;云是开源软件允许的最佳环境之一&#xff0c;也为开源软件插上安全高效的腾飞引擎。本文试图从企业软件的历史&#xff0c;结合开源软件…

荔枝音质高保真AI降噪技术分享

“荔枝音频处理目标就是两个字&#xff1a;清静——清晰、安静。让用户听得更清晰、更真切、更好。”荔枝集团技术副总裁刘晓宇谈及音频技术要攻克的几个难点时一针见血地提到。 随着疫情下直播、在线社交、在线课堂、在线会议等快速发展和元宇宙产业不断壮大&#xff0c;音频…

19年兰州大学计算机分数线,兰州大学2019年在广东省录取分数线

免费申请学习规划请选择在读年级学前小学初中高中大学留学其他已为10472位学员提供学习规划*验证码*短信验证码{"text1":{"label":"薄弱科目","placeholder":"请输入你的薄弱科目","required":1,"formType&q…

最佳实践丨构建云上私有池(虚拟IDC)的5种方案详解

简介&#xff1a;云上私有池系列终篇终于来了&#xff0c;本文将重点介绍构建云上的私有池&#xff08;虚拟IDC&#xff09;的多种方案和各自的优缺点&#xff0c;并给出相关的性价比优化建议。 本文作者&#xff1a;阿里云技术专家李雨前 摘要 围绕私有池&#xff08;虚拟I…

阿里云万郁香:多样付费选择构筑成本最优的弹性体验

简介&#xff1a;云上成本优化三部曲&#xff1a;云上资源归属拆解、确定资源需求及购买优先级、选择最佳的付费方式。 2021年12月21日&#xff0c;阿里云弹性计算年度峰会在上海举行&#xff0c;本次峰会通过全实景直播的形式为大家呈现。峰会上&#xff0c;阿里云弹性计算高…

智能分层、满足更高工作负载,亚马逊云科技加速云端存储服务创新

编辑 | 宋慧 出品 | CSDN 云计算 分布式存储 Amazon S3、弹性计算 Amazon EC2&#xff0c;都是亚马逊云科技的当家产品。在云原生、人工智能、数据分析领域继续发挥技术优势&#xff0c;夯实云技术领先的地位之后&#xff0c;亚马逊云科技在存储领域的研究和发展也没有止步不前…

计算机开机黑屏,开机黑屏,电脑无法进入系统

win10开机进安全模式我相信经常用电脑的童鞋也遇到过这样的问题&#xff0c;就是桌面上什么都没有&#xff0c;电脑也开着。怎么了&#xff1f;通常&#xff0c;不显示桌面有很多原因。如何解决这个问题&#xff1f;等等&#xff0c;别担心&#xff0c;小...相信经常使用电脑的…

最佳实践丨三种典型场景下的云上虚拟IDC(私有池)选购指南

简介&#xff1a;业务上云常态化&#xff0c;业务在云上资源的选购、弹性交付、自助化成为大趋势。不同行业的不同客户&#xff0c;业务发展阶段不一样&#xff0c;云上资源的成本投入在业务整体成本占比也不一样&#xff0c;最小化成本投入、最大化业务收益始终是不同客户间的…

客流量总是少?是你门店选址出了问题!

零售行业最本质的需求就是降本增效、引流提销&#xff0c;实现利润最大化。如何利用大数据、人工智能、云计算、AIOT等前沿技术&#xff0c;助力企业数智化转型&#xff0c;全生态效率提升和可持续发展&#xff0c;是零售企业的核心诉求。 零售行业客流管理的现状 零售行业已进…

大数据领域的专精特新“小巨人”中科闻歌

客户故事 中科闻歌创立于2017年3月。在成立的四年内&#xff0c;它完成了五轮融资&#xff0c;被评为国家级专精特新“小巨人”企业。2020年&#xff0c;中科闻歌与阿里云展开合作&#xff0c;通过云服务器 ECS&#xff08;Elastic Compute Service&#xff09;为核心业务提供底…

计算机网络c类网络划分子网介绍,IP地址的子网划分详解

原标题&#xff1a;IP地址的子网划分详解来源&#xff1a;今日头条北京炫亿时代一、子网划分基础1、子网划分的若干个好处&#xff1a;①减少网络流量②提高网络性能③简化管理④可以更为灵活的形成大覆盖范围的网络2、你最好遵循以下步骤来进行子网划分&#xff1a;①确认所需…

直播回顾:准确性提升到 5 秒级,ssar 独创的 load5s 指标有多硬核?| 龙蜥技术

简介&#xff1a; 你还在为分析机器负载高而苦恼&#xff1f;这款 ssar 工具独创 load5s 指标精准定位超硬核。 编者按&#xff1a;本文整理自龙蜥SIG技术周会&#xff0c;作者闻茂泉&#xff0c;阿里云计算平台事业部SRE运维专家&#xff0c;是龙蜥社区跟踪诊断SIG核心成员…

dos系统重启计算机名,dos系统重启的命令是是

用DOS命令可以实现很多功能&#xff0c;而且有时候这相对于其他方法比较简单易行&#xff0c;下面就让学习啦小编教大家用dos系统重启的命令&#xff0c;还有自动关机和注销等功能。dos系统重启的命令按快捷键“winR”&#xff0c;输入cmd后按回车进入DOS环境&#xff1a;输入命…

如何搭建云原生大数据平台的K8s底座

作者 | 智领云科技云平台研发经理 金津 供稿 | 智领云科技 伴随着数字化转型脚步的加快&#xff0c;大数据已成为企业经营管理的主要手段之一&#xff0c;越来越多的行业也选择通过大数据来实现业绩增长。今年年初&#xff0c;CNCF中国区总监陈泽辉在2022云原生超级英雄会上表…