在本指南中,我们包含了在您的组织中采用 GitOps 和 Argo CD 时需要考虑的几个与 Helm 相关的主题。
我们描述:
          GitOps 存储库的推荐 Helm 结构
          何时使用Argo CD 的多源功能以及何时不使用它
          如何创建 Helm 价值层次结构以及其重要性
          人们将 Helm 的常见错误做法和误解带到了 Argo CD
如果您喜欢我们的指南,但想知道我们的建议如何与 Helm 而不是 Kustomize 配合使用,那么本指南适合您!
您可以在https://github.com/kostis-codefresh/multi-sources-example找到完整的示例。
Helm 价值观如何发挥作用
Helm 的原始设计是拥有一个通用图表(没有任何硬编码配置),然后使用几个不同的值文件来保存特定于环境的配置。我们在Helm 值指南中详细介绍了这种情况。如果没有添加外部值,图表也可以使用默认值。
您需要确定 Helm Chart 是否映射到特定的应用程序。一种方法是为您开发的每个应用程序都创建一个 Helm Chart。在这种情况下,Helm Chart 有两个版本。一个版本保存 Chart 本身的历史记录,另一个版本(Chart.yml 文件中的 appVersion)跟踪 Chart 中包含的应用程序。
使用第二种方法,您将获得一个可重复使用的“单一”图表,该图表适用于多种应用程序。它本身并不包含特定的应用程序。您始终需要将其与定义图像/标签/配置的值组合使用。
两种方法都有效,Argo CD 也支持这两种方法。不过,为您的组织选择一种策略才是明智之举。
假设 QA/Staging/Prod 的经典三位一体,您应该能够轻松安装具有适当配置的任何图表,如下所示:
helm install ./my-chart/ --generate-name -f values-qa.yaml 
helm install ./my-chart/ --generate-name -f values-staging.yaml 
helm install ./my-chart/ --generate-name -f values-production.yaml
在这个非常简单的例子中,图表与其可能的配置一起保存在 Git 中作为普通文件。
使用 Helm 值层次结构创建可重用配置
上述结构适用于大多数组织。然而,在某些情况下,应用程序需要为大量环境定义复杂的配置。您可以为每个环境复制一个值文件,但这会导致繁琐的设置,因为您需要更改某些环境之间的通用配置。
为了克服这一挑战,Helm 还支持值层次结构。这意味着,在安装 Chart 时,您可以定义多个值文件,而不是单个。然后,Helm 会合并所有值文件,对于多次定义的属性,最后一个文件将生效。
这意味着您可以执行以下操作:
helm install ./my-chart/ — 生成名称 -f common.yaml -f more.yaml -f some-more.yaml
如果您的属性同时存在于 common.yaml 和 more.yaml 中,则后者将生效。同样,some-more.yaml 中定义的所有属性都将覆盖您在前面文件中定义的所有其他属性。
这种模式的明显优势是,您可以创建 Helm 值文件的层次结构,其中“早期”文件包含大多数环境的通用值,“晚期”文件包含单个部署的特定值。
可能的设置是:
通用值.yaml 
+-----所有生产环境.yaml 
    +----特定生产集群.yaml
这意味着公共值会在所有部署之间共享,除非它们在所有生产环境的“all-prod-envs”中被覆盖,而特定集群的“specific-prod-cluster.yaml”也可以覆盖它们。
为了使其工作,您需要按照预期的顺序应用所有文件 – 记住最后一个文件获胜。
helm install ./my-chart/ — 生成名称 -f common-values.yaml -f all-prod-envs.yaml -f specific-prod-cluster.yaml
如果您将 Helm 用于自己的应用程序,则必须为所有 Helm 应用程序创建适当的层次结构,以平衡灵活性和最少的重复。
还需要记住的是,Helm 内置了这些层次结构。它们与 Argo CD 无关。
将 Helm 值层次结构与 Argo CD 结合使用
在花时间设计 Helm 值层次结构之后,您现在就可以使用 Argo CD 了。好消息是,Argo CD 开箱即用地支持 Helm 层次结构,无需任何其他配置。
这是一个示例应用程序:
apiVersion: argoproj.io/v1alpha1
种类: 应用
程序元数据:
  名称: my-app
  命名空间: argocd
规范:
  项目: 默认
  来源:
    图表: my-chart 
    repoURL: https:  //github.com/my-example-app 
    targetRevision: 2.43 
    helm:
      valueFiles:
      -common  -values.yaml 
      -  all-prod-envs.yaml             
      -  specific-prod-cluster.yaml
  目标:
    服务器: “https://kubernetes.default.svc”
    命名空间: 默认 
valueFiles 属性接受一个值文件数组。与 Helm CLI 类似,列表中每个文件的值都会覆盖前面所有文件的值。最后一个文件的值优先于前面的文件。
为什么这很重要?正如我们在上一篇指南中所述,我们已经看到一些团队尝试使用各种技巧和变通方法来复制这种默认/特定于环境的值模式。通常,使用这些变通方法的团队并不了解 Helm 值层次结构的工作原理。
不要陷入仅为了复制 Helm 值层次结构而向应用程序或应用程序集添加另一层模板的陷阱。
将本地 Helm 值与 Helm 存储库中的图表结合使用
所有前面的示例都假设您的 Helm chart 及其值位于 Git 中。我们始终建议您这样做,尤其是对于您自己的应用程序。然而,有些组织更喜欢将 chart 存储在 Helm 存储库或 OCI 注册表中。Argo CD 支持这种方案,但您需要了解其含义:
          Helm 仓库(以及 OCI 构件)是可变的。这意味着您今天下载的 Helm chart 1.2.3 版本可能与您昨天下载的 1.2.3 版本内容不同。当然,这违反了 GitOps 原则。
          Chart 中没有内置审计或更改历史记录。如果您使用 Git,则可以“免费”获得这些功能。
          完整性和安全性方面存在风险。您能验证从注册表下载的图表是否是创建者上传的图表吗?同样,如果您使用自己的 Git 仓库,则可以监视图表上发生的所有更改,并可选择批准这些更改。
如果您坚持从外部存储库加载图表,您仍应将自己的值保留在自己的 Git 存储库中。然后,Argo CD 可以使用多个源将两者合并。
多源是 Argo CD 专为此场景创建的功能。在最基本的情况下,您应该定义两个源。一个包含您的外部 Helm 图表,另一个包含您的 Helm 值。
与以前一样,您也可以拥有 Helm 层次结构。
apiVersion: argoproj.io/v1alpha1
类型: 应用
程序 元数据:
  名称: my-fancy-app
  命名空间: argocd
规范:
  项目: 默认
  目标:
    服务器: https://kubernetes.default.svc
    命名空间: prod-us
  来源:
    -  repoURL: https ://acme.github.io/my-charts/
      图表: my-app 
      targetRevision: 2.43 
      helm:
        valueFiles:
        -  $values/common-values.yaml       
        -  $values/all-prod-envs.yaml                 
        -  $values/specific-prod-cluster.yaml 
    -  repoURL: 'https://github.com/example-org/all-my-values.git' 
      targetRevision: HEAD 
      ref: values
注意这里“ref:values”字段与 helm 属性中“$values”前缀之间的关系。当然,你可以为引用选择任何名称,而不仅仅是“values”。
需要明确的是,使用此语法,Argo CD 内置了对 Helm 值层次结构的支持。Argo CD 将从外部源加载图表,并将其与按顺序定义的所有值文件(最后一个生效)组合在一起。
另外,请勿滥用 Argo CD 的多源功能。它并非对应用程序进行分组的通用方法。通常情况下,您应该只有 2 个相关数据源(如下所示),它们构成一个应用程序。如果您发现自己将不相关的应用程序分组,或者拥有超过 2 到 3 个数据源,则需要查看“应用程序组合”和“应用程序集”。
使用带有 Helm 值层次结构的应用程序集
如果您将 Helm Charts 部署为单独的 Argo CD 应用程序,则应该对应用程序集执行相同的操作。我们在之前的指南中详细介绍了应用程序集。
再次强调,这里的关键点是应用程序集也支持 Helm 值层次结构。并且,与应用程序中的所有其他内容一样,您可以模板化图表值、文件夹、修订版本或任何其他您想要的内容。
应用程序集也适用于多个来源。因此,我们可以将目前为止看到的所有内容组合到一个应用程序集中,如下所示:
apiVersion:  argoproj.io/v1alpha1 
kind:  ApplicationSet 
metadata: 
  name:  my-fancy-apps 
  namespace:  argocd 
spec: 
  goTemplate:  true 
  goTemplateOptions: [ "missingkey=error" ] 
  generators: 
  -  list: 
      elements: 
      -  env:  qa 
        type:  non-prod            
      -  env:  prod-eu  
        type:  prod       
      -  env:  prod-us 
        type:  prod       
  template:       
    metadata: 
      name:  ' {
           {.env}} ' 
    spec: 
      # 应用程序所属的项目。
      project:  default 
      sources: 
        -  repoURL:  https://acme.github.io/my-charts/ 
          chart:  my-chart 
          targetRevision:  2.43 helm 
          : 
            valueFiles: 
            -  $values/common-values.yaml           
            -  $values/all-{
           {.type}}-envs.yaml               
            -  $values/{
           {.env}}-values.yaml   
        -  repoURL:  'https://github.com/example-org/all-my-values.git' 
          targetRevision:  HEAD 
          ref:  values 
     
      # 部署应用程序的目标集群和命名空间
      destination: 
        server:  https://kubernetes.default.svc 
        namespace:  ' {
           {.env}} '
此应用程序集定义了 3 个环境(qa、prod-eu、prod-us)。它使用 Helm 层次结构和外部图表。
请注意,我们可以模板化所有值文件的位置,而无需任何额外的模板解决方案。
我们看到许多团队将他们的应用程序 CRD(或应用程序集 CRD)放在 Helm Chart 中,以便在第二层级上进行模板化。这种复杂性是不必要的。应用程序集本身就涵盖了大多数常见场景。应用程序集是一种模板化的方式(与 Helm 相同)。使用 Helm 生成应用程序集(或应用程序)无异于自找麻烦。
如果有些内容无法使用应用程序集模板化,那么最好打开增强请求,而不是再引入另一层模板。
具有 Helm 值的 GitOps 环境完整示例
让我们通过一个半实际的例子来看一下一切是如何运作的。你可以在https://github.com/kostis-codefresh/multi-sources-example找到所有 Kubernetes 清单和 Argo CD 资源。
该存储库包含:
          Git 中的通用 Helm 图表,以及 GitHub 页面提供的 Helm repo 的一部分,网址为https://kostis-codefresh.github.io/multi-sources-example/
          图表中不同环境的Helm 值
          引用 Helm 图表的示例应用程序集
          使用 Helm 层次结构的示例应用
这些环境与推广指南中定义的环境类似,但这次我们使用 Helm 值而不是 Kustomize 覆盖。

我们有以下环境:
          集成测试(非 GPU 和支持 GPU)
          QA(仅一个实例,位于美国)
          在欧盟、亚洲和美国上演
          仅在欧盟和美国生产
与Kustomize 可重用组件类似,我们也有一个可重用的 Helm 值结构,您可以以分层方式使用它。

预期是,要形成完整的 Helm 版本,您需要按顺序组合多个值文件。
例如,要将应用程序部署到欧盟地区的“Staging”环境,您需要使用普通的 Helm 执行以下操作:
helm install ./my-chart/ --generate-name --create-namespace -n staging-eu  
-f my-values/common-values.yaml  
-f my-values/app-version/staging-values.yaml  
-f my-values/env-type/non-prod-values.yaml  
-f my-values/regions/eu-values.yaml  
-f my-values/envs/staging-eu-values.yaml
请记住,最后一个设置有效。您始终可以使用树中更深层的文件的不同配置覆盖通用设置。
 当然,我们不想使用 Helm,而是使用 Argo CD 安装相同的层次结构。这是相应的 Argo CD 应用程序。
apiVersion: argoproj.io/v1alpha1
种类: 应用
程序元数据:
  名称: staging-eu-app
  命名空间: argocd终结器
  :
    -resources-finalizer.argocd.argoproj.io 规范:项目:默认目标:服务器:https://kubernetes.default.svc命名空间:staging-eu来源:-repoURL :https ://github.com/kostis-codefresh/multi-sources-example.git路径:my-chart targetRevision:HEAD helm:valueFiles:- $values/my-values/common-values.yaml - $values/my-values/app-version/staging-values.yaml - $values/my-values/env-type/non-prod-values.yaml - $values/my-values/regions/eu-values.yaml - $values/my-values/envs/staging-eu- values.yaml repoURL:'https://github.com/kostis-codefresh/multi-sources-example.git' targetRevision:HEAD ref:值syncPolicy:syncOptions:-CreateNamespace = true自动化:prune:true selfHeal:true    
   
  
     
     
  
      
       
       
      
        
                   
                       
           
                         
         
      
       
       
  
    
         
    
       
       
再次注意值文件的层次结构。该文件还遵循了我们的应用程序集指南中概述的最佳实践。
如果您使用 Argo CD 部署此应用程序,您可以轻松验证设置是否根据以正确顺序“合并”的所有值正确定义(如果属性重复,则最后一个值获胜)。

这很棒。但正如我们之前多次提到的,您不应该只处理单个应用程序。我们也可以使用 Helm 层次结构和应用程序集。
有很多方法可以对应用程序进行切片和切块。以下示例仅展示了 Helm 层次结构的可能组合。
单一维度上的应用集
这是一个非常简单的应用程序集,其中包括一个列表生成器,用于为单个应用程序建模区域。
apiVersion:  argoproj.io/v1alpha1 
kind:  ApplicationSet 
metadata: 
  name:  my-staging-appset 
  namespace:  argocd 
spec: 
  goTemplate:  true 
  goTemplateOptions: [ "missingkey=error" ] 
  generators: 
  -  list: 
      elements: 
      -  region:  us 
      -  region:  eu 
      -  region:  asia       
  template:       
    metadata: 
      name:  'staging- {
           {.region}} ' 
    spec: 
      # 应用程序所属的项目。
      项目: 默认
      来源:
        -  repoURL: https:  //github.com/kostis-codefresh/multi-sources-example.git
          路径: my-chart 
          targetRevision: HEAD 
          helm:
            valueFiles:
            -  $values/my-values/common-values.yaml           
            -  $values/my-values/app-version/staging-values.yaml               
            -  $values/my-values/env-type/non-prod-values.yaml   
            -  $values/my-values/regions/{
           {.region}}-values.yaml                 
            -  $values/my-values/envs/staging-{
           {.region}}-values.yaml 
        -  repoURL: 'https://github.com/kostis-codefresh/multi-sources-example.git' 
          targetRevision: HEAD 
          ref: values 
     
      # 部署应用程序的目标集群和命名空间 目标
      :
        服务器: https://kubernetes.default.svc
        命名空间: 'staging- {
           {.region}} ' 
      # 同步策略
      syncPolicy: 
        syncOptions: 
          -  CreateNamespace=true   
        automated: 
          prune:  true 
          selfHeal:  true
这里,Helm 值位置根据应用程序所在的区域进行模板化。另一种方法是使用列表生成器生成应用、集群或环境类型的列表。部署此应用程序集将创建 3 个应用程序,每个区域一个。

同样,您可以轻松验证每个部署是否根据各自的 Helm 值层次结构获得适当的设置。
具有多个模板值的应用程序集
在前面的例子中,我们只循环了值文件夹的“region”属性。我们可以使用列表生成器来循环遍历多个不同的属性。
apiVersion:  argoproj.io/v1alpha1 
kind:  ApplicationSet 
metadata: 
  name:  all-my-envs 
  namespace:  argocd 
spec: 
  goTemplate:  true 
  goTemplateOptions: [ "missingkey=error" ] 
  generators: 
  -  list: 
      elements: 
      -  env:  integration-gpu 
        region:  us 
        type:  non-prod 
        version:  qa 
      -  env:  integration-non-gpu 
        region:  us 
        type:  non-prod 
        version:  qa
 [ ...snip… ]     
      -  env:  prod-us 
        region:  us 
        type:  prod 
        version:  prod         
  template:       
    metadata: 
      name:  ' {
           {.env}} ' 
    spec: 
      # 应用程序所属的项目。
      project:  default 
      sources: 
        -  repoURL:  https://github.com/kostis-codefresh/multi-sources-example.git 
          path:  my-chart 
          targetRevision:  HEAD 
          helm: 
            valueFiles: 
            -  $values/my-values/common-values.yaml           
            -  $values/my-values/app-version/{
           {.version}}-values.yaml               
            -  $values/my-values/env-type/{
           {.type}}-values.yaml   
            -  $values/my-values/regions/{
           {.region}}-values.yaml                 
            -  $values/my-values/envs/{
           {.env}}-values.yaml 
        -  repoURL:  'https://github.com/kostis-codefresh/multi-sources-example.git' 
          targetRevision:  HEAD 
          ref:  values 
     
      # 部署应用程序的目标集群和命名空间 destination 
      : 
        server:  https://kubernetes.default.svc 
        namespace:  ' {
           {.env}} '
在上面的示例中,每个部署取决于不同的因素,包括应用程序版本、是否为生产环境、其所在区域等。
该应用程序集实际上只需一步即可创建我们所有的应用程序。

同样,如果您查看每个单独应用程序的资源,您会发现每个应用程序根据文件树中“合并”的所有 Helm 值都有不同的配置。
使用具有 Helm 值层次结构的 Helm 存储库
在之前的所有示例中,我们都使用了 Git 中的 Helm Chart,这也是我们的推荐做法。但是,我们知道有些团队喜欢使用 OCI 注册表或 Helm 存储库。您可以修改之前的“应用程序集”,并使用Helm 存储库(而不是 Git 文件夹)来引用 Helm Chart。
apiVersion:  argoproj.io/v1alpha1 
kind:  ApplicationSet 
metadata: 
  name:  all-my-envs-from-repo 
  namespace:  argocd 
spec: 
  goTemplate:  true 
  goTemplateOptions: [ "missingkey=error" ] 
  generators: 
  -  list: 
      elements: 
      -  env:  integration-gpu 
        region:  us 
        type:  non-prod 
        version:  qa
 [ ...snip… ] 
      -  env:  prod-us 
        region:  us 
        type:  prod 
        version:  prod         
  template:       
    metadata: 
      name:  ' {
           {.env}} ' 
    spec: 
      # 应用程序所属的项目。
      项目: 默认
      来源:
        -  repoURL: https ://kostis-codefresh.github.io/multi-sources-example
          图表: my-chart 
          targetRevision: 0.1 .0 
          helm:
            valueFiles:
            -  $values/my-values/common-values.yaml           
            -  $values/my-values/app-version/{
           {.version}}-values.yaml               
            -  $values/my-values/env-type/{
           {.type}}-values.yaml   
            -  $values/my-values/regions/{
           {.region}}-values.yaml                 
            -  $values/my-values/envs/{
           {.env}}-values.yaml 
        -  repoURL: 'https://github.com/kostis-codefresh/multi-sources-example.git' 
          targetRevision: HEAD 
          ref: values 
     
      # 部署应用程序的目标集群和命名空间目标
      :
        服务器: https://kubernetes.default.svc
        命名空间: ' {
           {.env}} ' 
      # 同步策略
      syncPolicy: 
        syncOptions: 
          -  CreateNamespace=true   
        automated: 
          prune:  true 
          selfHeal:  true
您可以看到,我们现在从 GitHub 页面中托管的 Helm 存储库专门定义 0.1.0 图表,而不是从 Git 修订版加载图表。
除此之外,应用程序集完全相同。部署后的最终结果也与前面的示例相同。
将环境配置保存在自己的文件中
最后一个例子有一个很长的列表生成器。随着你添加更多环境,列表会变得更长。将这些有用的信息提取到单独的文件中要容易得多。我们可以使用Git 文件生成器来实现这一点。
apiVersion: argoproj.io/v1alpha1 
kind: ApplicationSet 
metadata:
  name: all-my-envs-from-repo-with-version 
  namespace: argocd 
spec:
  goTemplate: true 
  goTemplateOptions: [ “missingkey = error” ] 
  generators:
  -git  :
      repoURL: https:  //github.com/kostis-codefresh/multi-sources-example.git
      修订: HEAD
      文件:
      -path  : “appsets / 4-final / env-config / ** / config.json”      
  模板:      
    metadata:
      name: ' {
           {.env}} ' 
    spec:
      #应用程序所属的项目。
      项目: 默认
      来源:
        -  repoURL: https ://kostis-codefresh.github.io/multi-sources-example
          图表: my-chart 
          targetRevision: ' {
           {.chart}} ' 
          helm:
            valueFiles:
            -  $values/my-values/common-values.yaml           
            -  $values/my-values/app-version/{
           {.version}}-values.yaml               
            -  $values/my-values/env-type/{
           {.type}}-values.yaml   
            -  $values/my-values/regions/{
           {.region}}-values.yaml                 
            -  $values/my-values/envs/{
           {.env}}-values.yaml 
        -  repoURL: 'https://github.com/kostis-codefresh/multi-sources-example.git' 
          targetRevision: HEAD 
          ref: values 
     
      # 部署应用程序的目标集群和命名空间 目标
      :
        服务器: https://kubernetes.default.svc
        命名空间: ' {
           {.env}} '
在此示例中,我们提取了config.json 文件中的所有环境配置。我们还对 chart 版本进行了模板化,以便可以针对每个环境进行不同的定义。

这允许您单独编辑每个环境。例如,我们想在所有生产环境中使用 Chart 版本 0.1.0,在所有其他环境中使用 0.2.0。
以下是 prod-us 的配置:
{ 
    “env” : “prod-us” ,
    “region” : “us” ,
    “type” : “prod” ,
    “version” : “prod” ,
    “chart” : “0.1.0” 
  }
QA 部分:
{ 
    “env” : “qa” ,
    “region” : “us” ,
    “type” : “non-prod” ,
    “version” : “qa” ,
    “chart” : “0.2.0” 
  }
现在您拥有一个非常灵活的 Argo CD 设置,可以用最少的努力覆盖大多数场景。
场景 1 — 一步启动所有应用 -> 部署应用程序集
场景 2 — 为所有欧洲部署添加新设置 -> 更改文件 my-values/regions/eu-values.yaml
场景 3 — 对生产环境以外的所有环境进行通用更改 -> 更改文件 my-values/env-type/non-prod-values.yaml
场景 4 — 更改美国生产环境中的 chart 版本 -> 更改文件 env-config/prod/us/config.json
场景 5 — 使 QA 环境继承欧洲地区而非美国的设置 -> 更改文件 env-config/qa/config.json
场景 6 — 创建一个名为“负载测试”的全新环境,其设置与“集成(GPU)”相同 -> 将文件夹 env-config/integration/gpu/ 复制到 env-config/load-testing,并相应地编辑 config.json 文件。
结论:从简单开始
在本指南中,您了解了如何将不同的配置设置与 Helm Chart 组合,以及如何使用 Helm 值层次结构来建模环境而不产生重复。您还学习了如何正确使用 Argo CD 的多源功能。




















暂无评论内容