草庐IT

80%的软件环境管理问题,根因都在这里 | 研发效能提升36计

云效DevOps 2023-03-28 原文

专栏策划|雅纯
志愿编辑|jimmy、吕瑞星


软件交付的终态是提供稳定可预期的系统,要做到这一点,我们需要确保:一、软件制品的一致性;二、运行环境的一致性。

第3讲我们分享了如何保证软件制品的一致性,这一讲我们来谈谈如何保证环境的一致性

运行环境一致性的目标是环境可预期、稳定、低成本。其中低成本比较关键,因为环境资源的成本一般比较高。

我们可以将运行环境分为3部分:制品、执行引擎和编排规则。

 

要保证制品的一致性,第一是保证代码及其依赖的一致性;第二是保证构建环境的一致性;最后是保证构建脚本的一致性。保证环境的一致性,也包含了三点:

  1. 应用的一致性,比如一致的容器镜像;
  2. 容器运行所需的上下文的一致性,比如一致的数据配置等;
  3. 编排规则的一致性,需要保证编排执行相同的规则,比如相同容器部署规则、相同节点分布规则、相同备份规则等。

保证这3点,部署完成之后才会形成一致的可运行环境。但是现实当中,环境还是会有很多其它的问题,比如:

  • 配置文件中有好多监控之类的配置,对于使用者来说,不知道配置的具体作用,需要修改时不知如何设置。
  • 测试的时候依赖的环境经常发生问题,耗费大量等待和排查时间。比如说依赖的API经常出问题,排查修复可能需要等待依赖方很久,导致测试工作无法继续进行。
  • 新环境的搭建很耗时。搭建一个新的环境是很痛苦的事情,比如国际化团队,经常要搭建新的站点,而每搭一个新的环境就要耗费一整天的时间是很痛苦的。
  • 应用在本地无法运行。比如因为缺某个资源导致应用无法正常运行。
  • 配置环境需要小心翼翼,可能出现配置遗漏。每次配环境的时候需要很小心,特别是当环境配置由多人配合时,会出现配置冲突,导致程序无法运行,需要全链路排查解决。

这里我们简单列了五个常见的问题,它们的根源都是环境缺乏清晰的定义:不清楚环境的具体内容、对环境搭建过程的认知模糊。

环境的清晰定义,包括环境包含什么制品、这些制品如何部署等。那么环境管理的终态是什么呢?

当制品相同、运行上下文相同,并且资源数据是一样的情况下,基于相同的编排规则,环境就应该是一致的。同时,环境可以由软件来定义和声明。这是我们认为的环境管理的终态,简单来说,即软件定义的不可变环境。软件定义的不可变环境,可以纳入版本管理,保证环境首先是定义明确的,其次是有明确版本的。

环境管理的3个阶段

阶段一:说明书

环境管理的第一个阶段是说明文档,这点相信很多人都经历过。当我们在做一个项目或产品时,会写整个产品的部署说明书、说明文档、升级文档等各种文档。但文档很难保证实用,也不一定是最新的、准确的。每次我们去现场交付时,都会遇到一些文档里没有描述的问题。这时候还得打电话确认,是否有遗漏什么。用文档或说明书去管理环境,存在很大的弊端,所以我们想到了用命令的方式去管理。

阶段二:命令

第二阶段,我们通过命令的方式,写了各种shell、Python脚本,把相关命令组合在一起。之前我们在做一个产品的私有化交付的时候,一开始的做法就是用脚本去管理环境,因为开启一个新环境实在太痛苦了,需要花很多时间改参数、找包、配IP等,效率太低。所以我们写了脚本来管理,用脚本代替了文档。

但是用脚本管理环境也存在很多问题。我们要应对各种各样的环境,同一个任务在不同的场景里,命令组合可能是不一样的,所以脚本会越来越多,维护脚本的成本也越来越高。

阶段三:声明

为了解决命令脚本的维护和稳定性问题,我们进入了第三个阶段,声明式——通过配置的方式表达环境,把环境定义出来。声明式的描述提供了环境的确定性表达。

以k8s为例,我们以一个例子来看,如何做环境声明

上图是K8S的简单架构,左上角是K8S的master,左下角是node,master有好几个组件:scheduler、ControllerManager、APIserver,以及Etcd。Etcd是一个分布式存储,配置信息都在Etcd里面。Node是物理机或者虚拟机,在每一个Node上面会有多个pod,上面会运行很多的容器。

我们知道K8S的最小单元是pod,里面有容器,还有各种网络存储等,通过pod声明去描述。声明被apply后,具体的事情在controller里面处理。

通过sidecar分离关注点

我们写一个应用,这个应用里面大量的代码其实与业务无关,而是包含很多服务治理的代码,例如日志、监控、限流、熔断等。这些代码占了很大的比重,而且这些代码的维护者和应用开发者不一定是同一批人。服务治理相关的代码,在很多企业会有专门的团队负责维护和升级,类似阿里的中间件团队。传统的情况下,我们需要升级并重新部署应用才能升级服务治理能力。但是在云原生时代,应用开发者希望仅关注应用业务代码,服务治理相关的代码放在其他的容器里面,业务容器和服务治理容器通常会编排在同一个pod里面,但是服务治理容器的管理、开发、发布都跟应用开发者没有关系,这些就是sidecar容器。sidecar容器实现了关注点的分离,应用的开发者和中间件的开发者以及运维相关的开发者,都可以有自己的关注点。

我们以两个角色为例,一是业务的开发者,关注的是应用的容器,所以发布的时候,他的关注点都在应用容器这一块。二是企业的SRE,他的关注点往往在sidecar的各种服务治理容器上,比如logagent的日志级别和采样率是否合理等。

通过sidecar,业务开发者和SRE的关注点就分离了。这样分离还有一个好处,就是中间件下沉,都以sidecar的方式管理。一旦遇到相应的中间件需要升级,业务代码不需要做任何的改变和发布,只需要做sidecar的发布就好了。

我们前面提到,一致的环境需要有3个组成部分:相同的制品、相同的运行上下文以及相同的编排规则。相同的运行上下文,本质就是里面的配置要一致。最早我们是用文档告诉我们怎么把环境管理起来,之后用脚本,最后用环境声明。

然而,用声明式的方式定义环境也并不完美。举个具体的例子,在应用运行的时候需要有一些相应的配置,中间件、基础资源、CPU、存储等都需要配置,这样会面临一个很大的问题——环境相关的配置太多了。

环境相关的配置太多,该怎么管理好呢?

通过IaC来定义环境

为了解决这个问题,业内采用了IaC的概念(InfrastructureasCode)。早期在云机房上架的时候会用到IaC,比如有一个新的机器过来,要装成centos7的系统,里面要配特定的DNS服务等等。这是就会定义一个声明文件,发送给saltstack这样的工具。现在整个环境都是通过基础设施来描述出来的,所以整个环境包括中间件的资源都是基础设施了,在范围上比原先要广的多。

从配置的角度,我们有应用配置、运维配置、基础设施运维配置,甚至软件生产过程的配置。我们把应用代码和IaC代码,放在两个库里面(也有放到一个库里面的,各有利弊,在此我们不展开也不评价)。

比如上图中,在IaCRepo里我们放了动态配置(即运行时的配置)、BaaS配置(基础设施,如数据库、中间件存储、消息队列等)、监控配置(如监控粒度、采样频率)、发布配置等。所有的配置都声明在代码库里面,基于该声明编排的所有环境就都是一致的了。

任何事情都是有利有弊,用IaC的方式管理环境又会带来什么新的挑战呢?

首先是“灵活的代价”。因为所有的配置都是松散的文本,缺少统一的聚合根,导致修改者需要自己理解这些配置背后对应的依赖关系。比如某个配置项设置为on会开启限流,但是必须配合特定的configMap一起使用;比如开启了一个Ingress插件,但如果另一个Rollout插件没有开启,会无法正常工作;再比如HPA和CronHPA无法同时使用,会产生冲突。由于编写的灵活性,会导致无穷的组合形式,其组合产生的后果往往在运行时才会发现。

其次是知识的成本。IaC将一个环境所有的配置都以文本的界面给到了开发者,但是很多配置项是需要专业背景的,比如运维相关的策略、比如监控的配置方式等等,价值IaC本身的学习成本,往往让很多开发者望而生畏。

为了解决这个问题,阿里联合微软一起发布了OAM模型,以应用为统一维度,将IaC包含的各类资源和角色进行了分类和聚合。

首先,OAM引入了应用(Application)的概念,将应用的各类IaC配置都聚合在一起,解决其依赖问题。

其次,OAM将IaC的使用者分离为:应用开发者、应用运维、基础设施运维三大角色,彼此的关注点进行了分离。

OAM抽象和简化了IaC的定义和维护方式,降低开发者的学习和使用成本。

总结一下,我们认为,环境管理的终态是软件定义的不可变环境,而当下,它的最佳实践我们认为是基于OAM模型的、以应用为核心的IaC声明。

云效云原生应用管理平台AppStack正是基于OAM的应用交付平台,企业在云效AppStack,可以通过应用编排、占位符、变量等声明式定义,实现一套编排多环境差异化部署,同时基于版本和基线实现环境一键拉起、一键回滚。感兴趣的同学点下方链接即可免费使用。

https://www.aliyun.com/product/yunxiao/appstack?channel=yy_rccb_36


下篇预告:环境管理的目标是希望有一个稳定、可预期、低成本的环境。在软件开发中,我们会涉及到开发、测试、生产各种环境,如何保证这些环境的稳定、可预期、低成本呢?下一节我们将进一步展开,敬请期待。

阅读上篇:这样才是代码管理和 Commit 的正确姿势!

关于我们

了解更多关于云效DevOps的最新动态,可微信搜索并关注【云效】公众号;

福利:公众号后台回复【研发效能】,可获得精品课程【阿里巴巴研发效能提升36计】

ps:本课程将从研发效能的定义和度量着手,逐渐深入解析来自不同业务部门提升持续交付能力的实践、方法和工具,同时还将分享如何基于持续交付能力,切实提升产品和业务创新的效率和效果。

看完觉得对您有所帮助别忘记点赞、收藏和关注呦;

有关80%的软件环境管理问题,根因都在这里 | 研发效能提升36计的更多相关文章

  1. ruby - i18n Assets 管理/翻译 UI - 2

    我正在使用i18n从头开始​​构建一个多语言网络应用程序,虽然我自己可以处理一大堆yml文件,但我说的语言(非常)有限,最终我想寻求外部帮助帮助。我想知道这里是否有人在使用UI插件/gem(与django上的django-rosetta不同)来处理多个翻译器,其中一些翻译器不愿意或无法处理存储库中的100多个文件,处理语言数据。谢谢&问候,安德拉斯(如果您已经在ruby​​onrails-talk上遇到了这个问题,我们深表歉意) 最佳答案 有一个rails3branchofthetolkgem在github上。您可以通过在Gemfi

  2. ruby-on-rails - 获取 inf-ruby 以使用 ruby​​ 版本管理器 (rvm) - 2

    我安装了ruby​​版本管理器,并将RVM安装的ruby​​实现设置为默认值,这样'哪个ruby'显示'~/.rvm/ruby-1.8.6-p383/bin/ruby'但是当我在emacs中打开inf-ruby缓冲区时,它使用安装在/usr/bin中的ruby​​。有没有办法让emacs像shell一样尊重ruby​​的路径?谢谢! 最佳答案 我创建了一个emacs扩展来将rvm集成到emacs中。如果您有兴趣,可以在这里获取:http://github.com/senny/rvm.el

  3. ruby-on-rails - 在 Rails 开发环境中为 .ogv 文件设置 Mime 类型 - 2

    我正在玩HTML5视频并且在ERB中有以下片段:mp4视频从在我的开发环境中运行的服务器很好地流式传输到chrome。然而firefox显示带有海报图像的视频播放器,但带有一个大X。问题似乎是mongrel不确定ogv扩展的mime类型,并且只返回text/plain,如curl所示:$curl-Ihttp://0.0.0.0:3000/pr6.ogvHTTP/1.1200OKConnection:closeDate:Mon,19Apr201012:33:50GMTLast-Modified:Sun,18Apr201012:46:07GMTContent-Type:text/plain

  4. ruby-on-rails - 事件管理员日期过滤器日期格式自定义 - 2

    是否有简单的方法来更改默认ISO格式(yyyy-mm-dd)的ActiveAdmin日期过滤器显示格式? 最佳答案 您可以像这样为日期选择器提供额外的选项,而不是覆盖js:=f.input:my_date,as::datepicker,datepicker_options:{dateFormat:"mm/dd/yy"} 关于ruby-on-rails-事件管理员日期过滤器日期格式自定义,我们在StackOverflow上找到一个类似的问题: https://s

  5. Vscode+Cmake配置并运行opencv环境(Windows和Ubuntu大同小异) - 2

    之前在培训新生的时候,windows环境下配置opencv环境一直教的都是网上主流的vsstudio配置属性表,但是这个似乎对新生来说难度略高(虽然个人觉得完全是他们自己的问题),加之暑假之后对cmake实在是爱不释手,且这样配置确实十分简单(其实都不需要配置),故斗胆妄言vscode下配置CV之法。其实极为简单,图比较多所以很长。如果你看此文还配不好,你应该思考一下是不是自己的问题。闲话少说,直接开始。0.CMkae简介有的人到大二了都不知道cmake是什么,我不说是谁。CMake是一个开源免费并且跨平台的构建工具,可以用简单的语句来描述所有平台的编译过程。它能够根据当前所在平台输出对应的m

  6. 软件测试基础 - 2

    Ⅰ软件测试基础一、软件测试基础理论1、软件测试的必要性所有的产品或者服务上线都需要测试2、测试的发展过程3、什么是软件测试找bug,发现缺陷4、测试的定义使用人工或自动的手段来运行或者测试某个系统的过程。目的在于检测它是否满足规定的需求。弄清预期结果和实际结果的差别。5、测试的目的以最小的人力、物力和时间找出软件中潜在的错误和缺陷6、测试的原则28原则:20%的主要功能要重点测(eg:支付宝的支付功能,其他功能都是次要的)80%的错误存在于20%的代码中7、测试标准8、测试的基本要求功能测试性能测试安全性测试兼容性测试易用性测试外观界面测试可靠性测试二、质量模型衡量一个优秀软件的维度①功能性功

  7. ruby-on-rails - ruby gem如何在rails环境下工作 - 2

    我试图在rails中了解rubygems是如何变得可以自动使用的,而不是在使用required的文件中gem? 最佳答案 这是通过bundler/setup完成的:http://bundler.io/v1.3/bundler_setup.html.它在您的config/boot.rb文件中是必需的。简而言之,它首先将环境变量设置为指向您的Gemfile:ENV['BUNDLE_GEMFILE']||=File.expand_path('../../Gemfile',__FILE__)然后它通过要求bundler/setup将所有ge

  8. ruby - (Ruby || Python) 窗口管理器 - 2

    我想用这两种语言中的任何一种(最好是ruby​​)制作一个窗口管理器。老实说,除了我需要加载某种X模块外,我不知道从哪里开始。因此,如果有人有线索,如果您能指出正确的方向,那就太好了。谢谢 最佳答案 XCB,X的下一代API使用XML格式定义X协议(protocol),并使用脚本生成特定语言绑定(bind)。它在概念上与SWIG类似,只是它描述的不是CAPI,而是X协议(protocol)。目前,C和Python存在绑定(bind)。理论上,Ruby端口只是编写一个从XML协议(protocol)定义语言到Ruby的翻译器的问题。生

  9. ruby-on-rails - 事件管理员和自定义方法 - 2

    这是我在ActiveAdmin中的自定义页面ActiveAdmin.register_page"Settings"doaction_itemdolink_to('Importprojects','settings/importprojects')endcontentdopara"Text"endcontrollerdodefimportprojectssystem"rakedataspider:import_projects_ninja"para"OK"endendend我想做的是,当我单击“导入项目”按钮时,我想在Controller中执行rake任务。但是我无法访问该方法。可能是什

  10. ruby-on-rails - 如果条件与 &&,是否有任何性能提升 - 2

    如果用户是所有者,我有一个条件来检查说删除和文章。delete_articleifuser.owner?另一种方式是user.owner?&&delete_article选择它有什么好处还是它只是一种写作风格 最佳答案 性能不太可能成为该声明的问题。第一个要好得多-它更容易阅读。您future的自己和其他将开始编写代码的人会为此感谢您。 关于ruby-on-rails-如果条件与&&,是否有任何性能提升,我们在StackOverflow上找到一个类似的问题:

随机推荐