# DevOps
在DevOps(开发运维)方法中,开发团队和运维团队在软件开发生命周期的构建和部署阶段协同工作、分担责任,并持续沟通反馈。在整个构建阶段,软件构建会在类生产环境中频繁的被测试,这样有助于及早发现缺陷。
软件团队的开发和运维本应由一个团队负责,开发人员从运维人员提供的反馈中获取信息,并制定测试和部署策略,工程师参与了整个应用程序生命周期的工作,从开发、部署到运维每一个环节都进行着密切的合作和沟通。这样的团队需要掌握一系列的技能,才能提高产品交付速度,从而缩短产品推向市场的时间,使系统更易于维护。
DevOps是文化和实践的结合,它要求组织打破产品开发和交付生命周期中所有团队之间的壁垒。它的目标是建立可重复、可靠、稳定、有韧性和安全的持续交付模式,它有如下特点:
- 快速交付:DevOps通过流水线来自动化完成代码构建到代码部署并发布到生产环境的端到端过程,能够提高效率并快速的修复错误。
- 可靠性:DevOps提供了检查功能,可以确保交付质量并快速安全的更新应用程序,同时将自动化测试和安全检查嵌入其中,为终端用户体验提供保障。
- 规模化:DevOps通过各个环节自动化,帮助基础设施和应用实现按需伸缩。
- 协作:运维和开发团队在共享责任的模式下合作,团队间的协作流程得到简化,从而提高效率。
- 安全性:DevOps将安全性与合规性的最佳实践自动化,通过自动化的方式进行监控和纠正错误。
# DevOps的组成
# CI/CD
DevOps的工具和自动化将开发及系统运维结合在一起,自动化是贯穿所有要素的最佳实践,通过自动化流程可以快速可靠以及可重复的执行操作,这使团队能够快速配置和调试测试及生产环境。
在持续集成(CI)的实践中,开发人员频繁的将代码提交待代码仓库并频繁的构建代码,每次构建都会通过自动化的单元测试和集成测试来进行验证,在持续交付(CD)的实践中,CI构建的代码被部署到测试环境中,并执行自动化或手动测试,测试通过会将其部署到预生产或生产环境。
CI是指软件开发生命周期中构建和单元测试阶段,在代码仓库中提交的每次变更都会触发一次自动构建和测试。CD是CI的延伸,它将CI产生的构建物进一步部署到生产环境。CI/CD实践中,多名成员同时处理同一份代码,他们都必须使用最新的、可工作的构建来完成自己的工作。代码仓库维护着不同版本的代码供团队访问,我们可以从代码仓库中查看代码,在本地副本中进行修改或编写新的代码,同时编译和测试代码,然后频繁的将代码提交回代码仓库。
下图呈现了应用程序自动化相关的内容。从代码提交到代码仓库,再到部署流水线,开发人员将代码变更签入代码仓库,接着CI服务器会拉取代码,CI服务器触发构建以创建带有新的应用程序二进制文件和相应依赖的部署包。这些新的二进制文件被部署到目标开发或测试环境中,同时二进制文件也会被签入工件库中进行安全的版本控制存储。
在CI/CD中,软件开发生命周期的各个阶段都是通过DevOps流水线自动完成的,部署和环境准备节点的自动化需要使用脚本完成,监控可以使用工具实现自动化。一个健壮的流水线可以自动为测试和生产环境提供基础设施,并实现对测试和生产环境的监控及管理。
CD意味着每一个变更都满足部署到生产环境的条件,而不是开发人员提交的每一个变更都会部署到生产环境,当变更在类生产环境中被暂存和测试时,会启动审批流程,审批通过即可完成在生产环境中的部署。
# 持续监控和改进
持续监控有助于了解应用程序和基础设施的性能对产品的影响,我们可以通过分析数据和日志来了解代码变更的影响。如下DevOps相关指标可以作为监控和改进的参考:
- 变更量:开发的用户故事数量,以及修复的bug数量。
- 部署频率:团队部署应用的频率,这个指标应该保持稳定或上升趋势。
- 从开发到部署的准备时间:从开发周期开始到部署结束的时间,它可以用来识别发布周期中低效的步骤。
- 部署失败率:失败部署的百分比,该指标应于变更量一起审查,如果变更量不高,但部署失败的次数较多,应该分析潜在问题原因。
- 可用性:追踪有多少故障可能会违反SLA,以及应用程序的平均停机时间。
- 客户投诉量:客户提交的投诉数量。
- 用户增长带来的流量:追踪新用户数量以及由此带来的流量增长,它可以帮助我们扩展基础设施来支撑工作负载的增长。
# 基础设施即代码
基础设施的置备、管理,甚至停用需要消耗大量的人力资源,此外反复尝试手动构建和修改环境可能会产生大量的错误,我们可以将创建完整环境的任务自动化,任务自动化有助于低成本完成重复性任务,通过LaC,我们可以以模板的形式定义基础设施。
在LaC实践中,基础设施是通过代码和CI来配置和管理的,LaC模型可以帮助我们与基础设施进行大规模的程序化交互,我们通过代码管理基础设施有助于推动部署方法的标准化,任何补丁和版本都可以重复更新,不容易出现错误。Ansible和Terraform是目前比较留下的LaC的脚本工具。
# 配置管理
配置管理是利用自动化来标准化整个基础设施和应用程序资源配置的过程,配置管理工具可以帮助我们管理LaC,并自动化大多数系统管理任务,包括置备、配置和管理IT资源。在开发、构建、测试和部署阶段实现资源配置的自动化和标准化,可以确保一致性并避免因错误配置而导致的失败。
配置管理还允许以相同的配置自动部署到其他节点,同时它也能用来部署配置变更,配置管理应用除了存储之外还能进行版本控制,并完成审计配置。下图展示了几种常用的配置管理工具:
# DevSecOps和CI/CD
DevSecOps关注自动化安全和规模化安全实施,开发团队不断生成变更,并将变更发布到生产环境中,DevSecOps需要在整个流程中确保应用程序的安全。为了避免安全漏洞,需要自动的进行安全测试,并将其构建到CI/CD流水线中,通过实时监控设计与实时状态的漂移量将安全和合规性纳入其中。
DevSecOps实践需要嵌入CI/CD流水线的每一步,DevSecOps通过管理分配给每个服务器的正确访问权限和角色,确保构件服务器被加固,防止任何安全故障,从而确保流水线的安全性。除此之外,我们还需要确保所有工件都得到测试的验证,下图展示了安全便捷的多个阶段:
我们可以在每个集成点识别不同的问题:
- 编码阶段,扫描所有代码,以确保没有密码或访问密钥被硬编码在代码中。
- 构建阶段,标记所有安全工件,如加密密钥和访问令牌管理等。
- 测试阶段,扫描配置,通过安全测试确保满足所有安全标准。
- 部署和环境准备阶段,确保所有安全组件都已注册,执行校验,确保构建物没有被篡改。
- 监控阶段,监控所有违反安全标准的情况,以自动化的方式执行持续审计和验证。
DevSecOps和CI/CD可以让我们根据企业安全策略对代码进行验证,有助于避免后续部署工作中由于不同的安全配置而导致基础设施和应用程序的故障。
# 部署的策略
CD提供了应用程序现有版本到新版本的无缝迁移,通过CD实现迁移流行的技术如下:
- 就地部署:在现有服务器集群上推出新版本,更新是在一次部署行动中完成的,因此需要一定的停机时间,这种更新几乎不需要任何基础设施的改变,也不需要更新现有DNS记录,部署过程相对比较快,如果部署失败,就只有再重新部署。简单的说,就是用新版本应用程序替换服务器现有版本的应用程序,就地更新成本低,部署速度快。
- 滚动部署:服务器集群被划分成小组,不需要同时更新应用程序。在部署的过程中,统一服务器集群会使用不同的子组分别运行旧版和新版软件,滚动部署方式有助于实现零停机,如果新版本部署失败,那么整个服务器集群中只有一个子组的服务器会受到影响,风险较小。滚动部署有助于实现零停机,但是部署时间相对较长。
- 蓝绿部署:蓝色环境代表现有生产环境,承载着实时流量,绿色环境除了运行新版的代码外,其他与蓝色环境完全相同。当需要部署时,将生产流量从蓝色环境路由到绿色环境,如果绿色环境中遇到问题,可以通过将流量路由回先前的蓝色环境来实现回滚,如果绿色环境所有指标全都正常,就可以停用蓝色环境,释放资源。DNS切换和自动伸缩组交换是蓝绿部署中最常用的两种重新路由流量的方法。使用自动伸缩策略,可以用托管新版本应用程序的实例逐渐替换现有实例。利用DNS路由是在应用程序的不同版本之间执行复杂的负载均衡。蓝绿部署有助于实现零停机,具有简单的回滚机制,可以根据需要定制部署时间。
- 红黑部署:为了准备切换,新版系统和旧版系统同时运行。新系统的初始容量是通过检查当前生产环境中运行的实例数量来手动设置的,设置的数值为新的自动伸缩组的期望容量,一旦新系统启动并运行,两个都是红色系统,当前版本是唯一接受流量的版本。切换新版本时,使用DNS服务器将系统从现有版本切换至新版本,此时旧版本被视为黑色,它仍在运行,但不接受任何流量,新版本如果有问题,只需要将DNS服务指向托管旧系统的负载均衡器即可。此部署方式可以用作beta测试,利用这种方式明确的启用新功能。
- 不可变部署:如果应用程序具有未知的依赖项,那么可以简单选择不可变部署或一次性升级。发布新版本时,在终止旧实例的同时上线一组新的服务器实例,完全建立一套全新的服务器。
# 在CI/CD流水线中进行测试
频繁的检查代码并在CI/CD流水线中内置合理的测试策略,可以确保在交付时能高质量的完成反馈闭环。单元测试是测试策略中最大的一部分,它们通常在开发人员的机器上运行,速度最快、成本最低。测试阶段发现bug可以更快的修改问题,而且复杂度相对较低。单元测试通常由开发人员执行,一旦完成编码就会被部署来进行集成和系统测试。
- 开发阶段,可以对代码进行静态分析,对代码覆盖率、编码准则的遵守情况进行检查。
- 构建阶段,是测试组件以及不同组件之间集成的第一阶段,这一阶段需要测试开发团队提交的代码是否破坏了现有功能。
- 预备环境,是生产环境的镜像,在这个阶段会进行端到端的系统测试、性能测试、负载测试、压力测试和合规性测试。UAT也在这个阶段进行,目的是为生产部署做好准备。
- 生产阶段,使用A/B测试或金丝雀分析等策略来测试新版本应用程序的用户反馈。
# DevOps的工具
要建立CI/CD流水线,开发人员需要各种工具,下面我们来分别探讨一下流行的DevOps工具选择。
- 代码编辑器:推荐使用VSCode、Vim,它们具有标准的IDE功能,如实时语法和匹配高亮显示、自动缩进和补全、版本控制工具集成,内置流行编程语言以及调试工具等。
- 源代码管理:可以自己搭建Git服务器,也可以选择使用GitHub和Bitbucket等。我们需要为代码仓库建立认证和授权机制,以进行访问控制,授权团队成员读取或写入代码。
- CI服务器:它也被称为构建服务器,CI服务器提供了“钩子”,当代码提交到仓库时,该事件会触发构建,“钩子”表示在指定的必要动作发生时会触发自定义脚本。自定义钩子可以被用来触发对合并后主干代码的测试,并阻止无法通过测试的合并。Jenkins是目前构建CI服务器比较流行的工具,它可以帮助我们从源代码仓库中构建正确版本的代码,并在代码部署时帮助团队为测试做好准备并发布使用。
- 代码部署:构建完成后,我们也可以使用Jenkins服务器进行部署。部署代理通过一系列步骤来执行部署,部署会先停止应用程序,以便在复制文件时停止流量,软件服务器包括Tomcat、JBoos、WebSphere等。应用服务器停止后,部署代理开始从工件仓库(JFrog、Artifactory)下载提前构建好的部署包。部署代理执行预安装步骤,如创建当前版本的备份以及通过脚本进行所需的配置更新。预安装完成后,部署代理启动应用的安装程序,例如运行Ant或Maven脚本来安装Java应用程序。应用程序安装完成后,部署代理会触发更新安装后的配置(如本地内存设置和日志参数)。最后代理服务器启动应用程序,并通知运维团队成功或失败的情况。必要的时候也可以在部署环节加入验证服务,以对应用程序进行完整性检查,执行自动完整的测试和集成测试等步骤,来验证新版本应用程序是否正确安装。
# 代码流水线
代码流水线是要把所有内容协调在一起,以实现持续部署(CD)。在CD中,整个软件发布过程(构建、部署到生产发布)是完全自动化的。下面列举一些代码流水线中个阶段的动作和工具:
- 源代码:应用程序代码需要储存在具有版本控制机制的中央仓库中,流行的代码仓库有GitHub、Gitlab、Gitee等。
- 构建:构建是从源代码仓库中拉取代码,并创建二进制包。常用的构建工具有Jenkins、Solano CI等,构建完成后可以将二进制文件存储在JForg等工件仓库中。
- 部署:部署工具可以帮助我们在服务器中部署应用程序的二进制文件。流行的部署工具有:Chef、Puppet、Jenkins等。
- 测试:自动测试工具可以帮助我们完成并进行部署后的验证,常用的测试验证工具有Jenkins、BlazeMeter、Chost Inspector等。
- 执行:我们可以基于事件的脚本来执行和备份和告警任务,使用例如shell这种脚本语言来执行自定义的活动。
- 审批:审批是CD的一个重要步骤,我们可以通过电子邮件触发器进行手动审批,也可以集成企业应用来进行自动审批。
# DevOps的最佳实践
在设计流水线时要考虑如下几点:
- 定义阶段:要能够清晰的定义清楚开发、集成、系统、验收和生产阶段,以及每个阶段的完成标准。
- 明确测试类型:每个阶段会对应不同类型的测试,如单元测试、集成测试、系统测试、UAT、冒烟测试、负载测试和A/B测试等。
- 监控和报告:监控系统的缺陷和故障,并在故障时发送通知。
- 基础设施置备:为每个阶段提供必备的基础设施。
- 回滚:定义回滚策略,以便在需要的时候可以回到以前的版本。
有一种常见的反模式是在代码中保存构建的配置值,甚至让开发在构建过程中使用不同的工具,这可能会导致开发人员之间的构建不一致,为了克服这个问题,最好将构建配置从代码中分离出来,将这些配置外置到工具中,可以使它们在不同的构建之间保持一致,实现更好的自动化。
构建最佳实践应用可以遵循“十二要素”方法论,它的官网是:https://12factor.net (opens new window)。
← 解决方案架构的成本设计 数据工程和机器学习 →