本文翻译自:https://reurl.cc/OpqNqX,版权归原作者所有
今天,容器化已经成为在开发、测试和生产环境中运行应用程序的标准方式。因此,容器编排已经成为部署过程中不可或缺的一部分。
容器在一个独立的实例中运行应用程序及其所有依赖项,类似于 VM,但更轻量。它们与运行它们的主机共享操作系统内核存储和网络。容器可以在持续集成和持续部署过程中,保证操作系统、依赖项和应用程序不变。
目前为止,Docker 仍是最流行的容器运行时。当多个容器同时运行时,我们需要编排。可以在单个或少量 docker 服务器上部署许多容器,但管理网络,存储,容器编排,这就是 K8s 发挥作用的地方。
K8s 是一种编排解决方案,它抽象了运行多个容器的复杂性,甚至是在多个集群中运行这些容器的复杂性。它接管了成百上千个容器的计算、网络和存储,但它依赖这些底层基础设施。
对 CI/CD 流程的理解
在进入 GitOps 的核心概念之前,先了解一下容器和 k8s 是如何兼容 CI/CD Pipeline 的。
上图显示了一个标准的持续集成和交付过程。这个过程可能相当复杂,便于理解,我们尽量保持简单。
- 这里首先由开发人员提交代码并将其推送到版本控制系统 (通常是 git)。
- 创建一个 pull 请求合并到主分支。一旦代码被合并,它就会触发自动构建,将这些提交的更改合并到一起。
- 构建发生在 CI 服务器上,如果构建和测试一切顺利,则构建应用程序的容器镜像,并将其推送到容器注册中心。这个过程被称为持续集成。
- 代表应用程序不同版本的容器镜像存储在注册表中,以便部署在不同的环境中进行测试。作为持续集成的扩展,这些步骤被称为持续交付。
- 当测试通过时,可以触发应用程序新版本的自动化生产部署。
CI/CD 过程中可能涉及多个手动步骤,但是当随着时间推移,开发过程变得成熟时,可能会取消手动干预,这称为持续部署。
在持续交付过程中,在 k8s 中设置预期的状态,然后根据镜像创建单个容器。但是容器镜像在本质上是不可变的,所以当我们需要更新已部署的应用程序时,需要使用新代码和所有依赖项创建一个新的容器镜像。
为了获得所需的状态,k8s 从远程注册表获取镜像并达到期望状态。我们需要为它提供一组 k8s 配置清单,这些配置清单描述应用程序将如何运行。这些 YAML 清单引用容器镜像来标识部署的应用程序版本,还包含其他配置,如:副本实例数、健康检查、安全和自动伸缩等。
配置漂移问题
K8s 将尝试根据 YAML 中的定义,向期望状态接近,它也将响应之后的用户请求来更改所需状态。
这可以使用不依赖于 YAML 清单的命令 (kubectl 命令) 来完成。这些命令会改变期望状态,配置开始偏离 YAML 清单中已经定义的内容。
让我们用一个例子来理解它:
这里简化了 CI/CD 过程,以关注在一段时间内配置漂移问题是如何发生的。
从 v1 版本的应用程序部署到 k8s 集群开始。
我们已经定义的 CI/CD 流程,用于按照我们预期的状态 (DSC 1) 将配置应用到集群。
现在,应用程序在集群中以定义的期望状态 (DSC 1) 运行了一段时间,但最终出现了一些操作问题。
例如:由于流量突然增加,应用数量需要在节点级扩容,或一些安全配置需要立即应用到集群。为此,需使用必要的命令改变配置,改变已部署的应用程序。如下面所示图:
最终,在生产环境中长时间运行应用程序后,应用程序的版本 2 (App Version 2) 已经准备好了新特性,并上传工作负载清单以引用较新的镜像。
同样,我们的 CI/CD 将负责应用更新后的 YAML 清单,并且我们将依赖 K8s 在期望的状态下优雅地处理更改。
但理想状态是什么?是更新后的清单引用了新的容器镜像吗?
它是我们在动态集群中所做的必要更改和新的工作负载清单的合并吗?
K8s 认为理想状态应该是什么?
这个问题的答案是:K8s 会根据要求合并配置更改,但是集群的状态将不再准确反映我们开始时使用的 YAML 配置清单。
什么是 GitOps?
配置漂移可能是一个严重的问题,我们最好管理配置的完整性,以便在 K8s 中配置的内容准确地反映预期。
GitOps 就为了解决这个问题。它可以用来有效地管理配置,并帮助实现可靠和自动化的部署。
GITOPS 是依赖于软件自动化建立期望状态的云原生应用程序的操作模型模式,其使用版本控制系统,作为提供自动连续交付的真实来源。
所以 GitOps 通常描述的是期望的状态配置,并将其存储在版本控制系统中,它管理在期望状态下的变化。然后通过自动化代理 (如 Flux 或 Argo CD) 将这个期望的状态应用到目标环境(k8s,但不一定),然后根据版本控制系统中可用的内容持续监视系统的实际状态。
自动化代理可以是外部的,也可以在系统内运行。他们连续监测系统,并观察配置漂移的行为,做一些操作(可以配置为发出警报,或者以自动化的方式进行修复)。
GitOps 的部署策略
GitOps 的部署策略可以用推模型或拉模型来实现,下面我们试着去理解这两种模型。
Push Model
在本文开头,我们讨论了标准的 CI/CD 过程是怎样的,即开发人员将代码推送到 VCS,然后通过 pull request 触发 CI 构建。从那里产生的 docker 文件作为 CI 过程的结果,存储在注册表。在 CD 过程中部署到 K8s 集群,如下步骤 1,3,4,5 和 6 所示。
Push 部署策略
GitOps 的 Push 部署策略非常类似于 CI/CD 流程,只是清单文件包含了定义 K8 服务器需要创建对象的配置。Manifest 文件也在 VCS 中管理,可以是同一个 VCS,也可以是单独的存储库。
正如我们上面讨论的,部署和监控应用程序的自动化过程可以是外部的,也可以是内部的,对于 Push 部署策略,它是外部的,通常由同一个 CI 服务器管理。CI 服务器可以执行 kubectl apply 命令,将 manifest 应用到集群中。
Pull Model
在 GitOps Pull 场景中,自动化不是从集群外部操作,而是在集群内部部署一个代理。它作为 Kubernetes Operator 运行,能够跟踪包含 K8s 清单的 VSC 仓库。
Pull 部署策略
当它在集群中运行时,它知道集群的实际状态。如果它检测到 VCS 中包含的真实源与集群中的实际状态之间存在差异,它就会采取行动。要么发出告警,要么试图通过与 VCS 的内容同步来调和差异。还可以将代理配置为以新镜像的形式,监视远程容器注册表中应用程序代码的新版本。然后代理能够在 VCS 中更新清单,并基于新镜像触发新的自动部署。
由于 Pull 部署策略需要 K8s Operator 来执行操作,我们需要为此寻找特定的工具。虽然有多种可用的工具,但其中两个是最受欢迎的,CNCF 也推荐了它们。例如 Flux[1] 和 ArgoCD[2]。可以在官网中获得更多细节。
本文是对 GitOps 的理解,以及它如何解决配置漂移问题,来实现系统的高级治理。深入研究 GitOps 工具,看它们是如何实现的,将在后续文章中做分析。