https://github.com/devops-ws/argo-workflows-guide
Argo Workflows Guide
https://github.com/devops-ws/argo-workflows-guide
argo-workflows guide
Last synced: 7 months ago
JSON representation
Argo Workflows Guide
- Host: GitHub
- URL: https://github.com/devops-ws/argo-workflows-guide
- Owner: devops-ws
- License: mit
- Created: 2022-12-09T01:00:05.000Z (almost 3 years ago)
- Default Branch: master
- Last Pushed: 2024-05-14T02:47:23.000Z (over 1 year ago)
- Last Synced: 2025-01-16T02:17:15.746Z (9 months ago)
- Topics: argo-workflows, guide
- Language: Dockerfile
- Homepage: https://devops-ws.github.io/argo-workflows-guide/
- Size: 91.8 KB
- Stars: 27
- Watchers: 1
- Forks: 8
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
[Argo Workflows](https://argoproj.github.io/argo-workflows/) 是一个[云原生](https://en.wikipedia.org/wiki/Cloud-native_computing)的通用的工作流引擎。本教程主要介绍如何用其完成持续集成(Continous Integration, CI)任务。
## 基本概念
对任何工具的基本概念有一致的认识和理解,是我们学习以及与他人交流的基础。以下是本文涉及到的概念:
* WorkflowTemplate,工作流模板
* Workflow,工作流为方便读者理解,下面就几个同类工具做对比:
| Argo Workflow | Jenkins |
|---|---|
| WorkflowTemplate | Pipeline |
| Workflow | Build |## 最佳实践
* 把所有 Workflow YAML 文件存到一个 Git 仓库(例如:`infra/workflows`)中,并利用 [Argo CD](https://github.com/devops-ws/argo-cd-guide) 同步到 Kubernetes 集群
* 团队之间共用的部分封装为 `ClusterWorkflowTemplate`## 安装
首先,你需要有一套 [Kubernetes](https://github.com/kubernetes/kubernetes/) 环境。下面的工具可以帮助你快速按照好一套 Kubernetes 环境:> 推荐使用 [hd](https://github.com/LinuxSuRen/http-downloader) 安装下面的工具
>
> 安装 `hd` 的命令为:`curl https://linuxsuren.github.io/tools/install.sh|bash`| 工具 | 工具安装 |使用 |
|---|---|---|
| [k3d](https://k3d.io/) | `hd i k3d` | `k3d cluster create` |
| [kubekey](https://github.com/kubesphere/kubekey) | `hd i kk` | `kk create cluster` |
| [minikube](https://github.com/kubernetes/minikube) | `hd i minikube` | `minikube start` |当 Kubernetes 环境就绪后,就可以通过下面的命令会在命名空间(`argo`)下安装最新版本的 `Argo Workflow`:
```shell
kubectl create namespace argo
kubectl apply -n argo -f https://github.com/argoproj/argo-workflows/releases/latest/download/install.yaml
```如果你的环境访问 GitHub 时有网络问题,可以使用下面的命令来安装:
```shell
docker run -it --rm -v $HOME/.kube/:/root/.kube --network host --pull always ghcr.io/linuxsuren/argo-workflows-guide:master
```推荐使用的工具:
|||
|---|---|
| [k9s](https://k9scli.io/) | K9s is a terminal based UI to interact with your Kubernetes clusters. |## 设置访问方式
我们可以用下面的方式或者其他方式来设置 Argo Workflows 的访问端口:```shell
kubectl -n argo port-forward deploy/argo-server --address 0.0.0.0 2746:2746
# 或者设置为 NodePort
kubectl -n argo patch svc argo-server --type='json' -p '[{"op":"replace", "path":"/spec/type", "value":"NodePort"}, {"op":"add", "path":"/spec/ports/0/nodePort","value":31517}]'
# 暴露 k3d 端口
k3d node edit k3d-k3s-default-serverlb --port-add 31517:31517
```> 需要注意的是,这里默认的配置下,服务器设置了自签名的证书提供 HTTPS 服务,因此,确保你使用 `https://` 协议进行访问。
例如,地址为:`https://10.121.218.242:2746/`
Argo Workflows UI 提供了多种认证登录方式,对于学习、体验等场景,我们可以通过下面的命令直接设置绕过登录:
```shell
kubectl patch deployment \
argo-server \
--namespace argo \
--type='json' \
-p='[{"op": "replace", "path": "/spec/template/spec/containers/0/args", "value": [
"server",
"--auth-mode=server"
]}]'
```## 简单示例
下面是一个非常简单的示例:
```shell
cat < /proc/sys/user/max_user_namespaces
```除了 `buildkit` 以外,也可以考虑使用 `kaniko`(你可以从 [library.yaml](templates/library.yaml)中找到对应的配置)。
### 小结
在上面的例子中,有如下几点需要注意的:* 采用 buildkit 构建镜像,避免挂载本地 Docker 的 `/var/run/docker.sock` 文件
* 上面的例子,在 Kubernetes 集群不以 Docker 作为[容器运行](https://kubernetes.io/docs/setup/production-environment/container-runtimes/)时也能正常使用
* 在实际使用过程中,有遇到过 buildkit 报错的情况,可以考虑增加重试机制进一步保障构建成功
* `registry.insecure=true` 这个参数对于私有化环境中没有证书的情况非常重要
* buildkit 还支持缓存持久化,从而加快构建速度,有兴趣的朋友可以翻阅官方文档,或帮助完善这里的例子
* Go 缓存代理是可选的,但推荐在内网中部署以加快依赖下载速度## 循环任务
Argo Workflow 的 [Loop](https://argoproj.github.io/argo-workflows/walk-through/loops/) 功能,可以简化重复的任务,方便维护。以下是一个例子:```shell
cat < /tmp/version' # 将期望输出的内容写入文件
outputs:
parameters:
- name: version
valueFrom:
path: /tmp/version # 读取容器中的文件,并作为内容输出到变量 version 中
- name: print
inputs:
parameters:
- name: version # 定义输入变量
container:
image: alpine
command:
- sh
- -c
- 'echo {{inputs.parameters.version}}'
EOF
```## Webhook
所有主流 Git 仓库都是支持 webhook 的,借助 webhook 可以当代码发生变化后实时地触发工作流的执行。Argo Workflows 利用 `WorkflowEventBinding` 将收到的 webhook 请求与 WorkflowTemplate 做关联。请参考下面的例子:
```shell
cat < values.yaml < \dt
List of relations
Schema | Name | Type | Owner
--------+--------------------------------+-------+-------
public | argo_archived_workflows | table | root
public | argo_archived_workflows_labels | table | root
public | argo_workflows | table | root
public | schema_history | table | root
(4 rows)app_db=> select name,phase from argo_archived_workflows;
name | phase
--------------+-----------
plugin-pl6rx | Succeeded
plugin-8gs7c | Succeeded
```## GC
Argo Workflows 有个工作流执行记录(Workflow)的清理机制,也就是 Garbage Collect(GC)。GC 机制可以避免有太多的执行记录,
防止 Kubernetes 的后端存储 Etcd 过载。我们可以在 ConfigMap 中配置期望保留的工作执行记录数量,这里支持为不同状态的执行记录设定不同的保留数量。配置方法如下:
```yaml
apiVersion: v1
data:
retentionPolicy: |
completed: 3
failed: 3
errored: 3
kind: ConfigMap
metadata:
name: workflow-controller-configmap
namespace: argo
```需要注意的是,这里的清理机制会将多余的 Workflow 资源从 Kubernetes 中删除。如果希望能更多历史记录的话,建议启用并配置好归档功能。
除了工作流有回收清理机制外,也可以针对 Pod 设置回收机制,参考配置如下:
```yaml
apiVersion: argoproj.io/v1alpha1
kind: WorkflowTemplate
metadata:
name: hello-world # Name of this Workflow
namespace: default
spec:
podGC:
strategy: OnPodCompletion
```清理策略的可选值包括:
* `OnPodCompletion`
* `OnPodSuccess`
* `OnWorkflowCompletion`
* `OnWorkflowSuccess`建议 PodGC 与日志持久化配合使用,不然可能会由于 Pod 被删除后无法查看工作流日志。
## 可观测
Argo Workflows 支持通过 Prometheus 采集监控指标,包括:[预定义、自定义](https://argoproj.github.io/argo-workflows/metrics/)的指标,下面是添加自定义指标的示例:```yaml
spec:
metrics:
prometheus:
- name: exec_duration_gauge
labels:
- key: name
value: '{{workflow.name}}' # 工作流名称
- key: templatename
value: '{{workflow.labels.workflows.argoproj.io/workflow-template}}' # 工作流模板名称
- key: namespace
value: '{{workflow.namespace}}' # 工作流所在命名空间
help: Duration gauge by name
gauge:
value: '{{workflow.duration}}' # 工作流执行时长
- counter:
value: "1"
help: "Total count of all the failed workflows"
labels:
- key: name
value: '{{workflow.name}}'
- key: namespace
value: '{{workflow.namespace}}'
- key: templatename
value: '{{workflow.labels.workflows.argoproj.io/workflow-template}}'
name: failed_count
when: '{{workflow.status}} == Failed'
- counter:
value: "1"
help: "Total count of all the successed workflows"
labels:
- key: name
value: '{{workflow.name}}'
- key: namespace
value: '{{workflow.namespace}}'
- key: templatename
value: '{{workflow.labels.workflows.argoproj.io/workflow-template}}'
name: successed_count
when: '{{workflow.status}} == Succeeded'
- counter:
value: "1"
help: "Total count of all the workflows"
labels:
- key: name
value: '{{workflow.name}}'
- key: namespace
value: '{{workflow.namespace}}'
- key: templatename
value: '{{workflow.labels.workflows.argoproj.io/workflow-template}}'
name: total_count
```上面包含了工作流的成功、失败、总量的数据指标。
## 工作流默认配置
在实际场景下,我们往往需要配置不少的工作流模板,而这些模板中也通常会有一些通用的配置项,例如:
拉取私有镜像的凭据、Pod 回收策略、卷挂载等待。我们可以把这些公共配置加到 ConfigMap 中,请参考如下:```yaml
apiVersion: v1
data:
workflowDefaults: |
spec:
podGC:
strategy: OnPodCompletion # Pod 完成后即删除
imagePullSecrets:
- name: harbor-pull # 公共的私有镜像拉取凭据
volumeClaimTemplates: # 默认的代码拉取卷位置
- metadata:
name: work
spec:
accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: 64Mi
kind: ConfigMap
metadata:
name: workflow-controller-configmap
namespace: argo
```## Golang SDK
Argo Workflows 官方[维护了 Golang、Java、Python 语言](https://argoproj.github.io/argo-workflows/client-libraries/)的 SDK。下面以 Golang 为例,讲解 SDK 的使用方法。在运行下面的示例前,有两点需要注意的:
* Argo Workflows Server 地址
* Token你可以选择直接使用 `argo-server` 的 Service 地址,将端口 `2746` 转发到本地,或将 Service 修改为 `NodePort`,或者其他方法暴露端口。也可以执行下面的命令,再启动一个 Argo 服务:
```shell
argo server
```第二个,就是用户认证的问题了。如果你对 Kubernetes 认证系统非常熟悉的话,可以跳过这一段,直接找一个 Token。为了让你对 Argo 的用户认证更加了解,我们为下面的测试代码创建一个新的 ServiceAccount。
我们需要分别创建:
* Role,规定可以对哪些资源有哪些操作权限
```shell
kubectl create role demo --verb=get,list,update,create --resource=workflows.argoproj.io --resource=workflowtemplates.argoproj.io -n default
```* ServiceAccount,代表一个用户
```shell
kubectl create serviceaccount demo -n default
```* RoleBinding,将用户和角色(Role)进行绑定
```shell
kubectl create rolebinding demo --role=demo --serviceaccount=default:demo -n default
```* Secret,关联一个 ServiceAccount,并自动生成 Token
```shell
kubectl apply -n default -f - < 上面的例子中,我们使用的是 `Role` 和 `RoleBinding` ,这样的角色只能允许访问所在命名空间(namespace)的资源。上面创建的用户,只能够访问 `default` 这命名空间下的 `Workflow` 和 `WorkflowTemplate` 。
> 如果想要创建一个全局的角色以及绑定,可以使用 `ClusterRole` 和 `ClusterRoleBinding` 。上面的用户创建完成后,我们就可以通过下面的命令拿到指定权限的 `Token` 了:
```shell
kubectl get secret -n default demo.service-account-token -ojsonpath={.data.token}|base64 -d
```接下来,创建一个 Golang 工程,并将下面的示例代码拷贝到源文件 `main.go` 中。
```shell
mkdir demo
cd demo
go mod init github.com/linuxsuren/demo
go get github.com/argoproj/argo-workflows/v3@v3.4.4
go mod tidy
```示例代码:
```golang
package mainimport (
"fmt"
"github.com/argoproj/argo-workflows/v3/pkg/apiclient"
"github.com/argoproj/argo-workflows/v3/pkg/apiclient/workflow"
"github.com/argoproj/argo-workflows/v3/pkg/apiclient/workflowtemplate"
"github.com/argoproj/argo-workflows/v3/pkg/apis/workflow/v1alpha1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)/**
** Before run this demo, please create a parameterless WorkflowTemplate in namespace default.
** In this demo, we will print all the WorkflowTemplates in namespace default.
** Then run a Workflow base on the first WorkflowTemplate.
*/func main() {
opt := apiclient.Opts{
ArgoServerOpts: apiclient.ArgoServerOpts{
URL: "localhost:31808", // argo-server address
Path: "/",
Secure: true,
InsecureSkipVerify: true,
},
AuthSupplier: func() string {
return "Bearer your-token"
},
}
ctx, client, err := apiclient.NewClientFromOpts(opt) // the context will carry on auth
if err != nil {
panic(err)
}wftClient, err := client.NewWorkflowTemplateServiceClient()
if err != nil {
fmt.Println("failed to get the WorkflowTemplates client", err)
return
}
defaultNamespace := "default"fmt.Println("get the WorkflowTemplate list from", defaultNamespace)
wftList, err := wftClient.ListWorkflowTemplates(ctx, &workflowtemplate.WorkflowTemplateListRequest{
Namespace: defaultNamespace,
})
if err != nil {
fmt.Println("failed to list WorkflowTemplates", err)
return
}
for _, wft := range wftList.Items {
fmt.Println(wft.Namespace, wft.Name)
}if wftList.Items.Len() > 0 {
wft := wftList.Items[0]wfClient := client.NewWorkflowServiceClient()
_, err := wfClient.CreateWorkflow(ctx, &workflow.WorkflowCreateRequest{
Namespace: defaultNamespace,
Workflow: &v1alpha1.Workflow{
ObjectMeta: metav1.ObjectMeta{
GenerateName: wft.Name,
},
Spec: v1alpha1.WorkflowSpec{
WorkflowTemplateRef: &v1alpha1.WorkflowTemplateRef{
Name: wft.Name,
},
},
},
})
if err != nil {
fmt.Println("failed to create workflow", err)
}
}
}
```最后,执行命令:`go run .`
> 把上面的示例代码编译后,二进制文件大致在 60M+
## References
* [DevOps Practice Guide](https://github.com/LinuxSuRen/devops-practice-guide)
* [Argo CD Guide](https://github.com/LinuxSuRen/argo-cd-guide)
* [Argo Rollouts Guide](https://github.com/LinuxSuRen/argo-rollouts-guide)
* [更多场景下的模板样例](templates/README.md)