DevOps

DevOps是目前较为流行的一种软件开发理念、开发流程。有人说DevOps是软件工程领域的第三次革命。

下面是维基百科对DevOps的定义:

DevOps(开发Development与运维Operations的组合词)是一种文化、一场运动或实践,强调在自动化软件交付流程及基础设施变更过程中,软件开发人员与其他信息技术(IT)专业人员彼此之间的协作与沟通。它旨在建立一种文化与环境,使构建、测试、软件发布得以快速、频繁以及更加稳定地进行。

但DevOps从来就没有什么官方定义,DevOps之父Patrick用一个词来形容DevOps——“盲人摸象”,说明了项目团队需要结合自身实际情况,去探索和实践DevOps。

下面介绍一下软件工程三个重要发展阶段:

瀑布开发模式

瀑布模型

瀑布式开发模式将软件交付过程划分成几个阶段,从需求到设计,再到开发、测试、运维,它的理念是软件开发的规模越来越大,必须以一种工程管理的方式来定义每个阶段,以及相应的交付产物和交付标准,以期通过一种重流程,重管控的方式,按照计划一步步推进整个项目的交付过程,中间一旦出错,就要返工重做。

敏捷开发模式

敏捷模型

敏捷开发的核心理念是,既然我们无法充分了解用户的真实需求是怎样的,那么不如将一个大的目标不断拆解,把它变成一个个可交付的小目标,然后通过不断迭代,以小步快跑的方式持续开发。

与此同时,将测试工作从开发之后的一个独立环节注入到整个开发活动中,对开发每次交付的内容进行测试验证。这样的持续迭代和验证节省了大量不必要的时间浪费和返工工作。

DevOps

DevOps

敏捷开发的应用使得开发和测试团队抱团取暖。可是问题又来了,开发和测试团队发现,现在软件交付效率的瓶颈出现在了运维上。毕竟,无论开发了多少新功能,如果没有经过运维环节的发布、部署上线给最终用户使用,那么软件交付便是失败的。

于是,DevOps最开始想要打破的就是开发和运维之间的对立和隔阂,让团队中的每个人都紧密结合起来。

在DevOps的流程下,运维人员会在项目开发期间就介入到开发过程中,了解开发人员使用的系统架构和技术路线,从而制定适当的运维方案。而开发人员也会在运维的初期参与到系统部署中,并提供系统部署的优化建议。

DevOps

总结

所以综上,我个人对DevOps的理解是:

DevOps要解决的问题或者说目标是:如何提高软件交付的效率和质量

DevOps提供一个平台,一个团队成员可以在上面进行紧密协作的平台,只需要成员们遵守共同的标准流程和规则

DevOps的行动准则可以说是:为了改进软件的开发流程,需要让流程中一切可以自动化的地方进行自动化

DevOps和CI/CD

DevOps是一组技术和方法,包括:持续交付、自动化运维、高频部署、容器技术等多个方面的内容。

DevOps是一种文化,推倒Dev与Ops之间的阻碍墙,加强团队协作。

DevOps是一种组织架构,将Dev和Ops置于一个团队内,一同工作,同化目标,以达到DevOps文化的彻底贯彻。

团队协作的关键

现代软件开发讲究效率和质量,大多依赖于多团队间的协作来实现。对于一些大型软件来说,即便是百人团队规模的协作也没什么奇怪的。如果软件架构没有良好的拆分,很有可能出现几百人在同一个代码仓库里面工作的情况。这时,代码分支管理就成了不可或缺的功能,这也是DevOps的基础。

我个人比较熟悉Git,Git常见的几种分支管理(工作流WorkFlow)方式如下:

  1. Git Flow
  2. GitHub Flow
  3. GitLab Flow

可以自己去网上了解一下,这里就不作详细介绍了。

Continuous Integration

简称CI,持续集成。

在20世纪90年代,软件开发还是瀑布模式的天下,人们发现,在很长一段时间里,软件是根本无法完整运行的。因为按照项目计划,软件的功能被拆分成各个模块,由不同的团队分别开发,只有到了开发完成之后的集成阶段,软件才会被真正地组装到一起。可是,往往几个月开发下来,到了集成的时候,大量分支合并带来的冲突和功能问题集中爆发,团队疲于奔命,各种救火,甚至有时候发现压根集成不起来,就让开发人员很头痛。

CI采用了一种反常规的思路来解决软件集成的困境,其核心理念就是:越是痛苦的事情,就要越频繁地做

如果开发周期末端的一次性集成有这么大的风险和不确定性,那不如把集成的频率提高,让每次集成的内容减少,这样即便失败,影响的也仅仅是一次小的集成内容,问题定位和修复都可以更加快速地完成。每次开发人员提交了新代码之后,都自动地完成编译构建、自动化测试(单元测试或者集成测试)、代码质量扫描等等流程,并反馈结果给开发人员。这样一来,可以防止分支大幅偏离主干,导致日后难以集成,还可以让最新的代码保持可用的状态,以供测试、发布使用。

这个从编码到构建再到测试,开发人员修复问题后再构建……,这样反复持续的过程,就叫作“持续集成”。

Continuous Delivery

简称CD,持续交付。

代码进行了持续集成后,说明这个代码是可以交付的,但这不代表这个代码是完美无缺、最优的,代码还需要根据用户的使用来逐步进行优化。这里的用户并不一定是指真实的最终用户,还可以是测试团队、QA(质量保证)团队、安全团队、产品等等,需要他们来对软件进行测试检查或者使用,然后反馈发现的问题。这样不断获取外部反馈结果,再通过持续集成来对软件进行优化的过程,就叫作持续交付。

持续交付是一种软件工程手法,让软件的产出过程在一个短周期内完成,以保证软件可以稳定、持续的保持在随时可以发布的状态。

Continuous Deployment

简称CD,持续部署。

通常来说,最终软件的发布和部署是最艰难的一个步骤。而持续部署就是将可交付的软件产品,自动、安全、快速地交付给最终真实用户使用的一套方法和系统,它是持续交付的最后“一公里”。

总结

总的来说,我们没必要纠结于具体的语义,只需理解CI/CD其实就是一个流程(通常形象地表述为管道Pipeline),用于实现软件开发流程的高度持续和自动化

可以通过下面这幅图,大概理解DevOps和CI/CD的关系:

DevOps & CI/CD

Jenkins + Pipeline

Jenkins是一个基于Java开发的CI/CD软件工具,在CI/CD领域上非常流行,可以用于实现和编译构建、测试、部署软件相关的各种自动化任务。

Pipeline是Jenkins在2.0版本后推出的一个功能,是一套运行于Jenkins之上的工作流框架。可以将独立运行于单个节点或者多个节点的任务连接起来,共同完成一系列复杂的软件交付流程。

Pipeline不同于以往的Jenkins,需要在Web页面上配置构建任务和步骤,它的实现方式是基于Groovy语言定义的一个领域特定语言(DSL),有一套自己的语法进行CI/CD流程脚本的编写。并且Jenkins支持从代码库中直接读取Pipeline的脚本,这样可以将脚本也纳入版本控制,从而实现pipeline as code的理念。

Pipeline脚本支持两种编写方式,一种是声明式,一种是脚本式。官方推荐使用声明式,可以在其中嵌入Groovy的代码。

声明式的Pipeline脚本如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
// pipeline声明式定义
pipeline {

agent any // 指定pipeline在哪个node上运行,any为任意,也可以在stage块中配置指定阶段在哪个node上运行

// 通过键值对的方式定义整个pipeline或者stage中使用的环境变量
environment {
key = "value"
}

// 定义全局工具,要先在Jenkins的Web页面上配置好
tools {

}

// 实现参数化构建,根据用户指定的参数,执行不同的构建操作
parameters {

}

// 设置一些配置
options {
disableConcurrentBuilds() // 禁止pipeline并发执行
timeout(time:6, unit:'HOURS') // 设置pipeline执行时间,超时则终止整个pipeline的执行
}

stages {
// 阶段定义
stage("delivery") {
// 步骤定义
steps {
// 执行脚本或者命令
echo key
// 在script块中编写Groovy脚本,进行编程
script {
def var = x
}
}
}
}

// 配置pipeline执行完后的收尾工作,可以根据本次构建状态进行不同操作
post {
// 总是执行
always {
echo "pipeline done"
}
// 构建成功
success {
echo "pipeline success"
}
// 构建失败
failure {
echo "pipeline failure"
}
// 构建中断
aborted {
echo "pipeline aborted"
}
}
}

后记

以上都是我个人对DevOps的浅薄理解,欢迎在评论区中进行交流~