现在很多团队采纳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多平台公布