
作者 | 云昭
Devops作为一种围绕开发团队和IT运营团队营造协作氛围的文化,自提出以来,业内就存在倡导与质疑两种声音。一方面,在人力成本攀高、市场竞争日趋激烈、用户需求变化频繁的情况下,DevOps形成了一系列理念、实践和工具的结合,一定程度上提高了企业在产品和服务交付的效率,成为了快速上线的组织神器;另一方面,DevOps被很多人调侃为“系统集成”、“软件堆砌”,难以实际落地,甚至有人认为:DevOps运动失败了。在加快软件交付上,DevOps的确功不可没。它给企业项目团队带来了高敏捷性、减少人工、高效的跨职能团队协作、持续创新、最小缺陷等优点,但“成也萧何,败也萧何”,此时的DevOps多少有些沦为一种工具的危险,已非初时的模样。
说起DevOps,就不得不从DevOps之父——Patrick Debois说起。2007 年,Patrick参与了比利时一个政府下属部门的大型数据中心迁移项目。在这个项目中,他分别负责测试和验证的工作。这就意味着他不光有机会和开发团队(Dev)工作,也时常要和运维团队(Ops)工作。 在开发团队中,他需要适应敏捷交付的节奏,但在运维团队他又得按照传统模式,像管理消防队员那样维护系统。两种工作氛围的来回切换,令他十分沮丧:不同的工作方式、思维方式势必存在着巨大差异,所以在这两者之间工作,到处都是冲突。应用程序在实际生产中会遇到各种未知且棘手的问题,很难及时处理。这就促使了运维等相关人员在软件研发生命周期的早期就需要参与进来。作为敏捷开发的拥趸,Patrick果断调整,试图通过打通开发和运维的这堵部门墙。而他所开展的敏捷管理实践就是DevOps发展的第一个雏形。
DevOps概念形成有两个关键时刻,一个是Patrick Debois和Andrew Clay Shafer在多伦多敏捷会议上的会面,另一个便是John Allspaw和Paul Hammond在 Velocity'09的演讲。经过探讨,DevOps准确的定义就是Development和Operations的组合,是一组过程、方法与系统的统称,用于促进开发、技术运营和质量保障(QA)部门之间的沟通、协作与整合。彼时的概念很朴素:修复文化。而为了让“DevOps”取得成功,有分歧的相关方都需要参与。时隔十余年,现在看来,企业虽然多了“DevOps工程师”的职位,在DevOps会议上却失去了这种初衷:大量运维、运营人员参与,而开发人员参加的较少。
随着DevOps的流行,很多企业的做法却相当粗暴:将Dev、Ops两个团队合并,或者将运维划归开发。这是理念上的错误。此外,在客观条件上也缺土壤。尤其在微服务盛行的今天,系统被分成了几十个甚至几百个服务组件,如果没有敏捷的基础设施服务作为先行条件,做DevOps基本上就是空谈。这也是DevOps这些年一直难以落地的主要的两点原因。下面举个真实的例子。Lee Briggs是一位拥有15年经验的云工程技术的资深专家和创业者,他曾聊到有关DevOps的一次感到困惑的经历:一位负责开发某产品的董事级同事在会上提到他的团队是“真正的Devops”,却从未和Briggs谈论过他们的运维需求,Briggs甚至不知道他们在做什么,只知道他们在使用AWS ECS部署应用程序。
Briggs感到很困惑:如果连本公司的运维团队都没有参与进来,他们怎么可能是“真正的Devops”?
后来经过与其团队中的开发人员的对话,Briggs才明白整背后的含义:公司的开发人员接管了整个应用程序的生命周期,一条龙处理,不需要运维参与了——他们使用boto3并编写部署脚本来发布新版本,并雇佣了精通AWS以及后端业务的“全栈工程师”。DevOps初衷纯粹是为了让开发人员能够更轻松的工作,本意是减少甚至是消除他们在部署、管理部署等在基础架构生命周期的种种繁琐的操作与困扰。而现在,别人口中侃侃而谈“真正的Devops”时,他们的意思却是让开发者把运维的工作也包揽了。
如今,我们正在用今天的运维人员所熟悉的久经考验的工具来给到开发者,其中包括GitLab CI、Terraform(Terraform是一个IT基础架构自动化编排工具,可以用代码来管理维护IT资源),当然还有Kubernetes。事情就变成了这样:“嘿,你应该试试使用我们的平台!我们已经修复了所有这些Bug,它比原来的工具要好得多。”“谢谢,但我们不感兴趣。”“呃,为什么?它更可靠、更快,并且是使用业界标准的工具。”“是的,但我们一点也不了解他们。我们还是对自己的东西更熟悉些。”运维人员一直相信自己的方法很管用:毕竟运维部门知道如何在云上运行软件。但开发者往往不买单。Briggs陈述了这段经历——“运维人员总是试图说服开发人员来参加DevOps会议。一味地解释自身打造的平台做了什么,以及它将如何帮助他们。我在与开发人员的对话中一直在争论,拼命想给整个公司带来一种“DevOps”的心态,而这个团队对这种心态的回应却是‘我们自己来做,谢谢。’”
Briggs终于意识到:DevOps这种改变文化的尝试失败了。
最终,Briggs对2022年DevOps的做出了以下总结:现在的DevOps是更多的站在运维角度上,试图说服开发人员按照运维的方式做事。原因一目了然,目前市面上几乎所有被称为“DevOps”的工具都专注于运维层面。如果你浏览/r/devops,你会看到一篇又一篇关于运维或工具的文章。如果您查看DevOps工程师的工作描述,它看起来与2013年的系统管理员角色非常相似,只不过其中涉及的不再是原来的机架和堆叠着的服务器,取而代之的是一些容器或云的提供商管理。因此,如果DevOps本应致力于改变整体文化,那么它就不能被视为一场成功的运动。看好这场运动的人可能会高兴地说:“我们正在努力!”但其实他们明白,他们只不过是局限在运维方面在做单方面的努力——而这显然,有悖于DevOps最初强调的“一条双向的道路”。值得记住的是,在任何给定项目或组织中,运维的人数通常至少超过1/5。试图说服每一位开发人员以“运维”和“使用运维工具”的方式做开发,最终都将是一件愚蠢的差事。
归根结底,“DevOps”一词,可能已经显得有些陈旧了。现在如果还有人向你推销DevOps,那可能太过时了。我们真正希望看到的是,DevOps人在日常角色中的思维方式发生根本性转变。我们往往忽视了以下两点:一、DevOps人第一要义是要以运维为中心的,角色定位是帮助开发人员将功能交付给客户(或帮助开发人员实现其他业务目标)。二、当为开发人员提供产品和功能时,需要注意:寻找到一条阻力最小的路径是保持速度的关键,让开发人员学习和维护所有操作实践是不可扩展的,也不可行的。回看DevOps最初的想法,重点是消除开发人员和运维团队之间的摩擦:让运维者不再一味地对开发人员说“不”,让开发者不再强push运维人员去上线。这些想法和目标仍然是崇高的,企业今天仍然应该追求它们,但DevOps的世界到底是什么样子的呢?如果我们认可“DevOps”是一种试图将开发人员带到运维世界的尝试,并且也同意这种尝试在很大程度上已经失败,那么现在,我们需要一个新术语。
Briggs提出了一个新名词:“SoftOps”。
SoftOps,听起来有点俗套,但理念却是崭新的。SoftOps的理念是,重点是让开发人员更好地工作。运维人员不会告诉他们该做什么,而是会问他们在运维方面想做什么,然后让他们尽可能地轻松。这个名词得益于Briggs加入Pulumi后的经历,他通过一个不同的视角来看待这个世界:以开发者为中心。SoftOps是一种将开发人员作为主要客户放在首位的想法。构建面向开发人员的运维实践(理论上)应该让开发人员参与进来,以便协同工作。也许,如果我们只专注于这一目标,我们将最终解决DevOps在2009年一直试图解决的问题。在这个新的理念下,“下载这个工具,阅读这个48页的手册页,告诉你的PM你错过了sprint的最后期限”的命令开发者的对话场景将一去不复返;此外,“把它给我,我会为你做”开发者包揽运维工作的日子也将一去不复返。
写在最后
今年3月,AbsoluteReports发布了《全球DevOps平台市场2022调查报告》,报告中预测,到2028年,全球DevOps平台市场规模将从2021年的67.376亿美元增长到263.70亿美元,看起来2022-2028年的复合年增长率为20.7%。从这些数字可以看出:DevOps作为提高企业技术可靠性、保证稳定的业务增长的利器,全球企业DevOps工具的需求愈发强烈。而从DevOps文化来看,DevOps在演变成一场让开发者使用新的运维工具的运动。但这种运动,无疑存在“跑偏”的迹象,这也是DevOps难以落地的根本原因:文化的缺失。如果不能改变观念,即使将员工放在一起,也只是增加两个团队的争吵而已。换言之,DevOps考验的不仅是一家企业的技术,更是管理水平和企业文化。Briggs提出的“SoftOps”的概念,一改“开发、运维全包揽”的现状,想要重新梳理开发和运维流程的规范,让开发人员在运维初期就给出系统部署的优化建议。虽然名词改变了,但SoftOps与DevOps的初衷却是一致的:减少开发团队与运维团队之间的摩擦,而不是某一方强势包揽、拒绝沟通,甚至简单沦为一种新工具。
参考资料:https://leebriggs.co.uk/blog/2022/06/21/devops-is-a-failure
更多精彩技术文章尽在51CTO技术精选期刊,下载链接:https://www.51cto.com/journalDetail/6.html
我已经构建了一些serverspec代码来在多个主机上运行一组测试。问题是当任何测试失败时,测试会在当前主机停止。即使测试失败,我也希望它继续在所有主机上运行。Rakefile:namespace:specdotask:all=>hosts.map{|h|'spec:'+h.split('.')[0]}hosts.eachdo|host|begindesc"Runserverspecto#{host}"RSpec::Core::RakeTask.new(host)do|t|ENV['TARGET_HOST']=hostt.pattern="spec/cfengine3/*_spec.r
我正在尝试在Rails上安装ruby,到目前为止一切都已安装,但是当我尝试使用rakedb:create创建数据库时,我收到一个奇怪的错误:dyld:lazysymbolbindingfailed:Symbolnotfound:_mysql_get_client_infoReferencedfrom:/Library/Ruby/Gems/1.8/gems/mysql2-0.3.11/lib/mysql2/mysql2.bundleExpectedin:flatnamespacedyld:Symbolnotfound:_mysql_get_client_infoReferencedf
我需要一个非常简单的字符串验证器来显示第一个符号与所需格式不对应的位置。我想使用正则表达式,但在这种情况下,我必须找到与表达式相对应的字符串停止的位置,但我找不到可以做到这一点的方法。(这一定是一种相当简单的方法……也许没有?)例如,如果我有正则表达式:/^Q+E+R+$/带字符串:"QQQQEEE2ER"期望的结果应该是7 最佳答案 一个想法:你可以做的是标记你的模式并用可选的嵌套捕获组编写它:^(Q+(E+(R+($)?)?)?)?然后你只需要计算你获得的捕获组的数量就可以知道正则表达式引擎在模式中停止的位置,你可以确定匹配结束
我正在尝试在配备ARMv7处理器的SynologyDS215j上安装ruby2.2.4或2.3.0。我用了optware-ng安装gcc、make、openssl、openssl-dev和zlib。我根据README中的说明安装了rbenv(版本1.0.0-19-g29b4da7)和ruby-build插件。.这些是随optware-ng安装的软件包及其版本binutils-2.25.1-1gcc-5.3.0-6gconv-modules-2.21-3glibc-opt-2.21-4libc-dev-2.21-1libgmp-6.0.0a-1libmpc-1.0.2-1libm
一段时间以来,我一直在使用open_uri下拉ftp路径作为数据源,但突然发现我几乎连续不断地收到“530抱歉,允许的最大客户端数(95)已经连接。”我不确定我的代码是否有问题,或者是否是其他人在访问服务器,不幸的是,我无法真正确定谁有问题。本质上,我正在读取FTPURI:defself.read_uri(uri)beginuri=open(uri).readuri=="Error"?nil:urirescueOpenURI::HTTPErrornilendend我猜我需要在这里添加一些额外的错误处理代码...我想确保我采取一切预防措施来关闭所有连接,这样我的连接就不是问题所在,但是我
我在思考流量控制的最佳实践。我应该走哪条路?1)不要检查任何东西并让程序失败(更清晰的代码,自然的错误消息):defself.fetch(feed_id)feed=Feed.find(feed_id)feed.fetchend2)通过返回nil静默失败(但是,“CleanCode”说,你永远不应该返回null):defself.fetch(feed_id)returnunlessfeed_idfeed=Feed.find(feed_id)returnunlessfeedfeed.fetchend3)抛出异常(因为不按id查找feed是异常的):defself.fetch(feed_id
我正在为毕业设计开发GEM,TravisCI构建不断失败。这是我在Travis上的链接:https://travis-ci.org/ricardobond/perpetuus/builds/8709218构建错误是:$bundleexecrakerakeaborted!Don'tknowhowtobuildtask'default'/home/travis/.rvm/gems/ruby-1.9.3-p448/bin/ruby_noexec_wrapper:14:in`eval'/home/travis/.rvm/gems/ruby-1.9.3-p448/bin/ruby_noexec_
运行:ruby1.9.3p0和Rails3.2.1尝试使用rspec但当我尝试将其安装到我的应用程序中时出现以下错误:/Users/Si/.rvm/gems/ruby-1.9.3-p0/gems/railties-3.2.1/lib/rails/railtie/configuration.rb:85:in`method_missing':undefinedmethod`generators'for#(NoMethodError)from/Users/Si/.rvm/gems/ruby-1.9.3-p0/gems/rspec-rails-2.0.0.beta.18/lib/rspec-r
我正在运行这样的代码:ifvalid_from>Date.today当我运行它时,我得到一个错误提示comparisonofDatewithnilfailed我假设它正在发生,因为在某些情况下valid_from是nil。有没有办法避免出现此错误? 最佳答案 你可以这样做:ifvalid_fromandvalid_from>Date.today...end这将在第一个子句上短路,因为valid_from为nil,因此为false。 关于ruby-Date与nil的比较失败-ruby,我们
基本上我想要做的是在MyModelLog表中记录对MyModel的操作。这是一些伪代码:classMyModel我也有一个看起来像这样的模型:classMyModelLog"somethinghappened")endend为了记录我尝试:在MyModel的something方法中添加MyModelLog.log_something在MyModel的after_validation回调上调用MyModelLog.log_something在这两种情况下,创建都会在验证失败时回滚,因为它在验证事务中。当然我也想在验证失败时记录。我真的不想登录文件或数据库以外的其他地方,因为我需要日志条目