云原生时代的DevOps平台设计之道
开发人员与运维人员是 IT 领域很重要的两大人群,他们都会参与到各种业务系统的建设过程中去。DevOps 是近年间火爆起来的一种新理念,这种理念被很多人错误的解读为“由开发人员(Dev)学习一大堆新的技能,从而掌握运维人员(Ops)该处理的事情”。然而能力越大,责任越大,当维持生产环境稳定为要位的运维责任落到开发人员的肩头时,多数程序员发出了 扯淡的DevOps,我们开发者根本不想做运维! 的呼喊。那么在云原生时代,到底应该怎样达成 DevOps 的体验呢?我的观点是由平台工程来衔接这两大人群,各自做好各自领域的事情。
令人“厌恶”的DevOps
首先,我非常希望你能先看一看引言中提到的 扯淡的DevOps,我们开发者根本不想做运维! 这篇文章。这篇文章从亚马逊云科技社区参与负责人 Emily Freeman 的一条推特入手,观察了很多留言后,得出了文章标题这种类似咆哮一般的结论。从绝大多数回复这条推特的 IT 从业者的口中,我听到了对于将运维职责强加给开发人员这种 DevOps 体验深恶痛绝。
开发人员对于 “谁构建,谁运行” 这种大义凛然的话表示无感,对于学习运维领域的新技能,亦或是将自己加入轮班支持人员的行列都感觉力不从心;运维人员的本职工作被剥离之后,则对本专业的前景惶惶不安,会害怕运维团队的重新洗牌。
开发与运维,的的确确是两个不同的工种,有着类似“车床工与管道工”的区别。
| 开发 人员 | 运维人员 | |
|---|---|---|
| 专业技能 | 开发语言、开发框架、中间件、数据库 | 硬件、操作系统、网络、存储、虚拟化 |
| 日常工作 | 理解需求、开发文档写作、开发代码 | 安装部署、监控、日志、问题排查、变更 |
| 文化标签 | 自由、创造 | 保守、责任 |
一些公司认为从表格中把大量的运维人员管辖的工作,一股脑的“左移”给开发人员就是 DevOps。在专业技能和日常工作领域带来的缺口,可以通过开发人员的勤劳学习加以补足,然而在文化标签领域的冲突,将会是导致开发人员厌恶这种 DevOps 体验的根本原因。
DevOps 的真意与平台工程
在我看来,DevOps 的真意是利用软件工程思维,解决复杂且繁重的运维问题。真正适合做 DevOps 工作的人,是具备一定软件工程能力的运维专家,在这里,对运维能力的要求更重要。
DevOps 工程师,可以通过设计或选择一款平台产品,来将复杂的运维工作抽象为产品化的运维特征。从这个角度上讲,开发人员将会是这个平台产品的用户,他们能够在不了解复杂基础设施的情况下,操作并维护应用程序。DevOps 工程师,应该是更懂开发人员需求的运维工程师。
在追根溯源,找到了这条推特 之后,我了解到了更多 IT 业内人士对 DevOps 的看法,从中找到了很多和我有共鸣的声音。
To me that's a sign we haven't made ops intuitive/easy enough for most devs to be able to handle it.
对我来说,这表明我们还没有让运维变得足够直观/简单,以至于大多数开发人员都无法处理它。
—— @Liz Fong-Jones (方禮真)
The "platform" should do the heavy lifting ops, lacking a real platform the ops team (DevOps/are/platform team) is the platform. Devs can then focus on the application level operations of their apps using the knobs and levers provided by the platform.
“平台”应该做繁重的运维,缺乏真正的平台时运维团队就是平台(DevOps/are/platform team)。然后,开发人员可以使用平台提供的旋钮和杠杆专注于其应用程序的应用程序级操作。
—— @pczarkowski
IT 行业近年来的发展趋势,一直是不断以平台能力的提升,来解决复杂基础设施的使用问题的。最开始,程序开发人员需要面对的是一台物理服务器,在缺乏运维能力的情况下,会由运维人员处理有关服务器的一切,包括操作系统、网络配置等等。而到现在,程序开发人员已经很少需要跟服务器打交道,甚至我见过的很多程序员并不掌握任何有关命令行的知识,就可以面向服务器开发应用系统。这种转变让程序开发人员更加专注于业务代码本身,不必分神去做一些繁重且琐碎的运维事务。带来这种转变的,是处于发展过程中的平台工程,在让基础设施不断变得简单易用。

最原始的裸机时代,并没有开发运维之分。从底层基础设施,一直到最顶层的业务系统都是同一批人在处理,这一批老程序员可以被称为真正的全栈工程师。但毫无疑问,每一个开发人员,都希望能够抛却运维工作,更专注于自己开发的代码。
云计算时代的兴起以虚拟化技术为基础,软件定义基础设施变得炙手可热起来。运维人员通过建设并维护一套 IaaS 云平台,将计算资源进行池化。开发人员按需申请自己需要的虚拟机,从而得到一个操作系统界面来进行交互。与操作系统打交道,对开发人员依然是个巨大的挑战,在 IT 领域,操作系统就像一座漂浮在海上的冰山,看似只露出冰山一角,然而其庞大的知识领域“身躯”都隐藏在海平面以下。和裸机时代相比较,开发人员和运维人员已经是两个完全不同的群体,开发人员已经可以将自己的大部分精力放在业务系统上了。值得一提的是,对操作系统的掌控是不折不扣的运维领域技能。
容器技术以及 Kuberentes 的横空出世,成为了云计算时代的分水岭。软件定义基础设施的技术手段已经被发挥到了极致,并且成为了现阶段运维人员的标配技能。运维人员通过建设并维护一套 PaaS 云平台,终于将操作系统这一座最后的“大山”从开发人员的身上搬开。开发人员可以将更多的精力放在业务系统上了,除了他们依然需要学习容器技术和 Kubernetes ,至少他们要学会如何面向 Kubernetes 编写业务系统所需的声明式配置文件。运维人员也通过 PaaS 云平台得到了自己想要的能力,容器技术和 Kubernetes 为他们带来了弹性、便捷性的巨大提升。
跟随时代的变迁,我得出了一个结论:从开发人员与运维人员的关系上来看,IT 领域的演变,就是运维人员通过不断向上接手开发人员眼中“跟开发无关的杂 活”,来不断为开发人员减负。开发人员在得到了解放后,可以将视角更多的聚焦在自己开发的业务系统上,释放出自己的创造力。
那么跟随结论中的趋势,解放开发人员负担的脚步绝对不会停止。DevOps 的工作,就是以开发人员为用户群体,打造一套可以让开发人员毫无障碍的使用基础设施的“云原生平台“。
云原生是一种面向云设计应用的思想理念,充分发挥云效能,组织内 IT 人员相互协作构建弹性可靠、松耦合、易管理、可观测的云应用系统,最终目标是提升软件交付效率,降低运维复杂度。相比上文中提到的 PaaS 平台,起码要能够避免开发人员去编写复杂的 Kubernetes 声明式配置文件。
现有开源产品情况
在云原生平台领域,已经有不少项目在深耕。在这里我列举了三个各具特色的云原生领域的平台级产品:Rancher、KubeSphere、Rainbond ,后续的具体设计思路中,也会关注已有产品的实现。
这三款开源产品中,Rancher 是元祖级容器管理平台,加入 SUSE 后,能够明显感觉在云原生生态领域不断发力,Rancher 在各个层次可以集成的云原生领域工具集已经非常丰富。Rancher 专注于帮助 DevOps 团队面对多集群情况下的运维和安全挑战,从这一点来说,Rancher 更偏向于运维人员的使用体验,而非面向开发人员提供更高的易用性。
KubeSphere 是来自青云的 “面向云原生应用的 容器混合云”。除了对 Kubernetes 集群内的各种资源的管理能力之外,Kubesphere 主打即插即用的插件式生态扩展能力。
Rainbond 由北京好雨科技出品,从其介绍来看,它是一款主打易用性的云原生多云管理平台。
降低业务部署难度
诚实地讲,为现代开发语言开发而来的业务系统制作容器镜像并不是什么难以掌握的技能。但是不可否认的是,绝大多数 IT 从业人员依然会将制作镜像这件事情归为运维人员管理,而不是开发人员要关心的事情。
那么 DevOps 工程师就有必要考虑,如何在开发人员对容器技术一无所知的情况下,使之可以直接从代码开始部署业务系统。
在这个方面,Heroku 是无可争议的先行者。Heroku 是一个支持多种编程语言的云平台即服务产品。在2010年被 Salesforce.com 收购。 Heroku 作为最元祖的云平台之一,从2007年6月起开发,当时它仅支持 Ruby,但后来增加了对 Java、Node.js、Scala、Clojure、Python 以及 PHP 和 Perl 的支持。
开发人员在使用云原生平台时,只需要在界面中填写代码仓库的地址,对应的用户名密码等基础信息,就可以等待代码构建成为镜像,并自由的运行在 Kubernetes 云环境中去。
现有开源产品也在这方面给予了一定的支持:
| Rancher | KubeSphere | Rainbond | |
|---|---|---|---|
| 实现方式 | 通过集成 Epinio 项目,继而深入集成了Paketo Buildpacks 来实现源码构建 | 提供定制化的基础镜像来结合用户代码构建项目 | 基于 Heroku buildpack 定制的源码构建能力 |
| 支持语言类型 | Java、GraalVM、Golang、.NetCore、Nodejs、PHP、Ruby、Python | Java、Nodejs、Python | Java、Golang、.NetCore、Nodejs、PHP、Python、Html静态 |
| 使用体验 | 全部命令行操作,使用复杂 | 图形化操作,直接提供代码地址,构建产出镜像,进而部署业务 | 图形化操作,提供代码地址即可完成构建与部署,构建参数可配置,自由度高 |
更进一步的设计,是将代码的提交、检测、部署等流程都集成到 CI/CD 流水线中去,开发人员只需要进行代码的提交,后续的流程会自动触发完成,生成检测报告,并完成代码的上线部署。而与之相关的第三方工具集,由 DevOps 团队负责进行维护,开发人员可以充分的发扬拿来主义——拿来用就好。
在这方面 KubeSphere 做的更加全面,通过集成 Jenkins 实现了基于图形化的流水线配置,这种方式对于以前就在使用 Jenkins 的团队很友好。并且这种实现继承了 Jenkins 生态原有的高自由度,可以更好的将其他第三方CI工具纳入流程之中。
Rainbond 通过在构建流程中加入自制的自动触发能力,也可以完成部分流水线工作。这种配置相对编写 Jenkinsfile 来说更简单一些,能够满足一些基本场景。然而其扩展性和自由度不足,能够接纳的第三方CI工具不够丰富。
Rancher 并没有在产品中集成 CI 方面的能力,在 CD 方面通过集成 fleet 项目来实现 GitOps ,使用的门槛较高。

这样的使用体验还有一个优点,从始至终都不需要开发人员去编写格式严苛的 Kubernetes 声明式配置文件。这对开发人员而言无疑是一个极大的利好,Kubernetes 虽好,但学习曲线非常陡峭。Kubernetes 默认通过 yaml 格式的声明式配置文件来部署业务系统,其中绝大多数的字段定义都是运维特征的体现,换句话说,绝大多数的字段定义,都不应该是开发人员关注的事情。
DevOps 工程师应该抓住开发人员使用 Kubernetes 的痛点,避免其接触复杂运维事务。云原生平台理应提供这种使用体验,让开发人员对 Kubernetes 完全无感知的情况下,完成业务系统的部署工作。换句话说,让 Kubernetes 变得对开发人员“透明”。
从这个方面来说,通过对三款开源云原生平台的体验,发现 Rancher 和 KubeSphere 虽说均可以基于图形化界面来部署自己的业务组件,然而这些图形化配置只是 yaml 声明式配置文件的 “翻译”,对于 Kubernetes 不够熟悉的用户想要顺利使用,还是有一定的门槛。Rainbond 这一点则做的非常不错,部署业务时完全感受不到 Kubernetes 的存在,对于不熟悉 Kubernetes 的用户而言非常友好。然而产品化定制的程度越高,跟随 Kubernetes 前进的脚步就越难,上游 Kubernetes 不断在推出新的功能特性,如何将新特性抽象成为用户易于理解的功能将会是个挑战。最新版本的 Rainbond 推出了 Kubernetes 属性这一功能特性,允许用户以 yaml 形式编辑 workload ,也是为打破自设的“天花板”。