argo workflows触发方式

定时触发

类似于 k8s 中的 job 和 cronjob,CronWorkflow 会定时创建 Workflow 来实现定时触发。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
apiVersion: argoproj.io/v1alpha1
kind: CronWorkflow
metadata:
name: test-cron
spec:
workflowMetadata: #元数据,由这个CronWorkflow创建的Workflow都会带有这个labels
labels:
dou: bao
schedule: "* * * * *"
concurrencyPolicy: "Replace"
startingDeadlineSeconds: 0
serviceAccountName: argo
workflowSpec:
entrypoint: whalesay
templates:
- name: whalesay
inputs:
parameters:
- name: message #模板的输入参数
value: cron-test
container:
image: docker/whalesay
command: [cowsay]
args: ["{{inputs.parameters.message}}"] #引用模板的入参

yaml 内容据分析

  • WorkflowSpec :就是 Workflow 的 Spec。
  • Cron Spec:一些 Cron 相关字段,
    • schedule:cron 表达式,* * * * * 每分钟创建一次
    • concurrencyPolicy:并发模式,支持 Allow、Forbid、Replace
      • Allow:允许同时运行多个 Workflow
      • Forbid:禁止并发,有 Workflow 运行时,就不会再创建新的
      • Replace: 表示新创建 Workflow 替换掉旧的,不会同时运行多个 Workflow。
    • startingDeadlineSeconds:Workflow 创建出来到第一个 Pod 启动的最大时间,超时后就会被标记为失败。
    • suspend:flag 是否停止 CronWorkflow,在定时任务不需要执行是可以设置为 true。
    • timezone:时区,默认使用机器上的本地时间
  • WorkflowMetadata:元数据,由这个 CronWorkflow 创建的 Workflow 都会带有这个 labels

Event

argo 提供了一个 Event API:/api/v1/events/{namespace}/{discriminator},此 API 可以接受任意 json 数据。

示例:

1
2
3
curl https://localhost:2746/api/v1/events/argo/ \
-H "Authorization: $ARGO_TOKEN" \
-d '{"message": "hello"}'

或者

1
2
3
curl https://localhost:2746/api/v1/events/argo/my-discriminator \
-H "Authorization: $ARGO_TOKEN" \
-d '{"message": "hello"}'

创建 access token

新建一个 role

1
kubectl create role jenkins --verb=list,update --resource=workflows.argoproj.io

新建一个 sa 账号

1
kubectl create sa jenkins

绑定 role 和 sa 账号

1
kubectl create rolebinding jenkins --role=jenkins --serviceaccount=argo:jenkins -n argo

创建 access token

1
2
3
4
5
6
7
8
9
kubectl apply -f - <<EOF
apiVersion: v1
kind: Secret
metadata:
name: jenkins.service-account-token
annotations:
kubernetes.io/service-account.name: jenkins
type: kubernetes.io/service-account-token
EOF

查看 token 信息

1
2
3
4
root@devops:~/argo/host-data# ARGO_TOKEN="Bearer $(kubectl get secret jenkins.service-account-token -o=jsonpath='{.data.token}' | base64 --decode)"
echo $ARGO_TOKEN
Bearer eyJhbGciOiJSUzI1NiIsImtpZCI6IjFDazhnZ2ozUU1nWGxoUGwtaTMzMGcwc183Q0JzSE5Mc0lUMS1FQmhJcmMifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJkZWZhdWx0Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZWNyZXQubmFtZSI6ImplbmtpbnMuc2VydmljZS1hY2NvdW50LXRva2VuIiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZXJ2aWNlLWFjY291bnQubmFtZSI6ImplbmtpbnMiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC51aWQiOiJiNTk2ZjAzOC01MmJlLTRjMmEtYjAzNi03YmNkNjQzMjMwYjQiLCJzdWIiOiJzeXN0ZW06c2VydmljZWFjY291bnQ6ZGVmYXVsdDpqZW5raW5zIn0.do-IZT-k2-Hx8sk8_R-f8z5RKN0WGBGenYq-hyxszAGy7BXRIUpwdKqBGz48ZZOsJxBixfMjvdWEqeRTSJ870P8yJFHYOROA1exrcR8fWxjiC_VOqii9_bwKEA1z38zumuMpw3NopfZ-oqhRj9f2bucC2Gq3XypIRt5Zlnsb6__Vk8TQMO0rKnuELDNzqF1A6dgPU1ZGu_ZPRCwZNj_2r5bAnlId5mOnUDwCX8BydColtVn0J4GkmYefXRFVjW6C8PPy3lXneLBeofrWDggnsASd5A_J4Gb_gmuScq0GfKLR68QG4phOkFktUcLNUVhwWTVyy4hxNYAsHabSIxaKDw
root@devops:~/argo/host-data#

测试 access token 是否可用,-k 忽略 ssl 校验

1
2
root@devops:~/argo/host-data# curl https://192.168.121.210:30701/api/v1/workflow-event-bindings/default -k -H "Authorization: $ARGO_TOKEN"
{"metadata":{"resourceVersion":"655035"},"items":null}root@devops:~/argo/host-data#

WorkflowEventBinding

为了接收 Event,可以创建 WorkflowEventBinding 对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
apiVersion: argoproj.io/v1alpha1
kind: WorkflowEventBinding
metadata:
name: event-consumer
spec:
event:
# metadata header name must be lowercase to match in selector
selector: payload.message != "" && metadata["x-argo-e2e"] == ["true"] && discriminator == "my-discriminator"
submit:
workflowTemplateRef:
name: my-wf-tmple
arguments:
parameters:
- name: message
valueFrom:
event: payload.message

创建被引用的模板

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
apiVersion: argoproj.io/v1alpha1
kind: WorkflowTemplate
metadata:
name: my-wf-tmple
spec:
templates:
- name: main
inputs:
parameters:
- name: message
value: "{{workflow.parameters.message}}"
container:
image: docker/whalesay:latest
command: [cowsay]
args: ["{{inputs.parameters.message}}"]
entrypoint: main

测试 api 触发 event 来触发 workflow

1
2
3
4
5
6
7
8
9
10
root@devops:~/argo/host-data# curl https://192.168.121.210:30701/api/v1/events/argo/my-discriminator \
-H "Authorization: $ARGO_TOKEN" \
-H "X-Argo-E2E: true" \
-k \
-d '{"message": "hello events"}'
{}root@devops:~/argo/host-datakubectl get workflow -n argo |grep my
my-wf-tmple-4ynl1 Running 6s
my-wf-tmple-84vly Succeeded 60s
my-wf-tmple-w7udm Succeeded 96s
root@devops:~/argo/host-data#

Webhook

Event 可以通过发送 HTTP 请求的方式来触发 Workflow,但是需要客户端提供 AuthToken。

但是 Github、Gitlab 等 Git 仓库配置 Webhook 触发的 hook 是没有 token 的,因此需要额外配置来进行验证,保证 argo 只处理来自 Github、Gitlab 等等平台的 Webhook 请求。

  • 1)创建 RBAC 相关对象,role、rolebinding、sa 准备好 token
  • 2)配置 Webhook-clients,告诉 argo 什么类型的 Webhook 过来使用那个 secret 作为 token

webhook-clients config

新建一个Secret

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
kind: Secret
apiVersion: v1
metadata:
name: argo-workflows-webhook-clients
# The data keys must be the name of a service account.
stringData:
# https://support.atlassian.com/bitbucket-cloud/docs/manage-webhooks/
bitbucket.org: |
type: bitbucket
secret: "my-uuid"
# https://confluence.atlassian.com/bitbucketserver/managing-webhooks-in-bitbucket-server-938025878.html
bitbucketserver: |
type: bitbucketserver
secret: "shh!"
# https://developer.github.com/webhooks/securing/
github.com: |
type: github
secret: "shh!"
# https://docs.gitlab.com/ee/user/project/integrations/webhooks.html
gitlab.com: |
type: gitlab
secret: "shh!"
  • 其中 Key 必须是当前 Namespace 下的 Serviceaccount 名称。
  • Value 则包含 type 和 secret 两部分。
    • type:Webhook 来源,比如 github、gitlab
    • secret:一个字符串,非 k8s secret,一般在对应平台添加 Webhook 时进行配置

以 Github 具体,secret 配置如下:

在添加 Webhook 时可以填一个 Secret 配置,实际就是一串加密字符,随便填什么都可以。

这样 Github 发送 Webhook 请求时就会携带上这个 Secret 信息,Argo 收到后就根据argo-workflows-webhook-clients 的 Secret 里配置的 type=github 的 secret 字段进行对比,如果匹配上就处理,否则就忽略该请求。

如果能匹配上就从对应的 Serviceaccount 中解析 Token 作为 Authorization 信息。

image-20240810180437311