Kubernetes中Argo CD ApplicationSet Generators的艺术

🚀解锁云原生新姿势!本文详解如何用 Argo CD ApplicationSetGit Generator,基于 GitOps 轻松管理 Kubernetes 集群。通过 Helm chart 模板化部署,实现跨环境应用和组件的自动化配置与同步,告别手动部署烦恼!

译自:The Art of Argo CD ApplicationSet Generators with Kubernetes - Piotr's TechBlog

作者:Piotr Minkowski

本文将教你如何使用 Argo CD ApplicationSet 生成器,通过 GitOps 方法来管理你的 Kubernetes 集群。Argo CD ApplicationSet 是一种 Kubernetes 资源,允许我们管理和部署多个 Argo CD 应用程序。它基于给定的模板动态生成多个 Argo CD 应用程序。因此,我们可以跨多个 Kubernetes 集群部署应用程序,为不同的环境(例如,开发、测试、生产)创建应用程序,并管理许多存储库或分支。通过最少的源代码工作,一切都可以轻松实现。

Argo CD ApplicationSet 支持几种不同的生成器。在本文中,我们将重点介绍 Git 生成器类型。它基于 Git 存储库中的目录结构或分支更改生成 Argo CD 应用程序。它包含两个子类型:Git 目录生成器和 Git 文件生成器。如果你对其他 Argo CD ApplicationSet 生成器感兴趣,你可以在我的博客上找到一些文章。例如,以下文章展示了如何使用 List Generator 在环境之间提升镜像。你还可以找到一篇关于集群决策资源生成器的文章,该文章展示了如何在多个 Kubernetes 集群之间动态传播应用程序。

源代码

如果你想自己尝试,请随时使用我的源代码。为此,你必须克隆我的示例 GitHub 存储库。你必须转到 appset-helm-demo 目录,其中包含该练习所需的完整配置。然后,你只需按照我的说明进行操作即可。

Argo CD 安装

Argo CD 是我们唯一需要在 Kubernetes 集群上安装的工具。我们可以使用官方 Helm chart 在 Kubernetes 上安装它。首先,让我们添加以下 Helm 存储库:

shell 复制代码
helm repo add argo https://argoproj.github.io/argo-helm

之后,我们可以使用以下命令在 argocd 命名空间中的当前 Kubernetes 集群中安装 ArgoCD:

shell 复制代码
helm install my-argo-cd argo/argo-cd -n argocd

我在本练习中使用 OpenShift。使用 OpenShift 控制台,我可以轻松地使用 OpenShift GitOps operator 在集群上安装 ArgoCD。

安装完成后,我们可以轻松访问 Argo CD 仪表板。

我们可以使用 OpenShift 凭据在那里登录。

动机

在本练习中,我们的目标是在 Kubernetes 上部署和运行一些应用程序(一个简单的 Java 应用程序和 Postgres 数据库),并尽量减少源代码工作。这两个应用程序仅展示了如何创建一个标准,该标准可以轻松应用于部署在集群上的任何应用程序类型。在此标准中,目录结构决定了我们的应用程序在 Kubernetes 上的部署方式和位置。我的示例配置存储在单个 Git 存储库中。但是,我们可以使用多个存储库轻松地对其进行扩展,其中 Argoc CD 在中央存储库和其他包含具体应用程序配置的 Git 存储库之间切换。

这是用于部署我们的两个应用程序的目录结构和文件。自定义应用程序和 Postgres 数据库都部署在三个环境中:devtestprod。我们使用 Helm chart 来部署它们。每个环境目录都包含一个带有安装参数的 Helm values 文件。该配置区分了两种不同的安装类型:应用程序和组件。每个应用程序都使用专用于标准部署的相同 Helm chart 进行安装。每个组件都使用该组件提供的自定义 Helm chart 进行安装。例如,对于 Postgres,我们将使用以下 Bitnami chart

arduino 复制代码
.
├── apps
│   ├── aaa-1
│   │   └── basic
│   │       ├── prod
│   │       │   └── values.yaml
│   │       ├── test
│   │       │   └── values.yaml
│   │       ├── uat
│   │       │   └── values.yaml
│   │       └── values.yaml
│   ├── aaa-2
│   └── aaa-3
└── components
    └── aaa-1
        └── postgresql
            ├── prod
            │   ├── config.yaml
            │   └── values.yaml
            ├── test
            │   ├── config.yaml
            │   └── values.yaml
            └── uat
                ├── config.yaml
                └── values.yaml

在部署应用程序之前,我们应该准备带有配额的命名空间、Argo CD 项目和 ApplicationSet 生成器,以管理应用程序部署。以下是全局配置仓库的结构。它还使用 Helm chart 将清单的该部分应用于 Kubernetes 集群。projects 目录中的每个目录都决定了我们的项目名称。另一方面,一个项目包含多个 Kubernetes 命名空间。每个项目可能包含几个不同的 Kubernetes 部署。

markdown 复制代码
.
└── projects
    ├── aaa-1
    │   └── values.yaml
    ├── aaa-2
    │   └── values.yaml
    └── aaa-3
        └── values.yaml

准备全局集群配置

用于命名空间和配额的 Helm 模板

以下是用于为每个命名空间创建命名空间和配额的 Helm 模板。我们将为每个环境(阶段)创建一个项目命名空间。

yaml 复制代码
{{- range .Values.stages }}
---
apiVersion: v1
kind: Namespace
metadata:
  name: {{ $.Values.projectName }}-{{ .name }}
---
apiVersion: v1
kind: ResourceQuota
metadata:
  name: default-quota
  namespace: {{ $.Values.projectName }}-{{ .name }}
spec:
  hard:
    {{- if .config }}
    {{- with .config.quotas }}
      pods: {{ .pods | default "10" }}
      requests.cpu: {{ .cpuRequest | default "2" }}
      requests.memory: {{ .memoryRequest | default "2Gi" }}
      limits.cpu: {{ .cpuLimit | default "8" }}
      limits.memory: {{ .memoryLimit | default "8Gi" }}
    {{- end }}
    {{- else }}
      pods: "10"
      requests.cpu: "2"
      requests.memory: "2Gi"
      limits.cpu: "8"
      limits.memory: "8Gi"
    {{- end }}
{{- end }}

chart/templates/namespace.yaml

用于 Argo CD AppProject 的 Helm 模板

Helm chart 还会为我们的每个项目创建一个专用的 Argo CD AppProject 对象。

yaml 复制代码
apiVersion: argoproj.io/v1alpha1
kind: AppProject
metadata:
  name: {{ .Values.projectName }}
  namespace: {{ .Values.argoNamespace | default "argocd" }}
spec:
  clusterResourceWhitelist:
  - group: '*'
    kind: '*'
  destinations:
  - namespace: '*'
    server: '*'
  sourceRepos:
  - '*'

chart/templates/appproject.yaml

用于 Argo CD ApplicationSet 的 Helm 模板

之后,我们可以继续进行我们练习中最棘手的部分。Helm chart 还定义了一个用于创建 Argo CD ApplicationSet 的模板。此 ApplicationSet 必须分析存储库结构,其中包含应用程序和组件的配置。我们为每个项目定义两个 ApplicationSet。第一个使用 Git Directory 生成器来确定 apps 目录的结构,并使用我的自定义 spring-boot-api-app chart 在所有环境中部署应用程序。可以使用放置在每个应用程序目录中的 Helm 值覆盖 chart 参数。

第二个 ApplicationSet 使用 Git Files 生成器来确定 components 目录的结构。它读取每个目录中 config.yaml 文件的内容。config.yaml 文件设置 Helm chart 的存储库、名称和版本,该 chart 必须用于在 Kubernetes 上安装组件。

yaml 复制代码
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
  name: '{{ .Values.projectName }}-apps-config'
  namespace: {{ .Values.argoNamespace | default "argocd" }}
spec:
  goTemplate: true
  generators:
    - git:
        repoURL: https://github.com/piomin/argocd-showcase.git
        revision: HEAD
        directories:
          {{- range .Values.stages }}
          - path: appset-helm-demo/apps/{{ $.Values.projectName }}/*/{{ .name }}
          {{- end }}
  template:
    metadata:
      name: '{{`{{ index .path.segments 3 }}`}}-{{`{{ index .path.segments 4 }}`}}'
    spec:
      destination:
        namespace: '{{`{{ index .path.segments 2 }}`}}-{{`{{ index .path.segments 4 }}`}}'
        server: 'https://kubernetes.default.svc'
      project: '{{ .Values.projectName }}'
      sources:
        - chart: spring-boot-api-app
          repoURL: 'https://piomin.github.io/helm-charts/'
          targetRevision: 0.3.8
          helm:
            valueFiles:
              - $values/appset-helm-demo/apps/{{ .Values.projectName }}/{{`{{ index .path.segments 3 }}`}}/{{`{{ index .path.segments 4 }}`}}/values.yaml
            parameters:
              - name: appName
                value: '{{ .Values.projectName }}'
        - repoURL: 'https://github.com/piomin/argocd-showcase.git'
          targetRevision: HEAD
          ref: values
      syncPolicy:
        automated:
          prune: true
          selfHeal: true
---
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
  name: '{{ .Values.projectName }}-components-config'
  namespace: {{ .Values.argoNamespace | default "argocd" }}
spec:
  goTemplate: true
  generators:
    - git:
        repoURL: https://github.com/piomin/argocd-showcase.git
        revision: HEAD
        files:
          {{- range .Values.stages }}
          - path: appset-helm-demo/components/{{ $.Values.projectName }}/*/{{ .name }}/config.yaml
          {{- end }}
  template:
    metadata:
      name: '{{`{{ index .path.segments 3 }}`}}-{{`{{ index .path.segments 4 }}`}}'
    spec:
      destination:
        namespace: '{{`{{ index .path.segments 2 }}`}}-{{`{{ index .path.segments 4 }}`}}'
        server: 'https://kubernetes.default.svc'
      project: '{{ .Values.projectName }}'
      sources:
        - chart: '{{`{{ .chart.name }}`}}'
          repoURL: '{{`{{ .chart.repository }}`}}'
          targetRevision: '{{`{{ .chart.version }}`}}'
          helm:
            valueFiles:
              - $values/appset-helm-demo/components/{{ .Values.projectName }}/{{`{{ index .path.segments 3 }}`}}/{{`{{ index .path.segments 4 }}`}}/values.yaml
            parameters:
              - name: appName
                value: '{{ .Values.projectName }}'
        - repoURL: 'https://github.com/piomin/argocd-showcase.git'
          targetRevision: HEAD
          ref: values
      syncPolicy:
        automated:
          prune: true
          selfHeal: true

chart/templates/applicationsets.yaml 在此配置中有几个重要的元素,我们应该注意。Helm 和 ApplicationSet 都使用基于 {{ ... }} 占位符的模板引擎。因此,为了避免冲突,我们应该从 Helm 模板元素中转义 Argo CD ApplicationSet 模板元素。模板中负责生成 Argo CD 应用程序名称的以下部分是该方法的一个很好的例子: '{{{{ index .path.segments 3 }}}}-{{{{ index .path.segments 4 }}}}'。首先,我们使用 AppliocationSet Git 生成器参数 index .path.segments 3,它返回目录路径的第三部分的名称。这些元素使用 ``` 字符进行转义,因此 Helm 不会尝试分析它。

Helm Chart 结构

我们的 ApplicationSets 使用"应用程序的多个来源"功能从 Helm values 文件中读取参数,并将它们从远程存储库注入到 Helm chart 中。因此,我们的应用程序和组件的配置存储库仅包含标准化目录结构中的 values.yaml 文件。我们存储在示例存储库中的唯一 chart 已在上面描述,它负责创建在集群上运行应用程序部署所需的配置。

markdown 复制代码
.
└── chart
    ├── Chart.yaml
    ├── templates
    │   ├── additional.yaml
    │   ├── applicationsets.yaml
    │   ├── appproject.yaml
    │   └── namespaces.yaml
    └── values.yaml

ShellSession 默认情况下,每个项目定义三个环境(阶段):testuatprod

yaml 复制代码
stages:
- name: test
  additionalObjects: {}
- name: uat
  additionalObjects: {}
- name: prod
  additionalObjects: {}

chart/values.yml 我们可以覆盖 Helm values 中特定项目的默认行为。每个项目目录都包含 values.yaml 文件。以下是 aaa-3 项目的 Helm 参数,它仅针对 test 环境将 CPU 请求配额从 2 个 CPU 覆盖为 4 个 CPU。

yaml 复制代码
stages:
- name: test
  config:
    quotas:
      cpuRequest: 4
  additionalObjects: {}
- name: uat
  additionalObjects: {}
- name: prod
  additionalObjects: {}

projects/aaa-3/values.yaml

运行同步过程

在集群上生成全局结构

要启动一个过程,我们必须创建读取项目目录结构的 ApplicationSet。projects 目录中的每个子目录都指示我们项目的名称。我们的 ApplicationSet 使用 Git 目录生成器为每个项目创建一个 Argo CD 应用程序。它的名称包含子目录的名称和 config 后缀。每个生成的应用程序都使用先前描述的 Helm chart 来创建项目请求的所有命名空间、配额和其他资源。它还利用"应用程序的多个来源"功能,允许我们覆盖默认的 Helm chart 设置。它从目录名称读取项目名称,并将其作为参数传递给生成的 Argo CD 应用程序。

yaml 复制代码
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
  name: global-config
  namespace: openshift-gitops
spec:
  goTemplate: true
  generators:
  - git:
      repoURL: https://github.com/piomin/argocd-showcase.git
      revision: HEAD
      directories:
      - path: appset-helm-demo/projects/*
  template:
    metadata:
      name: '{{.path.basename}}-config'
    spec:
      destination:
        namespace: '{{.path.basename}}'
        server: 'https://kubernetes.default.svc'
      project: default
      sources:
      - path: appset-helm-demo/chart
        repoURL: 'https://github.com/piomin/argocd-showcase.git'
        targetRevision: HEAD
        helm:
          valueFiles:
          - $values/appset-helm-demo/projects/{{.path.basename}}/values.yaml
          parameters:
          - name: projectName
            value: '{{.path.basename}}'
          - name: argoNamespace
            value: openshift-gitops
      - repoURL: 'https://github.com/piomin/argocd-showcase.git'
        targetRevision: HEAD
        ref: values
      syncPolicy:
        automated:
          prune: true
          selfHeal: true

YAML 一旦我们创建了 global-config ApplicationSet 对象,奇迹就会发生。以下是从 Git 配置存储库中的目录生成的 Argo CD 应用程序的列表。

首先,有三个带有项目配置的 Argo CD 应用程序。这是因为我们在 projects 目录中定义了 3 个子目录,名称为 aaa-1aaa-2aaa-3

那些 Argo CD 应用程序所应用的配置非常相似,因为它们使用的是同一个 Helm chart。我们可以查看由 aaa-3-config Application 管理的资源列表。这里有三个命名空间(aaa-3-testaaa-3-uataaa-3-prod),它们带有资源配额,一个单独的 Argo CD AppProject,以及两个 ApplicationSet 对象,负责为 appscomponents 目录生成 Argo CD 应用程序。

在这个配置中,我们可以验证 request.cpu ResourceQuota 对象的值是否已从 2 个 CPU 覆盖为 4 个 CPU。

让我们分析一下发生了什么。以下是 Argo CD ApplicationSets 的列表。global-config ApplicationSetprojects 目录中检测到的每个项目生成 Argo CD 应用程序。然后,这些应用程序中的每一个都使用 Helm 模板将两个 ApplicationSet 对象应用到集群。

arduino 复制代码
$ kubectl get applicationset
NAME                    AGE
aaa-1-components-config   29m
aaa-1-apps-config         29m
aaa-2-components-config   29m
aaa-2-apps-config         29m
aaa-3-components-config   29m
aaa-3-apps-config         29m
global-config             29m

以下是已创建的命名空间的列表:

r 复制代码
$ kubectl get ns
NAME        STATUS   AGE
aaa-1-prod  Active   34m
aaa-1-test  Active   34m
aaa-1-uat   Active   34m
aaa-2-prod  Active   34m
aaa-2-test  Active   34m
aaa-2-uat   Active   34m
aaa-3-prod  Active   34m
aaa-3-test  Active   34m
aaa-3-uat   Active   34m

生成和应用部署

我们的示例配置仅包含两个 Deployment。我们在 aaa-1 项目中的 apps 目录中定义了 basic 子目录,在 components 目录中定义了 postgres 子目录。为了简化,aaa-2aaa-3 项目不包含任何 Deployment。但是,我们在其中创建的带有 values.yaml 文件的子目录越多,部署在集群上的应用程序就越多。以下是使用标准 Helm chart 部署的简单应用程序的典型 values.yaml 文件。它定义了镜像仓库、名称和标签。它还设置了 Deployment 名称和环境。

yaml 复制代码
image:
  repository: piomin/basic
  tag: 1.0.0
app:
  name: basic
  environment: prod

对于 postgres 组件,我们必须在 Helm values 中设置更多参数。以下是最终列表:

yaml 复制代码
global:
  compatibility:
    openshift:
      adaptSecurityContext: force
image:
  tag: 1-54
  registry: registry.redhat.io
  repository: rhel9/postgresql-15
primary:
  containerSecurityContext:
    readOnlyRootFilesystem: false
persistence:
  mountPath: /var/lib/pgsql
extraEnvVars:
  - name: POSTGRESQL_ADMIN_PASSWORD
    value: postgresql123
postgresqlDataDir: /var/lib/pgsql/data

以下 Argo CD 应用程序由 aaa-1-apps-config ApplicationSet 生成。它检测到 apps 目录中的 basic 子目录。basic 子目录包含 3 个子目录:带有 values.yaml 文件的 testuatprod。因此,我们有每个环境的 Argo CD 负责在目标命名空间中部署 basic 应用程序。

以下是由 basic-prod Application 管理的资源列表。它使用我的自定义 Helm chart 并将 DeploymentService 对象应用到集群。

以下 Argo CD 应用程序由 aaa-1-components-config ApplicationSet 生成。它检测到 components 目录中的 basic 子目录。postgres 子目录包含 3 个子目录:带有 values.yamlconfig.yaml 文件的 testuatprod。ApplicationSet Files 生成器从 config.yaml 文件中的配置读取仓库、名称和版本。

以下是带有 Bitnami Postgres chart 设置的 config.yaml 文件。我们可以将我们想要在集群上安装的其他任何 chart 放在这里。

yaml 复制代码
chart:
  repository: https://charts.bitnami.com/bitnami
  name: postgresql
  version: 15.5.38

以下是由生成的 Argo CD 应用程序使用的 Bitnami Helm chart 安装的资源列表。

最后的想法

本文证明了 Argo CD ApplicationSet 和 Helm 模板可以一起使用来创建高级配置结构。它展示了如何使用 ApplicationSet Git Directory 和 Files generators 来分析 Git config 仓库中目录和文件的结构。通过这种方法,我们可以提出整个组织中配置结构的标准化,并将其类似地传播到 Kubernetes 集群中部署的所有应用程序。一切都可以在集群管理员级别轻松管理,只需使用访问许多不同配置仓库的单个全局 Argo CD ApplicationSet。

相关推荐
木鱼时刻1 天前
容器与 Kubernetes 基本概念与架构
容器·架构·kubernetes
chuanauc2 天前
Kubernets K8s 学习
java·学习·kubernetes
庸子2 天前
基于Jenkins和Kubernetes构建DevOps自动化运维管理平台
运维·kubernetes·jenkins
李白你好2 天前
高级运维!Kubernetes(K8S)常用命令的整理集合
运维·容器·kubernetes
Connie14512 天前
k8s多集群管理中的联邦和舰队如何理解?
云原生·容器·kubernetes
伤不起bb2 天前
Kubernetes 服务发布基础
云原生·容器·kubernetes
别骂我h3 天前
Kubernetes服务发布基础
云原生·容器·kubernetes
weixin_399380693 天前
k8s一键部署tongweb企业版7049m6(by why+lqw)
java·linux·运维·服务器·云原生·容器·kubernetes
斯普信专业组3 天前
K8s环境下基于Nginx WebDAV与TLS/SSL的文件上传下载部署指南
nginx·kubernetes·ssl
&如歌的行板&3 天前
如何在postman中动态请求k8s中的pod ip(基于nacos)
云原生·容器·kubernetes