1.1 GitOps的演进

基础设施配置和软件部署是管理和运维计算机系统的两项日常任务。基础设施配置用于准备供软件应用程序正确运行的计算资源(例如服务器、存储和负载均衡器)。软件部署是采用特定版本的软件应用程序,并使其准备好在计算基础设施上运行的过程。管理这两个过程是GitOps的核心。然而,在我们深入研究如何在GitOps中实行这种管理之前,了解导致行业迈向DevOps的那些挑战以及GitOps的不可变、声明式基础设施是非常有用的。

1.1.1 传统Ops

在传统的信息技术运维模型(见图1.1)中,开发团队负责定期将软件应用程序的新版本交付给质量保证(QA)团队,该团队测试新版本,然后将其交付给运维团队进行部署。新版本的软件可能每年发布一次,每季度发布一次,或者以更短的时间间隔发布。如今传统的运维模式越来越难以支撑日益压缩的发布周期。

图1.1 传统IT团队通常由独立的开发团队、QA团队和运维团队组成,每个团队专注于应用程序开发过程的不同方面

运维团队负责基础设施配置和新版本软件应用程序到该基础设施的部署。团队的工作重点是确保运行软件的系统的可靠性、弹性和安全性。如果没有精细的管理框架,基础设施管理可能是一项艰巨的任务,它需要大量的专业知识。

IT运维 IT运维是所有流程和服务的集合,这些流程和服务均由IT人员向内部或外部客户提供,以满足业务的技术需求。运维工作包括维护工单或客户问题的响应。[1]

由于涉及三个团队,通常会伴有不同的管理汇报结构(见图1.2),因此需要详细的移交过程和完整的应用程序变更文档,以此来确保对应用程序进行充分的测试、对基础设施进行恰当的更改,以及对应用程序进行正确的安装。然而这些要求导致部署时间很长并且降低了部署的频率。此外,随着团队之间的每次交接,必要的细节未被传达的可能性会增加,这可能导致测试中的偏差或不正确的部署。

图1.2 在传统的部署流程中,开发团队为QA团队开一张工单来测试新的产品版本。测试成功后,QA团队会为运维团队开一张工单,以便将最新版本部署到生产中

幸运的是,大多数开发团队使用自动化构建系统和称为持续集成(CI)的过程来编译、测试和生成可部署的制品。但新代码的部署往往靠运维团队手动实施,涉及冗长的手动过程,或者通过部署脚本实现部分自动化。在最坏的情况下,运维工程师会手动将可执行的二进制文件复制到多台服务器,并手动重新启动应用程序使新的二进制版本生效。此过程容易出错,并且可供的控制选项极少,例如检查、审批、审计和回滚。

持续集成 CI涉及软件应用程序的自动化构建、测试和打包。在典型的开发工作流程中,软件工程师进行代码更改,然后将其签入中央代码仓库。这些更改必须经过测试,并与计划部署到生产环境的主代码分支集成。CI系统有助于代码的审查、构建和测试,以便代码在合并到主干分支之前确保其质量。

随着云计算基础设施的兴起,管理计算和网络资源的交互越来越多地基于应用程序编程接口(API),这样便于实现更多的自动化,但也需要更多的编程技能。这一既成事实,加上许多组织希望优化运营,缩短部署时间,提高部署频率,以及提升计算系统的可靠性、稳定性和性能,导致了一个新的行业趋势:DevOps。

1.1.2 DevOps

DevOps强调自动化的组织架构和思维方式的转变。运维团队不再负责部署和运维,而是转由应用程序的开发团队承担这些责任。

DevOps DevOps是一套软件开发实践,它将软件开发(Dev)和IT运维(Ops)结合在一起,在缩短系统开发生命周期的同时,频繁交付与业务目标密切相关的功能、补丁和更新。[2]

图1.3显示了在传统的运维模式中,组织是如何按职能边界划分不同的开发、QA和运维团队的。在DevOps模型中,团队按产品或组件划分并且是跨领域的,团队中包含具有跨所有职能技能集的团队成员。尽管图1.3显示了具有特定角色的团队成员,但实践DevOps的高素质团队中的所有成员都能跨职能做出贡献—每个成员都能够编码、测试、部署和运维其产品或组件。

图1.3 传统组织模型具有独立的开发、QA和运维团队。DevOps组织模型允许以特定产品或组件为中心的跨领域团队。每个DevOps团队自给自足,包含具备开发、测试和部署应用程序技能的成员

DevOps带来的好处包括:

□开发和运维之间更好的协作。

□提升产品质量。

□更频繁的发布。

□缩短新功能的面市时间。

□降低设计、开发和运维的成本。

案例研究:Netflix

Netflix是DevOps过程的早期采用者之一,其每个工程师都负责功能的编码、测试、部署和支持。Netflix的文化提倡“自由和责任”,这意味着每个工程师都可以独立推送版本,但必须确保该版本的正常运行。所有部署过程都是完全自动化的,因此工程师只需按一下按钮即可部署和回滚。在功能完成的那一刻,所有的新特性就已在最终用户手中。

1.1.3 GitOps

GitOps一词于2017年8月由Weaveworks[3]的联合创始人兼首席执行官Alexis Richardson在一系列博客中创造出来。从那时开始,该术语在整个云原生社区,尤其是Kubernetes社区中引起了广泛的关注。GitOps是一个DevOps中的过程(见图1.4),其特点是:

□部署、管理和监控容器化应用程序的最佳实践。

□以开发人员为中心的应用程序管理体验,使用Git进行开发和运维的全自动化流水线/工作流。

□使用Git版本控制系统跟踪和审批对应用程序的基础设施和运行时环境的变更。

图1.4 GitOps发布工作流从创建代码仓库的分支开始,其中包含对系统所需状态的定义的更改

GitHub以及GitLab、Bitbucket等是现代软件开发生命周期的核心,因此将它们用于系统运维和管理似乎也理所当然。

在GitOps模型中,系统的期望配置存储在版本控制系统中,例如Git。工程师不是通过UI或CLI直接对系统进行更改,而是对代表期望状态的配置文件进行更改。Git中存储的期望状态与系统实际状态之间的差异表明并非所有变更都已部署。这些变更可以通过标准的版本控制流程(例如拉取请求、代码审查、合并到主干)来审查和批准。当变更被批准并合并到主干分支时,一个Operator软件进程负责根据存储在Git中的配置将系统的当前状态更改为期望状态。

在理想的GitOps实现中,手动更改系统是不被允许的,所有配置更改都必须对存储在Git中的文件施行。在极端情况下,更改系统的许可仅授予Operator软件进程。基础设施和运维工程师在GitOps模型中的角色从执行基础设施变更和应用程序部署转变为开发和维护GitOps自动化,并通过使用Git帮助团队审查和批准变更。

Git有许多特性和技术能力,是与GitOps一起使用的理想选择:

□Git存储每个提交。通过适当的访问控制和安全配置(见第6章),所有的变更都是可审计和防篡改的。

□Git中的每个提交都表示到该时间点为止系统的完整配置。

□Git中的每个提交对象都与其父提交相关联,以便在创建和合并分支时,提交的历史记录在需要时可用。

GitOps很重要,因为它可以跟踪对环境所做的变更,并支持使用Git(大多数开发人员已经熟悉的工具)实现轻松回滚、可恢复性和自我修复。

Git提供了验证和审计部署的基础。尽管可以使用Git以外的版本控制系统来实现GitOps,但Git的分布式特性、分支和合并策略以及应用的广泛性使其成为理想的选择。

GitOps不需要特定的工具集,但这些工具必须提供以下标准功能:

□对存储在Git中的系统的期望状态进行操作。

□检测期望状态和实际状态之间的差异。

□在基础设施上执行所需的操作,将实际状态与期望状态同步。

尽管本书重点介绍了与Kubernetes相关的GitOps,但GitOps的许多原则是可以独立于Kubernetes实现的。