“ DevOps 是使软件开发和 IT 团队之间的流程自动化的一组实践,以便他们可以更快,更可靠地构建,测试和发布软件。DevOps 的概念建立在建立团队之间协作文化的基础上,这些团队过去一直在相对孤岛中运作。”
类似于这种的 DevOps 相关的描述听起来特别抽象,非常学术,非常教科书,让人感觉无法落地,不知道该如何入手。很多团队在了解 DevOps,实践 DevOps 的时候不能很好的多维度看待 DevOps,实践的过程也很痛苦,不知道这种新型的理念如何实际提升自己团队的战斗力。
本文从开发和运维两个视角多层次的讲解什么场景应该 Dev 和 Ops、什么场景应该 DevOps,即 DevOps 的分与合,并使用一个 Demo 示例告诉大家 DevOps 中的关键步骤持续部署如何实践。
DevOps 的两个视角
DevOps 从字面上看就是开发和运维,也有翻译为开发运维(运营)一体化。我们这里的两个视角不是别的东西,正是开发和运维。这里的开发,不能简单的理解为开发工程师,指代的是整个软件的研发过程所含的所有要素,涵盖需求分析、开发、测试等等,其终点是可交付的软件制品。同样运维不仅仅是运维工程师,指代的是软件交付后投产过程以及后续的运营,反馈等系列过程,其起点是接受交付的软件制品。
这么两个视角的区分是隐含着软件工程背后的逻辑的,就像一栋大楼,他的建设方是建筑和设计公司,他的运营方是物业公司一样,两者之间有相对清晰的界限。
我们需要回顾软件行业的发展,来看为什么 DevOps 被提出来,为什么现在要强调 Dev 和 Ops 的紧密结合以及什么场景要紧密结合,什么场景不需要。
以下四个方面促使了软件行业开始意识到 DevOps 的作用:
如果你的软件不符合上述四个发展方向,看到这里就够了,你不需要去实践人云亦云的 DevOps,尝试只会给你带来不必要的麻烦。
DevOps 正逐渐把开发和运维中间的界限模糊掉:
本文在探讨完毕两个视角、双向移动、四个层面后会把开发和运维的中间重叠部分(软件交付)为主题来详细阐述这一 DevOps 实践的最大难题。
开发阶段关注的信息和概念跟运维运营阶段有相当大的差异又有部分的重叠:
同样的,运维阶段关注的信息和概念与开发阶段有相当大的差异,又有部分重叠:
在对 DevOps 概念进行理解,全局考虑的时候需要能像上文中提的一样理解开发阶段和运维阶段的广义性,但在本文设计的持续部署话题,因篇幅限制,会把视角聚焦在开发阶段的结束和运维阶段,考虑狭义的运维概念(即传统理解的运维工程师的工作范畴)通过剖析运维工程师的工作内容变化来讨论 DevOps 的分与合。
那么对于运维工程师的基本工作而言,可以把模型简化为如下两个方面:
在高频次的程序发布,爆发式业务增长的场景下,运维团队越来越痛苦,在加上很多团队没有合适的工具系统和标准化的部署流程,经常会看到团队内的双向吐槽:
开发团队说:
为什么我们这边修好了 bug 今天不能给我发布?我需要查一下生产环境日志要等 3 个小时?运维同学能不能不要总是抄错配置项?
运维团队说:
请用文档详细撰写清楚发布步骤和注意事项并仔细评估发布风险。运维团队已经排满了所有发布计划,你这个修复问题不严重,请等下周再排。
运维团队陷入无限的机械性重复劳动中,而其中大部分工作都是低杠杆的执行发布,查询日志,执行回退等。
这属于 DevOps 的分离的场景,团队与团队之间有工作压力不均,信任感缺失,目标不一致等问题,建议尝试做一些业务运维的左移,也即在合适的工具系统基础上把业务运维的部分权力或者人员分配到开发团队,使之可以完成大部分的程序发布、配置更新、日志查询等工作,解放运维。
形成下图效果,从人员上可以是开发兼职业务运维,也可以是开发团队有专职业务运维人员,其本质是业务运维的主要工作闭环在开发团队内部,实现高效运转。
这样即在某种程度上实现了 Dev 和 Ops 的合。
信息数据的安全诉求,以云为代表的基础设施的虚拟化、弹性化、甚至于代码化的发展也给运维团队的基础设施运维工作带来了新的挑战和机遇。我们会发现基础设施运维团队在云的发展下渐渐的实现了右移(把基础设施全信任的交给云处理)。
在没有云主机的年代,运维团队不得不扛着沉重的服务器去机房里,对照着官方指南,安装操作系统、配置网络策略;云主机时代,容器还未到来之时,运维团队摆脱了物理服务器,却不得不维护大量的服务器软件,安装、卸载、批量发布等,去维护业务运行的基础软件环境;在有了 Kubernetes,Docker 等容器技术之后,运维工程师从维护软件运行基础环境中解脱,转而做更上层的基础设施:监控体系、负载均衡等;不远的将来,当 Serverless 重构云计算体系的时候,运维人员连监控体系、负载均衡等都不需要关注了,全量交给云来解决。
云的不断发展的历程也是一个逐步吞噬基础设施运维人员工作的历程,如今运维人员在云的基础上有了云 LB 不需要再运维 HAProxy,Nginx 等,有了云数据库不需要再运维 MySQL、Redis 等。如此种种,基础设施运维的工作都右移给了云。
当然这个右移不是一蹴而就的,是个渐进的过程,需要行业慢慢去接受,也需要云的成熟与发展。最近沸沸扬扬的微盟运维人员删库跑路事件是一个很好的佐证,他们使用了腾讯云,腾讯云最终帮他们找回了数据,但他们基础设施运维的右移程度不够高,换句话说叫做云原生渗透不够深,如果使用的是类似于云数据库这类云提供的数据库基础设施,那也许大可不必使用硬盘恢复技术来找回数据。
诚然,云产品还有长远的路要发展,但在现有的云的能力下,各位可以思考下,自己团队的基础设施运维右移了多少,阻碍右移的问题是什么,右移不够导致浪费了多少人员精力,带来了多少风险。
认真评估你的软件的交付机制以及运维团队左移和右移的程度是你选择采用何种 DevOps 分合策略,以及 DevOps 实践是否成功的关键因素。
DevOps 的分与合,与运维工作的左移右移,云技术的发展,云原生标准的统一有极大关系,DevOps 概念可以在很多层面上得到体现,本文就其中主要的,可以让 DevOps 团队真切感知的四个层面来做简要介绍:
要想实践 DevOps 的分与合,必须要配置上合适的团队配置。这里有若干种配置的分类:
第一种模式属于 Dev 和 Ops 分的比较彻底的类型,这种人员模型可以适配业务运维左移程度较少,交付流程较为标准化的场景,运维团队制定流程,流程和运维服务共享给所有开发团队。
第二种模式属于 Dev 和 Ops 合的比较彻底的类型,这种人员模型可以适配业务运维左移程度很高,基础设施运维右移程度也很高的场景,基本上实现了每个开发团队配合云就能完整实现闭环,已经没有传统意义的独立运维部门。
第三种模式属于 Dev 和 Ops 部分分开、部分合并的类型,这种人员模型可以适配业务运维左移程度较多,但基础设施运维右移程度较少的场景,适用于希望能实现开发团队闭环,又对云基础设施有信任问题,需要自建基础设施(例如私有云,或基于公有云的私有基础设施)类型的团队,这种模式跟第二种模式的唯一差异是是否有自主基础设施运维团队,在超大规模 DevOps 建设私有云的场景多见。
第四种模式属于 Dev 和 Ops 的合并已经达到极致,可以完全无运维团队工作,在使用云基础设施和合适的开发工具基础上就可以实现开发团队内完整闭环,例如全量使用 Serverless 技术,无需担心负载均衡,弹性扩缩容,监控等基础设施工作。
没有哪个模式是完美的,在实践自己的 DevOps 人员配置的时候,要想清楚自己的实际场景,当想清楚自己的人员配置的时候,要想保持高效就要考虑这些人与人之间信息如何流转顺畅。
DevOps 是一种协作文化,协作流程,而协作的本质是顺畅、精准的信息流转。一个简化的典型的 DevOps 信息流转模型大致如下:
信息流转顺畅和精准的根本在于信息是否是结构化、流程化、标准化的。一个所有信息流转都依赖聊天群、开会、邮件等形式解决,看似能够一触即达的信息流转,往往会有重点不突出,信息遗漏,信息依赖人为跟进等问题,其实是不顺畅也不精确的。
核心要把握 DevOps 实践团队的如下节点是否信息传输顺畅且精准:
这几个关键环节都定义好标准和流程的时候,再次要去看其他环节的细化信息流转问题,接下来就是需要考虑使用何种工具系统为此标准和流程提速的时候了。
DevOps 的协作文化目的是提升团队的效能,而自动化工具是必备的,好的工具体系应该是整合的、角色切面的、自动流转的。工具系统目标是顺畅精准的传输信息并且高效的执行机械化操作。
整合性:DevOps 的开源、商业软件有很多款,然而大多数软件系统之间都是弱整合状态,很多都是宣称支持 OAuth 或者 LDAP 用户体系就算整合了,这里面的差距还很大,例如 Jira 的项目和 GitLab 的项目,GitLab 的项目与 TestLink 的测试计划,这些实际的概念在不同的系统之间都遵从着不同的产品设计哲学,实际上弱整合的工具系统在提升团队信息流转效率上并没有太大帮助。
角色切面:好的 DevOps 工具系统应该像是一个为工厂量身定制的生产流水线,各个角色各司其职,关注精准的信息,执行标准的操作,输出标准的结果。在弱整合的工具系统里可能不同系统的用户、角色、权限设计都有很大差异,难以实现角色切面。例如一套基于 Jira + GitLab + Jenkins + Kubernetes 的体系,运维角色应该加入 Jira 的项目中么?产品经理是否需要关注 Jenkins 的 Job 执行状态?
自动流转:自动流转是为了解决重复性的机械劳动而设计的,要想具备自动流转的特性,整合性和角色切面也必须设计的非常好,开发完毕到提测自动部署,测试通过到自动发布,在设计好流程和标准后都是一些机械化的重复劳动。
工具系统不是万能的,有时候你会发现有了好的人员结构、信息流转方式、整合性的工具系统,实践起 DevOps 还是有一定困难,那你可以看看如下这个点:技术架构。
技术架构对 DevOps 的影响主要体现在构建、部署、运维环节。不同的软件类型,技术架构在这三方面是有很大差异的。例如单机手游,只有构建和发布市场,基本不存在部署、运维环节。而微服务架构 SaaS 化的多租户云服务在这方面就复杂的多。
这里以典型的服务器端应用的技术架构升级过程来作简要分析,例如对于一个基于 Spring 框架写成的 Java Web 应用,其发展历程可能是这样的:
云的发展也映射着技术架构的变迁,也引领着基础设施运维的右移,大致分为三个阶段:
每一种技术架构的 DevOps 的实践模式是有差异的,分与合的程度也不一样。仔细品味这些技术架构的特点,认真评估自身团队业务运维左移和右移的程度,就可以选择出合适的人员管理模式、选择适合自己的工具系统,形成顺畅、精准的信息流转,从而让 DevOps 的实践取得实质性成果。
持续部署是软件交付的一种形式,常用于服务器端软件的交付,在这里我们以 CODING CD + Kubernetes 来简要讲述一个服务器软件持续部署模式,我们假定团队现在的各方面基本情况如下:
这种模式可能是适合目前国内大多数团队的现状的模式,具备相当的代表性,跟此模式有差异的团队也可以通过此模式来品味本文的 DevOps 思考,去改进自身的实践。
本示例代码比较简单,我直接贴出几个对应的核心文件:
app.py
from flask import Flask
app = Flask(__name__)
@app.route("/")
def hello():
return "<h1>欢迎使用 CODING CD!!</h1>"
if __name__ == '__main__':
app.run(debug=True,host='0.0.0.0')
Dockerfile
FROM python:3.7
COPY . /app
COPY pip.conf /etc/
WORKDIR /app
RUN pip install -r requirements.txt
ENTRYPOINT ["python"]
CMD ["app.py"]
Jenkinsfile
pipeline {
agent any
environment {
ENTERPRISE = "wzw-test"
PROJECT = "demo-for-cd"
ARTIFACT = "demo-for-cd"
CODE_DEPOT = "demo-for-cd"
ARTIFACT_BASE = "${ENTERPRISE}-docker.pkg.coding.net"
ARTIFACT_IMAGE="${ARTIFACT_BASE}/${PROJECT}/${ARTIFACT}/${CODE_DEPOT}"
}
stages {
stage('检出') {
steps {
checkout([$class: 'GitSCM', branches: [[name: env.GIT_BUILD_REF]],
userRemoteConfigs: [[url: env.GIT_REPO_URL, credentialsId: env.CREDENTIALS_ID]]])
}
}
stage('打包镜像') {
steps {
sh "docker build -t ${ARTIFACT_IMAGE}:${env.GIT_BUILD_REF} ."
sh "docker tag ${ARTIFACT_IMAGE}:${env.GIT_BUILD_REF} ${ARTIFACT_IMAGE}:latest"
}
}
stage('推送到制品库') {
steps {
script {
docker.withRegistry("https://${ARTIFACT_BASE}", "${env.DOCKER_REGISTRY_CREDENTIALS_ID}") {
docker.image("${ARTIFACT_IMAGE}:${env.GIT_BUILD_REF}").push()
}
}
}
}
}
}
deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: demo-for-cd
name: demo-for-cd-deployment
spec:
replicas: 3
selector:
matchLabels:
app: demo-for-cd
template:
metadata:
labels:
app: demo-for-cd
spec:
containers:
- image: demo-for-cd-image
name: demo-for-cd
ports:
- containerPort: 5000
imagePullSecrets:
- name: coding-registry
service.yaml
apiVersion: v1
kind: Service
metadata:
labels:
name: demo-for-cd-service
spec:
ports:
- name: http
port: 5000
protocol: TCP
selector:
app: demo-for-cd
type: LoadBalancer
CODING 提供了团队和项目两个层面的基于角色的权限控制可以方便的实现不同角色的切面效果:
具体来讲可以在团队成员管理和项目成员管理进行具体角色的分配。
在此示例中我们的项目名称叫做 demo-for-cd, 应用名称叫做 flaskapp.
1. 配置云账号(让 CODING 持续部署跟 Kubernetes 集群打通)
2. 创建应用 flaskapp
3. 把应用 flaskapp 跟项目 demo-for-cd 关联:关联后可以理解为这个应用的相关发布权限和配置管理权限下放到项目中,映射我们提的“业务运维左移”思想
4. 在应用内创建部署流程:应用该怎么部署,在什么条件下部署,需要什么资源这些由运维团队制定,映射我们提的“交付发布”要标准化,流程化
这里有几个细节需要注意:
几个最佳实践提示:
在运维进行完上述配置后,开发人员就可以在项目里独立进行发布操作了(映射我们提的业务运维左移至开发团队)。
开发团队在确认新版本的三个制品(一个 Docker 镜像,两个 Kubernetes Yaml 文件)准备好后直接可以新建发布单来执行发布,因事先预配置好了流程标准,这里开发无需跟运维团队进行低效的无意义的其他形式的沟通,直接选定三个资源的版本即可执行发布。
开发也可以通过上游的代码仓库、持续集成和制品库的配合完成全自动化发布,实现分钟级自动上线。
持续部署是 DevOps 的关键环节,跟 DevOps 一样与团队的运维左移右移程度,技术架构等有很大关系,没有哪个持续部署工具系统是可以涵盖所有的场景的。CODING 持续部署希望能涵盖大多数较新的技术体系,以及拥抱云原生的部署场景。这里给出几点关于其他常见的持续部署的做法提示:
看到这里,我相信你已经能够把握住 DevOps 的几个实践的核心要素,DevOps 不是非黑即白的,只要有开发和运维的团队自始至终都一直在实践着 DevOps,只是效果有好坏,水平有高低。业务体系、团队配置、技术架构、工具系统都有差异,脱离这些基本现实去喊口号,聊价值是无意义的。你的 DevOps 团队要分还是要合,分合到什么程度,请冷静思考文中提到的几个合。