现在很多团队采纳 GitOps 作为规范部署流程,这篇文章总结了 GitOps 的 12 个痛点,从而帮忙咱们在采纳这一实际的过程中更好的了解 GitOps 的劣势和缺点,抉择适宜本人的解决方案。原文:The pains of GitOps 1.0[1]
GitOps 作为软件公布实际有很多长处,但就像其余解决方案一样,它也有毛病,当咱们从采纳 GitOps 的狂热中冷静下来后,也须要讨论一下 GitOps 的问题了(以及古代 GitOps 工具)。
在本文中,咱们将探讨 GitOps 的 12 个痛点:
- GitOps 只笼罩软件生命周期的一个子集
- 用 GitOps 宰割 CI 和 CD 并不容易
- GitOps 无奈将公布部署到不同的环境中
- 对于多环境配置建模没有规范实际
- 主动扩容和动静资源管理毁坏 GitOps
- 对于回滚没有最佳实际
- GitOps(和 Git)的可察看性不成熟
- 只管所有信息都在 Git 中,审计还是有问题
- 大规模运维 GitOps 很艰难
- GitOps 和 Helm 并不总是可能很好的单干
- 继续部署和 GitOps 不能一概而论
- 没有治理密钥的规范计划
GitOps 只笼罩软件生命周期的一个子集
这是以后 GitOps 工具的次要运作模式,只管 GitOps(方法论)有一些乏味的特点和卖点,但以后的 GitOps 工具只关注应用程序的部署局部,其余什么都没有。这些工具解决了“我想把 Git 中形容的货色放到集群中”的问题,然而软件开发的所有其余方面都没有波及到:
之所以提到这一点,是因为 GitOps 工具有时被宣传为万能解决方案,能够解决所有的发行问题,但这是不对的。首先,GitOps 要求所有部署构件曾经存在,这意味着……
- 编译代码
- 运行单元 / 集成测试
- 平安扫描
- 动态剖析
……并不是 GitOps 工具所关怀的问题,而是被认为都曾经筹备好了。
甚至部署问题 (例如环境降级、密钥治理、冒烟测试等) 也被轻易排除在 GitOps 范式之外,采纳 GitOps 的团队须要为软件交付的所有方面创立本人的最佳实际。
因而,不能简略“采纳 GitOps 解决方案”并就此结束。GitOps 只是整个倒退策略的一部分,应该确保所有其余流程和工作流程曾经筹备好与 GitOps 单干。
用 GitOps 宰割 CI 和 CD 并不容易
GitOps 被认为是一种将 CI 与部署拆散的办法。在 CI/CD 零碎的经典利用中,流程中的最初一步是部署。
应用 GitOps,能够维持纯正的 CI 流程,只有将候选版本通过 Git 提交,而不须要部署。Git 提交触发部署解决方案,该计划监听 Git 存储库,并通过在集群中拉取变更来解决理论的部署(从而使集群状态与 Git 状态统一)。
该场景在实践上很完满,也实用于简略的场景,但当波及到大型组织采纳的高级部署时,很快就会解体。
混合 CI 和 CD 的典型例子是冒烟测试,有时候咱们心愿在部署实现后运行冒烟测试,并依据测试的后果决定是否回滚变更。
正如后面所说,GitOps 只解决部署构件,通常不波及 (或不理解) 源代码,然而在大多数状况下,为了运行单元测试,咱们须要拜访应用程序的源代码。
以后的 GitOps 工具不能运行单元 / 集成测试,因为这要求可能看到源代码以及测试所需的所有框架和库。这意味着,为了运行冒烟测试,不得不再次回到 CI 解决方案。
最终的后果是 CI-CD-CI-CD 组件的混合,这违反了 GitOps 的次要精力。当然还有一些潜在问题,比方不晓得环境何时实现部署以触发测试。
基于传统的 CI/CD 流水线执行雷同的场景会很简略。
GitOps 无奈将公布部署到不同的环境中
这可能是对于 GitOps 探讨最多的问题之一,也是当谈到 GitOps 如何在大型组织中工作时最先探讨的话题之一。
思考一个常见场景:在 Git 中合并(或创立提交),环境 X 的集群当初部署了新版本,然而如何将这个版本部署到环境 Y 中呢?
每当有人声称采纳 GitOps 很简略时,我总会问他们在不同环境之间的部署是如何工作的,但总是失去不同的答案:
- “咱们用 CI 零碎来做到这一点。”这意味着再次将 CI 和 CD 混在一起,并且抵赖 GitOps 无奈笼罩这一场景。
- “咱们为其余环境开一个新的 pull request。”这意味着必须为每个环境应用不同的 Git 分支(稍后会具体介绍),并且还须要引入更多的手动步骤,以便部署公布。
- “咱们只有一个环境。”这可能适宜小公司,但在其余状况下不可行。
很令人悲观,就连专门为解决 GitOps 问题而创立的页面 [2] 都说:
“GitOps 并没有提供一个将变更从一个阶段流传到下一个阶段的解决方案。咱们倡议只应用一个环境,并防止多阶段流传。”
解决不同环境的最风行的办法仿佛是应用不同的 Git 分支,但这个解决方案有几个毛病:
- 人们有可能会在特定分支上提交特定于某个环境的代码。
- 我的项目有可能会耦合到特定的环境(而不是通用的)。
- 这给 CI 零碎带来了不必要的压力,它必须查看 / 重建 / 单元测试每个独立的分支。
此外,如果有很多环境,多分支解决可能会很快失控。
对于多环境配置建模没有规范实际
上一个问题的论断是,如果咱们须要多环境部署,那么 GitOps 在没方法帮忙咱们。事实上,它会迫使咱们采纳特定的 Git 分支模式(每个环境用特定分支),从而让事件变得更糟。
一个典型例子是,每个天文区域 (每个大陆或每个国家) 都有不同的环境。
假如咱们的利用部署在 10 个国家,咱们心愿一个国家一个国家的推广版本,GitOps 有什么解决方案?
- 一个有 10 个分支的存储库,这意味着须要在每次公布时开 10 个 pull request。
- 10 个 Git 存储库,这意味着须要编写本人的解决方案,在存储库之间复制提交(或者应用 Pull Requests)。
- 一个蕴含 10 个子文件夹的 Git 存储库,同样须要内部解决方案来确保更改同步到所有文件夹。
不论哪种计划,公布过程都十分繁琐,目前的 GitOps 工具对于哪种才是规范计划还没有给出答案[3]。
主动扩容和动静资源管理毁坏 GitOps
在部署实现后,集群状态与 Git 存储库中形容的完全相同,这是 GitOps 的关键点。
在大部分简略的状况下,这没有问题,但一旦咱们引入了变量,GitOps 工具就会呈现抵触,典型例子如下:
- 配置了 autoscaler 的集群的正本个数
- 配置了 optimizer 的集群的资源限度
- 内部工具增加的额定属性(特地是带有日期或工夫戳的值)
一旦集群状态发生变化,GitOps 工具就会尝试从 Git 同步初始值,但在大多数状况下这违反了咱们的冀望。
Argo 反对自定义差别[4],Flux 也有相干倡议[5],但这些变通方法只是简略的 hack 了 GitOps,背离了 GitOps 的次要承诺,从长期看会产生其余一些问题[6]。
对于回滚没有最佳实际
集群历史的所有记录都在 Git 中,这使得在 GitOps 中回滚 (据说) 非常容易。如果想回滚到以前的版本,只须要对以前的某个提交利用同步操作就行了。
然而在实践中,“应用以前的提交”的确切含意并不明确,因而不同的人会应用不同的回滚形式:
- 简略的将集群指向一个以前的 Git 哈希值,而后让 GitOps 工具同步这个哈希值。这是最快的回滚形式,但依据定义,因为集群不蕴含上次 Git 提交中所形容的内容,因而会使集群处于不统一的状态。
- 应用规范的 Git reset, Git revert 命令,而后让 GitOps 工具像平常一样执行同步操作。这保障了 GitOps 的承诺(在集群中领有 Git repo 中的内容),当然,这须要手工干涉。
- 能够组合采纳下面 2 种形式,GitOps 工具将之前的 Git 哈希同步到集群,并主动提交 (或还原) 到 Git repo,以放弃一致性。这非常复杂,并且不是所有团队都想让部署工具对 Git repo 有写权限。
不用说,不同的人可能心愿应用齐全不同的回滚计划。然而,在撰写本文时,目前的 GitOps 工具对于如何以规范形式执行回滚只有很少的反对和领导。
GitOps(和 Git)的可察看性不成熟
GitOps 非常适合查看集群状态,并保障与 Git 状态相匹配。然而,Git 的哈希和提交只对开发和运维人员有用,业务相干方对集群中部署了什么 Git 哈希不感兴趣。
因而,只管 GitOps 在技术层面上的可察看性很好,但更重要的是要记住,在软件团队中有一些更有用的问题:
- 生产环境是否蕴含个性 X?
- 个性 X 是否革除了预发环境?
- bug X、Y 只呈现在预发环境还是也呈现在生产环境?
对于大多数产品所有者和项目经理来说,这类问题十分重要,应该尽快找到答案。
目前,GitOps 工具工作在最低级别(即 Git 哈希值),并且与每个部署的业务价值没有任何关联,开发 / 运维人员须要找到产品部署和业务价值之间的关联。
在目前的状态下,GitOps 工具在技术层面上非常适合察看集群的内容,然而在监控每个部署的业务指标方面却很蹩脚。
只管所有信息都在 Git 中,审计还是有问题
上一点的推论是,仅仅因为能够以 Git 提交的模式拜访集群的整个部署历史,并不意味着能够轻松审计它的性能。
以后的 Git 工具非常适合治理 Git 哈希,然而当波及到搜寻和了解业务价值时,正如 Adam 在 Lack of Visibility[7]中提到的那样,只能提供简略的自在文本搜寻性能。
假如咱们正在某个特定我的项目中应用 GitOps,并且晓得 Git 历史记录与集群历史记录相匹配,仅仅通过查看 Git History,能够多快答复以下问题?
- 个性 X 在投入生产之前在预发环境中停留了多长时间?
- 前两个月的最差、最好和均匀交付工夫 (从开发人员执行提交到理论投入生产的工夫) 是多少?
- 对环境 X 的部署胜利百分比是多少,须要回滚的百分比是多少?
- 有多少个性在环境 X 中存在但在环境 Y 中还没有?
这些问题在大型软件团队中很常见,除非在部署平台上有专门的工具,否则仅通过拜访 Git 存储库及其历史来答复这些问题是十分艰难的。
大规模运维 GitOps 很艰难
Adam 在“Git 库的扩大”[7]一文中也提到了这一点。如果在领有大量环境和利用的大公司中采纳 GitOps,那么 Git 存储库的数量会迅速飙升。
这使得跟踪每个环境中正在产生的事件变得十分艰难,并且可能很快导致配置冗余或者人们不得不向特定环境提交(而不是应用共享配置)。
例如,如果咱们有 20 个存有 Kubernetes manifests 的 git 仓库,当咱们须要实现一个重要变更(例如,在每个部署中增加一个新的全公司范畴的标签),须要手动实现 20 个 git 提交,或者创立一些胶水代码来帮咱们实现。
另一方面,能够为所有环境 (或集群) 提供一个 Git 存储库,在这些环境中,所有人都与 CI/CD 零碎合作。
但正如 Adam 所解释的那样,这就产生了 Git 抵触的问题(Git 存储库和很多 CI 流程交互,因为 Git 仓库在这一过程中产生了变更,造成推送失败)。
领有一个微小的 Git 存储库会很快成为 GitOps 流程的瓶颈,这会在扫描存储库进行更改时引入性能问题。
GitOps 和 Helm 并不总是可能很好的单干
Helm 是 Kubernetes 的包管理器,通常被视为在集群中部署第三方应用程序的事实标准,当然也能够用于本人的部署。
Helm 的工作形式是将 Kubernetes manifests 的一组模板及其运行时值联合起来,这些模板被合并从而最终实现集群的部署。
当 Helm 装置一个公布时,咱们能够提供 values.yml,最好的做法是将 values 文件提交给 Git,能够为每个环境 (例如 qa/ 预发 / 生产) 提供不同的 values。
Helm 自身并没有规定这 3 个组件 (源代码、manifests、values) 应该保留在哪里。能够将它们全副保留在同一个 Git 存储库中,也能够将它们保留在三个不同的存储库中。然而,广泛承受的做法是,如果咱们有不同环境的 values,能够将它们与模板保留在不同的地位,模板 (chart 自身) 存储在 chart 存储库中,每个环境的特定 values 存储在 git 存储库中。
这意味着在部署过程中必须实现以下步骤:
- 从 chart 存储库中下载 chart
- 从 Git 存储库中获取 values
- values 和 chart 合并,从而创立一组 Kubernetes manifests
- 在集群上利用这组 manifests
这仅用于初始部署。依照 GitOps 范例,应该监督蕴含 values 文件的 Git 存储库以及 chart 存储库中的 chart。如果它们的合并后果与集群状态不同,则应该进行新的部署。
在撰写本文时,Flux[8]和 ArgoCD 都不反对这个根本的 Helm 场景。如果心愿采纳基于 Helm chart 的 GitOps,那么必须采纳一些变通方法和限度,从而使这一过程变得比须要的简单得多。
继续部署和 GitOps 不能一概而论
GitOps 是一个很棒的继续交付解决方案,每个提交都会产生一个公布候选版本,并将其推向生产环境。另一方面,继续部署是间接提交到生产的整个过程,无需任何人工干预[10]。
如果作为开发人员,能够在周五下午提交变更,而后立刻开始享受周末,那么就是在实际继续部署,提交的变更将在几分钟内通过所有质量检查和测试后投入生产。
依据定义,GitOps 是由蕴含 manifests 的仓库上的 Pull Request 驱动的。在大多数状况下,须要人工审查和批准这些 Pull Request,这意味着实际 GitOps 至多须要一些手动步骤来解决这些 Pull Request。
实践上,人们能够通过齐全自动化的 Pull Request 来实现继续部署,同时依然采纳 GitOps。然而,以后的 GitOps(和 Git)工具并没有思考到这种自动化,所以如果你想走这条路,就只能靠本人了。
记住,继续部署并不是圣杯。对于一些组织来说,继续交付曾经足够了,在某些状况下,甚至可能受到法律的束缚,必须明确禁止齐全自动化的部署。
然而如果想要更快的交付工夫,GitOps 并不是最好的解决方案。
没有治理密钥的规范计划
这是 GitOps 的一个家喻户晓的问题,所以为了表述残缺,我也把它包含进来。密钥解决是软件部署最重要的方面之一,然而,GitOps 并没有解决这一问题。
对于如何治理密钥,目前还没有公认的做法。如果将密钥存储在 Git 中,则须要进行加密,并且在部署过程中采纳本人的工作流。如果不存储在 Git 中,那么让集群状态与 Git 雷同的想法就不再正确了。
每个公司的密钥治理都有本人的解决方案,所以我心愿 GitOps 工具可能提供一个开箱即用的解决方案。
References: \
[1] The pains of GitOps 1.0: https://codefresh.io/about-gitops/pains-gitops-1-0/ \
[2] GitOps: https://www.gitops.tech/ \
[3] Document best practises on working with multiple environments: https://github.com/fluxcd/flux/issues/1071 \
[4] Diffing Customization: https://argoproj.github.io/argo-cd/user-guide/diffing/ \
[5] How can I prevent flux overriding the replicas when using HPA: https://docs.fluxcd.io/en/1.17.0/faq.html#how-can-i-prevent-f… \
[6] Maintain difference in cluster and git values for specific fields: https://github.com/argoproj/argo-cd/issues/2913 \
[7] Lack of Visibility: https://blog.container-solutions.com/gitops-the-bad-and-the-ugly \
[8] Flux helm repository chart updates: https://docs.fluxcd.io/projects/helm-operator/en/latest/helmr… \
[9] Helm chart + values files from Git: https://github.com/argoproj/argo-cd/issues/2789 \
[10] What the Heck Is Continuous Integration (CI), Delivery (CD), and Deployment (CDP)? https://codefresh.io/continuous-deployment/heck-continuous-in…你好,我是俞凡,在 Motorola 做过研发,当初在 Mavenir 做技术工作,对通信、网络、后端架构、云原生、DevOps、CICD、区块链、AI 等技术始终保持着浓重的趣味,平时喜爱浏览、思考,置信继续学习、一生成长,欢送一起交流学习。\
微信公众号:DeepNoMind
本文由 mdnice 多平台公布