【GitOps系列】使用 ArgoCD ApplicationSet 来实现多环境管理

文章目录

      • 前言
      • 自动多环境管理概述
      • 自动化管理多环境实战
        • 示例应用简介
        • ApplicationSet 简介
        • 部署 ApplicationSet
        • 访问多环境
      • 创建新环境实验
      • 结语

前言

聊起多环境,通常可能会立即想到下面几个常见的环境:

  • 开发环境
  • 测试环境
  • 预发布环境
  • 生产环境

为了让不同职责的人员在不同的环境下独立工作,我们一般会将不同环境隔离。通常,开发环境主要用于开发人员的日常开发,测试环境则是为测试团队而准备的,预发布是正式发布到生产环境之前的最后一道防线,除了数据以外,应该尽量和生产环境保持一致。
当然,对有些团队来说,他们可能还希望开发人员之间相互隔离,也就是为每一个开发者分配一个独立的开发环境,使他们互不干扰。
在非云原生技术架构体系下,环境一般是由特定的团队人工维护的。所以,要想得到一个新的环境,由于文档和技术方面的原因,过程并不简单。但是,在云原生的业务架构体系下,应用是通过标准的 Kubernetes 对象被“定义”出来的。所以,在这种情况下,得到一个新的环境就变得非常容易了。本次学习如何使用ArgoCD ApplicationSet来实现 GitOps 自动多环境管理,并通过ArgoCD Generator来达到“代码即环境”的效果。

自动多环境管理概述

使用 ArgoCD ApplicationSet 来实现自动多环境管理的整体架构
【GitOps系列】使用 ArgoCD ApplicationSet 来实现多环境管理_第1张图片
在这张架构图中,首先会创建一个 ApplicationSet 对象,它是一个 Application 集合。它可以生成 Application CRD 资源,进而自动创建多个 ArgoCD 应用。不同应用实际上就对应了不同的环境。
ApplicationSet 怎么知道要创建几个 Application 对象呢?这就需要用到 ApplicationSet Generators 了。
ApplicationSet Generators 是一个可以自动生成 Application 对象的生成器,它可以通过遍历 Git 仓库中的目录来决定生成几个 Application 对象,如下架构图:
【GitOps系列】使用 ArgoCD ApplicationSet 来实现多环境管理_第2张图片
假设我们现在有一个 Helm 应用的 Git 仓库,env 目录下存放了不同环境的values.yaml配置文件,那么,ApplicationSet Generators 就可以遍历这些目录,并且自动创建不同环境的 Application 对象,这样就实现了目录和环境的映射关系。也就是说,当我们需要创建一个新的环境时, 只需要创建一个目录以及配置文件 values.yaml 就可以了!
这样,不管是为同一个应用创建不同的环境,还是为不同的开发者创建隔离的开发环境,都可以把创建环境等同于创建目录,实现了 “代码即环境”。

自动化管理多环境实战

示例仓库代码:https://github.com/Hugh-yw/kubernetes-example/tree/main/helm-env

示例应用简介

将示例应用克隆到本地之后,进入 helm-env 目录,目录结构如下:

.
├── Chart.yaml
├── applicationset.yaml
├── env
│   ├── dev
│   │   └── values.yaml
│   ├── prod
│   │   └── values.yaml
│   └── test
│       └── values.yaml
└── templates
    ├── frontend.yaml
    └── ingress.yaml

从它的目录结构可以看出,它由 Chart.yaml、applicationset.yaml、env 目录和 templates 目录组成,熟悉 Helm 的同学应该一眼就能看出,其实它是一个 Helm Chart。不同的是,Helm 的配置文件 values.yaml 并没有放在 Chart 的根目录,而是放在了 env 目录下。

templates 目录存放着示例应用的 Kubernetes 对象,为了简化演示过程,本次只部署前端相关的对象,也就是 frontend.yaml。

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: frontend
  annotations:
    kubernetes.io/ingress.class: nginx
spec:
  rules:
    - host: {{ .Release.Namespace }}.env.my
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: frontend-service
                port:
                  number: 3000

需要注意的是:我在 Ingress 对象中使用了 Helm 的内置变量,也就是 Release.Namespace,它实际上指的是 Helm Chart 部署的命名空间,我把它和域名做了拼接。不同的环境将会被部署到独立的命名空间下,这样也就使不同的环境具备了独立的访问域名,如下图所示:
【GitOps系列】使用 ArgoCD ApplicationSet 来实现多环境管理_第3张图片

ApplicationSet 简介

它可以自动生成多个 Application 对象,不同的 Application 对象实际上对应了不同的环境。
示例应用目录下有一个名为 applicationset.yaml 的文件,它定义了 ApplicationSet 的内容。

cat applicationset.yaml
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
  name: frontend
  namespace: argocd
spec:
  generators:
  - git:
      repoURL: "https://github.com/Hugh-yw/kubernetes-example.git"
      revision: HEAD
      files:
      - path: "helm-env/env/*/values.yaml"
  template:
    metadata:
      name: "{{path.basename}}"
    spec:
      project: default
      source:
        repoURL: "https://github.com/Hugh-yw/kubernetes-example.git"
        targetRevision: HEAD
        path: "helm-env"
        helm:
          valueFiles:
          - "env/{{path.basename}}/values.yaml"
      destination:
        server: 'https://kubernetes.default.svc'
        namespace: '{{path.basename}}'
      syncPolicy:
        automated: {}
        syncOptions:
          - CreateNamespace=true

这里我们分成两部分:
第一部分是 spec.generators,第二部分是 spec.template。
Generators 指的是生成器。这里,我们使用 Git 生成器,并指定了 Helm Chart 仓库地址。请注意, 你需要将这个地址替换为自己的仓库地址,如果仓库为私有权限,那么还需要在 ArgoCD 控制台配置仓库的凭据信息
revision 的值的 HEAD,指的是远端最新修改的版本。files 字段是配置的重点,它通过通配符“*”号来匹配 env 目录下的 values.yaml 文件,并为 template 字段下的 path 变量提供值。
template 字段:template 实际上就是在为 Application 配置模板,结合生成器,它能够动态生成 Application 对象。例如,metadata.name 字段配置了每一个 Application 的名称,在这个例子中,path.basename 变量对应三个值,分别是 env 下子目录的名称,也就是 dev、test 和 prod。
source.repoURL 字段表示 Helm Chart 的来源仓库, 替换为你的仓库地址。
此外,在 helm.valueFiles 里同样也用到了这个变量,在这里,我们为不同的环境指定了不同的 values.yaml,这样就实现了环境隔离。
最后,destination.namespace 字段也使用了变量,它配置了部署应用的命名空间。
最终,在这个例子中,ApplicationSet 会根据目录结构生成 三个 Application 对象,而 Application 对象又会在不同的命名空间下部署示例应用,它们分别对应 dev、test 和 prod 环境。

部署 ApplicationSet

kubectl apply -f applicationset.yaml 
applicationset.argoproj.io/frontend created

打开 ArgoCD 控制台,可以看到 ApplicationSet 创建了三个应用,名称分别为 dev、test 和 prod,并且它们分别被部署在了不同的命名空间下

访问多环境

dev.env.my test.env.my prod.env.my 域名提前配置好解析

到这里,我们就成功使用 ApplicationSet 创建了多个隔离环境。当我们需要对不同的环境进行更新时,只需要更新 env 目录下对应环境的 values.yaml 文件,就可以触发 ArgoCD 自动同步了,不同环境之间互不影响。
此外,当我们需要创建新的环境时,只需要在 env 目录下增加一个目录和 values.yaml 文件就可以了,ArgoCD 会根据配置自动创建新的环境。

创建新环境实验

首先,在 env 目录下创建 staging 目录,表示预发布环境

cd helm-env/env
mkdir staging

$ cp dev/values.yaml staging
$ git add .
$ git commit -m 'add stagign'
$ git push origin main

稍等几分钟,ArgoCD 将自动同步,并为我们创建新的 staging 环境,如下图所示:
【GitOps系列】使用 ArgoCD ApplicationSet 来实现多环境管理_第4张图片

结语

本次主要学习了如何通过 ApplicationSet 来创建和管理多环境。在实际的业务场景中,我们通常会有多环境的业务需求,相比较传统的创建环境的方式,使用 ApplicationSet 大大简化了拉起一个新环境的过程。

“代码即环境”听起来虽然比较抽象,但实现起来并没有这么困难。借助应用定义,结合 Git 仓库,我们很容易就可以实现多环境管理。需要注意的是,在众多 GitOps 多环境管理的方案中,你可能还会看到另一种方案: 通过分支来管理多环境。

简单对比一下这两种方式。采用多分支来管理 GitOps 中的多环境并不能够很好地同时解决可维护性和唯一可信源的问题。首先,分支管理模型会使我们面临差异和合并的问题,这对长期维护来说成本较高,并且在更新环境时,需要切换到不同的分支去操作,这更容易导致人为的错误。其次,分支的管理方式没有目录管理方式来得直观。
所以, 在实际的项目中,我推荐你按照这节课的讲解以目录的方式来管理不同的环境。

多环境除了可以用来区分开发环境、测试环境和生产环境之外,还可以很方便地为每一位开发者提供独立的开发环境。
此次演示中,由于所有环境都共用 Helm Chart 的 Template 目录,所以对于应用而言,我们只需要维护 Template 目录就可以间接管理所有的环境了。而对于不同的环境,我们可以使用环境目录下的 values.yaml 文件进行差异化的配置。这样就同时兼顾了可维护性和环境的差异化配置。

参考资料:
https://time.geekbang.org/column/intro/100312001

你可能感兴趣的:(CLOUD,NATIVE,#,Kubernetes,CI/CD,argocd,ci/cd,GitOps)