这篇文章主要讲解了“如何用faas实现issueops”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“如何用faas实现issueops”吧!
创新互联公司主营东港网站建设的网络公司,主营网站建设方案,重庆APP开发,东港h5微信小程序搭建,东港网站营销推广欢迎东港等地区企业咨询
听过chatops,gitops还没听过issueops,顾名思义issueops就是在讨论issue的时候把ops的事给干了,讨论问题就把问题给解决,美哉。
kubernetes项目issue或者PR中会经常看到这样的东西:
类似/kind feature
这样的指令是给机器人看的,这里就要介绍一位非常勤奋的小伙伴了:
他叫k8s-ci-robot,我想没有谁的贡献有他多了吧,这可不是刷出来的,都是实打实的工作量:
收到指令后robot就忙着打标签,验证提问题的有没有cla认证,分配review代码的人等:
然后懒汉们review完代码就又吩咐机器人测试:
小伙伴就一顿操作梦如虎的干了好多事情还不拿年终奖:
以上,企业是不是发现养一个robot胜似招10个员工,是不是比疫情期间面向周报编程程序员靠谱多了~
Prow 就是robot的实现,原理非常简单,就是通过github webhook去监听github产生的事件,分析里面的指令去执行对应的job,它能干的几个重点的事:
执行任务,特别是测试任务
合并代码,你可能觉得这不就是点个按钮的事吗?其实不是,比如一个bug的修复可能要合并到很多个版本中,做起来枯燥且恶心,而且很多时候还是希望合并代码时能做些额外的事,如通知,打标签等等
解析并执行类似/foo
的指令,这很重要基本想干啥都行
一个前端用于显示merge状态,任务等
Prow部署步骤大概如下:
申请一个github账户,给机器人用,推荐用独立的账号
有个k8s集群
配置权限,以及创建secret用于存储github账户的token,调用github SDK需要用
启动prow,就会得到一个http的地址
在你的github仓库里配置,webhook指向prow地址
别忘了我们很穷,在家隔离马上都要失业了服务器都买不起哪来的k8s集群?所以讨论这么多prow有啥用!
接下来白嫖模式开启
我们需要解决两个问题:
免费的计算资源跑http服务,给github webhook调用
一个免费跑job的平台
怎么去找一个免费的http服务?我们自然把恶毒的目光投向函数计算:
阿里云腾讯云都有免费额度,而且这个量对于我这种小任务完全够用了,这个羊毛不薅一把我简直良心不安。
很遗憾阿里云没有默认的golang的函数模板,但是支持自定义环境,只要监听9000端口就行。
对于鄙视UI的我来说在页面上创建函数丢不起这人,命令行工具fun必须要用:
函数配置信息
template.yml:
ROSTemplateFormatVersion: '2015-09-01' Transform: 'Aliyun::Serverless-2018-04-03' Resources: CRService: Type: 'Aliyun::Serverless::Service' Properties: Description: 'custom runtime demo' LogConfig: # 日志配置,需要与日志服务打通,这块对新手体验不是太好 Project: 'sealyun' Logstore: 'robot' Policies: - AliyunLogFullAccess robot: Type: 'Aliyun::Serverless::Function' Properties: Handler: index.handler CodeUri: ./code.zip Description: 'demo with custom runtime' Runtime: custom Events: http_t: Type: HTTP Properties: AuthType: ANONYMOUS Methods: ['GET', 'POST', 'PUT', 'DELETE', 'HEAD'
代码框架,body里就是github传过来的events信息了:
func handler(w http.ResponseWriter, req *http.Request) { b,err := ioutil.ReadAll(req.Body) event := &issue.IssueCommentEvent{} ... } func main() { fmt.Println("FunctionCompute go runtime inited.") http.HandleFunc("/", handler) port := os.Getenv("FC_SERVER_PORT") if port == "" { port = "9000" } http.ListenAndServe(":" + port, nil) }
写个简单脚本去部署函数:
函数启动时只认bootstrap二进制文件,用zip格式打包,fun deploy时会提示一些accesskey相关的配置
go build -o bootstrap faas.go zip code.zip bootstrap fun deploy
部署完你的触发器里就有个地址了:
把这个地址配置到github webhook中
这基本问题就解决了,要注意函数计算日志配置有点小绕,这里不细提了
如果函数计算的自定义环境足够强大,那我们可以直接在函数里去执行一些任务,如编译,测试等,但是这不太友好也不太现实,不友好的地方是自定义环境的方式过于简陋,比如你需要函数中调用git命令,那你只能放zip里一起打包,没有像Dockerfile那样灵活,也没发现哪家能兼容Dockerfile的标准。 还有就是打包的东西太多可能函数的冷启动会很慢。
同样我还希望实现一些功能时不需要对机器人的代码进行变更,只需要修改一些外部配置或者脚本就可以实现不同的任务的处理。如此,drone来也
先介绍一下drone promote事件,允许我们通过http触发pipeline中的一个动作。这个使用场景非常广泛,典型的一个场景:我们的项目编译发布结束之后需要上线,有两个环境,开发环境,测试环境
pipeline配置中:
- name: dev image: golang:1.12 commands: - echo "部署到开发环境" when: event: - promote target: - dev - name: test image: golang:1.12 commands: - echo "部署到测试环境" when: event: - promote target: - test
这样我们想先只在开发环境中部署,那么就执行下面命令:
# drone build promote 项目 build编号 目标 drone build promote fanux/sealos 42 dev
这样dev这个步骤就会被执行,而test不会.
如果你是开源项目,那可以免费的使用drone提供的公有服务,又薅得一手好羊毛 cloud.drone.io
既然是触发promote事件那下载下drone命令行就是了,何必又监听事件,又调用SDK绕一圈? 这就回到最开始的议题:我希望在讨论问题时把问题解决。
我也喜欢把所有东西放在云端,压根不想本地安装drone客户端,而且很多时候我可以在手机上发号施令。而且还希望执行完后能回覆issue执行结果等等
这里使用drone官方sdk即可:
// 创建client config := new(oauth3.Config) auther := config.Client( context.Background(), &oauth3.Token{ AccessToken: d.DroneToken, }, ) client := drone.NewClient(d.DroneServer, auther) // 触发promote事件 _,err := client.Promote(namespace,name,cmd.Build,cmd.Target,cmd.Params)
namespace就是github用户名或者组名,name是仓库名,如 drone/drone-go 项目 drone就是namespace drone-go就是name Params是一个key value的参数,会注入到pipeline的环境变量中,也是非常有用的。
把以上东西写到FaaS中雏形就有了。
最终效果: 回复一下issue
pipeline被执行
当然我希望robot的功能扩展性尽可能好,而且不仅仅能对接drone还可以对接其它的系统,以及扩展别的指令。所以我已经写好了一个框架:robot
只需要写一个特定命令的特定处理器,然后注册到框架中即可:
type Robot interface { Process(event IssueEvent) error }
注意要想Processor生效必须要注册处理器 issue.Regist(命令,处理器)
以drone promote处理器为例:
// 结构体包含drone服务器地址和token type DronePromote struct { DroneServer string DroneToken string } // 实现一下处理器接口 func (d *DronePromote) Process(event issue.IssueEvent) error { ... }
这里event会把issue中的命令解析好丢给你的处理器处理:
type IssueEvent struct { *IssueCommentEvent Command *Command Client *github.Client }
你只需要关心你的处理器要处理啥指令就行,比如使用promote处理器时:
// github 把事件数据以json格式发送过来,已经被解析到event结构体中 func promote(ctx context.Context, event issue.IssueCommentEvent) (string, error) { // or using env: GITHUB_USER GITHUB_PASSWD // github 账户名和密码,因为机器人可能还要回复issue什么的操作,这里建议单独给机器人申请个账号 // 不传参数就会从环境变量中读取 config := issue.NewConfig("sealrobot", "xxx") // regist what robot your need, and the robot config // 注册一下你希望哪个机器人处理,因为一条issue中可能会有很做指令,我们只关心/promote即可 // Drone的处理器需要知道drone的地址和token是什么 issue.Regist("/promote", &drone_promote.DronePromote{"https://cloud.drone.io", "QS3SmhZVpJAmb7tWPuWIOh4BhuI"}) // 处理issue err := issue.Process(config, event) return fmt.Sprintf("goversionecho %s", err), nil }
使用Regist注册你的处理器,这样这个处理器只会处理issue中"/promote ..."的指令:
issue.Regist("/promote", &drone_promote.DronePromote{"https://cloud.drone.io", "QS3SmhZVpJAmb7tWPuWIOh4BhuI"})
感谢各位的阅读,以上就是“如何用faas实现issueops”的内容了,经过本文的学习后,相信大家对如何用faas实现issueops这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是创新互联,小编将为大家推送更多相关知识点的文章,欢迎关注!