Argo Workflows VolumeClaimGC 详解Workflow 完成后自动清理 PVC 的策略配置与源码剖析【免费下载链接】argo-workflowsWorkflow Engine for Kubernetes项目地址: https://gitcode.com/gh_mirrors/ar/argo-workflows本篇文章以 Argo Workflows 的VolumeClaimGCAPI 类型为线索深入讲解如何在 Workflow 结束后自动回收由volumeClaimTemplates动态创建的持久卷声明PersistentVolumeClaimPVC。读完本文你将掌握volumeClaimGC.strategy两种策略OnWorkflowCompletion与OnWorkflowSuccess的语义差异、默认行为、实际 YAML 配置方式以及控制器底层删除 PVC 的实现逻辑与测试验证方法。一、为什么需要 VolumeClaimGC在 Argo Workflows 中你可以通过 Workflow 级别的volumeClaimTemplates字段为任务动态申请持久化存储。控制器会在 Workflow 运行时为每个模板创建对应的 PVC并将其挂载到 Pod 中。这些 PVC 的生命周期默认与所属 Workflow 绑定通过 ownerReference 关联。问题在于Workflow 结束后这些 PVC 并不会自动消失。如果不做清理每次运行都会遗留一批 PVC日积月累会耗尽集群存储配额、产生费用也增加运维负担。为此Argo Workflows 在WorkflowSpec中提供了volumeClaimGC字段专门描述如何从已完成的 Workflow 中删除卷PVC。从源码看该字段定义在WorkflowSpec中位于 pkg/apis/workflow/v1alpha1/workflow_types.go// VolumeClaimGC describes the strategy to use when deleting volumes from completed workflows VolumeClaimGC *VolumeClaimGC json:volumeClaimGC,omitempty protobuf:bytes,36,opt,namevolumeClaimGC,casttypeVolumeClaimGC与之对应的 CRD schema 也同步生成于 manifests/base/crds/full/argoproj.io_workflows.yamlWorkflow、WorkflowTemplate、CronWorkflow、ClusterWorkflowTemplate 四类资源的 CRD 中均有volumeClaimGC定义。二、VolumeClaimGC 结构唯一的 strategy 字段Java SDK 生成的 API 文档即本文依据的原始文档sdks/java/client/docs/IoArgoprojWorkflowV1alpha1VolumeClaimGC.md指出VolumeClaimGC类型只包含一个属性其字段结构如下名称类型描述备注strategyString回收策略取值只能是OnWorkflowCompletion或OnWorkflowSuccess默认值为OnWorkflowSuccess可选字段对应的 Go 类型定义位于 pkg/apis/workflow/v1alpha1/workflow_types.go// VolumeClaimGC describes how to delete volumes from completed Workflows type VolumeClaimGC struct { // Strategy is the strategy to use. One of OnWorkflowCompletion, OnWorkflowSuccess. Defaults to OnWorkflowSuccess Strategy VolumeClaimGCStrategy json:strategy,omitempty protobuf:bytes,1,opt,namestrategy,casttypeVolumeClaimGCStrategy }而VolumeClaimGCStrategy是一个字符串枚举类型两个合法的取值定义在同文件 workflow_types.go// VolumeClaimGCStrategy is the strategy to use when deleting volumes from completed workflows type VolumeClaimGCStrategy string const ( VolumeClaimGCOnCompletion VolumeClaimGCStrategy OnWorkflowCompletion VolumeClaimGCOnSuccess VolumeClaimGCStrategy OnWorkflowSuccess )此外VolumeClaimGC还提供了便捷方法GetStrategy()当strategy未设置时返回默认值OnWorkflowSuccess见 workflow_types.go。三、两种策略的语义与默认行为3.1OnWorkflowSuccess默认PVC 只在 Workflow成功Succeeded时被删除。如果 Workflow 失败Failed或出错ErrorPVC 会被保留下来。这样设计的核心动机是为重试复用存储失败的 Workflow 往往会被 retry/resubmit保留 PVC 可以继续使用其中已经写入的数据如中间产物、断点数据避免数据丢失。3.2OnWorkflowCompletion只要 Workflow进入终态Completed即成功、失败或出错无论结果如何都会删除 PVC。适合对数据不敏感、用完即弃的场景。3.3 未配置时的默认行为如果在 Workflow spec 中完全没有设置volumeClaimGC控制器会按OnWorkflowSuccess处理。这一点由WorkflowSpec.GetVolumeClaimGC()方法保证workflow_types.go// GetVolumeClaimGC returns the VolumeClaimGC that was defined in the workflow spec. If none was provided, a default value is returned. func (wfs WorkflowSpec) GetVolumeClaimGC() *VolumeClaimGC { // If no volumeClaimGC strategy was provided, we default to the equivalent of OnSuccess // to match the existing behavior for back-compat if wfs.VolumeClaimGC nil { return VolumeClaimGC{Strategy: VolumeClaimGCOnSuccess} } return wfs.VolumeClaimGC }注意源码注释中的back-compat也就是说在引入volumeClaimGC字段之前Argo Workflows 的既有行为就是在 Workflow 成功时清理 PVC默认值的选择是为了保持向后兼容避免破坏老用户的工作流。四、控制器底层实现deletePVCs 的执行逻辑真正执行 PVC 删除的是 workflow-controller 中wfOperationCtx.deletePVCs()方法位于 workflow/controller/operator.gofunc (woc *wfOperationCtx) deletePVCs(ctx context.Context) error { gcStrategy : woc.execWf.Spec.GetVolumeClaimGC().GetStrategy() switch gcStrategy { case wfv1.VolumeClaimGCOnSuccess: if woc.wf.Status.Phase ! wfv1.WorkflowSucceeded { // Skip deleting PVCs to reuse them for retried failed/error workflows. // PVCs are automatically deleted when corresponded owner workflows get deleted. return nil } case wfv1.VolumeClaimGCOnCompletion: default: return fmt.Errorf(unknown volume gc strategy: %s, gcStrategy) } ... }这段代码揭示了两个关键事实OnWorkflowSuccess的判定只有woc.wf.Status.Phase WorkflowSucceeded时才会继续删除流程否则直接返回。注释明确说明跳过删除是为了在重试失败/出错的 Workflow 时复用 PVC且这些 PVC 会随所属 Workflow 被删除ownerReference 机制而自动清理。OnWorkflowCompletion不做阶段判断无论最终阶段是成功、失败还是错误都会进入后续的删除逻辑未知的策略值会直接返回错误unknown volume gc strategy。继续往下看operator.go删除过程会遍历woc.wf.Status.PersistentVolumeClaims列表逐个调用 Kubernetes 客户端删除 PVC并记录第一个遇到的错误totalPVCs : len(woc.wf.Status.PersistentVolumeClaims) if totalPVCs 0 { // PVC list already empty. nothing to do return nil } pvcClient : woc.controller.kubeclientset.CoreV1().PersistentVolumeClaims(woc.wf.Namespace) newPVClist : make([]apiv1.Volume, 0) // Attempt to delete all PVCs. Record first error encountered var firstErr error for _, pvc : range woc.wf.Status.PersistentVolumeClaims { woc.log.WithField(pvcName, pvc.PersistentVolumeClaim.ClaimName).Info(ctx, deleting pvc) err : pvcClient.Delete(ctx, pvc.PersistentVolumeClaim.ClaimName, metav1.DeleteOptions{}) if err ! nil { if !apierr.IsNotFound(err) { // 删除失败保留在列表中以便后续重试并记录第一个错误 newPVClist append(newPVClist, pvc) ... } } }其中Status.PersistentVolumeClaims是控制器在 PVC 创建成功后被追加到 Workflow 状态中的卷列表见 operator.go也是 Workflow 完成后能够精确找到自己创建的 PVC 的依据。apierr.IsNotFound(err)的处理意味着如果某个 PVC 已经被删除例如被外部清理控制器不会把它当作错误而是静默跳过。此外删除前如果环境变量ARGO_REMOVE_PVC_PROTECTION_FINALIZER未设置为false控制器还会主动移除 PVC 上的kubernetes.io/pvc-protectionfinalizer以避免 PVC 因保护机制卡在 Terminating 状态无法被真正删除见 operator.go。五、实战配置YAML 示例与逐步说明下面是一个完整可运行的配置示例结构与控制器单元测试TestVolumeGCStrategy中使用的 Workflow 模板一致见 workflow/controller/operator_test.goapiVersion: argoproj.io/v1alpha1 kind: Workflow metadata: name: workflow-with-volumes spec: entrypoint: workflow-with-volumes volumeClaimGC: strategy: OnWorkflowCompletion # 或 OnWorkflowSuccess默认值 volumeClaimTemplates: - metadata: name: claim-vol spec: accessModes: [ ReadWriteOnce ] resources: requests: storage: 1Gi volumes: - name: existing-vol persistentVolumeClaim: claimName: my-existing-volume templates: - name: workflow-with-volumes script: image: python:alpine3.23 command: [python] volumeMounts: - name: claim-vol mountPath: /mnt/vol - name: existing-vol mountPath: /mnt/existing-vol source: | print(hello world)配置要点说明spec.volumeClaimGC.strategy选择回收策略合法值仅OnWorkflowCompletion与OnWorkflowSuccess省略时等价于OnWorkflowSuccess。spec.volumeClaimTemplates声明需要动态创建的 PVC 模板控制器会为每个模板创建名为workflow-name-template-name的 PVC如上述示例中的workflow-with-volumes-claim-vol并在 Workflow 状态中登记。spec.volumes可以同时挂载外部已有的 PVC如上例的my-existing-volume。需要注意VolumeClaimGC 只删除由volumeClaimTemplates动态创建、并登记在Status.PersistentVolumeClaims中的 PVC不会删除用户预先创建的外部 PVC避免误删共享存储。该字段同样适用于 WorkflowTemplate、CronWorkflow 与 ClusterWorkflowTemplate 中的 Workflow spec 部分SDK 文档 IoArgoprojWorkflowV1alpha1WorkflowSpec.md 也列出了volumeClaimGC为可选属性。在 WorkflowTemplate 与 Workflow 合并时volumeClaimGC属于被合并的字段之一见 workflow/util/merge.go因此可以在模板中预设回收策略再由具体 Workflow 覆盖。六、测试验证四种组合的行为矩阵控制器单元测试 workflow/controller/operator_test.go 的TestVolumeGCStrategy用表驱动的方式覆盖了策略 × 最终阶段的四种组合是理解 VolumeClaimGC 语义最直接的证据测试用例名称strategyWorkflow 最终阶段期望剩余 PVC 数failed / OnWorkflowCompletionOnWorkflowCompletionFailed0已删除failed / OnWorkflowSuccessOnWorkflowSuccessFailed1保留succeeded / OnWorkflowSuccessOnWorkflowSuccessSucceeded0已删除succeeded / OnWorkflowCompletionOnWorkflowCompletionSucceeded0已删除测试的核心断言是assert.Len(t, wf.Status.PersistentVolumeClaims, tt.expectedVolumesRemaining)——通过比较 Workflow 操作完成后Status.PersistentVolumeClaims列表的长度来验证 PVC 是否被清理。注意表中保留的用例其 PVC 并不会永久存在而是依赖 ownerReference当所属 Workflow 被删除时Kubernetes 会自动级联删除这些 PVC这也是源码注释中强调的兜底机制。七、与 PodGC、ArtifactGC、TTL 的定位差异volumeClaimGC与 Workflow 级别的其他回收机制同属生命周期资源清理体系但针对的对象和触发时机各不相同从 pkg/apis/workflow/v1alpha1/workflow_types.go 可以对照总结回收机制清理对象策略取值默认行为volumeClaimGC由 volumeClaimTemplates 创建的 PVCOnWorkflowCompletion/OnWorkflowSuccessOnWorkflowSuccesspodGC已完成的 PodOnPodCompletion/OnPodSuccess/OnWorkflowCompletion/OnWorkflowSuccess等不设置则不清除 PodartifactGC输出产物ArtifactsOnWorkflowCompletion/OnWorkflowSuccess/OnWorkflowDeletion/Never等策略未定义ttlStrategy整个 Workflow 资源按成功/失败后的存活秒数不设置则不过期实际使用时可根据存储成本与数据复用需求组合配置例如希望失败可重试、成功即清理保持默认OnWorkflowSuccess即可若存储昂贵、失败也不打算复用数据则显式设置OnWorkflowCompletion。八、注意事项与最佳实践默认值即最佳实践多数批处理场景下Workflow 成功后清理、失败后保留供重试正是OnWorkflowSuccess的语义因此不配置volumeClaimGC通常就已足够。失败重试依赖 PVC 保留如果为失败 Workflow 配置了OnWorkflowCompletion重试时将无法复用上次写入的卷数据请确认业务是否依赖中间结果。外部 PVC 不受影响VolumeClaimGC 只清理 Workflow 自己动态创建的 PVC共享或预置的 PVC 需要自行管理生命周期。删除是尽力而为的删除过程中会记录错误并保留未删成功的 PVC 条目以便后续重试不会阻塞 Workflow 终态推进同时控制器默认会移除 PVC 保护 finalizer可参考环境变量ARGO_REMOVE_PVC_PROTECTION_FINALIZER控制该行为设为false可关闭。Java SDK 对应类型在 Java 客户端中使用时对应模型类为IoArgoprojWorkflowV1alpha1VolumeClaimGC其唯一公开属性strategy为String类型可参考 IoArgoprojWorkflowV1alpha1VolumeClaimGC.md 的字段说明进行赋值。通过上述配置与源码印证你可以精准控制 Argo Workflows 中动态卷的生命周期在存储成本与数据复用之间找到适合自己业务的平衡点。【免费下载链接】argo-workflowsWorkflow Engine for Kubernetes项目地址: https://gitcode.com/gh_mirrors/ar/argo-workflows创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考