原创 吴就业 205 0 2023-10-13
本文为博主原创文章,未经博主允许不得转载。
本文链接:https://wujiuye.com/article/81808166feb2400088f1128c7bc58f18
作者:吴就业
链接:https://wujiuye.com/article/81808166feb2400088f1128c7bc58f18
来源:吴就业的网络日记
本文为博主原创文章,未经博主允许不得转载。
官方提供的工作流步骤有限,另外,对于自研的PaaS平台,我们需要借助工作流步骤实现一些例如存量项目基础设施导入、项目环境初始化、平台组件共享基础设施需要解决的差异对比审核、基础设施漂移等。
由于kubevela以Addon提供安装扩展,因此我们需要用Addon作为自定义工作流步骤的载体,通过Addon安装工作流步骤和升级、卸载工作流步骤。 自定义工作流步骤需要使用CUE语言,并且只能使用语言本身支持的操作和kubevela为我们提供的一系列内置操作。 假设我们自定义一个工作流步骤是调用一个接口做某件事情,如果接口返回0,就是需要暂停工作流步骤等待人工完成审核,如果接口返回1,就是审核通过需要恢复工作流步骤,如果返回2,就是审核被驳回,需要终止工作流。
这里我们需要用到官方提供的3个操作:
另外还需要依赖encoding/json库的序列化和反序列化操作。
apiVersion: core.oam.dev/v1beta1
kind: WorkflowStepDefinition
metadata:
name: custom-ws
namespace: vela-system
spec:
schematic:
cue:
template: |
import (
"vela/op"
"encoding/json"
)
reqBody: {
... // 省略
stepId: ad123213 ## 让接口实现幂等,识别是同一个工作流发出的请求
}
http: op.#HTTPDo & {
method: "POST"
url: parameter.url
request: {
body: json.Marshal(reqBody)
header: "Content-Type": "application/json"
}
}
if http.response.statusCode != 200 {
fail: op.#Fail & {
message: "request of \(parameter.url) is fail: \(http.response.statusCode)"
}
}
if http.response.statusCode == 200 {
response: json.Unmarshal(http.response.body)
if response.code != 0 {
exception: op.#Fail & {
message: "request of \(parameter.url) is fail. code:\(response.code) msg:\(response.msg)"
}
}
## 状态为2失败终止工作流
if response.code == 0 && response.data.status == 2 {
terminated: op.#Fail & {
message: "Manual handle terminated the workflow"
}
}
## 状态为0等待审核
if response.code == 0 && response.data.status == 0 {
diff: op.#Suspend & {
message: "Suspend."
}
}
## 状态为1继续工作流,不需要写什么
}
parameter: {
url: *"http://127.0.0.1:8080/api/custom-ws" | string
}
如果你实践过上面的案例,或者实践过类似案例,那么你应该发现问题了。那就是工作流步骤首先被暂停了一下,然后:如果接口响应2,就立马失败了,我们都没执行vela workflow terminated命令;如果接口响应1,就继续走到下一个工作流步骤了,我们也没执行vela workflow resume命令。看起来就像是暂停方法没被执行一样。
这是因为kubevela执行工作流步骤的原理并不是我们理解的代码执行流程。工作流步骤的代码无法像我们写的go代码一样被kubevela挂起和恢复。工作流步骤的暂停是指不执行后面的代码,而工作流的恢复是指重新执行一次工作流步骤。
当工作流步骤中调用Suspend操作,首先会终止本次工作流的执行,然后修改状态为Suspend。由于controller只要监听到事件,如果工作流状态不是成功或失败或终止,都会执行一次工作流,工作流的未完成步骤也会执行,而被暂停的工作流步骤是未完成状态,因此也会被执行。
当我们执行vela workflow resume命令后,发现被暂停的工作流步骤又被执行一次。
但我们用官方的Suspend工作流步骤并不会重复执行,这是为什么呢。其实只是我们看到的结果是没有重复执行而已。官方文档可能也觉得这个解释起来有些难以用正常的逻辑理解,或者是因此用起来麻烦,因此并没有在参考手册-CUE操作符中给出Suspend这个操作符,我们是通过查看Suspend工作流步骤的定义找到的Suspend这个操作符。
为了解开这个疑惑,我们只能从源码找答案了。
源码位置: - 官方的Suspend工作流步骤定义:https://github.com/kubevela/kubevela/blob/master/charts/vela-core/templates/defwithtemplate/suspend.yaml - cue操作声明:https://github.com/kubevela/workflow/blob/main/pkg/stdlib/actions/v1/op.cue - go代码实现:https://github.com/kubevela/workflow/blob/main/pkg/providers/workspace/workspace.go
我们找到Suspend操作对应的Go语言实现,从上面代码不难看出,该操作通过stepId(每次执行工作流步骤都会生成一个id)确保此步骤只会生效一次,多次执行不会有任务操作,而当执行vela workflow resume命令后,此工作流步骤的状态会变为Running,代码中有这样一句注释:“if it is already suspended before and has been resumed, we should not suspend it again.”。即多次重复执行Suspend操作实际会被忽略,当我们执行vela workflow resume后,重复执行不会导致工作流又被暂停,而是已经暂停过的工作流步骤不会再被执行,继续下一个工作流步骤了。
声明:公众号、CSDN、掘金的曾用名:“Java艺术”,因此您可能看到一些早期的文章的图片有“Java艺术”的水印。
KubeVela于2020年年底开源,距离现在还未满三年时间,是一个非常年轻的产物。KubeVela是非常创新的产物,如OAM模型的抽象设计。所以也并未成熟,除了官方文档,找不到更多资料,在使用过程中,我们也遇到各种大大小小的问题。
由于我们的使用场景是将基础设施资源定义成KubeVela的组件,一个terraform “module”对应的就是一个kubevela的组件,对应terraform-controller的一个Configuration资源。因此导入的最小粒度是组件,即一个terraform “module”。
我们基于KubeVela开发的云原生应用交付平台,提供如初始化基础设施导入、中间件部署共用基础设施等相关能力的测试,需要依赖基础设施。虽然terraform是面向公司内部的混合云平台,但是测试都要跨部门配置效率太低了,而且这种模式无法支持持续测试。
如何Debug Terraform Controller;如何让Configuration可以指向私有仓库;为云资源编写ComponentDefinition;验证流程是否跑通。
terraformProvider、multiclusterProvider、oamProvider、configprovider、kube这些provider的Install方法注册了很多操作处理方法。这些方法就是提供给CUE中调用的方法。
订阅
订阅新文章发布通知吧,不错过精彩内容!
输入邮箱,提交后我们会给您发送一封邮件,您需点击邮件中的链接完成订阅设置。