亲手写 Application 与 AppProject
目标
亲自编写 ArgoCD 的 Application 和 AppProject,用声明表达“从哪里读取什么,以什么顺序和策略应用到何处”。
为什么重要
把部署建模为对象而非脚本,会带来三项能力:可向集群查询“当前正在接收什么部署”;自动获得 RBAC 和审计日志;还能将声明本身提交回 git。本实验填写的每个字段都对应真实事故:prune 能把一次仓库路径拼写错误变成大规模删除;没有 retry.backoff 时,失败同步会以固定间隔持续冲击 API 服务器;没有 ignoreDifferences 时,HPA 与 ArgoCD 会反复争夺 replicas。但本环境并未运行 ArgoCD 控制器。你可以注册 CRD 并创建自定义资源,但它们不会自行变为 Synced/Healthy。因此评分检查的是声明是否准确;真实控制器会如何执行这些声明,已在前面的阅读材料和最后一个模块中说明。
步骤
- 在
/opt/crds/下的离线 CRD 包中查找包含 ArgoCD CRD 的文件(grep -l applications.argoproj.io /opt/crds/*.yaml),用kubectl apply -f应用。必须创建applications.argoproj.io与appprojects.argoproj.io两个 CRD,且Established条件为True;还须存在命名空间argocd。将已注册类型列表保存到/root/gitops/app/out/crds.txt(必须包含字符串applications)。 - 在
argocd命名空间创建kind: Application、metadata.name: web的对象。spec.source.repoURL为file:///root/gitops/repo,spec.source.path为apps/web,spec.source.targetRevision为main,spec.destination.server为https://kubernetes.default.svc,spec.destination.namespace为gitops-lab,spec.project为platform。 - 为
web添加spec.syncPolicy.automated,设置prune: true、selfHeal: true。在/root/gitops/app/out/prune-note.txt中用两三行中文说明启用 prune 的风险:一个指向错误路径的提交可能导致大规模删除。 - 在
web的spec.syncPolicy.syncOptions中加入CreateNamespace=true和ServerSideApply=true;在spec.syncPolicy.retry中设置limit: 3、backoff.duration: 10s、backoff.factor: 2、backoff.maxDuration: 5m。 - 若仓库
/root/gitops/repo尚不存在,先创建它:将/opt/lab/fixtures/gitops/seed/中的deployment.yaml和service.yaml复制到/root/gitops/repo/apps/web/,执行git init后提交。随后为/root/gitops/repo/apps/web/中的service.yaml添加argocd.argoproj.io/sync-wave: "-1"注解,为deployment.yaml添加argocd.argoproj.io/sync-wave: "0"。值必须是用双引号包裹的字符串。在/root/gitops/app/out/wave-note.txt中说明,同一 wave 内按资源种类(kind)的默认顺序应用。 - 在
/root/gitops/repo/apps/web/presync-job.yaml创建kind: Job的钩子资源。添加注解argocd.argoproj.io/hook: PreSync和argocd.argoproj.io/hook-delete-policy: BeforeHookCreation;容器名为migrate,spec.backoffLimit为1,Pod 的restartPolicy为Never。该目录中带钩子注解的文件必须只有这一个。 - 在
argocd命名空间创建kind: AppProject、metadata.name: platform。spec.sourceRepos只能包含file:///root/gitops/repo(禁止*);spec.destinations[0]包含 serverhttps://kubernetes.default.svc和 namespacegitops-lab(禁止*);spec.clusterResourceWhitelist包含 group""/ kindNamespace;spec.namespaceResourceBlacklist包含 group""/ kindResourceQuota与 group""/ kindLimitRange。Applicationweb的spec.project必须为platform。 - 为
web添加spec.ignoreDifferences:groupapps、kindDeployment,jsonPointers中包含/spec/replicas(由 HPA 所有)。将spec.revisionHistoryLimit设为5。最后创建/root/gitops/app/out/gitops-report.json:applications是包含argocd命名空间全部 Application、形式为{"name": "..."}的数组;project为"platform";self_heal为true。
参考
Application指向 Pod 内的本地仓库路径。若前一个实验在另一 Pod 中完成,/root/gitops/repo会为空,须在第 5 步用 fixture(/opt/lab/fixtures/gitops/seed/)重建。确认声明指向的目标真实存在,也是 GitOps 工作的一部分。- 本环境没有远程 git,因此
repoURL为本地路径(file://)。实际工作中通常使用https://或git@地址,仓库凭据由argocd命名空间中的 Secret(标签argocd.argoproj.io/secret-type: repository)管理。 - 使用
kubectl apply -f 파일创建清单。必须先注册 CRD,集群才能识别Application类型。 - 第 8 步报告不要手工凑数量,而应查询集群。对
kubectl get application -n argocd -o json使用jq,即使应用增加,数量也会自动准确。 - 常见错误 1:把 sync wave 写成不带引号的
argocd.argoproj.io/sync-wave: -1。注解值必须是字符串,否则 YAML 解析器读成数字,应用会被拒绝。 - 常见错误 2:把两个钩子注解键误认为一个。
argocd.argoproj.io/hook与argocd.argoproj.io/hook-delete-policy是不同键,二者缺一不可。
注册 ArgoCD API 类型
在 /opt/crds/ 下的离线 CRD 包中查找包含 ArgoCD CRD 的文件(grep -l applications.argoproj.io /opt/crds/*.yaml),用 kubectl apply -f 应用。必须创建 applications.argoproj.io 与 appprojects.argoproj.io 两个 CRD,且 Established 条件为 True;还须存在命名空间 argocd。将已注册类型列表保存到 /root/gitops/app/out/crds.txt(必须包含字符串 applications)。
由于没有互联网,请使用离线 CRD 包。不要死记文件名,而应按内容搜索——可用 grep 查找哪个文件包含 applications.argoproj.io。
定义 Application 的源与目标
在 argocd 命名空间创建 kind: Application、metadata.name: web 的对象。spec.source.repoURL 为 file:///root/gitops/repo,spec.source.path 为 apps/web,spec.source.targetRevision 为 main,spec.destination.server 为 https://kubernetes.default.svc,spec.destination.namespace 为 gitops-lab,spec.project 为 platform。
Application 对象自身所在位置与部署目标命名空间不同。source 必须同时说明从哪里、读取哪里以及使用哪个修订版本。
启用自动同步、清理与自愈
为 web 添加 spec.syncPolicy.automated,设置 prune: true、selfHeal: true。在 /root/gitops/app/out/prune-note.txt 中用两三行中文说明启用 prune 的风险:一个指向错误路径的提交可能导致大规模删除。
automated 下两个开关承担不同职责:一个处理从仓库删除的资源,另一个纠正集群中的漂移。还必须写明其中危险的一项是什么。
添加同步选项与重试退避
在 web 的 spec.syncPolicy.syncOptions 中加入 CreateNamespace=true 和 ServerSideApply=true;在 spec.syncPolicy.retry 中设置 limit: 3、backoff.duration: 10s、backoff.factor: 2、backoff.maxDuration: 5m。
syncOptions 是 키=값 字符串数组。重试不能只有次数,还需要三个让间隔逐渐拉长的值。
用 sync wave 创建部署顺序
若仓库 /root/gitops/repo 尚不存在,先创建它:将 /opt/lab/fixtures/gitops/seed/ 中的 deployment.yaml 和 service.yaml 复制到 /root/gitops/repo/apps/web/,执行 git init 后提交。随后为 /root/gitops/repo/apps/web/ 中的 service.yaml 添加 argocd.argoproj.io/sync-wave: "-1" 注解,为 deployment.yaml 添加 argocd.argoproj.io/sync-wave: "0"。值必须是用双引号包裹的字符串。在 /root/gitops/app/out/wave-note.txt 中说明,同一 wave 内按资源种类(kind)的默认顺序应用。
wave 值是注解,必须写成用双引号包裹的字符串,而非数字。应先创建的资源使用更小的值,必要时可用负数。要体现顺序,至少需要两个文件。
编写 PreSync 钩子 Job
在 /root/gitops/repo/apps/web/presync-job.yaml 创建 kind: Job 的钩子资源。添加注解 argocd.argoproj.io/hook: PreSync 和 argocd.argoproj.io/hook-delete-policy: BeforeHookCreation;容器名为 migrate,spec.backoffLimit 为 1,Pod 的 restartPolicy 为 Never。该目录中带钩子注解的文件必须只有这一个。
钩子本质上是普通 Job。需要两个注解:一个决定所处阶段,一个决定何时清理。遗漏清理策略会使钩子资源不断累积。
用 AppProject 划定边界
在 argocd 命名空间创建 kind: AppProject、metadata.name: platform。spec.sourceRepos 只能包含 file:///root/gitops/repo(禁止 *);spec.destinations[0] 包含 server https://kubernetes.default.svc 和 namespace gitops-lab(禁止 *);spec.clusterResourceWhitelist 包含 group "" / kind Namespace;spec.namespaceResourceBlacklist 包含 group "" / kind ResourceQuota 与 group "" / kind LimitRange。Application web 的 spec.project 必须为 platform。
白名单表示“只允许列出的内容”,黑名单表示“只禁止列出的内容”。仓库和命名空间若使用 *,项目隔离就失去意义。也不要忘记把应用归入该项目。
指定忽略字段并创建配置报告
为 web 添加 spec.ignoreDifferences:group apps、kind Deployment,jsonPointers 中包含 /spec/replicas(由 HPA 所有)。将 spec.revisionHistoryLimit 设为 5。最后创建 /root/gitops/app/out/gitops-report.json:applications 是包含 argocd 命名空间全部 Application、形式为 {"name": "..."} 的数组;project 为 "platform";self_heal 为 true。
若连其他控制器所有的字段也强行回滚,就会形成无限同步。报告中的应用数量不要手工统计,而应查询集群生成,才能始终与实际一致。