Argo CD ApplicationSet Cluster Generator 完整指南:基于集群 Secret 自动生成跨集群 Application
Argo CD ApplicationSet Cluster Generator 完整指南基于集群 Secret 自动生成跨集群 Application【免费下载链接】argo-cdDeclarative Continuous Deployment for Kubernetes项目地址: https://gitcode.com/GitHub_Trending/ar/argo-cd本篇技术指南围绕 Argo CD 的 ApplicationSet Cluster Generator 展开深入讲解它如何以 Argo CD 命名空间中的集群 Secret 为唯一真相来源source of truth自动为每个已注册集群生成参数并渲染出对应的 Application 资源。读完本文你将掌握 Cluster Generator 的自动参数模型、标签选择器label selector、本地集群in-cluster处理、基于 Kubernetes 版本选集群、values字段扩展以及flatList扁平化输出等完整实战能力并了解其底层源码实现与测试验证方式。Cluster Generator 工作原理集群 Secret 即真相来源在 Argo CD 中被纳管的集群与仓库、仓库凭据一样都是以 Kubernetes Secret 的形式存储在 Argo CD 命名空间中的。每个集群 Secret 必须带有标签argocd.argoproj.io/secret-type: cluster用于标识其类型参见 声明式集群配置。ApplicationSet Controller 中的 Cluster Generator 正是读取这些 Secret将其中携带的集群信息转换成一组参数并交给 Application 模板渲染从而为每个匹配的集群生成一个对应的 Application 资源。从源码实现来看applicationset/generators/cluster.goClusterGenerator实现了Generator接口其核心逻辑在GenerateParams方法中它会通过缓存好的 controller-runtime client 列出所有带argocd.argoproj.io/secret-type: cluster标签的 Secret然后为每个 Secret 调用getClusterParameters提取参数见 cluster.go#L48-L108。特别值得一提的是GetRequeueAfter始终返回NoRequeueAfter因为集群 Secret 一旦发生变化clusterSecretEventHandler事件处理器会自动触发相关 ApplicationSet 的重新入队见 cluster.go#L38-L42无需周期轮询。自动提供的参数对于 Argo CD 中注册的每一个集群Cluster Generator 会自动向 Application 模板提供以下参数参数含义name集群名称取自集群 Secret 的name数据字段nameNormalizedname的规范化版本仅包含小写字母数字字符、-或.server集群 API Server 地址取自 Secret 的server数据字段projectSecret 中的project字段若不存在则默认为空字符串metadata.labels.keySecret 上每一个标签label都会映射为对应的参数metadata.annotations.keySecret 上每一个注解annotation都会映射为对应的参数注意如果集群名称包含 Kubernetes 资源名不支持的字符如下划线_请使用nameNormalized参数。例如名为my_cluster的集群直接渲染会得到非法的资源名my_cluster-app1而使用nameNormalized会将其转换为合法的my-cluster-app1。在源码层面见 cluster.go#L128-L163getClusterParameters负责组装这些参数nameNormalized由utils.SanitizeName对name清洗得到。清洗规则见 applicationset/utils/template_functions.go#L14-L29包括全部转为小写、用-替换非法字符、总长度不超过 253 个字符、并以字母数字字符开头和结尾。测试用例TestSanitizeClusterName见 applicationset/generators/cluster_test.go#L859-L867验证了-.--CLUSTER/name -./.-会被清洗为cluster-name。另外要注意 GoTemplate 模式与非 GoTemplate 模式下metadata的暴露形式不同开启goTemplate: true时metadata以嵌套 map 形式提供如{{index .metadata.annotations my-annotation}}未开启时则展平为metadata.labels.key、metadata.annotations.key这样的扁平键。本文示例均基于 GoTemplate 模式。基础用法为每个集群部署一套应用集群 Secret 中的name和server数据字段描述了一个集群Cluster Generator 会自动识别 Argo CD 中定义的集群并将其数据提取为参数。以下是最基础的完整示例它会对所有注册集群分别渲染一个名为集群名-guestbook的 ApplicationapiVersion: argoproj.io/v1alpha1 kind: ApplicationSet metadata: name: guestbook namespace: argocd spec: goTemplate: true goTemplateOptions: [missingkeyerror] generators: - clusters: {} # 自动使用 Argo CD 内定义的全部集群 template: metadata: name: {{.name}}-guestbook # 使用集群 Secret 的 name 字段 spec: project: my-project source: repoURL: https://github.com/argoproj/argocd-example-apps/ targetRevision: HEAD path: guestbook destination: server: {{.server}} # 使用集群 Secret 的 server 字段 namespace: guestbook在这个例子中集群 Secret 的name和server字段被用来填充 Application 资源的metadata.name和spec.destination.server从而让生成的 Application 精确指向它对应的集群。仓库中提供了可直接运行的完整示例cluster-example.yamlGoTemplate 风格与 cluster-example-fasttemplate.yaml快速模板风格。对应的集群 Secret 形态如下Kubernetes 中data字段实际是 Base64 编码此处为便于阅读已解码Cluster Generator 传入参数时同样会先解码kind: Secret data: config: {tlsClientConfig:{insecure:false}} name: in-cluster2 server: https://kubernetes.default.svc metadata: labels: argocd.argoproj.io/secret-type: cluster # (...)关于集群 Secret 支持的全部数据字段可参见 声明式集群配置其中name、server为必填project可选用于将集群限定到某个 Projectnamespaces、clusterResources可选config必填且为 JSON 结构内含 basic authusername/password、bearer token、awsAuthConfig、execProviderConfig、proxyUrl、tlsClientConfig等认证配置。使用 Label Selector 精准选择目标集群当集群数量变多时通常不希望把应用部署到所有集群。可以使用标签选择器label selector将目标集群范围收窄到匹配特定标签的集群apiVersion: argoproj.io/v1alpha1 kind: ApplicationSet metadata: name: guestbook namespace: argocd spec: goTemplate: true goTemplateOptions: [missingkeyerror] generators: - clusters: selector: matchLabels: staging: true # Cluster generator 同样支持 matchExpressions #matchExpressions: # - key: staging # operator: In # values: # - true template: # (...)上述选择器会匹配带有如下标签的集群 SecretapiVersion: v1 kind: Secret data: # (... 字段同上 ...) metadata: labels: argocd.argoproj.io/secret-type: cluster staging: true # (...)标签选择器同样支持基于集合set-based的需求表达式例如operator: In、NotIn、Exists、DoesNotExist等。从源码看见 cluster.go#L165-L188getSecretsByClusterName会把用户配置的 selector 与argocd.argoproj.io/secret-type: cluster标签合并metav1.AddLabelToSelector因此无论是否显式配置集群 Secret 的必备标签都会被自动加上。测试用例见 applicationset/generators/cluster_test.go覆盖了「production-only」「production or stagingmatchExpressions」「matchExpressions matchLabels 组合」等多种选择器场景可对照验证行为。部署到本地集群in-cluster在 Argo CD 语境中「本地集群」local cluster指的是 Argo CD 及 ApplicationSet Controller 自身运行所在的那个集群用来与通过声明式配置见 声明式集群配置或 Argo CD CLIargocd cluster add添加的「远程集群」相区分。Cluster Generator 会对所有匹配集群选择器的本地集群与远程集群一视同仁地自动生成参数。源码层面见 cluster.go#L90-L105的处理逻辑是当没有配置 selector 时如果集群 Secret 列表中不包含 in-cluster 凭据则自动为本地集群补充一组参数——name为in-cluster、nameNormalized为in-cluster、server为https://kubernetes.default.svc、project为空字符串这两个常量定义于 pkg/apis/application/v1alpha1/application_defaults.go#L30-L34。只想部署到远程集群如果希望生成的 Application 只面向远程集群例如要排除本地集群可以配置带标签的选择器spec: goTemplate: true goTemplateOptions: [missingkeyerror] generators: - clusters: selector: matchLabels: argocd.argoproj.io/secret-type: cluster # Cluster generator 同样支持 matchExpressions #matchExpressions: # - key: staging # operator: In # values: # - true这个选择器不会匹配默认的本地集群因为默认的本地集群没有对应的 Secret自然也没有argocd.argoproj.io/secret-type标签。因此任何基于该标签进行选择的 selector 都会自动排除默认本地集群。这一点与源码中ignoreLocalClusters的判断一致只要配置了非空的MatchExpressions或MatchLabels就会忽略本地集群见 cluster.go#L58-L60。既想包含本地集群又要使用标签匹配如果既想使用标签匹配、又想包含本地集群可以在 Argo CD Web UI 中为本地集群创建一个 Secret在 Argo CD Web UI 中进入Settings再选择Clusters。选择你的本地集群通常名为in-cluster。点击Edit按钮将集群的NAME改为其他值例如in-cluster-local任意其他值均可。其余字段保持不变。点击Save。这些步骤看似违反直觉但修改本地集群默认值的行为会触发 Argo CD Web UI 为该集群创建一个新的 Secret。此时在 Argo CD 命名空间中会看到名为cluster-集群后缀的 Secret且带有标签argocd.argoproj.io/secret-type: cluster。也可以改为通过声明式配置创建本地集群 Secret见 声明式集群配置或使用 CLI 命令argocd cluster add (context name) --in-cluster创建而不必走 Web UI。基于 Kubernetes 版本筛选集群Cluster Generator 还支持按集群的 Kubernetes 版本筛选。实现方式为在集群 Secret 上设置标签argocd.argoproj.io/auto-label-cluster-info: true。一旦设置Controller 会自动为该集群 Secret 动态打上其所运行 Kubernetes 版本的标签。随后便可在选择器中用argocd.argoproj.io/kubernetes-version标签取值spec: goTemplate: true generators: - clusters: selector: matchLabels: argocd.argoproj.io/kubernetes-version: v1.28.1 # 同样支持 matchExpressions #matchExpressions: # - key: argocd.argoproj.io/kubernetes-version # operator: In # values: # - v1.27.1 # - v1.28.1这一能力在需要按 Kubernetes 版本分批升级、或针对特定版本集群做差异化发布例如灰度到 v1.28 集群、跳过 v1.27 集群的场景下非常实用。通过values字段传递额外键值对Cluster Generator 支持通过values字段向模板传递额外的任意字符串键值对。经由values字段添加的值在模板中以values.字段名的形式访问。以下示例根据集群 Secret 的标签匹配为不同类型的集群传入不同的revision参数spec: goTemplate: true goTemplateOptions: [missingkeyerror] generators: - clusters: selector: matchLabels: type: staging # 任意参数的键值映射 values: revision: HEAD # staging 集群使用 HEAD 分支 - clusters: selector: matchLabels: type: production values: # production 使用不同的 revision 值即 stable 分支 revision: stable template: metadata: name: {{.name}}-guestbook spec: project: my-project source: repoURL: https://github.com/argoproj/argocd-example-apps/ # 每个 generator 的 cluster values 字段会在此处被替换 targetRevision: {{.values.revision}} path: guestbook destination: server: {{.server}} namespace: guestbook该示例中generators.clusters.values提供的revision值会以values.revision的形式进入模板——由哪个 generator 生成的参数集决定其取值为HEAD或stable。注意通过generators.clusters.values提供的值总会自动加上values.前缀。在template中使用该参数时务必包含此前缀。在 values 中插值集群参数values字段还支持对页面开头列出的集群参数进行模板插值包括namenameNormalizedname的规范化形式仅含小写字母数字、-或.servermetadata.labels.keySecret 中的每个标签metadata.annotations.keySecret 中的每个注解扩展上面的示例可以实现「根据集群 Secret 注解动态决定 revision」spec: goTemplate: true goTemplateOptions: [missingkeyerror] generators: - clusters: selector: matchLabels: type: staging # 任意参数的键值映射 values: # 如果集群 Secret 中有 my-custom-annotationrevision 将被替换为该注解的值。 revision: {{index .metadata.annotations my-custom-annotation}} clusterName: {{.name}} - clusters: selector: matchLabels: type: production values: # production 使用不同的 revision 值即 stable 分支 revision: stable clusterName: {{.name}} template: metadata: name: {{.name}}-guestbook spec: project: my-project source: repoURL: https://github.com/argoproj/argocd-example-apps/ # 每个 generator 的 cluster values 字段会在此处被替换 targetRevision: {{.values.revision}} path: guestbook destination: # 此处等价于直接使用 {{name}} server: {{.values.clusterName}} namespace: guestbook源码中values的插值由appendTemplatedValues完成调用见 cluster.go#L81且会为插值结果统一加上values.前缀测试用例验证了values中引用其他values.*、metadata.annotations.*、metadata.labels.*、server等参数的嵌套插值行为见 applicationset/generators/cluster_test.go#L390-L474。使用 flatList 将集群信息聚合成扁平列表有时你并不需要为每个集群部署一个 Application而是希望一次性获取所有集群的信息例如在一个 Application 中统一生成 Helm values。此时可以使用 Cluster Generator 的flatList选项。使用flatList: true时所有匹配集群的参数不会各自渲染一个 Application而是聚合为单个参数集其中以clusters为键包含所有集群的参数字典列表供模板用range遍历spec: goTemplate: true goTemplateOptions: [missingkeyerror] generators: - clusters: selector: matchLabels: type: staging flatList: true template: metadata: name: flat-list-guestbook spec: project: my-project source: repoURL: https://github.com/argoproj/argocd-example-apps/ targetRevision: HEAD path: helm-guestbook helm: values: | clusters: {{- range .clusters }} - name: {{ .name }} {{- end }} destination: server: my-cluster namespace: guestbook假设有两个集群 Secret 匹配名称分别为cluster1和cluster2上述配置将生成唯一一个ApplicationapiVersion: argoproj.io/v1alpha1 kind: Application metadata: name: flat-list-guestbook namespace: guestbook spec: project: my-project source: repoURL: https://github.com/argoproj/argocd-example-apps/ targetRevision: HEAD path: helm-guestbook helm: values: | clusters: - name: cluster1 - name: cluster2在源码实现中见 cluster.go#L110-L126paramHolder的consolidate方法在isFlatMode为 true 时会把收集到的所有参数切片包装成{clusters: [...]}的单一参数集返回对应测试用例如「flat mode without selectors」「production or staging with flat mode」见 applicationset/generators/cluster_test.go#L222-L288验证了这一聚合行为。注意如果同时使用多个带flatList的 Cluster Generator则每个 Cluster Generator 各生成一个 Application。这是因为无法简单合并各 generator 中可能不同的 values 与模板。小结与源码速查Cluster Generator 是 ApplicationSet 中最常用的生成器之一其设计核心是「集群即 Secret、Secret 即参数」只要集群以带argocd.argoproj.io/secret-type: cluster标签的 Secret 形式注册在 Argo CD 中Cluster Generator 就能自动生成参数并渲染 Application。结合标签选择器、values插值与flatList它可以灵活支撑按环境staging/production选集群、按 Kubernetes 版本选集群、跨集群统一参数注入以及集群信息聚合等多种多集群发布场景。关键源码与示例位置速查生成器核心实现applicationset/generators/cluster.go名称清洗函数SanitizeNameapplicationset/utils/template_functions.go单元测试含 GoTemplate 与非 GoTemplate、flatList、values 插值applicationset/generators/cluster_test.go可运行示例applicationset/examples/cluster/cluster-example.yaml 与 cluster-example-fasttemplate.yaml集群 Secret 声明式字段说明docs/operator-manual/declarative-setup.md#clusters本地集群与远程集群相关常量pkg/apis/application/v1alpha1/application_defaults.go#L30-L34【免费下载链接】argo-cdDeclarative Continuous Deployment for Kubernetes项目地址: https://gitcode.com/GitHub_Trending/ar/argo-cd创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考