Kubernetes GitOps 工具

Kubernetes GitOps Tools

译自:Kubernetes GitOps Tools

本文很好地介绍了GitOps,并给出了当下比较热门的GitOps工具。

简介

在本文中,将回顾一下kubernetes上我比较喜欢的GitOps工具。

在我看来,Kubernetes的优势主要在于它的声明式性质与控制循环相结合,并通过这些控制循环持续监控集群的活动状态,确保它与etcd中存储的期望状态保持一致。这种方式非常强大,但同时其数据库也被限制为etcd(etcd仅提供了有限的可观察性),并影响到了集群变更时的责任性和审计性。另外一个缺点是将etcd和代码仓库作为两个SOT(sources of truth),有可能会导致配置漂移,造成管理上的困难。

开发者使用代码仓库这种安全且可追溯的方式来保存代码,并开发出了Workflows这种方式来高效地管理*仓库,不同的团队可以并行工作,且不会产生过多的冲突,同时保证对所有变更进行审核,并支持追溯和回滚。

如果我们能够从围绕Git仓库创建的流程中获得这些优势,并将它们扩展到基础设施或是kubernetes中,那不是很好吗?…欢迎来到GitOps的世界!

首先聊一下什么是GitOps,以及如何将其应用到Kubernetes,然后再看一下在kubernetes中实现的GitOps声明式工具,最后回顾一些GitOps友好的工具,即它们是以代码的形式实现和声明的工具。

什么是GitOps?

GitOps的目的是将etcd的这种声明式特性扩展到(保存代码的)Git 仓库,并作为SSOT(single source of truth)。通过这种方式,我们可以利用Git带来的优势,如代码监视、历史变更、快速回滚、可追溯性等等。

GitOps的核心观点是使用包含当前期望的(生产环境基础设施的)声明式描述的GIt仓库,并通过自动化流程来确保生产环境与仓库中的期望状态保持一致。如果你想要部署一个新的应用或更新一个现有的应用,只需要更新相应的仓库即可(自动化流程会处理后续的事情)。这就像在生产中使用巡航控制来管理应用程序一样。

GitOps 不仅限于Kubernetes,实际上它还可以通过将基础设施作为代码保存到GIt仓库中来将应用代码延伸到基础设施中,这通常是通过Terraform这样的工具进行普及的。声明式基础设施既代码在实现GitOps中扮演着一个重要的作用,但不仅限于此。GitOps围绕Git构建了整个生态系统和工具,并将其应用到基础设施,仅仅在Git中使用Terraform并不能保证基础设施的状态能够与生产环境保持一致,还需要持续运行Terraform命令(trrraform apply)来监控实时版本的变化,以及在流水线中实现手动审批等功能。

GitOps的理念是持续监控集群的状态并与Git仓库进行对比,在配置不一致时立即采取相应的动作,防止发生配置漂移。除此之外,你还可以获得Git带来的好处,如通过代码监视进行手动审批。

对于我来说,这些理念是革命性的,如正确使用,可以让组织更多关注功能特性,并减少自动化脚本的编写工作。这种观念可以延申到软件开发的其他领域,如可以将文档存储在代码中,以此来跟踪历史变更,并保证文档的及时更新;或使用 ADRs来跟踪架构决策。

Kubernetes中的Gitops

Kubernetes从一开始就有控制循环的想法,这意味着Kunernetes总是会监控集群的状态来保证达到期望状态。例如,使运行的副本数与期望的副本数匹配。将GitOps的理念延申到应用,这样就可以将服务定义为代码,例如,通过定义 Helm Charts,并使用一个通过K8s提供的功能来监控App状态的工具来调整对应的集群状态,即,更新了代码仓库,或更新了生产集群的helm chart。这才是真正的持续部署。其中的核心原则是,应用部署和生命周期管理应该是自动化的、可审计并易于理解的。

每个环境都应该有一个代码仓库,用于定义给定集群的期望状态。然后Kubernetes Operators 会持续监控特定分支(通常是master分支),并在探测到Git发生变更后,将此次变更传递到集群,并更新etcd中的状态。在这种方式中,etcd只作为一个数据库,且不是唯一的SOT。可以在包含声明式Kubernetes基础设施的Git仓库中定义应用的Helm chart。此外,还可以链接存储库,这样一个存储库可以监视另一个存储库,以此类推。Kubernetes GitOps工具可以监控其他仓库(如Helm Chart仓库)的状态,这样你的集群环境仓库中无需包含Helm Chart,只需要一条到Helm 仓库的连接,并使用该链接监控其变更即可,这样当你发布的一个新的chart时,后续会将该chart自动部署到集群。通过这种方式自动执行端到端的声明式CI/CD流水线。

声明式GitOps工具

如果考虑Kubernetes上的GitOps,就需要讨论那些在Kubernetes上实现了GitOps原则的工具(负责监控Git的状态,并将其同步到集群)。

ArgoCD

在我看来,Kubernetes上最好的GitOps工具就是ArgoCD。ArgoCD 是Argo生态系统的一部分,该生态系统包含了很多很好的工具,后续会进行讨论。

使用ArgoCD,可以在代码库中定义每个环境的所有配置。Argo CD会在特定的目标环境中自动部署所需的应用状态。

Kubernetes GitOps 工具

Argo CD 作为一个kubernetes controller,持续监控运行的应用,并将当前的活动状态与所需的目标状态(如Git repo中描述的状态)进行比较。Argo CD会报告并呈现这种差异,并通过自动或手动的方式将实时状态同步到期望的目标状态。

Kubernetes GitOps 工具

ArgoCD有一个非常棒的UI,支持SSO,它是安全、可扩展且易于使用的。

Flux

Flux 是除Argo CD外另一个非常有名项目。最近的版本包含很多改进,功能上非常接近Argo CD,Flux是CNCF孵化项目。

Kubernetes GitOps 工具

GitOps工具

在本节中,回顾一下我比较喜欢的GitOps友好的(即基于CRD的)工具。

helm

Helm 无需多言,它是Kubernetes上最著名的包管理器,当然,你应该像在编程语言中使用包一样,在K8s中使用包管理器。Helm允许使用Charts 的方式打包应用,将复杂的应用抽象为可重用的简单组件,便于定义、安装和升级。

它还提供了一个强大的模板引擎,Helm 已经很成熟,它包含很多预定义的charts,支持性强,使用方便。

Helm可以很好地集成到ArgoCD或Flux,后者可以监控Helm仓库的变化,并在发布新的charts时进行部署。实现思路是将ArgoCD或Flux 指向Helm仓库,并指定一个特定的版本或通配版本。如果使用通配版本,一旦发布了新的版本,就会进行自动部署。你可以使用主版本或次版本的方式进行命名。我通常倾向于将应用打包到charts中,将其作为CI/CD的一部分进行构建,并让ArgoCD监控特定的仓库。这种关注点分离允许开发者在独立于环境的仓库中管理应用,并让ArgoCD选择在哪个环境中部署哪个charts。你可以使用多个Helm仓库并根据不同的环境推送变更。例如,在合并一个PR后,可以执行一次"bronce"构建,该构建会将Helm chart发布到一个名为"bronce"的仓库中。dev环境的ArgoCD仓库指向"bronce"仓库,并在可用时部署新版本。staging 环境的ArgoCD仓库会指向名为"silver"仓库,而production 环境则指向名为"gold"的仓库。当需要向staging或production环境推送某些内容时,CI/CD只需将该chart发布到下一个仓库即可。

ArgoCD可以覆盖任何环境的特定Helm值。

Kustomize 是一个新的helm的替代品,它不需要模板引擎,而使用了一个overlay引擎,之上有基本定义和overlays 。

Argo Workflows 和 Argo Events

在Kubernetes中,你可能需要运行批量任务或复杂的工作流,作为数据处理流程、异步处理或CI/CD的一部分。除此之外,你可能需要运行驱动微服务来响应特定的事件,如文件上传或发送消息到某个队列。为了实现这些功能,可以使用 Argo WorkflowsArgo Events

虽然它们是独立的项目,但趋向于部署到一起。

Argo Workflows是一个类似Apache Airflow 的编排引擎,但天然适用于Kubernetes。它使用CRDs来定义复杂的workflows(使用YAML表示的steps或DAGs 来表达工作流)。它还有个不错的UI,支持重试机制,定时任务,输入输出跟踪等。你可以使用它来编排数据处理流水线和批量任务等。

有时你可能希望将流水线与异步服务(如流引擎Kafka、队列、webhook或底层存储服务)集成到一起。例如,你可能希望对上传文件到S3这样的事件做出响应,此时你可以使用Argo Events

Kubernetes GitOps 工具

上述两种工具为需要CI/CD流水线提供了简单且强大的解决方案,可以在Kubernetes上运行CI/CD流水线。

由于所有workflows 定义都可以打包到Helm charts中,因此Argo Workflows 可以很好地集成到ArgoCD。

对于ML流水线,可以使用Kubeflow实现相同的目的。

对于CI/CD流水线,可以使用Tekton

Istio

Istio 是市面上最著名的服务网格,它是开源的,且非常流行。由于服务网格内容庞大,因此这里不会讨论细节,但如果你在构建微服务,有可能你会需要一个服务网格来管理通信、可观测性、错误处理、安全以及(作为微服务架构一部分的)其他交叉方面。使用服务网格可以避免因为重复的逻辑而污染微服务的代码。

Kubernetes GitOps 工具

简而言之,一个服务网格就是一个特定的基础设施层,你可以在上面添加应用,它允许透明地添加可观测性、流量管理和安全,而无需自己实现这些功能。

Istio使用 CRDs 来实现其所有功能,因此可以将virtual services、gateways、policies等作为代码打包在Helm charts中,并使用ArgoCD或Flux来让Istio变得GitOps友好(虽然不是那么强大)。

还可以使用LinkerdConsul替代Istio。

Argo Rollouts

上面已经提到过,你可以使用Kubernetes来运行使用Argo Workflows或类似工具的CI/CD流水线。下一步逻辑上是执行持续部署,但在现实场景中,由于其风险较高,因此大部分公司只做了持续交付,这意味着他们可以实现自动化,但仍然采用手动方式进行审批和校验,这类手动步骤的根因是这些团队无法完全信任其自动化。

那么该如何构建这种信任度来避免使用脚本,进而实现从代码到生产的完全自动化。答案是:可观测性。你需要关注资源的指标,并通过采集所有的数据来精确地传达应用的状态,即使用一组指标来构建信任度。如果Prometheus中包含所有的数据,那么就可以实现自动化部署,因为此时你可以根据指标来实现滚动更新应用。

简单地说,你可以使用K8s提供的开箱即用的高级部署技术--滚动升级。我们需要使用金丝雀部署来实现渐进式发布,目的是将流量逐步路由到新版本的应用,等待指标采集,然后进行分析并于预先定义的规则进行匹配。如果检查正常,则增加流量;如果发现问题,则回滚部署。

在Kubernetes上可以使用Argo Rollouts来实现金丝雀发布。

Argo Rollouts是一个Kubernetes controller,它使用一组CRDs来提供高级部署能力,如蓝绿、金丝雀、金丝雀分析、实验等,并向Kubernetes提供渐进式交付功能。

虽然像 Istio 这样的服务网格可以提供金丝雀发布,但Argo Rollouts简化了处理流程,且以开发者为中心。除此之外,Argo Rollouts还可以集成到任何服务网格中。

Argo Rollouts 是GitOps友好的,且能很好地与Argo Workflows和ArgoCD进行集成。使用这三种工具可以为部署创建一个非常强大的声明式工具集。

Flagger 和Argo Rollouts非常类似,可以很好地与Flux进行集成,因此如果你正在使用Flux,可以考虑使用Flagger。

Crossplane

Crossplane是我最近喜欢的K8s工具,它填补了Kubernetes的一个关键空白:像管理K8s资源一样管理第三方服务。这意味着,你可以使用YAML中定义的K8s资源,像在K8s中配置数据库一样配置AWS RDS或GCP cloud SQL等云供应商的数据库。

Kubernetes GitOps 工具

有了Crossplane,就不需要使用不同的工具和方法来分离基础设施和代码。你可以使用K8s资源定义所有内容。通过这种方式,你无需去学习并分开保存像Terraform 这样的工具。

Crossplane 是一个开源的Kubernetes扩展,可以让平台团队组合来自多个供应商的基础设施,并为应用团队提供更高级别的自服务APIs(而无需编码任何代码)。

Crossplane 扩展了Kubernetes集群,使用CRDs来提供基础设施或管理云服务。再者,相比于Terraform这样的工具,它可以完全实现自动部署。Crossplane 使用现成的K8s能力,如使用控制循环来持续监控集群,并自动检测配置漂移。例如,如果定义了一个可管理的数据库实例,后续有人手动进行了变更,Crossplane 会自动检测该问题,并将其设置回先前的值。它将基础设施作为代码并按照GitOps原则来执行。

Crossplane 可以与ArgoCD配合起来,监控源代码,并保证代码库是唯一的信任源(SOT),代码中的任何变更都会传递到集群以及外部云服务。

如果没有Crossplane,你可以在K8s服务中实现GitOps,但无法在没有额外处理的前提下实现云服务的GitOps。

Kyverno

Kubernetes为敏捷自治团队提供了极大的灵活性,但能力越大责任越大。必须有一套最佳实践和规则来保证部署的一致性和连贯性,并使工作负载遵循公司要求的策略和安全。

Kyverno 是一种为Kubernetes设计的策略引擎,它可以像管理Kubernetes资源一样管理策略,不需要使用新的语言来编写策略。Kyverno 策略可以校验、修改和生成Kubernetes资源。

Kubernetes GitOps 工具

Kyverno 策略是一组规则,每条规则包含一个match子句,一条exclude子句和validate, mutategenerate中的某条子句。一条规则定义中只可以包含一个validate, mutategenerate子节点。

你可以配置任何有关最佳实践、网络或安全的策略。例如,可以强制所有包含标签的服务或所有容器运行在非root权限下。 这里提供了一些Kyverno 策略的例子。策略可以应用到整个集群或特定的命名空间中。你可以选择是否期望对策略进行审计或强制它们阻止用户部署资源。

Kubevela

Kubernetes 的一个问题是开发者需要知道并对平台和集群配置有所了解。很多开发者抱怨K8s的抽象级别太低,因此在那些只关心编写和交付应用的开发者中间出现了争议。

Open Application Model (OAM) 可以解决这个问题,它的理念是围绕应用创建一个更高级别的抽象,其独立于底层运行时。更多参见这里.。

通过关注应用而非容器或编排器。OAM带来了模块化、可扩展和可移植的设计,通过更高级别且一致的API对应用程序部署进行建模。

Kubevela是OMA模型的一种实现。KubeVela是运行时无关,且可扩展的,但最重要的是,它以应用程序为中心。在Kubevela 中,应用程序是以Kubernetes资源实现的一等公民。需要区分集群运维人员(平台团队)和开发者(应用团队)的区别。集群运维人员通过定义components(构成应用程序的可部署/可提供的实体,如helm charts)和traits来管理集群和不同的环境。开发者通过组装components 和traits来定义应用。

Kubernetes GitOps 工具

平台团队:将平台能力作为components或traits以及目标环境规范进行建模和管理。

应用团队:选择一个环境,组装需要的components和traits,并将其部署到目标环境中。

KubeVela 是CNCF的沙盒项目,目前正处于初始阶段,在不久的将来,它可以改变开发者使用Kubernetes的方式,使他们能够更加关注应用本身。但我对OAM在现实世界中的适用性有一些担忧,由于一些像系统程序、ML或大数据处理之类的服务,它们在很大程度上取决于底层细节,这种情况就很难融入OAM模型。

Schema Hero

软件开发中另一种常见的的处理流程是在使用关系型数据库时,需要管理schema的演进。

SchemaHero是一个开源数据库的schema迁移工具,可以将schema定义转化为可以在任何环境运行的迁移脚本。它使用了Kubernetes的声明特性来管理数据库schema的迁移。你可以指定期望的状态,并让SchemaHero管理剩下的工作。

Bitnami Sealed Secrets

至此,我们已经涵盖了很多GitOps工具,我们的目标是将所有内容保存到Git,并使用Kubernetes的声明特性来让环境保持同步。我们可以(也应该)在Git中保证SOT,并让自动化流程处理配置更改。

有一种资源通常难以保存到Git中,即secret,如DB密码或API密钥。一种常见的解决方案是使用外部"保险库",如 AWS Secret Manager 或HashiCorp Vault 来保存这些secret,但这样也产生了冲突,你需要一个单独的流程来处理secrets。理想情况下,我们希望通过某种方式将secrets像其他资源一样安全地保存到Git中。

Sealed Secrets 就是用来解决这种问题的,它允许你将敏感数据通过强加密保存到Git中,Bitnami Sealed Secrets天然集成进了Kubernetes中,可以使用Kubernetes中运行的Kubernetes controller来解密secret,而无需依赖其他组件。controller可以解密数据并创建原生的K8s secrets资源。通过这种方式可以将所有内容作为代码保存到仓库中,进而可以安全地执行持续部署,不需要依赖外部资源。

Sealed Secrets包含两部分:

  • 集群侧的控制器
  • 客户端侧程序:kubeseal

kubeseal 程序使用非对称加密来对secrets进行加密,且只有controller可以解密。这些加密的secrets被编码到了K8s的SealedSecret资源中(可以保存到Git中)。

Capsule

很多公司使用多租户来管理不同的客户,这在软件开发中很常见,但很难在Kubernetes中实现。一种方式是通过命名空间将集群划分为独立的逻辑分区,但无法完全隔离用户,还需要引入网络策略、配额等等。你可以在每个命名空间中创建网络策略和规则,但这是一个让人乏味的过程,且无法扩展,而且租户无法使用多个命名空间,这是一个很大的限制。

分层命名空间 可以用来解决这些问题。方法是为每个租户分配分配一个父命名空间,并为该租户配置通用的网络策略和配额,并允许创建子命名空间。这是一个很大的改进,但在租户层面,缺少安全性和治理方面的原生支持。此外,它还没有达到生产状态,但预计将在未来几个月发布1.0版本。

一种常见的方式是为每个客户创建一个集群,这样做相对比较安全,并给租户提供了所需的一切内容,但这种方式很难管理,费用也很高。

Capsule 是一种在单个集群中为Kubernetes提供多租户功能的工具。使用Capsule,你可以将所有租户放到一个集群中。Capsule会为租户提供一个"近乎"原生的体验(虽然有一些小小的限制),租户可以在其集群中创建多个命名空间。这种方式隐藏了多租户共享底层集群的事实。

Kubernetes GitOps 工具

在一个集群中,Capsule控制器将多个命名空间聚合到一起,抽象为一个轻量级的Kubernetes,称为租户,它是一组Kubernetes命名空间。在每个租户中,用户可以创建其命名空间并共享分配到的资源,Policy Engine 保证租户间的隔离性。

租户级别定义的 Network and Security Policies, Resource Quota, Limit Ranges, RBAC以及其他策略会自动继承到租户的所有命名空间中(类似分层命名空间)。这样,用户可以自主地操作他们的租户,而不需要集群管理员的干预。

由于Capsule 的所有配置都可以保存到Git中,因此它是GitOps的。

上一篇:Unity3D 升级2020版VR开发的一些问题


下一篇:Unity之引导功能遮罩事件穿透