# GitOps 实现云原生的持续交付



# GitOps

**GitOps是一种持续交付的方式。它的核心思想是将应用系统的声明性基础架构和应用程序存放在Git版本库中**

* `Git` 作为交付流水线的核心, 每个开发人员都可以提交拉取请求`（Pull Request）`并使用`Git`来加速和简化`Kubernetes`的应用程序部署和运维任务。通过使用像`Git`这样的简单工具, 开发人员可以更高效地将注意力集中在创建新功能而不是运维相关任务上（例如: 应用系统安装、配置、迁移等）。



## GitOps 优点

1. 使用Git提交基础架构代码更改时, 自动化的交付流水线`(Pipeline)`会将这些更改应用到应用程序的实际基础架构上。

2. 通过应用GitOps最佳实践, 应用系统的基础架构和应用程序代码都有`"真实来源"` —— 其实是将基础架构和应用程序代码都存放在`gitlab`、或者`github`等版本控制系统上。这使开发团队可以提高开发和部署速度并提高应用系统可靠性。


> GitOps理论方法应用在持续交付流水线上, 有诸多优势和特点

* 安全的云原生CI/CD管道模型

* 更快的平均部署时间和平均恢复时间

* 稳定且可重现的回滚 (例如, 根据Git恢复/回滚/fork)

* 与监控和可视化工具相结合, 对已经部署的应用进行全方位的监控


## GitOps With Kubernetes


* GitOps 是在具体`Kubernetes`的应用实践中出现的, GitOps 需要依托于 "不可变基础架构" 才能发挥其作用。 在一定程度上说, "不可变基础架构" 为GitOps的出现创造了必要的条件, 反过来GitOps 应用`Kubernetes`的容器编排能力, 能够迅速的使用镜像搭建出应用系统所需的组件。


* 所谓不可变基础架构:

  * 应用都需要运行在多台机器上，它们被组织成不同的环境，例如开发环境、测试环境和生产环境等等。需要将相同的应用部署到不同的机器上。通常需要系统管理员确保所有的机器都处于相同的状态。接着所有的修改、补丁、升级需要在所有的机器中进行。随着时间的推移，很难再确保所有的机器处于相同的状态，同时越来越容易出错。这就是传统的可变架构中经常出现的问题。这时我们有了不可变架构，它将整个机器环境打包成一个单一的不可变单元, 而不是传统方式仅仅打包应用。这个单元包含了之前所说的整个环境栈和应用所有的修改、补丁和升级, 这就解决了前面的问题。


* 所谓声明性容器编排:

  * `Kubermetes`作为一个云原生的工具, 可以把它的`"声明性"`看作是`"代码"`, 声明意味着配置由一组事实而不是一组指令组成。


* GitOps充分利用了`"不可变基础设施"`和`"声明性容器编排"`, 通过GitOps可以轻松地管理多个部署。为了最大限度地降低部署后的变更风险, 无论是有意还是偶然的"配置偏差", GitOps构建了一个可重复且可靠的部署过程, 在整个应用系统宕机或者损坏情况下, 为快速且完全恢复提供了所需条件。



## GitOps 基本原则

* 任何能够被描述的内容都必须存储在Git库中

  * 通过使用Git作为存储声明性基础架构和应用程序代码的存储仓库，可以方便地监控集群，以及检查比较实际环境的状态与代码库上的状态是否一致。所以，我们的目标是描述系统相关的所有内容：策略，代码，配置，甚至监控事件和版本控制等，并且将这些内容全部存储在版本库中，在通过版本库中的内容构建系统的基础架构或者应用程序的时候，如果没有成功，则可以迅速的回滚，并且重新来过。

* 不应直接使用Kubectl

  * 一般规则, 不提倡在命令行中直接使用`kubectl`命令操作执行部署基础架构或应用程序到集群中。 还有一些开发者使用CI工具驱动应用程序的部署, 但如果这样做可能会给生产环境带来潜在不可预测的风险。


* 调用`Kubernetes`的API的接口或者控制器应该遵循`Operator`模式。

  * 调用 `Kubernetes` 的API的接口或者控制器应该遵循 `Operator` 模式, 集群的状态和Git库中的配置文件等要保持一致, 并且查看分析它们之间的状态差异。

    * 所谓 `Operator` 模式 - 是 `Kubernetes` 的扩展软件, 它利用自定义资源管理应用及其组件。 `Operator` 遵循 `Kubernetes` 的理念, 特别是在控制回路方面。 `Kubernetes`为自动化而生。无需任何修改, 您即可以从`Kubernetes`核心中获得许多内置的自动化功能。 您可以使用`Kubernetes`自动化部署和运行工作负载, 甚至可以自动化 `Kubernetes` 自身。 



## 推送流水线


* `推送流水线`

  * 目前大多数CI / CD工具都使用基于推送的模型。基于推送的流水线意味着代码从CI系统开始, 通过一系列构建测试等最终生成镜像, 最后手动使用 `kubectl` 将任何更改推送到`Kubernetes` 集群。 

{{< mermaid >}}
graph LR;
    A( Dev ) -->| RW | B( Git Code Repo )
    C(CI 流程) -->| RO | B
    C -->| RW | D( Docker Image Repo )
    E( Kuberneres Cluster ) -->| RO | D
{{< /mermaid >}}



## 拉式流水线

* `拉式流水线`

  * GitOps中, 镜像被拉出并且凭证保留在集群中.

  * Git库是拉式流水线模式的核心, 它存储应用程序和配置文件集。开发人员将更新的代码推送到`Git`代码库, CI 工具获取更改并最终构建`Docker`镜像。GitOps 检测到有镜像, 从存储库中提取新镜像, 然后在Git配置仓库中更新其YAML。然后, GitOps 会检测到群集已过期, 并从配置库中提取已更改的清单, 并将新镜像部署到群集。



{{< mermaid >}}
graph LR;
    A( Dev ) -->| RW | B( Git Code Repo )
    C(CI 流程) -->| RO | B
    C -->| RW | D( Docker Image Repo )
    E( Kuberneres Cluster Operator ) -->| RO | D
    E -->| RW | F( Config Repo )
{{< /mermaid >}}



### 拉式流水线 流程



1. 开发人员将更新的代码推送到 `Git` 代码库.

2. CI 工具获取最新代码并最终构建成`Docker image`.

3. GitOps 的 `Config Update` 检测到有镜像, 从存储库中提取新镜像, 然后在 `Git` 配置仓库中更新其 `YAML` 。

4. GitOps 的 `Deploy Operator` 会检测到群集已过期, 并从配置库中提取已更改的清单, 并将新镜像部署到群集。


---
* 使用群集内部的 `Deploy Operator`, 群集凭据不会在生产环境之外公开。一旦将 `Deploy Operator` 安装到集群与 Git 仓库建立连接, 线上环境中的任何更改都将通过具有完全回滚的 `Git pull` 请求以及 `Git` 提供的方便审计日志完成。


* 部署和发布自动化是应用落实 GitOps , 并使交付流水线工作的基础。GitOps 不仅要保证, 当开发人员通过 `Git` 更新配置文件集的时候, GitOps 流水线要自动根据最新的配置文件状态更新线上环境, 而且 GitOps 还要能够实时比对 `Git` 库中配置文件集最新的状态与线上环境最新的状态保持一致。



---
* `Config Update` 和 `Deploy Operator`, 根据 GitOps 的实践, `Config Update` 和 `Deploy Operator` 是需要进行设计开发的, 它们是实现 GitOps 流水线必须的关键组件。GitOps 赋予了它们神奇的魔法, 它们既是自动化容器升级和发布到线上环境的工具, 可能也要负责服务、部署、网络策略甚至路由规则等任务。因此, `Config Update` 和 `Deploy Operator` 是映射代码, 服务和运行集群之间所有关系的"粘合剂"。 当然, 您可以根据具体的设计, 赋予各种其他的功能, 但是自动同步是一定需要的, 确保如果对存储库进行任何更改, 这些更改将自动部署到线上环境中。



