ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Argo CD Sync Wave 清理顺序实战:syncwaves-prune-order 端到端测试与反向 Prune 原理解析

Argo CD Sync Wave 清理顺序实战:syncwaves-prune-order 端到端测试与反向 Prune 原理解析 Argo CD Sync Wave 清理顺序实战syncwaves-prune-order 端到端测试与反向 Prune 原理解析【免费下载链接】argo-cdDeclarative Continuous Deployment for Kubernetes项目地址: https://gitcode.com/GitHub_Trending/ar/argo-cd本篇围绕 Argo CD 端到端测试数据目录test/e2e/testdata/syncwaves-prune-order展开讲解 Sync Wave同步波次机制在资源清理prune阶段如何按创建顺序的逆序执行删除并通过一个带 finalizer 的 Pod 构造出顺序错误即卡死 Terminating的强校验场景。读完本文你将理解同步波次如何控制创建顺序、反向 prune 的源码实现位置、如何设计能暴露顺序错误的删除依赖测试以及该 e2e 测试的完整执行链路。1. 测试场景用顺序依赖验证反向 Prune该目录下的 README.md 定义了测试的核心思想This test example is for testing the reverse pruning of resources with syncwaves during sync operation.即同步时资源按 wave 从小到大创建prune 时必须按 wave 从大到小创建逆序删除。具体设定为阶段Wave资源说明创建wave 0ServiceAccount Role权限基础最先创建创建wave 1RoleBinding将权限绑定到 SA创建wave 2Pod携带 finalizer最后创建清理wave 2Pod必须第一个删除清理wave 1RoleBinding第二个删除清理wave 0ServiceAccount Role最后删除README 指出了该场景的校验机制如果删除顺序不满足上述逆序Pod 会因一个由 Kubernetes 容器生命周期钩子container lifecycle hook负责移除的 finalizer 而卡在 Terminating 状态。换言之只要 e2e 测试最终断言Pod 成功消失且操作成功就反向证明了 prune 顺序是正确的——这是一种把删除依赖转化为可观测故障的测试设计。2. 资源文件解析权限链路与 finalizer 陷阱该测试目录只包含两个清单文件它们共同构成了一个自洽的删除依赖闭环。2.1 rbac.yamlwave 0 权限与 wave 1 绑定rbac.yaml 定义了三个资源通过argocd.argoproj.io/sync-wave注解分配波次ServiceAccountmodify-pods-sawave 0Pod 运行身份拥有 patch 自身所需的权限来源Rolemodify-pods-rolewave 0授予对pods资源的get/list/delete/update/patch权限apiGroup 为空即核心组RoleBindingmodify-pods-rolebindingwave 1将 Role 绑定到modify-pods-sa。这里的波次划分是刻意的权限主体SA Role在 wave 0 就位绑定关系在 wave 1 生效最终让 Pod 在 wave 2 启动时就已具备修改自身的权限。2.2 pod.yaml用 finalizer 制造顺序约束pod.yaml 是这个测试的陷阱核心关键要素有三个argocd.argoproj.io/sync-wave: 2波次注解是字符串形式值为 2保证 Pod 在 SA/Role/RoleBinding 之后创建finalizers: [example.com/block-delete]这个 finalizer 会阻止 Pod 真正被删除。Kubernetes 语义下只要 finalizer 列表非空对象删除请求只会打 deletionTimestamp对象将持续存在并处于 Terminating 状态preStop 生命周期钩子利用 Pod 自身的 ServiceAccount token通过 curl 向 API Server 发起 JSON Patch移除/metadata/finalizerslifecycle: preStop: exec: command: - /bin/sh - -c - | set -e SERVICE_ACCOUNT_TOKEN$(cat /var/run/secrets/kubernetes.io/serviceaccount/token) POD_URLhttps://kubernetes.default.svc/api/v1/namespaces/$NAMESPACE/pods/$POD_NAME PATCH_PAYLOAD[{op: remove, path: /metadata/finalizers}] curl -k -v -H Authorization: Bearer $SERVICE_ACCOUNT_TOKEN -H Content-Type: application/json-patchjson -X PATCH --data $PATCH_PAYLOAD $POD_URL文件中的注释点明了意图remove this finalizers using container preStop lifecycle hook on delete。由于 preStop 只有在 Pod 正常进入删除流程graceful shutdownterminationGracePeriodSeconds: 15时才会执行而执行它又依赖 SA 权限链路完整SA/Role/RoleBinding 尚未被 prune这就构成了严格的顺序依赖若 prune 先删掉了 wave 0 的 SA/RolepreStop 的 patch 请求就会因权限不足失败Pod 永久卡在 Terminating。3. e2e 测试执行链路从创建到逆序 Prune该场景由 sync_waves_test.go 中的TestSyncPruneOrderWithSyncWaves驱动完整链路如下兜底清理defer测试一开始就注册了 defer无论测试在哪个阶段失败都通过argocd app patch-resource命令移除pod-with-finalizers的 finalizer防止测试失败后资源卡死污染后续用例argocd app patch-resource app-name \ --kind Pod --resource-name pod-with-finalizers \ --patch [{op: remove, path: /metadata/finalizers}] \ --patch-type application/json-patchjson --all创建应用并首次同步ctx.Path(syncwaves-prune-order).When().CreateApp().Sync().Wait()断言应用达到SyncedHealthy此时创建顺序为 sa role → rolebinding → pod制造删除意图DeleteFile(pod.yaml).DeleteFile(rbac.yaml).Refresh(RefreshTypeHard)从 Git 源中移除全部清单并强制刷新断言应用变为OutOfSync执行带 prune 的同步Sync(--prune).Wait()断言OperationSucceeded、Synced、Healthy、名为pod-with-finalizers的 Pod 已不存在Expect(NotPod(...))且资源结果编号为 4对应被清理的 4 个资源——注释明确标注// prune order: pod - rolebinding - sa role。整条链路中第 4 步的Pod 消失 操作成功组合断言正是对 README 所述顺序错误则 Pod 卡 Terminating假设的完整证伪。4. 源码纵深反向 Prune 波次是如何实现的e2e 测试验证的行为其实现位于 gitops-engine 的同步上下文。在 sync_context.go 中可以看到关键逻辑对 prune 类任务收集各波次后将唯一波次排序再用对称交换symmetric swap重写 prune 任务的波次覆盖值使原 wave 0 的删除任务获得最高波次、原最高波次的删除任务获得 wave 0从而在执行调度上实现创建逆序的清理// for prune tasks, modify the waves for proper cleanup i.e reverse of sync wave (creation order) pruneTasks : make(map[int][]*syncTask) for _, task : range tasks { if task.isPrune() { pruneTasks[task.wave()] append(pruneTasks[task.wave()], task) } } // ... sort unique prune waves, then: for i : 0; i n/2; i { startWave : uniquePruneWaves[i] endWave : uniquePruneWaves[n-1-i] for _, task : range pruneTasks[startWave] { task.waveOverride endWave } // ... 对 endWave 一侧做对称处理 }对应的单元测试 sync_context_test.go 中也多处断言了 prune 波次重排的结果如// prune order : pod3 - pod2 - pod1与 e2e 场景形成单元测试锁定算法、e2e 锁定集群真实行为的双层验证。另外从 controller/sync.go 可以看到波次之间的执行间隔受环境变量ARGOCD_SYNC_WAVE_DELAY控制单位秒这意味着 wave 0 与 wave 1 的 prune 任务之间并非瞬时切换而是存在真实时间窗——这也解释了为什么 Pod 的 preStop 钩子在时序上来得及先于 RBAC 资源删除完成 finalizer 移除。5. 实践要点与适用边界适用前提本模式要求目标集群允许工作负载访问 API ServerPod 挂载 SA token 并持有 patch 自身 Pod 的权限且容器镜像需包含curl与sh示例使用nginx:alpine自带的工具链设计启示当你需要验证删除顺序如 CR 依赖 CRD、依赖方先于被依赖方下线时可用finalizer 生命周期钩子把顺序错误转化为确定性的可观测故障再配合 e2e 断言完成闭环失败兜底测试中 defer 强制移除 finalizer 的做法值得借鉴——任何人为构造的删除阻塞机制都必须自带逃生通道否则一次失败用例就会让测试集群长期残留 Terminating 资源行为边界反向 prune 的波次重排只发生在 prune 任务上创建路径仍严格按注解中的 wave 升序执行二者互不影响。参考文件索引文件作用README.md测试场景说明创建/清理顺序与 finalizer 陷阱定义rbac.yamlwave 0 的 SA/Role 与 wave 1 的 RoleBindingpod.yamlwave 2 的 Podfinalizer preStop 自移除钩子sync_waves_test.goTestSyncPruneOrderWithSyncWavese2e 测试主体sync_context.goprune 任务波次对称交换的核心实现sync_context_test.goprune 波次重排的单元测试断言controller/sync.goARGOCD_SYNC_WAVE_DELAY波次间隔环境变量定义【免费下载链接】argo-cdDeclarative Continuous Deployment for Kubernetes项目地址: https://gitcode.com/GitHub_Trending/ar/argo-cd创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表