TT Lab
开始
学习 学习路径 课程

CAPA — Argo 项目认证助理

从事件到工作流,从 Chart 到清单

在 TT Lab 中继续学习

一句话总结

Argo Events 由四个部件运转:EventSource 把外部事件转换成 CloudEvents 并送入 EventBus,Sensor 把它当作依赖来接收并执行 Trigger。Argo CD 只把 Helm 用于通过 helm template 展开(inflate)清单,生命周期由自己管理,并且当 path 中有 kustomization.yaml 时,用 Kustomize 渲染。

为什么需要它

“代码仓库有 push 时就运行流水线”“S3 来了文件就启动处理工作流”这类需求,都是先有事件(event),然后才有执行。工作流引擎本身并不监听事件。Argo Events 负责这一前端环节,从 20 多种事件源(Webhook、S3、计划任务、消息队列、GCP PubSub、SNS、SQS 等)接收事件,并执行 Kubernetes 对象、Argo Workflow 和无服务器工作负载。CAPA 的 Events 领域(12%)考查这四个组件各自负责什么,以及事件按什么顺序流动。

Argo CD 这边的问题不同。团队用 Helm Chart 或 Kustomize overlay 来管理部署物,如果不知道 Argo CD 是怎样把它们变成清单的,就找不到“改了 values 却没有生效”“应用一直 OutOfSync”这类问题的原因。Argo CD 领域(34%)中的 Helm & Kustomize 条目就是这部分内容。

工作原理

Argo Events 的四个部件

组件 作用 文档中的定义
EventSource 接收外部事件,转换为 CloudEvents 后发送到 EventBus 消费 AWS SNS、SQS、PubSub、Webhook 等外部来源事件的配置
EventBus 连接 EventSource 与 Sensor 的传输层 NATS(即将弃用)、Jetstream、Kafka 三种实现
Sensor 事件依赖(输入)与触发器(输出)的集合 监听 EventBus,依赖满足时执行触发器的依赖管理器
Trigger 依赖满足时执行的资源、工作负载 Argo Workflow、K8s 对象、HTTP、Lambda、Kafka/NATS 消息、Slack、Argo Rollouts、Log 等

流程如下。创建 Webhook EventSource 后,会生成 event-source Pod 和 Service(示例使用 12000 端口),向它 POST,事件就会转换成 CloudEvents 并送入 EventBus。Sensor 在 dependencies 中写明在等待“哪个 EventSource 的哪个事件”,在 triggers 中写明要执行什么。被触发的工作流日志中,会同时输出事件的 context(type、source、eventID、time、subject)和经过 base64 编码的 data。通过参数化(parameterization)可以取出事件中的特定键,作为工作流参数传入;通过触发器策略(policy),可以根据被执行对象的状态,决定继续还是停止。

EventBus 是命名空间资源,要让 EventSource 与 Sensor 正常工作,该命名空间中必须有 EventBus。惯例是用 default 这个名称放一个;使用其他名称,或放置多个时,要在 EventSource 和 Sensor 的 spec 中写上 eventBusName 来配对。如果工作流逻辑已经在 WorkflowTemplate 中,Sensor 不必重写步骤,直接提交通过 workflowTemplateRef 引用的 Workflow 即可。

triggers:
- template:
    name: argo-workflow-trigger
    argoWorkflow:
      operation: submit
      source:
        resource:
          apiVersion: argoproj.io/v1alpha1
          kind: Workflow
          metadata: {generateName: from-template-}
          spec:
            workflowTemplateRef: {name: workflow-template-print-message}

Argo CD 与 Helm——只做展开

文档中的一句话是关键:“Helm 只用于通过 helm template 展开 Chart,应用的生命周期由 Argo CD 而不是 Helm 管理。”Helm 仓库中的 Chart 用 source.chart、repoURL、targetRevision 指定(OCI 不带 oci:// 前缀),Git 中的 Chart 用 path 指定。提供 values 的方法有多种,而且优先级是确定的。

낮음  valueFiles  →  values  →  valuesObject  →  parameters  높음
      (여러 파일이면 뒤에 적은 파일이 이김)        (차트의 values.yaml 은 그보다 아래)

该代码块中的韩文注释依次说明:左侧为低优先级,右侧为高优先级;同一项有多个文件时,后写的文件优先;Chart 自带的 values.yaml 优先级比它们都低。

valueFiles 可以写多个,后写的文件覆盖前面的。如果有文件不存在,Helm 会报错,可以用 ignoreMissingValueFiles: true 忽略,用于“默认值 + 有则覆盖”的模式。glob(envs/*.yaml)会按字典序展开,所以建议像 00-defaults.yaml、10-region.yaml 这样用数字前缀表明顺序。其他仓库中的 values 要通过多来源(sources[].ref 与 $ref/path)获取。parameters 相当于 --set,可以用 forceString 强制按字符串处理,fileParameters 则是 --set-file。

有三个陷阱,摘自文档。第一,release 名称默认与 Application 名称相同,用 releaseName 修改后,可能与 Argo CD 为跟踪而添加的 app.kubernetes.io/instance 标签不一致,导致选择器失效。第二,Argo CD 无法区分是首次安装还是升级,所有操作都是 sync,所以 pre-install 和 pre-upgrade 钩子会同时运行。只要定义了一个 Argo CD 钩子,Helm 钩子就会全部被忽略。第三,用 randAlphaNum 生成值的 Chart 每次比较时值都不同,会始终 OutOfSync,所以必须固定这个值。要让 Chart 不安装 CRD,使用 skipCrds: true。

Argo CD 与 Kustomize

repoURL 与 path 所指位置有 kustomization.yaml 时,Argo CD 会用 Kustomize 渲染。要使用 overlay,就把 path 设为 overlay 目录。Application 的 source.kustomize 中可以写 namePrefix、nameSuffix、images(镜像覆盖)、replicas、commonLabels、commonAnnotations、namespace、patches、components(从 2.10 起)等。patches 的运作逻辑与 Kustomization 文件中的 patches 相同,会合并到已有的 patches 中。文档举了与 ApplicationSet 配合使用的例子,展示了不必为每个集群都创建 overlay,而是在模板的 kustomize.patches 中放入生成器属性({{.name}}),一次解决的方法。远程 base 是私有的时,会继承应用仓库的凭据,但无法访问需要其他凭据的仓库。

source:
  path: kustomize-guestbook
  repoURL: https://github.com/argoproj/argocd-example-apps.git
  targetRevision: master
  kustomize:
    patches:
    - target: {kind: Deployment, name: guestbook-ui}
      patch: |-
        - op: replace
          path: /spec/template/spec/containers/0/ports/0/containerPort
          value: 443

在现场相遇的样子

Argo Events 中最常见的第一个故障是“创建了 EventSource 和 Sensor,Pod 却没起来”。文档的排障步骤是:先看 EventSource 和 Sensor 对象的 Status,确认服务账号的 Role/RoleBinding,再看两个控制器的日志。命名空间里没有 EventBus 的话什么都不会运行,所以要先确认这一点。

Argo CD 中会有人问“UI 里看不到全部 values”。文档把它列为已知 bug:UI 只显示 parameters,不显示通过 values/valuesObject 放入的值。渲染本身是准确的,所以值并没有丢,文档给出的变通办法是用 parameters,这样一眼就能看到。

下一项测验要确认什么

测验会问:四个组件的作用、EventBus 的三种实现、EventBus 是命名空间资源这一点以及 eventBusName、Helm values 的优先级与 ignoreMissingValueFiles、修改 releaseName 时的标签问题、钩子与 randAlphaNum 的陷阱、Kustomize 的检测条件与 kustomize.patches。参考:Argo Events Architecture、EventBus、Sensor、Argo CD Helm、Argo CD Kustomize。