DevOps经过了10多年的发展,很多企业或组织都在实践DevOps。根据Gartner发布的2022年Agile(敏捷)和DevOps成熟度曲线(如图1-2所示)显示,DevOps的实践处于多点开花阶段(工具链、持续交付、DevSecOps等)。这充分说明DevOps已经经过了理论阶段,向着实践的深水区走去。
根据中国信通院(中国信息通信研究院的简称,下同)发布的《中国DevOps现状调查报告(2021)》DevOps进行了级别划分。
❖初始级:在组织局部范围内开始尝试DevOps活动,并取得初期效果。
❖基础级:在组织较大范围内推行DevOps实践,并获得局部效率提升。
图1-2 Gartner 2022年Agile & DevOps成熟度曲线
❖全面级:在组织内全面推行DevOps实践并贯穿软件全生命周期,获得整体效率提升。
❖优秀级:在组织内全面落地DevOps并可按需交付用户价值,达到整体效率最优化。
❖卓越级:在组织内全面形成持续改进的文化,并不断驱动DevOps在更大范围内取得成功。
2021年,成熟度处于全面级的企业最多,为35.4%,具备工具化、自动化、规范化的特点,同比增长8.84%;而16.53%的企业的实践成熟度处于优秀级,具备平台化、服务化、可视化与度量驱动改进的特点;0.87%的企业处于卓越级,能够实现DevOps的高度智能化、数据化和社会化的特点,如图1-3所示。
图1-3 企业DevOps成熟度分布
这些年,DevOps逐渐沉淀出了持续集成/持续交付(部署)(CI/CD)这种被认为是落地实践DevOps的核心手段。同样,《中国DevOps现状调查报告(2021)》显示:持续集成是最受欢迎的工程实践,与自动构建、单元测试、持续交付占据前四,其比例分别为85.16%、81.61%、81.53%和80.66%,如图1-4所示。
图1-4 DevOps最受欢迎的四大工程实践(中国)
下面简单介绍CI/CD的概念,第3章将详细介绍。
CI和CD是实践DevOps的两大核心,也是DevOps实践中比较容易实现的。
CI(Continuous Integration,持续集成):指开发人员将代码变更频繁地向主干分支集成的过程,目的是将代码变更可能造成的系统破坏性降到最小,一旦有问题,也能够快速地识别和隔离变更集,保证主干分支实时可用。当然,这种“小步快跑”的开发有一个前提,就是代码的集成要经过一系列既定的检测或者测试流程。
CD包括两种:Continuous Delivery(持续交付)、Continuous Deployment(持续部署)。
持续交付是一组通用的软件工程原则,允许通过使用自动化测试和持续集成频繁的发布软件新版本。持续交付可以认为是持续集成的延伸。
持续部署是指通过定义测试和验证来将风险最小化,从而将变更自动部署到生产环境。
为了推动CI/CD发展,Linux基金会专门成立了持续交付基金会(Continuous Delivery Foundation,CDF)。CDF的目标是改善软件的交付能力,让软件交付变得更快速、更安全。目前(截至本书编写时,全书同),CDF托管有Cdevent、Jenkins、Jenkins-X、Ortelius、Screwdriver.cd、Shipwright、Spinnaker、Tekton共8个与持续交付相关的开源项目。
【小结】 DevOps经过了10余年的发展,已经取得了不错的成果,而且在实践的过程中沉淀了以CI/CD为核心关键能力的实践方法。很多企业或组织在实践DevOps的时候,CI/CD往往成为第一入手点,而且围绕CI/CD产生了大量的开源项目,这也促成了CDF的成立。当然,CI/CD并不是DevOps的全部,也不等于DevOps。DevOps还在继续演进。
DevOps从未停下向前演进发展的脚步,从目前看,DevSecOps、Cloud Native(云原生)是两个非常明显的发展方向。
1.DevSecOps
DevSecOps可以认为是DevOps的外延或者扩展,目的是将安全融入DevOps,让安全能力渗透到软件开发生命周期的各阶段,从而为软件研发和交付提供全方位的安全保障能力。所以,DevSecOps可以定义为:DevSecOps描述了一个组织的文化和具体实践,这些文化和实践能够打破开发、安全、运维部门之间的壁垒,使得开发、运维和安全能够通过通力协作和敏捷开发来提高工作效率,实现软件的更快速、更安全交付。
DevSecOps有以下三个特点。
(1)安全左移
“左”或“右”是针对软件开发生命周期来说的。
在传统的软件开发模式下(典型如瀑布式开发,甚至DevOps出现的早期),安全介入的时间比较晚,一般是在软件开发的测试阶段,甚至更靠后,从软件开发生命周期看,是“向右”的。当软件交付的周期比较长(半年甚至一年以上)时,这种模式并不会有太多的问题,也是业界比较常用的模式,因为交付周期足够长,安全介入即使较晚,也有足够的时间来完成相关的工作。但随着用户需求的多样化、敏捷化,软件发布的频率必须提高才能响应用户日益增长的需求,所以软件的敏捷开发逐渐盛行,月发布、周发布甚至天发布都是稀松平常的。在这种发布频率下,还要保持软件的安全性,就给软件开发带来了很大的挑战。
为了应对这种挑战就需要让安全尽量早地介入,在编码甚至计划阶段就介入,从软件开发生命周期看,是“向左”的,这也是安全“左移”的由来,如图1-5所示。
图1-5 安全“左移”
安全“左移”的背后有一个安全问题修复成本与软件开发生命周期关系(如图1-6所示),也是为什么要实现安全“左移”的最大原因。可以看出,如果在软件开发生命周期早期(计划,编码阶段)发现安全问题,修复的成本是非常低的,越往后(测试,甚至生产阶段),修复的成本越高,而且这种成本是非线性增加的。
图1-6 安全问题修复成本与软件开发生命周期的关系
(2)持续自动化
要保证软件安全,需要有多种安全防护手段来为软件提供从计划到上线,从静态到动态的安全防护能力,诸如SCA、SAST、DAST、IAST、Pen Testing等。如果都采用手动测试,那么对于开发、安全和测试来说,都是极具挑战的,不仅增加了工作量,还可能导致这些人员在重复的体力劳动中丧失工作的积极性和创造性。因此,应该尽量实现安全防护手段的自动化,并且将其嵌入CI/CD,做到持续的自动化。
这样做有以下好处:
❖减少研发、测试等人员的工作量,减少重复的体力劳动,让他们把更多的精力放在业务创新和赋能上。
❖持续自动化能够针对每次代码变更都做到全方位安全防护,让每次代码变更都以安全方式交付。
(3)人人为安全负责
虽然从定义看,DevSecOps只包含开发(Dev)、安全(Sec)、运维(Ops)三个团队,但是现代软件的开发仅仅靠这三个团队是无法完成的,还需要其他团队的协作,如市场、销售、产品等。因此,任何与软件交付的团队或个人都应该为软件的安全交付负责,每个人都可能成为安全的瓶颈点,最终导致软件的不安全。这与给F1赛车换轮胎非常像(如图1-7所示),每个人都有自己的工作职责,但是最终的目的是一致的:在最短的时间内换好轮胎,并且保证安全性,从而提高车手获胜的可能性。
图1-7 人人为安全负责(来自fastcompany网站)
2.云原生(Cloud Native)
云原生(Cloud Native)是由Pivotal公司的Matt Stine在2013年提出的。Matt Stine在他的著作 Migrating to Cloud-Native Application Architectures 中定义了云原生的几个特点:①符合十二要素之应用(12-factor applications);②微服务(microservices);③自服务敏捷基础设施(self-service agile infra-structure);④API协同(API-based collaboration);⑤反脆弱(Anti-fragility)。2017年,他做了自服务敏捷基础设施如下修改:①模块化(modularity);②可观测性(observability);③可部署性(deployability);④可测试性(testability);⑤可替换性(replaceability);⑥可处理性(handleability)。
Pivotal公司官方也对云原生有一个定义:云原生是一种充分利用云计算交付模式来构建和运行应用程序的一种方式方法,通常具有4个特征,即DevOps、持续交付(部署)(Continuous Delivery)、微服务(Microservices)、容器(Containers),如图1-8所示。
图1-8 Pivotal最初对云原生的定义
不过,目前业界引用最多的是云原生计算基金会(Cloud Native Computer Foundation,CNCF)的定义:云原生技术有利于各组织在公有云、私有云、混合云中构建和运行可弹性扩展的应用。云原生的代表技术包括容器、服务网格、微服务、不可变基础设施和声明式API。
CNCF与CDF一样,也是Linux基金会的一个子基金会,是2015年由Google、RedHat、IBM、华为、Docker、VMware等公司共同成立的,致力于推广先进的容器技术。CNCF目前托管141个(18个已经毕业、37个正在孵化、83个处于沙箱,并且有越来越多的项目被捐赠到CNCF中)开源项目,涵盖计算、存储、网络、数据库、持续交付等领域。
下面讲述的Kubernetes和GitOps这些年在云原生领域非常热门。Kubernetes是云原生的基座,而GitOps是云原生应用实现持续交付的新范式。
(1)Kubernetes
Kubernetes是一个可移植的、可扩展的、开源的平台,主要用于通过声明式配置和自动化来管理容器化的工作负载和服务。Kubernetes的名字源自希腊语,意思是舵手或者飞行员。由于开头字母“K”与结尾字母“s”之间有8个字母,因此通常简称为“K8s”。
Kubernetes是谷歌(Google)公司2014年的一个开源项目,前身是Borg系统,始于2003年,是在谷歌公司内部使用的一个容器管理系统。Borg管理着来自数千个不同应用程序的数十万个作业,涉及许多集群,而每个集群拥有多达数万台计算机。2013年,另一个Omega系统在谷歌公司内部应用,可以看作是Borg的延伸,在大规模集群管理和性能方面优于Borg。但是Borg和Omega都是谷歌公司内部使用的系统,也就是所谓的闭源系统。2014年,谷歌公司以开源的形式推出了Kubernetes系统,同年6月7日在Github上完成了第一次提交;7月10日,Microsoft、IBM、Redhat、Docker加入了Kubernetes社区。2015年7月,Kubernetes发布了V1.0版本,到目前是V1.25版本。
Kubernetes集群主要的组件分为控制平面和节点(Node)(如图1-9所示)。控制平面(Control Plane)用来管理整个集群(如调度、检测和响应集群事件等);节点用来运行Pod(Kubernetes集群最基本的调度单元,其中运行一个或者多个容器,而应用程序运行在容器中)。
图1-9 Kubernetes集群组件
控制平面的主要组件包括如下。
①API Server(api):用来对外暴露API的组件,也是所有请求的唯一入口。
②etcd:具有一致性和高可用性的键值存储组件,主要用来存储Kubernetes集群中的所有数据。
③scheduler:针对新创建的Pod进行调度,为其选择一个合适的节点来运行。
④controller manager(c-m):用来运行控制器进程的组件。Kubernetes有多种控制器,如用来管理运行一次性任务的Job控制器,给每个新的命名空间创建默认账号的Service Account控制器,以及为其创建API访问令牌的Token控制器等。
⑤cloud controller manager(c-c-m):内嵌的特定的云端控制器逻辑,用于将用户集群与云供应商的API进行连接,并将与该云平台交互的组件和只与用户集群交付的组件进行隔离,只运行用户指定的特定云厂商的控制器。
节点的组件包括如下。
①kubelet:运行在每个节点上的代理,用于保证Pod内容器的正常运行。
②kube-proxy(k-proxy):运行在每个节点上的网络代理,主要用于实现Kubernetes中服务概念的一部分。
③Container runtime:容器运行时(runtime),用于运行容器。Kubernetes支持多种容器运行时,诸如containerd、CRI-O和其他实现了Kubernetes CRI的容器运行时。
(2)GitOps
GitOps是一个比较新的概念(由Gartner的2021 Agile和DevOps成熟度曲线也可以看出,GitOps处于萌芽期),由Weaveworks公司在2017年提出,是一种针对云原生应用进行持续部署的方式。其本质是利用云原生不可变基础设施和声明式API的特征,将云原生应用的状态描述文件存储在Git系统上(GitHub/GitLab等),任何变更的发起都在Git系统上,一旦有任何变动,变动会自动部署到目标系统上(通常是Kubernetes集群),如图1-10所示。
图1-10 GitOps原理
GitOps有如下三个特征。
①以Git为单一可信源。所有内容都存储在Git系统上,包括应用程序的源代码、配置文件等。常见的Git系统包括GitHub、GitLab、极狐GitLab等。
②一切皆代码。应用程序的描述、部署、基础设施(利用Infrastructure as Code,基础设施即代码)等都是通过代码的方式来进行描述的,然后存储到Git系统上。
③以声明式系统为基座。声明式系统(如Kubernetes)的好处是只需设定应用程序的期望状态,而不需关心整个过程,系统会自动将期望状态和实际状态进行对比,如果实际状态与期望状态有偏差,就会自动进行校正,直到期望状态和实际状态保持一致,如图1-11所示。
图1-11 声明式系统原理
GitOps的落地和实践请参阅第4章。
【小结】 DevOps目前的发展趋势是将安全融入DevOps,打造DevSecOps,同时由于云原生浪潮的推动,DevOps和云原生在互相推动着彼此的发展,目前逐渐被认可和实践的就有GitOps。