Argo CD argocd app create 命令深度解析:从 CLI 参数到 Application 资源构建的完整实现
【免费下载链接】argo-cdDeclarative Continuous Deployment for Kubernetes项目地址: https://gitcode.com/GitHub_Trending/ar/argo-cd
argocd app create是 Argo CD 中声明式应用接入的第一道入口:它把命令行参数(或 YAML 清单)在客户端侧组装成一个Application自定义资源(CR),再通过 gRPC 提交给 Argo CD API Server 完成校验、规范化与落库。读完本篇,你将掌握该命令的全部参数分类与用法、目录/Helm/Kustomize/Jsonnet/插件五种源类型的创建示例、基于清单文件(含 stdin 管道)批量创建应用的技巧,以及从cmd/argocd/commands/app.go到服务端Create的完整调用链路与幂等/upsert 语义。
命令语法与两种创建模式
命令的基本形式为:
argocd app create APPNAME [flags]它本质上只有两种输入模式,二选一:
- 参数模式:给出
APPNAME位置参数,配合--repo、--path、--dest-server等大量 flag 现场拼装spec; - 清单模式:通过
-f/--file提供本地文件、HTTP(S) URL 或-(stdin),直接反序列化Application清单(可包含多个文档,适合多源应用与 CI 模板化场景)。
这两种模式的分流逻辑在 cmd/util/app.go 的ConstructApps函数中实现:
func ConstructApps(fileURL, appName string, labels, annotations, args []string, appOpts AppOptions, flags *pflag.FlagSet) ([]*argoappv1.Application, error) { if fileURL == "-" { return constructAppsFromStdin() } else if fileURL != "" { return constructAppsFromFileURL(fileURL, appName, labels, annotations, args, appOpts, flags) } return constructAppsBaseOnName(appName, labels, annotations, args, appOpts, flags) }值得注意的是:清单模式下若应用为多源(multiple sources)应用,CLI 会跳过 flag 覆盖(见 cmd/util/app.go 中if !app.Spec.HasMultipleSources()的判断),因为多源应用的 source 列表结构无法用单源 flag 安全表达;而 stdin 模式(--file -)更是完全信任清单内容,常用于envsubst之类的 CI 变量替换管道:
envsubst < app-template.yaml | argocd app create my-billing-app --file -典型创建示例(官方文档全集)
以下示例来自 argocd app create 文档,覆盖了仓库中支持的全部源类型:
# 创建目录(plain manifest)应用 argocd app create guestbook \ --repo https://github.com/argoproj/argocd-example-apps.git \ --path guestbook \ --dest-namespace default \ --dest-server https://kubernetes.default.svc \ --directory-recurse # 创建 Jsonnet 应用(通过 TLA 传入外部参数) argocd app create jsonnet-guestbook \ --repo https://github.com/argoproj/argocd-example-apps.git \ --path jsonnet-guestbook \ --dest-namespace default --dest-server https://kubernetes.default.svc \ --jsonnet-ext-str replicas=2 # 创建 Helm 应用(--helm-set 覆盖参数) argocd app create helm-guestbook \ --repo https://github.com/argoproj/argocd-example-apps.git \ --path helm-guestbook \ --dest-namespace default --dest-server https://kubernetes.default.svc \ --helm-set replicaCount=2 # 从 Helm chart 仓库创建应用(--repo 指向 chart 仓库 + --helm-chart) argocd app create nginx-ingress \ --repo https://charts.helm.sh/stable \ --helm-chart nginx-ingress --revision 1.24.3 \ --dest-namespace default --dest-server https://kubernetes.default.svc # 创建 Kustomize 应用(--kustomize-image 注入镜像覆盖) argocd app create kustomize-guestbook \ --repo https://github.com/argoproj/argocd-example-apps.git \ --path kustomize-guestbook \ --dest-namespace default --dest-server https://kubernetes.default.svc \ --kustomize-image quay.io/argoprojlabs/argocd-e2e-container:0.1 # 从清单文件创建多源应用 argocd app create my-billing-app --file path/to/app.yaml # 从 stdin 创建(CI 场景),以清单中 metadata.name 为准 envsubst < app-template.yaml | argocd app create my-billing-app --file - # 使用自定义配置管理插件(CMP) argocd app create kasane \ --repo https://github.com/argoproj/argocd-example-apps.git \ --path plugins/kasane \ --dest-namespace default --dest-server https://kubernetes.default.svc \ --config-management-plugin kasane几个值得注意的语义细节(由源码确认):
--repo/--path/--name在清单模式下被忽略:这些 flag 的帮助文案明确写着 "ignored if a file is set",注册于 cmd/argocd/commands/app.go;- 位置参数与
--name的一致性校验:参数模式下若二者同时提供且不一致会直接报错(cmd/util/app.go);清单模式下若位置参数APPNAME与清单metadata.name不一致同样报错,但--name会被用于改写应用名(cmd/util/app.go); - 目录源的扩展名过滤:
--directory-disable-extension-filter默认关闭,即默认只有.yaml、.yml、.json、.jsonnet扩展名的文件被视为清单,开启后--directory-include/--directory-exclude才能匹配.yaml.sealed之类的自定义扩展名文件。
完整参数参考
以下参数表完整继承自 argocd app create 文档,并结合 cmd/util/app.go 中AddAppFlags的默认值注解做了补充。
通用与元数据类
| 参数 | 说明 |
|---|---|
-f, --file string | 本地文件、URL 或-(stdin),提供 Application 清单(可含多文档) |
-l, --label stringArray | 应用到应用的标签(key=value形式,可重复) |
--annotations stringArray | 设置 metadata annotations |
-N, --app-namespace string | Application CR 所在命名空间 |
--set-finalizer | 在应用上设置删除 finalizer,删除时级联清理集群资源 |
--upsert | 即使已有同名应用且 spec 不同,也允许覆盖(默认 false,详见下文幂等语义) |
--validate | 是否校验仓库与集群(默认true) |
--name string | 应用名(已废弃,设置 file 时忽略) |
--project string | 应用所属项目名 |
--env string | 监控的环境名(写入metadata.labels的环境标记) |
源(source)相关
| 参数 | 说明 |
|---|---|
--repo string | 仓库 URL(设置 file 时忽略) |
--path string | 仓库内应用目录路径(设置 file 时忽略) |
--revision string | 跟踪的分支/标签/commit 或 Helm chart 版本 |
--tag-prefix string | 将 targetRevision 作为 semver 约束求值前,按该前缀过滤 git tag |
--helm-chart string | Helm Chart 名(此时--repo应指向 chart 仓库) |
--ref string | 引用 sources 字段中的另一个 source(多源引用) |
--source-name string | sources 列表中该 source 的名称 |
--revision-history-limit int | 保留的 revision 历史条数(默认 10,默认值来自 pkg/apis/application/v1alpha1/application_defaults.go 的RevisionHistoryLimit常量) |
Helm 子集参数:
| 参数 | 说明 |
|---|---|
--values stringArray | 使用的 Helm values 文件 |
--values-literal-file string | 导入为字面量 Helm values 块的文件名或 URL(源码中会读取文件内容并整体写入helm.values,见 cmd/util/app.go) |
--release-name string | Helm release 名 |
--helm-version string | Helm 版本(3 或 2,用于锁定本地 helm 行为) |
--helm-set stringArray | 命令行设置值(可重复) |
--helm-set-string stringArray | 以字符串类型设置值(可重复) |
--helm-set-file stringArray | 从文件设置值(可重复) |
--helm-pass-credentials | 对所有域名传递凭证 |
--helm-skip-crds | 跳过 CRD 安装步骤 |
--helm-skip-schema-validation | 跳过 schema 校验步骤 |
--helm-skip-tests | 跳过 test manifests 安装步骤 |
--helm-namespace string | 渲染helm template使用的命名空间;不设置时使用spec.destination.namespace |
--helm-kube-version string | 渲染时使用的 kube-version;不设置时使用目标集群版本 |
--helm-api-versions stringArray | 渲染时的 api-versions([group/]version/kind格式);不设置时使用目标集群的 api-versions |
--ignore-missing-value-files | 忽略本地不存在的 valueFiles |
Kustomize 子集参数:
| 参数 | 说明 |
|---|---|
--nameprefix/--namesuffix string | Kustomize 名称前缀/后缀 |
--kustomize-namespace string | Kustomize 命名空间 |
--kustomize-image stringArray | 镜像覆盖,如--kustomize-image node:8.15.0或--kustomize-image mysql=mariadb,alpine@sha256:24a0... |
--kustomize-replica stringArray | 副本数覆盖,如--kustomize-replica my-development=2 |
--kustomize-version string | Kustomize 版本 |
--kustomize-common-label/--kustomize-common-annotation stringArray | 公共标签/注解 |
--kustomize-force-common-label/--kustomize-force-common-annotation | 强制覆盖同名标签/注解 |
--kustomize-label-without-selector | 不将公共标签应用到 selector(除非同时设置下一条) |
--kustomize-label-include-templates | 将公共标签也应用到资源模板 |
--kustomize-kube-version string | 渲染用 kube-version,仅在 Kustomize 构建启用 Helm 时有效 |
--kustomize-api-versions stringArray | 渲染用 api-versions,仅在 Kustomize 构建启用 Helm 时有效 |
--ignore-missing-components | 设置 Kustomize components 时忽略本地缺失的组件目录 |
目录、Jsonnet 与插件参数:
| 参数 | 说明 |
|---|---|
--directory-recurse | 递归目录 |
--directory-include/--directory-exclude string | 包含/排除文件的 glob 表达式 |
--directory-disable-extension-filter | 禁用内置扩展名过滤,使 include/exclude 可匹配自定义扩展名文件 |
--jsonnet-tla-str/--jsonnet-tla-code stringArray | Jsonnet TLA 字符串/代码参数 |
--jsonnet-ext-var-str/--jsonnet-ext-var-code stringArray | Jsonnet 扩展变量(字符串/代码) |
--jsonnet-libs stringArray | 附加 Jsonnet 库(以 repoRoot 为前缀) |
--config-management-plugin string | 配置管理插件名(此时--path指向插件输入目录) |
--plugin-env stringArray | 插件附加环境变量 |
同步策略类:
| 参数 | 说明 |
|---|---|
--sync-policy string | manual(别名none)或automated(别名auto、automatic);非法值会直接log.Fatalf(见 cmd/util/app.go) |
--auto-prune | 为 automated 策略开启自动剪枝 |
--self-heal | 为 automated 策略开启自愈 |
--allow-empty | 允许 0 个存活资源通过自动同步 |
--sync-option stringArray | 添加/删除同步选项;!前缀表示移除,如!Prune=false(实现见 cmd/util/app.go) |
--sync-retry-limit int | 允许的最大同步重试次数(默认 0 表示不重试;设为 0 且已有 retry 配置时会清除 retry) |
--sync-retry-backoff-duration duration | 重试退避基础时长,默认5s(常量见 pkg/apis/application/v1alpha1/application_defaults.go) |
--sync-retry-backoff-factor int | 每次失败后乘以基础时长的因子,默认2 |
--sync-retry-backoff-max-duration duration | 最大退避时长,默认3m0s |
--sync-retry-refresh | 重试时使用最新 revision 而非初始 revision |
目标(destination)类:
| 参数 | 说明 |
|---|---|
--dest-server string | 集群 URL(如https://kubernetes.default.svc) |
--dest-name string | 集群名(如minikube) |
--dest-namespace string | 目标命名空间 |
Hydrator(应用控制器外置水化)相关,由 cmd/util/app.go 的constructSourceHydrator构建spec.sourceHydrator:
| 参数 | 说明 |
|---|---|
--dry-source-repo string | dry source 的仓库 URL |
--dry-source-revision string | dry source 的 revision |
--dry-source-path string | dry source 在仓库中的路径 |
--sync-source-branch string | 应用同步所依据的分支 |
--sync-source-path string | 应用同步所依据的仓库路径 |
--hydrate-to-branch string | 水化产物的目标分支 |
继承自父命令的通用参数
这些 flag 作用于所有 argocd 子命令(连接、鉴权与日志),完整列表见 argocd app create 文档,常用的包括:--server(Argo CD 服务地址)、--auth-token(认证 token,或ARGOCD_AUTH_TOKEN环境变量)、--argocd-context、--insecure/--plaintext(跳过证书校验/禁用 TLS)、--grpc-web(API Server 在不支持 HTTP2 的代理后很有用)、--port-forward(经端口转发连接)、--core(直连 Kubernetes 而非 API Server)、--kube-context、--loglevel(debug|info|warn|error,默认info)、--logformat(json|text,默认json)、--config(默认~/.config/argocd/config)、--header(附加请求头)以及--server-name、--repo-server-name、--redis-name等用于 Helm chart 部署改名的场景。
参数如何落到 spec:客户端构建流程
参数模式下,flag 到ApplicationSpec的映射分为两层:
第一层:源构建。cmd/util/app.go 的ConstructSource通过flags.Visit只遍历用户显式设置过的 flag,逐个把--repo、--path、--revision等写入ApplicationSource的对应字段,并调用setHelmOpt、setKustomizeOpt、setJsonnetOpt*等填充子结构。每个 setter 都有“归零清理”:如 cmd/util/app.go 中if src.Helm.IsZero() { src.Helm = nil },保证未使用的源类型不会在 manifest 中留下空壳字段。
第二层:spec 级选项。cmd/util/app.go 的SetAppSpecOptions处理--dest-*、--project、--sync-policy、--sync-option、--sync-retry-*等写入spec顶层字段的参数。几个从源码结构看值得注意的行为:
--sync-option支持!前缀删除已有选项,且当SyncPolicy为空时会将其置回 nil,避免生成冗余字段;--auto-prune/--self-heal/--allow-empty即使未显式给出--sync-policy automated,也会自动创建Automated结构体并置Enabled: false的占位(cmd/util/app.go)——这意味着“只加剪枝不加自动同步”的组合是合法的;-p/--parameter仅对 Helm 应用生效,非 Helm 源会直接log.Fatal("Parameters can only be set against Helm applications")(cmd/util/app.go)。
提交与幂等语义:服务端 Create 的实现
客户端完成 Application 对象构建后,argocd app create的Run函数(cmd/argocd/commands/app.go)会先Get一次同名应用以区分结果,再发送ApplicationCreateRequest{Application, Upsert, Validate},最终打印application '<name>' created|unchanged|updated三态输出之一。
服务端的权威实现位于 server/application/application.go 的Create方法,其执行顺序是:
- RBAC 校验:
rbac.ResourceApplications + rbac.ActionCreate,无权限立即拒绝; - 项目锁与项目校验:
getAppProject确认 project 存在,validateAndNormalizeApp完成源合法性、destination 是否在项目允许列表内等规范化(受--validate控制); - 多命名空间校验:目标 app 命名空间未启用时返回
NamespaceNotPermittedError; - 安全防线:创建请求中若显式携带
spec.operation会被静默丢弃并记录 security 告警——因为直接设置 operation 可绕过同步分支保护规则,同步必须走 Sync API(server/application/application.go); - 幂等与 upsert:Kubernetes 层
Create若返回AlreadyExists,服务端会比较现有对象与新请求的spec、labels、annotations、finalizers:完全一致则直接返回现有对象(幂等);不一致则必须显式携带--upsert且通过ActionUpdate的 RBAC 校验,才会执行更新(server/application/application.go)。
客户端侧的created/unchanged/updated文案则由 cmd/argocd/commands/app.go 的hasAppChanged基于同样的 DeepEqual 逻辑计算。这也解释了为何argocd app create可以安全地用于 CI/CD 流水线中的重复执行:不加--upsert时它等价于“存在且一致则成功、不一致则报错”的声明式入口。
清单模式与 stdin:CI 场景的最佳实践
清单模式支持本地路径与 HTTP(S) URL(cmd/util/app.go 的readAppsFromURI按 scheme 分流本地读取与远端下载),且通过kube.SplitYAMLToString支持单个文件内多个 Application 文档——一次命令即可批量创建多个应用。stdin 模式则完全信任管道内容,位置参数APPNAME仅作为“至少有一个文档”的占位与文档数核对手段,应用名以清单metadata.name为准。
推荐实践:
- 简单单源应用用参数模式,参数即文档,
argocd app get可立即验证落库的 spec; - 多源应用、需要与 Git 中 GitOps 清单保持一致的场景用
--file清单模式,并可先在仓库中维护 YAML 模板; - 需要注入 CI 变量(如构建版本)时,用
envsubst(或其他模板工具)渲染后经--file -传入,保证 Argo CD 侧不落盘任何临时文件。
小结
argocd app create的参数表面庞杂,但可按“元数据 → 源类型子集(Helm/Kustomize/Jsonnet/目录/插件)→ 同步策略 → destination → Hydrator”五层理解;参数模式与清单模式在客户端由ConstructApps统一分流,最终都收敛为一次 gRPCCreate调用。服务端对 RBAC、项目约束、operation 注入防护与 AlreadyExists 幂等的处理,使该命令既适合交互式使用,也适合作为 CI 流水线中可重复执行的应用注册步骤。如需继续深挖,可阅读 cmd/argocd/commands/app.go、cmd/util/app.go 与 server/application/application.go 三个文件,它们分别对应命令定义、spec 构建与服务端裁决。
【免费下载链接】argo-cdDeclarative Continuous Deployment for Kubernetes项目地址: https://gitcode.com/GitHub_Trending/ar/argo-cd
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考