使用ApplicationSet协调多环境部署与应用依赖关系

本文基于Argo CDProgressive Syncs分阶段同步功能,结合ApplicationSet的多环境资源编排能力,构建了一套支持开发与预发布环境间多应用依赖管理的自动化部署体系。

背景信息

Web应用通常由前端(Frontend)、后端(Backend)和数据库(Database)三部分组成。您在部署时,会希望按以下顺序来部署:Database > Backend > Frontend,来保证其依赖性。当您使用ACK One GitOps来部署该类应用时,Database/Backend/Frontend每一部分对应一个Argo CD Applicaiton,则需要考虑处理多个Application之间的部署依赖问题。

ApplicationSet用于简化多集群应用编排,可以基于单一应用编排并根据编排内容自动生成一个或多个Application,所以通常使用ApplicationSet来管理您的应用的多集群或多环境部署(dev/staging/prod)。

同时满足应用间依赖管理和多环境部署的需求较为复杂。为此,本文将介绍一种ApplicationSet的高级用法,旨在实现对应用间依赖和多环境部署的统一管理。工作原理如下:

  1. 通过Matrix Generator定义生成多环境部署(dev/staging)的Application,并给Application添加应用名称标识的Label。

  2. rollingSync中定义有依赖关系的应用的创建顺序(例如先部署app1,再部署app2)。

配置完成后,将按照定义的dev-app1>dev-app2>staging-app1>staging-app2顺序进行部署,如下图所示:

image

Progressive Syncs

Argo CDProgreessive Syncs功能可以通过ApplicationSet实现智能部署编排。该功能根据ApplicationSet所管理的Application的依赖关系和健康状态,控制Application的创建和更新顺序。您可以定义steps列表,Progressive Syncs会持续监控每个阶段中Application的健康状态,当Application达到Healthy状态后,才会触发下一阶段的操作。

说明

DaemonSet、StatefulSetArgo Rollout均受Progressive Syncs功能支持,因为Application在 Pod 部署过程中会进入Progressing状态。实际上,任何具有健康检查并能够报告Progressing状态的资源都受Progressive Syncs功能支持。

应用示例目录结构

示例包含app1app2两个应用,app2需要依赖app1,并且两个应用都需要部署到devstaging环境,示例目录结构如下所示:

manifests
└── apps
    ├── env
    │   ├── dev
    │   │   └── config.json
    │   └── staging
    │       └── config.json
    ├── app1
    │   ├── base
    │   │   ├── deployment.yaml
    │   │   ├── kustomization.yaml
    │   │   └── service.yaml
    │   └── overlay
    │       ├── dev
    │       │   └── bj
    │       │       ├── deployment.yaml
    │       │       └── kustomization.yaml
    │       └── staging
    │           └── bj
    │               ├── deployment.yaml
    │               └── kustomization.yaml
    └── app2
        ├── base
        │   ├── deployment.yaml
        │   ├── kustomization.yaml
        │   └── service.yaml
        └── overlay
            ├── dev
            │   └── bj
            │       ├── deployment.yaml
            │       └── kustomization.yaml
            └── staging
                └── bj
                    ├── deployment.yaml
                    └── kustomization.yaml
  • manifests/apps/env:请根据具体环境做自定义配置。

    重要

    若您使用本示例进行部署,需要将示例Fork到您自己的仓库,并需修改config.jsoncluster_address为您关联集群的API Server端点

  • manifests/apps/app1:使用kustomize管理的应用1,每类型环境中可能包含多个地域(示例仅展示一个bj)。

  • manifests/apps/app2:使用kustomize管理的应用2,每类型环境中可能包含多个地域。

前提条件

步骤一:开启Progressive Syncs功能

当前ACK One GitOps仅在高可用模式支持开启Progressive Syncs,开启步骤如下。

  1. 使用舰队kubeconfig,执行以下命令修改配置。

    kubectl edit cm -nargocd argocd-cmd-params-cm

    argocd-cmd-params-cm添加配置applicationsetcontroller.enable.progressive.syncs: "true",如下所示。

    apiVersion: v1
    data:
      applicationsetcontroller.enable.progressive.syncs: "true"
      ...
    kind: ConfigMap
    metadata:
      name: argocd-cmd-params-cm
      namespace: argocd
      ...
  2. 执行如下命令,重启argocd-application-controller pod。

     kubectl rollout restart deployment argocd-application-controller -n argocd

步骤二:在舰队中创建管理应用间依赖和多环境部署的ApplicationSet

  1. 登录ACK One控制台,在左侧导航栏选择舰队 > 多集群应用

  2. 单击创建多集群应用 > GitOps进入创建多集群应用 - GitOps页面,单击YAML 创建,使用以下示例创建应用。

    apiVersion: argoproj.io/v1alpha1
    kind: ApplicationSet
    metadata:
      name: dependency-apps
      namespace: argocd
    spec:
      goTemplate: true
      goTemplateOptions: ["missingkey=error"]
      generators:
        - matrix:
            generators:
              - git:
                  repoURL: https://github.com/AliyunContainerService/gitops-demo.git
                  revision: main
                  pathParamPrefix: env
                  files:
                  - path: "manifests/apps/env/*/config.json"
              - git:
                  repoURL: https://github.com/AliyunContainerService/gitops-demo.git
                  revision: main
                  pathParamPrefix: target
                  directories:
                  - path: "manifests/apps/app1/overlay/{{.env.path.basename}}/*"
        - matrix:
            generators:
              - git:
                  repoURL: https://github.com/AliyunContainerService/gitops-demo.git
                  revision: HEAD
                  pathParamPrefix: env
                  files:
                  - path: "manifests/apps/env/*/config.json"
              - git:
                  repoURL: https://github.com/AliyunContainerService/gitops-demo.git
                  revision: HEAD
                  pathParamPrefix: target
                  directories:
                  - path: "manifests/apps/app2/overlay/{{.env.path.basename}}/*"        
      strategy:
        type: RollingSync
        rollingSync:
          steps:
            - matchExpressions:
                - key: app.kubernetes.io/instance
                  operator: In
                  values:
                    - app1
                - key: environment
                  operator: In
                  values:
                    - dev
            - matchExpressions:
                - key: app.kubernetes.io/instance
                  operator: In
                  values:
                    - app2
                - key: environment
                  operator: In
                  values:
                    - dev
            - matchExpressions:
                - key: app.kubernetes.io/instance
                  operator: In
                  values:
                    - app1
                - key: environment
                  operator: In
                  values:
                    - staging
            - matchExpressions:
                - key: app.kubernetes.io/instance
                  operator: In
                  values:
                    - app2
                - key: environment
                  operator: In
                  values:
                    - staging
      template:
        metadata:
          name: '{{.env.path.basename}}-{{index .target.path.segments 2}}-{{.target.path.basename}}'
          labels:
            app.kubernetes.io/instance: '{{index .target.path.segments 2}}'
            environment: '{{.env.path.basename}}'
        spec:
          project: default
          source:
            repoURL: https://github.com/AliyunContainerService/gitops-demo.git
            targetRevision: HEAD
            path: '{{.target.path.path}}'
          destination:
            #server: https://kubernetes.default.svc
            server: '{{index .cluster_address .target.path.basename}}'
            namespace: demo
          syncPolicy:
            automated:
              prune: true
              selfHeal: true
            retry:
              limit: 5
              backoff:
                duration: 5s
                maxDuration: 3m0s
                factor: 2
            syncOptions:
              - CreateNamespace=true

    本例使用Matrix Generator来管理应用部署到多环境,使用Progressive SyncsRollingSync来实现应用间的依赖。本例中,该ApplicationSet会生成四个Application。

    • Progressive SyncsrollingSync.steps中,匹配的LabelArgoCD ApplicationLabel,因此需要在.spec.template.metadata.labels中明确生成的Label。

    • Matrix Generator组合了两个Git Generator,以下是Git Generator提供的变量。

      参数

      说明

      本文示例值

      {{.path.basename}}

      配置文件所在目录的路径的基础名称。

      • dev

      • staging

      {{.target.path.path}}

      Git 仓库中包含匹配配置文件的目录路径。

      • manifests/apps/app2/overlay/dev/bj

      • manifests/apps/app2/overlay/staging/bj

      {{index .path.segments n}}

      Git 仓库中匹配配置文件的路径,拆分为数组元素(n - array index)。

      • app1

      • app2

      说明

      若您指定了pathParamPrefix,若需引用 {{.path.basename}} 等变量,则需要添加前缀路径以访问变量。例如原变量 {{.path.basename}} 需修改为 {{.target.path.basename}},其中 target 为 pathParamPrefix 的值。

重要

为保障生产环境的安全性,建议您将生产环境和开发测试预发环境分为两个不同的ApplicationSet。生成生产环境应用时,应选择Manual Sync方式。

步骤三:查看应用部署依赖关系和发布状态

由于每个应用需要发布到devstaging两个环境中,因此app1app2各自需要生成两个Application,共计四个应用实例。它们的部署顺序将为dev-app1>dev-app2>staging-app1>staging-app2,每个应用需等待前一个应用同步成功且状态健康后启动。

通过控制台查看

  1. 登录ACK One控制台,在左侧导航栏选择舰队 > 多集群应用

  2. 找到目标多集群应用,单击查看对应Applicationimage

    应用将按照如下顺序进行部署,预期输出如下:

    1. 部署dev-app1

      image

    2. 部署dev-app2image

    3. 部署staging-app1image

    4. 部署staging-app2image

通过命令行查看

使用舰队KubeConfig,执行如下命令查看应用状态。

 kubectl -nargocd get app

应用将按照如下顺序进行部署,预期输出如下:

  1. 部署dev-app1

    NAME              SYNC STATUS   HEALTH STATUS
    dev-app1-bj       Synced        Progressing
    dev-app2-bj       OutOfSync     Missing
    staging-app1-bj   OutOfSync     Missing
    staging-app2-bj   OutOfSync     Missing
  2. 部署dev-app2

    NAME              SYNC STATUS   HEALTH STATUS
    dev-app1-bj       Synced        Healthy
    dev-app2-bj       Synced        Progressing
    staging-app1-bj   OutOfSync     Missing
    staging-app2-bj   OutOfSync     Missing
  3. 部署staging-app1

    NAME              SYNC STATUS   HEALTH STATUS
    dev-app1-bj       Synced        Healthy
    dev-app2-bj       Synced        Healthy
    staging-app1-bj   Synced        Progressing
    staging-app2-bj   OutOfSync     Missing
  4. 部署staging-app2

    NAME              SYNC STATUS   HEALTH STATUS
    dev-app1-bj       Synced        Healthy
    dev-app2-bj       Synced        Healthy
    staging-app1-bj   Synced        Healthy
    staging-app2-bj   Synced        Progressing