探索了在多群集环境中使用 GitOps 进行工作负载管理

开发云原生应用程序的企业组织面临着在多个 Kubernetes 群集中大规模部署、配置和提升各种应用程序和服务的挑战。 此环境可能包括 Azure Kubernetes 服务 (AKS) 群集、在其他公有云提供商上运行的群集,或在通过 Azure Arc 连接到 Azure 的本地数据中心运行的群集。请参阅概念性文章,其中探索了业务流程、难题和解决方案体系结构。

本文将引导你了解多群集 Kubernetes 环境中工作负载部署和配置的示例场景。 首先,使用几个 GitHub 存储库和 AKS 群集部署示例基础结构。 接下来,完成一组用例,在这些用例中,你充当不同的角色(平台团队和应用程序团队)在同一环境中工作。

先决条件

为了成功部署示例,你需要:

  • Azure 订阅。 如果你还没有该订阅,请在开始之前先创建试用版订阅
  • Azure CLI
  • GitHub CLI
  • Helm
  • kubectl
  • jq
  • 具有如下范围的 GitHub 令牌:repoworkflowwrite:packagesdelete:packagesread:orgdelete_repo

1 - 部署示例

若要部署示例,请运行以下脚本:

mkdir kalypso && cd kalypso
curl -fsSL -o deploy.sh https://raw.githubusercontent.com/microsoft/kalypso/main/deploy/deploy.sh
chmod 700 deploy.sh
./deploy.sh -c -p <prefix. e.g. kalypso> -o <GitHub org. e.g. eedorenko> -t <GitHub token> -l <azure-location. e.g. chinanorth3> 

此脚本可能需要 10-15 分钟才能完成。 完成后,它会在输出中报告执行结果,如下所示:

Deployment is complete!
---------------------------------
Created repositories:
  - https://github.com/eedorenko/kalypso-control-plane
  - https://github.com/eedorenko/kalypso-gitops
  - https://github.com/eedorenko/kalypso-app-src
  - https://github.com/eedorenko/kalypso-app-gitops
---------------------------------
Created AKS clusters in kalypso-rg resource group:
  - control-plane
  - drone (Flux based workload cluster)
  - large (Flux based workload cluster)
---------------------------------  

备注

如果部署出现问题,可使用以下命令删除所创建的资源:

./deploy.sh -d -p <preix. e.g. kalypso> -o <GitHub org. e.g. eedorenko> -t <GitHub token> -l <azure-location. e.g. chinanorth3> 

示例概述

此部署脚本创建了一个基础结构,如下图所示:

显示示例基础结构的示意图。

有下面几个平台团队存储库:

  • 控制平面:包含使用概括性抽象定义的平台模型,例如环境、群集类型、应用程序和服务、映射规则和配置以及提升工作流。
  • 平台 GitOps:包含表示多群集环境拓扑的最终清单,例如在每个环境中有哪些群集类型可用、在其中计划了哪些工作负载以及设置了哪些平台配置值。
  • 服务源:包含示例拨号音平台服务的概括性清单模板。
  • 服务 GitOps:包含要跨群集部署的示例拨号音平台服务的最终清单。

基础结构还包括几个应用程序团队存储库:

  • 应用程序源:包含示例应用程序源代码,其中包括 Docker 文件、清单模板和 CI/CD 工作流。
  • 应用程序 GitOps:包含要部署到部署目标的最终示例应用程序清单。

该脚本创建了以下 Azure Kubernetes 服务 (AKS) 群集:

  • control-plane - 此群集是不运行任何工作负载的管理群集。 control-plane 群集托管 Kalypso 计划程序运算符,该运算符将概括性抽象从控制平面存储库转换到平台 GitOps 存储库中的原始 Kubernetes 清单。
  • drone - 示例工作负载群集。 此群集已安装 GitOps 扩展,并使用 Flux 协调平台 GitOps 存储库中的清单。 对于此示例,drone 群集可表示已启用 Azure Arc 的群集或具有 Flux/GitOps 扩展的 AKS 群集。
  • large - 示例工作负载群集。 此群集已安装 GitOps 扩展,并使用 Flux 协调平台 GitOps 存储库中的清单。

了解控制平面

control plane 存储库包含 3 个分支:maindevstagedevstage 分支包含特定于 DevStage 环境的配置。 另一方面,main 分支不表示任何特定环境。 main 分支的内容是通用的,供所有环境使用。 对 main 分支的任何更改都必须跨环境提升。 例如,只有在 Dev 环境中成功测试后,才能将新应用程序或新模板提升到 Stage 环境。

main 分支:

Folder 说明
.github/workflows 包含实现提升流的 GitHub 工作流。
.environments 包含环境列表,其中包含指向具有环境配置的分支的指针。
模板 包含各种协调器的清单模板,以及工作负载命名空间的模板。
工作负荷 包含已加入的应用程序和服务的列表,其中包含指向相应 GitOps 存储库的指针。

devstage 分支:

说明
cluster-types 包含环境中可用群集类型的列表。 群集类型分组到自定义子文件夹中。 每个群集类型都带有一组标签。 它指定用于从 GitOps 存储库提取清单的协调器类型。 子文件夹还包含许多配置映射,其中包含群集类型上可用的平台配置值。
configs/dev-config.yaml 包含配置映射,其中包含适用于环境中所有群集类型的平台配置值。
计划 包含将工作负载部署目标映射到环境中的群集类型的计划策略。
base-repo.yaml 一个指针,它指向 Control Plane 存储库 (main) 中计划程序应从中获取模板和工作负载注册的位置。
gitops-repo.yaml 一个指针,它指向 Platform GitOps 存储库中计划程序应对已生成的清单执行拉取请求 (PR) 的位置。

提示

Control Plane 存储库中的文件夹结构并不重要。 此示例提供了在存储库中整理文件的一种方法,但你也可随意按自己喜欢的方式进行整理。 计划程序关注的是文件的内容,而不是文件所在的位置。

2 - 平台团队:加入新的应用程序

应用程序团队运行其软件开发生命周期。 他们生成应用程序并跨环境对其进行提升。 该团队不知道哪些群集类型可用,也不知道应用程序将要部署到哪里。 但他们确实知道自己希望在 Dev 环境中部署应用程序来进行功能和性能测试,在 Stage 环境中部署应用程序来进行 UAT 测试。

应用程序团队在应用程序源存储库的工作负载文件中描述了这一意图:

apiVersion: scheduler.kalypso.io/v1alpha1
kind: Workload
metadata:
  name: hello-world-app
  labels:
    type: application
    family: force
spec:
  deploymentTargets:
    - name: functional-test
      labels:
        purpose: functional-test
        edge: "true"
      environment: dev
      manifests:
        repo: https://github.com/microsoft/kalypso-app-gitops
        branch: dev
        path: ./functional-test
    - name: performance-test
      labels:
        purpose: performance-test
        edge: "false"
      environment: dev
      manifests:
        repo: https://github.com/microsoft/kalypso-app-gitops
        branch: dev
        path: ./performance-test   
    - name: uat-test
      labels:
        purpose: uat-test
      environment: stage
      manifests:
        repo: https://github.com/microsoft/kalypso-app-gitops
        branch: stage
        path: ./uat-test   

此文件中有一个列表,上面列出了 3 个部署目标。 这些目标带有自定义标签,并指向应用程序 GitOps 存储库中的文件夹,应用程序团队在这些文件夹中为每个部署目标生成应用程序清单。

通过此文件,应用程序团队向平台团队请求 Kubernetes 计算资源。 作为回应,平台团队必须在控制平面存储库中注册应用程序。

若要注册应用程序,请打开终端并使用以下脚本:

export org=<GitHub org>
export prefix=<prefix>

# clone the control-plane repo
git clone https://github.com/$org/$prefix-control-plane control-plane
cd control-plane

# create workload registration file

cat <<EOF >workloads/hello-world-app.yaml
apiVersion: scheduler.kalypso.io/v1alpha1
kind: WorkloadRegistration
metadata:
  name: hello-world-app
  labels:
    type: application
spec:
  workload:
    repo: https://github.com/$org/$prefix-app-src
    branch: main
    path: workload/
  workspace: kaizen-app-team
EOF

git add .
git commit -m 'workload registration'
git push

备注

为简单起见,此示例将更改直接推送到 main。 在实际操作中,你将创建一个拉取请求来提交更改。

这样操作后,应用程序就会加入到控制平面中。 但控制平面仍然不知道如何将应用程序部署目标映射到所有群集类型。

在 Dev 环境上定义应用程序计划策略

平台团队必须定义如何在 Dev 环境中的群集类型上计划应用程序部署目标。 为此,请使用以下脚本提交 functional-testperformance-test 部署目标的计划策略:

# Switch to dev branch (representing Dev environemnt) in the control-plane folder
git checkout dev
mkdir -p scheduling/kaizen

# Create a scheduling policy for the functional-test deployment target
cat <<EOF >scheduling/kaizen/functional-test-policy.yaml
apiVersion: scheduler.kalypso.io/v1alpha1
kind: SchedulingPolicy
metadata:
  name: functional-test-policy
spec:
  deploymentTargetSelector:
    workspace: kaizen-app-team
    labelSelector:
      matchLabels:
        purpose: functional-test
        edge: "true"
  clusterTypeSelector:
    labelSelector:
      matchLabels:
        restricted: "true"
        edge: "true"
EOF

# Create a scheduling policy for the performance-test deployment target
cat <<EOF >scheduling/kaizen/performance-test-policy.yaml
apiVersion: scheduler.kalypso.io/v1alpha1
kind: SchedulingPolicy
metadata:
  name: performance-test-policy
spec:
  deploymentTargetSelector:
    workspace: kaizen-app-team
    labelSelector:
      matchLabels:
        purpose: performance-test
        edge: "false"
  clusterTypeSelector:
    labelSelector:
      matchLabels:
        size: large
EOF

git add .
git commit -m 'application scheduling policies'
git config pull.rebase false
git pull --no-edit
git push

第一个策略规定,应在带有标签 restricted: "true" 的所有环境群集类型上计划 kaizen-app-team 工作区的所有部署目标(带有标签 purpose: functional-testedge: "true")。 可以将工作区视为应用程序团队生成的一组应用程序。

第二个策略规定,应在带有标签 size: "large" 的所有环境群集类型上计划 kaizen-app-team 工作区的所有部署目标(带有标签 purpose: performance-testedge: "false")。

推送到 dev 分支会触发计划过程,并创建对 Platform GitOps 存储库中的 dev 分支的 PR:

显示针对 dev 环境的 PR 的屏幕截图,其中具有应用程序分配。

除了 Promoted_Commit_id(只跟踪提升 CD 流的信息)外,PR 还包含分配清单。 functional-test 部署目标分配至 drone 群集类型,performance-test 部署目标分配至 large 群集类型。 这些清单将存放在 dronelarge 文件夹中,其中包含对 Dev 环境中这些群集类型的所有分配。

Dev 环境还包括 command-centersmall 群集类型:

显示 Dev 环境中的群集类型的屏幕截图。

但是,定义的计划策略仅选择了 dronelarge 群集类型。

了解部署目标分配清单

在继续操作之前,请仔细查看为 functional-test 部署目标生成的分配清单。 有 namespace.yamlplatform-config.yamlreconciler.yaml 清单文件。

namespace.yaml 定义一个命名空间,该命名空间将在运行 hello-world 应用程序的任何 drone 群集上创建。

apiVersion: v1
kind: Namespace
metadata:
  name: "dev-drone-hello-world-app-functional-test" 
  labels:
    environment: "dev"
    workspace: "kaizen-app-team"
    workload: "hello-world-app"
    deploymentTarget: "hello-world-app-functional-test"
    someLabel: some-value

platform-config.yaml 包含应用程序可在 Dev 环境中使用的任何 drone 群集上可用的所有平台配置值。

apiVersion: v1
kind: ConfigMap
metadata:
  name: platform-config
  namespace: dev-drone-hello-world-app-functional-test
data:
  CLUSTER_NAME: Drone
  DATABASE_URL: mysql://restricted-host:3306/mysqlrty123
  ENVIRONMENT: Dev
  REGION: China North 3
  SOME_COMMON_ENVIRONMENT_VARIABLE: "false"

reconciler.yaml 包含 drone 群集用于获取应用程序清单的 Flux 资源,这些清单是由应用程序团队为 functional-test 部署目标准备的。

apiVersion: source.toolkit.fluxcd.io/v1beta2
kind: GitRepository
metadata:
  name: "hello-world-app-functional-test"
  namespace: flux-system
spec:
  interval: 15s
  url: "https://github.com/eedorenko/kalypso-tut-test-app-gitops"
  ref:
    branch: "dev"
  secretRef:
      name: repo-secret    
---
apiVersion: kustomize.toolkit.fluxcd.io/v1beta2
kind: Kustomization
metadata:
  name: "hello-world-app-functional-test"
  namespace: flux-system
spec:
  interval: 30s
  targetNamespace: "dev-drone-hello-world-app-functional-test"
  sourceRef:
    kind: GitRepository
    name: "hello-world-app-functional-test"
  path: "./functional-test" 
  prune: true

备注

control plane 定义 drone 群集类型使用 Flux 来协调应用程序 GitOps 存储库中的清单。 因此,reconciler.yaml 文件包含了 GitRepositoryKustomization 资源。

将应用程序提升到 Stage 环境

在批准 PR 并将其合并到 Platform GitOps 存储库后,表示相应群集类型的 dronelarge AKS 群集会开始提取分配清单。 drone 群集已安装 GitOps 扩展,指向 Platform GitOps 存储库。 它向 Azure Resource Graph 报告其 compliance 状态:

显示 drone 群集的符合性状态详细信息的屏幕截图。

PR 合并事件在 control plane 存储库中启动 GitHub 工作流 checkpromote。 此工作流会一直等待,直到所有安装了 GitOps 扩展且正在查看 Platform GitOps 存储库中的 dev 分支的群集都符合 PR 提交。 在此示例中,唯一的此类群集是 drone

显示提升到 dev 环境的屏幕截图。

checkpromote 成功后,它将启动 cd 工作流,将更改(应用程序注册)提升到 Stage 环境中。 为了提高可见性,它会还更新 control plane 存储库中的 git 提交状态:

显示部署到 dev 环境时的 git 提交状态的屏幕截图。

备注

如果 drone 群集因任何原因无法协调分配清单,提升流将失败。 提交状态将标记为“失败”,并且应用程序注册不会提升到 Stage 环境。

接下来,在 stage 环境中为 uat-test 部署目标配置计划策略:

# Switch to stage branch (representing Stage environemnt) in the control-plane folder
git checkout stage
mkdir -p scheduling/kaizen

# Create a scheduling policy for the uat-test deployment target
cat <<EOF >scheduling/kaizen/uat-test-policy.yaml
apiVersion: scheduler.kalypso.io/v1alpha1
kind: SchedulingPolicy
metadata:
  name: uat-test-policy
spec:
  deploymentTargetSelector:
    workspace: kaizen-app-team
    labelSelector:
      matchLabels:
        purpose: uat-test
  clusterTypeSelector:
    labelSelector: {}
EOF

git add .
git commit -m 'application scheduling policies'
git config pull.rebase false
git pull --no-edit
git push

该策略规定,应在环境中定义的所有群集类型上计划 kaizen-app-team 工作区中带有 purpose: uat-test 标签的所有部署目标。

将此策略推送到 stage 分支会触发计划过程,该过程会创建一个 PR,其中包含对 Platform GitOps 存储库的分配清单,类似于 Dev 环境的分配清单。

Dev 环境一样,在评审 PR 并将其合并到 Platform GitOps 存储库后,control plane 存储库中的 checkpromote 工作流将等待直到具有 GitOps 扩展的群集 (drone) 协调分配清单。

显示提升到 stage 环境的屏幕截图。

成功执行后,提交状态会更新。

显示成功提交状态的屏幕截图。

3 - 应用程序开发团队:生成和部署应用程序

应用程序团队定期向 Application Source 存储库中的 main 分支提交拉取请求。 将 PR 合并到 main 后,它将启动 CI/CD 工作流。 此处,工作流将手动启动。

转到 GitHub 中的 Application Source 存储库。 在“Actions”选项卡上,选择“Run workflow”。

显示“运行工作流”选项的屏幕截图。

工作流执行以下操作:

  • 生成应用程序 Docker 映像并将其推送到 GitHub 存储库包。
  • functional-testperformance-test 部署目标生成清单。 它将使用 dev-configs 分支中的配置值。 生成的清单将添加到拉取请求中,并在 dev 分支中自动合并。
  • uat-test 部署目标生成清单。 它将使用 stage-configs 分支中的配置值。

显示 CI/CD 工作流的屏幕截图。

生成的清单将添加到等待审批的 stage 分支拉取请求中:

显示针对 stage 环境的 PR 的屏幕截图。

若要在批准针对 Dev 环境的 PR 之前在 Stage 环境中手动测试应用程序,请先验证 functional-test 应用程序实例在 drone 群集上的工作方式:

kubectl port-forward svc/hello-world-service -n dev-drone-hello-world-app-functional-test 9090:9090 --context=drone

# output:
# Forwarding from 127.0.0.1:9090 -> 9090
# Forwarding from [::1]:9090 -> 9090

运行此命令时,请在浏览器中打开 localhost:9090。 你将看到以下问候页:

显示 Dev 问候页的屏幕截图。

下一步是检查 performance-test 实例在 large 群集上的工作方式:

kubectl port-forward svc/hello-world-service -n dev-large-hello-world-app-performance-test 8080:8080 --context=large

# output:
# Forwarding from 127.0.0.1:8080 -> 8080
# Forwarding from [::1]:8080 -> 8080

这次使用 8080 端口并在浏览器中打开 localhost:8080

Dev 环境满足需求后,批准 PR 并将其合并到 Stage 环境中。 之后,在 Stage 环境中针对这两个群集测试 uat-test 应用程序实例。

drone 群集运行以下命令,并在浏览器中打开 localhost:8001

kubectl port-forward svc/hello-world-service -n stage-drone-hello-world-app-uat-test 8001:8000 --context=drone

large 群集运行以下命令,并在浏览器中打开 localhost:8002

kubectl port-forward svc/hello-world-service -n stage-large-hello-world-app-uat-test 8002:8000 --context=large

large 群集上的应用程序实例显示以下问候页:

显示 stage 环境中的问候页的屏幕截图。

4 - 平台团队:提供平台配置

DevStage 环境中,群集中的应用程序都从同一数据库获取数据。 对其进行更改,并配置 china-north-3 群集,为在 Stage 环境中工作的应用程序提供不同的数据库 URL:

# Switch to stage branch (representing Stage environemnt) in the control-plane folder
git checkout stage

# Update a config map with the configurations for china-north-3 clusters
cat <<EOF >cluster-types/china-north-3/china-north-3-config.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: china-north-3-config
  labels:
     platform-config: "true"
     region: china-north-3
data:
  REGION: China North 3
  DATABASE_URL: mysql://west-stage:8806/mysql2
EOF

git add .
git commit -m 'database url configuration'
git config pull.rebase false
git pull --no-edit
git push

计划程序扫描环境中的所有配置映射,并根据标签匹配情况收集每个群集类型的值。 然后,它将 platform-config 配置映射放入 Platform GitOps 存储库中的每个部署目标文件夹。 platform-config 配置映射包含工作负载可在此环境中的此群集类型上使用的所有平台配置值。

几秒钟后,将显示针对 Platform GitOps 存储库中的 stage 分支的新 PR:

显示用于在 stage 环境中更新数据库 URL 的 PR 的屏幕截图。

批准 PR 并将其合并。

large 群集具有新配置后,请在运行以下命令后检查 localhost:8002 处的 uat-test 应用程序实例:

kubectl rollout restart deployment hello-world-deployment -n stage-large-hello-world-app-uat-test --context=large
kubectl port-forward svc/hello-world-service -n stage-large-hello-world-app-uat-test 8002:8000 --context=large

你将看到更新后的数据库 URL:

显示包含更新后的数据库 URL 的页面屏幕截图。

5 - 平台团队:向环境添加群集类型

目前,Stage 环境中仅包含 dronelarge 群集类型。 将 small 群集类型也包含在 Stage 中。 即使没有表示此群集类型的物理群集,也可以查看计划程序对此更改的反应。

# Switch to stage branch (representing Stage environemnt) in the control-plane folder
git checkout stage

# Add "small" cluster type in china-north-3 region
mkdir -p cluster-types/china-north-3/small
cat <<EOF >cluster-types/china-north-3/small/small-cluster-type.yaml
apiVersion: scheduler.kalypso.io/v1alpha1
kind: ClusterType
metadata:
  name: small
  labels: 
    region: china-north-3
    size: small
spec:
  reconciler: arc-flux
  namespaceService: default
  configType: configmap
EOF

git add .
git commit -m 'add new cluster type'
git config pull.rebase false
git pull --no-edit
git push

几秒钟后,计划程序会将 PR 提交到 Platform GitOps 存储库。 根据创建的 uat-test-policy,它将 uat-test 部署目标分配给新的群集类型,因为它适用于环境中所有可用的群集类型。

显示小型群集类型的分配的屏幕截图。

清理资源

如果不再需要,请删除你创建的资源。 为此,请运行以下命令:

# In kalypso folder
./deploy.sh -d -p <preix. e.g. kalypso> -o <GitHub org. e.g. eedorenko> -t <GitHub token> -l <azure-location. e.g. chinanorth3> 

后续步骤

你已针对多群集 Kubernetes 环境中的一些常见的工作负载管理场景执行了任务。 你可能还想探索许多其他场景。 请继续使用示例,并了解如何实现日常活动中最常见的用例。

若要更深入地了解基础概念和机制,请参阅以下资源: