GitOps 多环境部署问题及解决方案(下)

本文涉及的产品
容器服务 Serverless 版 ACK Serverless,317元额度 多规格
容器服务 Serverless 版 ACK Serverless,952元额度 多规格
简介: GitOps 多环境部署问题及解决方案(下)

5 个 GitOps 环境及其变更示例


我们来看一个实际的例子。


我们将对之前提到的环境进行建模,该公司有 5 个不同的环境:


  1. 负载测试
  2. 集成测试
  3. QA
  4. 预发
  5. 生产


我们假设最后两个环境也部署在欧洲、美国和亚洲,而前两个环境也有 GPU 和非 GPU 变体,这意味着该公司共有 11 个环境。


可以在 https://github.com/kostis-codefresh/gitops-environment-promotion 找到建议的文件夹结构,所有环境都是同一分支中的不同文件夹,对于不同的环境没有分支。如果想知道在一个环境中部署了什么,只需查看 repo 的主分支中的 envs/。


在解释结构之前,有一些免责声明:


免责声明 1: 写这篇文章花了我很长时间,因为不确定应该讨论 Kustomize[12]、Helm[13]还是普通的 manifests。我选择了 Kustomize,因为它更简单(在文章的最后我也提到了 Helm)。但是请注意,示例 repo 中的 Kustomize 模板只是为了演示目的。本文不是 Kustomize 教程。在实际应用中,你可能有 Configmap 生成器[14]、定制补丁[15],并采用和这里展示的完全不同的“组件”结构。如果你不熟悉 Kustomize,请先花些时间理解它的功能,然后再回来。

免责声明 2: 我用于部署的应用[16]完全只是为了演示,它的配置由于简洁和简单的原因而忽略了几个最佳实践。例如,某些部署缺少运行状况检查[17],所有部署都缺少资源限制[18]。同样,本文不会讨论如何创建 Kubernetes 部署,你应该已经知道正确的部署 manifests 是什么样子的。如果想了解更多关于生产级最佳实践的信息,请参阅另一篇文章 https://codefresh.io/kubernetes-tutorial/kubernetes-antipatterns-1/

抛开免责声明不说,下面是存储库的结构:

image.png


GitOps 目录结构


base 目录保存对所有环境通用的配置,不会经常改变。如果同时对多个环境进行更改,最好使用“variants”文件夹。


variants 文件夹(或者叫 mixins、components)保存不同环境之间的共同特征。在研究上一节讨论的应用程序之后,可以自行定义你认为的环境之间的“共同之处”。


在示例应用中,我们为所有 prod 和非 prod 环境以及地区提供了 variants。下面是一个适用于所有生产环境的 prod variant[19]示例。


---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: simple-deployment
spec:
  template:
    spec:
      containers:
      - name: webserver-simple
        env:
        - name: ENV_TYPE
          value: "production"
        - name: PAYPAL_URL
          value: "production.paypal.com"   
        - name: DB_USER
          value: "prod_username"
        - name: DB_PASSWORD
          value: "prod_password"                     
        livenessProbe:
          httpGet:
            path: /health
            port: 8080


在上面的示例中,我们确保所有生产环境都使用了生产 DB 凭证、生产支付网关和活动探针(这是一个精心设计的示例,请参阅本节开头的免责声明 2)。这些设置属于我们不希望在不同环境之间迁移的配置集,我们假设在整个应用生命周期中这些都是静态的。


准备好 base 和 variants 之后,可以用这些属性的组合来定义每个最终环境。


下面是一个 ASIA 环境的示例[20]:


apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namespace: staging
namePrefix: staging-asia-
resources:
- ../../base
components:
  - ../../variants/non-prod
  - ../../variants/asia
patchesStrategicMerge:
- deployment.yml
- version.yml
- replicas.yml
- settings.yml


首先定义一些公共属性,从 base 环境、非 prod 环境和 asia 的所有环境中继承所有配置。


这里的关键点是我们应用的补丁。version.yml[21]和 replicas.yml[22]是自解释的,只定义自己的镜像和副本,其他什么都没有。


version.yml 文件(这是环境间最重要的东西)只定义了应用的镜像,其他什么都没有。


---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: simple-deployment
spec:
  template:
    spec:
      containers:
      - name: webserver-simple
        image: docker.io/kostiscodefresh/simple-env-app:2.0


我们希望在不同环境之间部署的每个版本的相关设置也在 settings.yml[23]中定义。


---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: simple-deployment
spec:
  template:
    spec:
      containers:
      - name: webserver-simple
        env:
        - name: UI_THEME
          value: "dark"
        - name: CACHE_SIZE
          value: "1024kb"
        - name: PAGE_LIMIT
          value: "25"
        - name: SORTING
          value: "ascending"    
        - name: N_BUCKETS
          value: "42"         


请随意查看整个存储库[16],以理解所有 kustomizations 的构造方式。


通过 GitOps 执行初始部署


要将应用程序部署到相关的环境中,只需将 GitOps 控制器指向相应的“env”文件夹,kustomize 将创建完整的 settings 和 values 层次结构。


下面是在 Staging/Asia 中运行的示例应用程序[16]


image.png

GitOps 应用示例


可以在命令行上使用 Kustomize 预览将为每个环境部署的内容,例如:


kustomize build envs/staging-asia
kustomize build envs/qa
kustomize build envs/integration-gpu


当然,也可以将上述命令的输出通过管道输出到 kubectl 来部署每个环境,但在 GitOps 的上下文中,应该始终让 GitOps 控制器部署环境,避免手动 kubectl 操作。


比较两个环境的配置


对于软件团队来说,一个非常普遍的需求是理解两个环境之间的不同之处。我看到一些团队有这样的误解,他们认为只有使用分支才能很容易的发现不同环境之间的差异。


这与事实相去甚远。通过比较文件和文件夹,可以很容易的使用成熟的文件 diff 工具来查找环境之间的不同之处。


最简单的方法是只区分对应用程序至关重要的设置。


vimdiff envs/integration-gpu/settings.yml envs/integration-non-gpu/settings.yml


image.png

GitOps settings diff


在 kustomize 的帮助下,还可以比较任意数量的环境,获取整体的概念:


kustomize build envs/qa/> /tmp/qa.yml
kustomize build envs/staging-us/ > /tmp/staging-us.yml
kustomize build envs/prod-us/ > /tmp/prod-us.yml
vimdiff /tmp/staging-us.yml /tmp/qa.yml /tmp/prod-us.yml

image.png

GitOps 环境 diff


个人认为这种方式和在环境分支之间执行“git diff”没有什么差别。


如何在 GitOps 环境中进行部署升级


现在文件结构已经很清楚了,终于可以回答这个古老的问题:“我如何用 GitOps 部署发布”?


让我们看看下面一些部署场景。如果你有关注文件结构,应该已经了解到所有部署升级都可以解析为简单的文件复制操作。


场景: 在美国将应用版本从 QA 升级到预发环境:

  1. cp envs/qa/version.yml envs/staging-us/version.yml
  2. commit/push 变更


场景: 从 GPU 集成测试到 GPU 负载测试,再到 QA 的应用版本升级。这是一个两步的过程:

  1. cp envs/integration-gpu/version.yml envs/load-gpu/version.yml
  2. commit/push 变更
  3. cp envs/load-gpu/version.yml envs/qa/version.yml
  4. commit/push 变更


场景: 通过额外配置,将应用程序从 prod-eu 升级到 prod-us。这里我们还复制了 settings 文件。

  1. cp envs/prod-eu/version.yml envs/prod-us/version.yml
  2. cp envs/prod-eu/settings.yml envs/prod-us/settings.yml
  3. commit/push 变更


场景: 确保 QA 拥有与 staging-asia 相同的副本数量

  1. cp envs/staging-asia/replicas.yml envs/qa/replicas.yml
  2. commit/push 变更


场景: 从 QA 到移植所有配置到集成测试(非 gpu 版本)

  1. cp envs/qa/settings.yml envs/integration-non-gpu/settings.yml
  2. commit/push 变更


场景: 一次性对所有非 prod 环境进行全局更改(但请参阅下一节,以了解关于此操作的一些讨论)

  1. 在 variants/non-prod/non-prod.yml 中做出变更
  2. commit/push 变更


场景: 向所有美国环境(包括生产环境和预发环境)添加新的配置文件。

  1. 在 variants/us 文件夹中添加新的 manifest
  2. 修改 variants/us/kustomization.yml 引入新的 manifest
  3. commit/push 变更


一般来说,所有的部署升级只是复制操作。与 branch-per-environment 方法不同,现在可以自由的将任何东西从任何环境推广到其他环境,不必担心进行错误的变更。特别是当涉及到反向移植配置时,environment-per-folder 确实很出色,因为可以简单地“向上”或“向后”移动配置,甚至可以在不相关的环境之间移动配置。


注意,我使用 cp 操作只是为了演示。在实际的应用程序中,此操作将由 CI 系统或其他编排工具自动执行。根据环境的不同,你可能想先创建一个 Pull Request,而不是直接在主分支中编辑文件夹。

一次对多个环境进行更改


首先,我们需要定义“多重”环境的确切含义,假设以下两种情况。

  1. 同时更改同一“级别”上的多个环境。例如,想要同时变更“prod-us”、“prod-eu”和“prod-asia”。
  2. 同时更改不在同一级别上的多个环境。例如,想同时更改“integration”和“staging-eu”。


第一种情况是有效场景,我们将在下面讨论。但是,我认为第二个场景是反模式,拥有不同环境的关键在于能够以一种渐进的方式发布内容,并推动从一个环境到下一个环境的变化。因此,如果你发现自己在不同的环境中部署了相同的变化,问问自己是否真的需要这样做以及为什么。


对于部署单个更改到多个“类似”环境的有效场景,有两种策略:

  1. 如果你确定更改是绝对“安全的”,并且希望立即应用到所有环境,那么可以在适当的 variant(或各自的文件夹)中进行更改。例如,如果你在 variants/non-prod 文件夹中提交/推送一个更改,那么所有非生产环境都会同时应用这个更改。我个人反对这种方法,因为有些更改在理论上看起来是“安全的”,但在实践中可能会有问题。
  2. 更可取的方法是将更改应用于每个单独的文件夹,然后将其移动到“父”variant(当它在所有环境中都存在时)。


让我们举个例子。我们想做一个影响所有 EU 环境的改变(例如 GDPR 功能[24])。简单的方法是将配置更改直接提交/推送到 variants/eu 文件夹。这确实会影响到所有的 EU 环境(prod-eu 和 staging-eu)。但是,这有一点风险,因为如果部署失败,就会导致生产环境崩溃。


建议采用如下方法:


  1. 首先在 envs/staging-eu 中做出变更
  2. 然后对 envs/prod-eu 做同样的修改
  3. 最后,从两个环境中删除更改,并将其添加到 variants/eu 中(通过一个 commit/push 操作)。


image.png

GitOps 渐进升级


你可以从渐进的数据库重构[25]中认识到这种模式。最后的提交是“过渡性的”,不会以任何方式影响任何环境。Kustomize 将在这两种情况下创建完全相同的定义,GitOps 控制器应该不会发现任何差异。


这种方法的优点是,当我们在环境中移动更改时,可以轻松回滚/恢复更改。缺点是需要增加工作(和提交)将更改推广到所有环境,但是我相信这些工作的好处大于风险。


如果采用这种方法,意味着永远不会直接对 base 文件夹应用新的更改。如果希望对所有环境进行更改,则首先将更改应用于单个环境和/或 variants,然后将其反向移植到 base 文件夹,同时将其从所有下游文件夹中删除。

“environment-per-folder”方法的优点


既然我们已经分析了“environment-per-folder”方法的所有内部工作原理,现在就该解释为什么它比“branch-per-environment”方法更好了。如果你已经看过前面的部分,那么应该已经理解了“environment-per-folder”方法是如何避免之前分析的所有问题的。


环境分支最突出的问题是提交的顺序,以及从一个环境合并到另一个环境时带来不必要更改的风险。使用文件夹方法,这个问题就完全消除了:

  1. 提交顺序现在已经无关紧要了。当你将一个文件从一个文件夹复制到下一个文件夹时,不需要关心它的提交历史,只需要关心它的内容。
  2. 通过只复制周围的文件,只拿需要的东西,而不拿其他东西。当你复制 envs/qa/version.yml 到 env/staging-asia/version.yml 中,可以确定只升级了容器镜像,没有其他东西。如果其他人在 QA 环境中改变了副本,并不会影响升级流程。
  3. 不需要使用 git cherry-picks 或任何其他高级的 git 方法来升级版本,只需要复制文件,并且可以访问用于文件处理的实用程序的成熟生态系统。
  4. 可以自由的从任何环境对上游或下游环境进行任何更改,而不受环境正确“顺序”的任何限制。例如,如果想将设置从 prod-us 反向移植到 staging-us,可以简单的将 env/prod-us/settings.yml 拷贝到 env/staging-us/settings.yml,而不用担心可能会无意中部署了不相关的只应在生产环境中应用的修补程序。
  5. 可以容易的使用文件 diff 操作来了解各个环境之间的不同之处(源环境和目标环境,反之亦然)


我认为这些优势对于任何重要的应用程序都是非常重要的,我敢打赌大型组织中总会有几个“失败的部署”可以直接或间接归因于有问题的 environment-per-branch 模型。


之前我们提到的第二个问题是,将一个分支合并到下一个环境时,会出现配置漂移。这样做的原因是,当你执行“git merge”时,git 只会通知你它将带来的更改,而不会告诉你目标分支中已经发生了什么更改。


同样,文件夹方案完全消除了这个问题。正如前面说的,文件 diff 操作没有“方向”的概念,可以从任何环境向上或向下复制任何设置,如果对文件执行 diff 操作,可以看到环境之间的所有更改,而不管它们的上游/下游位置如何。


关于环境分支的最后一点是随着环境数量的增长,分支复杂性将会线性增加。对于 5 个环境,需要在 5 个分支之间切换更改,而对于 20 个环境,需要处理 20 个分支。在大量的分支之间正确迁移发布版本是一个繁琐的过程,在生产环境中,这是一场灾难。


使用文件夹方法,分支的数量不仅是静态的,而且只有一个。如果有 5 个环境,可以用“主”分支来管理,如果需要更多的环境,你只需要添加额外的文件夹。如果 20 个环境,仍然只需要一个 Git 分支。当只有一个分支时,获得部署的集中视图是很简单的。


在 GitOps 环境中使用 Helm


如果你不使用 Kustomize 而是更喜欢 Helm,也可以创建一个文件夹层次结构,其中包含所有环境的“通用”设置,特定的特性/mixins/组件,以及特定于每个环境的最终文件夹。


下面是文件夹结构的样子:


chart/
  [...chart files here..]
common/
  values-common.yml
variants/
  prod/
     values-prod.yml
  non-prod/
    Values-non-prod.yml
  [...other variants…]
 envs/
     prod-eu/
           values-env-default.yaml
           values-replicas.yaml
           values-version.yaml
           values-settings.yaml
   [..other environments…]


同样,你需要花一些时间来检查应用属性,并决定如何将它们分割成不同的 values 文件,以获得最佳的升级速度。


除此之外,在环境升级方面,大多数过程都是一样的。


场景: 在 US 将应用版本从 QA 提升到预发环境:

  1. cp envs/qa/values-version.yml envs/staging-us/values-version.yml
  2. commit/push 变更


场景: 从 GPU 集成测试到 GPU 负载测试,再到 QA 的应用版本升级。这是一个两步的过程:

  1. cp envs/integration-gpu/values-version.yml envs/load-gpu/values-version.yml
  2. commit/push 变更
  3. cp envs/load-gpu/values-version.yml envs/qa/values-version.yml
  4. commit/push 变更


场景: 通过额外配置,将应用从 prod-eu 提升到 prod-us。这里我们还复制了 settings 文件。

  1. cp envs/prod-eu/values-version.yml envs/prod-us/values-version.yml
  2. cp envs/prod-eu/values-settings.yml envs/prod-us/values-settings.yml
  3. commit/push 变更


理解 Helm(或者你的 GitOps 代理处理 Helm)如何处理多个 values 文件以及它们相互覆盖的顺序也是非常重要的。


如果希望预览某个环境,可以使用以下命令,而不是“kustomize build”:


helm template chart/ --values common/values-common.yaml --values variants/prod/values-prod.yaml –values envs/prod-eu/values-env-default.yml –values envs/prod-eu/values-replicas.yml –values envs/prod-eu/values-version.yml –values envs/prod-eu/values-settings.yml


可以看到,如果在每个环境文件夹中都有大量的 variants 或文件,那么 Helm 比 Kustomize 更麻烦一些。


environment-per-git-repo 方法


当我与大型组织讨论文件夹方法时,听到的第一个反对意见是,人们(尤其是安全团队)不喜欢看到单个 Git 存储库中的单个分支同时包含产品化和非产品化环境。


这是一个可以理解的反对意见,可以说是文件夹方法相对于“environment-per-branch”范式的唯一弱点。毕竟,在 Git 存储库中保护各个分支比在单个分支中保护文件夹要容易得多。


这个问题可以很容易的通过自动化、验证检查甚至手工批准(如果这对你的组织至关重要的话)来解决。我想再次强调,在文件操作中使用“cp”来升级发布版本,只是为了演示的目的,并不意味着当升级发生时,需要在交互式终端中手动运行 cp。


理想情况下,应该有一个自动化系统来复制文件并 commit/push 它们,可以是持续集成(CI)系统或处理软件生命周期的其他平台。如果仍然有人自己做出改变,不应该直接 commit “main”目录,而是应该发起一个 Pull Request,然后通过适当的流程,在合并之前检查 Pull Request。


然而,我意识到有些组织对安全问题特别敏感,当涉及到 Git 保护时,他们更喜欢完全隔离的方法。对于这些组织,可以使用 2 个 Git 存储库,一个保存 base 配置、所有生产 variants 和所有生产环境(以及所有与生产相关的东西),而第二个 Git 存储库保存所有非生产的东西。


这种方法让升级变得有点困难,因为现在需要在做任何升级之前签出 2 个 git 仓库。另一方面,它允许安全团队向“生产”Git 存储库放置额外的安全约束,并且无论部署到多少环境中,仍然拥有静态数量的 Git 存储库(只有 2 个)。


个人认为这种方法有些过分,至少在我看来,它显示出开发和运维缺乏信任。关于人们是否应该直接访问生产环境的讨论是一个复杂的问题,可能需要单独讨论。


拥抱文件夹,忘记分支


希望通过这篇文章,可以解决在多环境中部署的问题,现在你已经很好的理解了文件夹方法的好处以及应该使用它的原因。


GitOps 部署快乐!



References:

[1] Stop Using Branches for Deploying to Different GitOps Environments: https://medium.com/containers-101/stop-using-branches-for-deploying-to-different-gitops-environments-7111d0632402

[2] How to Model Your Gitops Environments and Promote Releases between Them: https://codefresh.io/about-gitops/how-to-model-your-gitops-environments-and-promote-releases-between-them/

[3] Multiple environments(dev, stage, ..,. prod ) example: https://github.com/argoproj/argocd-example-apps/issues/57

[4] A successful git branching model: https://nvie.com/posts/a-successful-git-branching-model/

[5] Trunk based development: https://trunkbaseddevelopment.com/

[6] Feature flags: https://trunkbaseddevelopment.com/feature-flags/

[7] git diff: https://git-scm.com/docs/git-diff

[8] git cherry-pick: https://git-scm.com/docs/git-cherry-pick

[9] Ingress: https://kubernetes.io/docs/concepts/services-networking/ingress/

[10] Manage resources containers: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/

[11] Helm deployment evnironments: https://codefresh.io/helm-tutorial/helm-deployment-environments/

[12] Kustomize: https://kustomize.io/

[13] Helm: https://helm.sh/

[14] Configmap generator: https://kubectl.docs.kubernetes.io/references/kustomize/kustomization/configmapgenerator/

[15] Patches strategic merge: https://kubectl.docs.kubernetes.io/references/kustomize/kustomization/patchesstrategicmerge/

[16] GitOps promotion source code: https://github.com/kostis-codefresh/gitops-promotion-source-code

[17] Configure liveness readiness startup probes: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/

[18] Manage resources containers: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/

[19] Sample prod: https://raw.githubusercontent.com/kostis-codefresh/gitops-environment-promotion/main/variants/prod/prod.yml

[20] Sample staging-asia: https://github.com/kostis-codefresh/gitops-environment-promotion/tree/main/envs/staging-asia

[21] Sample version.yml: https://github.com/kostis-codefresh/gitops-environment-promotion/blob/main/envs/staging-asia/version.yml

[22] Sample replicas.yml: https://github.com/kostis-codefresh/gitops-environment-promotion/blob/main/envs/staging-asia/replicas.yml

[23] Sample settings.yml: https://github.com/kostis-codefresh/gitops-environment-promotion/blob/main/envs/staging-asia/settings.yml

[24] GDPR: https://gdpr-info.eu/

[25] Database refactoring: https://databaserefactoring.com/


相关实践学习
通过Ingress进行灰度发布
本场景您将运行一个简单的应用,部署一个新的应用用于新的发布,并通过Ingress能力实现灰度发布。
容器应用与集群管理
欢迎来到《容器应用与集群管理》课程,本课程是“云原生容器Clouder认证“系列中的第二阶段。课程将向您介绍与容器集群相关的概念和技术,这些概念和技术可以帮助您了解阿里云容器服务ACK/ACK Serverless的使用。同时,本课程也会向您介绍可以采取的工具、方法和可操作步骤,以帮助您了解如何基于容器服务ACK Serverless构建和管理企业级应用。 学习完本课程后,您将能够: 掌握容器集群、容器编排的基本概念 掌握Kubernetes的基础概念及核心思想 掌握阿里云容器服务ACK/ACK Serverless概念及使用方法 基于容器服务ACK Serverless搭建和管理企业级网站应用
目录
相关文章
|
Kubernetes Cloud Native 安全
ArgoCD + KubeVela:以开发者为中心的 GitOps
在这篇博文中,我们将分享基于阿里云的用例,使用 Argo CD 和 KubeVela 构建以开发者为中心的持续应用交付流水线的经验。
ArgoCD + KubeVela:以开发者为中心的 GitOps
|
3月前
|
Kubernetes Java 开发工具
Kubernetes部署项目流程(新手上线新版本服务整个流程)
【8月更文挑战第1天】Kubernetes(k8s)新手上线新版本服务整个流程
|
6月前
|
Kubernetes Cloud Native Devops
云原生技术落地实现之二KubeSphere DevOps 系统在 Kubernetes 集群上实现springboot项目的自动部署和管理 CI/CD (2/2)
云原生技术落地实现之二KubeSphere DevOps 系统在 Kubernetes 集群上实现springboot项目的自动部署和管理 CI/CD (2/2)
154 1
|
6月前
|
Kubernetes Devops Java
云原生技术落地实现之一KubeSphere DevOps 系统在 Kubernetes 集群上实现springboot项目的自动部署和管理 CI/CD (1/2)
云原生技术落地实现之一KubeSphere DevOps 系统在 Kubernetes 集群上实现springboot项目的自动部署和管理 CI/CD (1/2)
118 0
云原生技术落地实现之一KubeSphere DevOps 系统在 Kubernetes 集群上实现springboot项目的自动部署和管理 CI/CD (1/2)
|
Kubernetes jenkins 测试技术
【Kubernetes的DevOps自动化,Jenkins上的Pipeline实现自动化构建、测试、部署、发布以及Bookinginfo实例的部署灰度发布故障注入流量】
【Kubernetes的DevOps自动化,Jenkins上的Pipeline实现自动化构建、测试、部署、发布以及Bookinginfo实例的部署灰度发布故障注入流量】
260 1
|
运维 Kubernetes jenkins
【Kubernetes测试生产环境整体部署及全链路测试、自动化运维平台Jenkins与Devops环境搭建】
【Kubernetes测试生产环境整体部署及全链路测试、自动化运维平台Jenkins与Devops环境搭建】
312 0
|
存储 关系型数据库 MySQL
rancher服务部署之DevOps流水线(一)—基础数据库服务部署及rancher相关配置私服信息
rancher服务部署之DevOps流水线(一)—基础数据库服务部署及rancher相关配置私服信息
|
存储 Kubernetes Docker
【排坑指南之kubeSphere】2022年最新版-”kubeSphere3.2.1 Paas容器云平台“使用DevOps-CICD之”排坑指南“
【排坑指南之kubeSphere】2022年最新版-”kubeSphere3.2.1 Paas容器云平台“使用DevOps-CICD之”排坑指南“
136 0
|
Kubernetes NoSQL 关系型数据库
开源项目:kubernetes+rancher部署ferry工单系统(20210820)
开源项目:kubernetes+rancher部署ferry工单系统(20210820)
472 0
开源项目:kubernetes+rancher部署ferry工单系统(20210820)
|
存储 Kubernetes 测试技术
GitOps 多环境部署问题及解决方案(上)
GitOps 多环境部署问题及解决方案(上)
273 0
GitOps 多环境部署问题及解决方案(上)