本文基于Argo CD的Progressive 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的高级用法,旨在实现对应用间依赖和多环境部署的统一管理。工作原理如下:
通过Matrix Generator定义生成多环境部署(dev/staging)的Application,并给Application添加应用名称标识的Label。
在
rollingSync
中定义有依赖关系的应用的创建顺序(例如先部署app1
,再部署app2
)。
配置完成后,将按照定义的dev-app1
>dev-app2
>staging-app1
>staging-app2
顺序进行部署,如下图所示:
Progressive Syncs
Argo CD的Progreessive Syncs功能可以通过ApplicationSet实现智能部署编排。该功能根据ApplicationSet所管理的Application的依赖关系和健康状态,控制Application的创建和更新顺序。您可以定义steps
列表,Progressive Syncs会持续监控每个阶段中Application的健康状态,当Application达到Healthy
状态后,才会触发下一阶段的操作。
DaemonSet、StatefulSet和Argo Rollout均受Progressive Syncs功能支持,因为Application在 Pod 部署过程中会进入Progressing
状态。实际上,任何具有健康检查并能够报告Progressing
状态的资源都受Progressive Syncs功能支持。
应用示例目录结构
本示例包含app1
和app2
两个应用,app2
需要依赖app1
,并且两个应用都需要部署到dev
和staging
环境,示例目录结构如下所示:
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.json
中cluster_address
为您关联集群的API Server端点。manifests/apps/app1
:使用kustomize管理的应用1,每类型环境中可能包含多个地域(示例仅展示一个bj)。manifests/apps/app2
:使用kustomize管理的应用2,每类型环境中可能包含多个地域。
前提条件
步骤一:开启Progressive Syncs功能
当前ACK One GitOps仅在高可用模式支持开启Progressive Syncs,开启步骤如下。
使用舰队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 ...
执行如下命令,重启argocd-application-controller pod。
kubectl rollout restart deployment argocd-application-controller -n argocd
步骤二:在舰队中创建管理应用间依赖和多环境部署的ApplicationSet
登录ACK One控制台,在左侧导航栏选择 。
单击
进入创建多集群应用 - 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 Syncs的RollingSync来实现应用间的依赖。本例中,该ApplicationSet会生成四个Application。
Progressive Syncs的
rollingSync.steps
中,匹配的Label是ArgoCD Application的Label,因此需要在.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方式。
步骤三:查看应用部署依赖关系和发布状态
由于每个应用需要发布到dev和staging两个环境中,因此app1
和app2
各自需要生成两个Application,共计四个应用实例。它们的部署顺序将为dev-app1
>dev-app2
>staging-app1
>staging-app2
,每个应用需等待前一个应用同步成功且状态健康后启动。
通过控制台查看
登录ACK One控制台,在左侧导航栏选择 。
找到目标多集群应用,单击查看对应Application。
应用将按照如下顺序进行部署,预期输出如下:
部署
dev-app1
。部署
dev-app2
。部署
staging-app1
。部署
staging-app2
。
通过命令行查看
使用舰队KubeConfig,执行如下命令查看应用状态。
kubectl -nargocd get app
应用将按照如下顺序进行部署,预期输出如下:
部署
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
部署
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
部署
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
部署
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