Home | 简体中文 | 繁体中文 | 杂文 | 知乎专栏 | 51CTO学院 | CSDN程序员研修院 | Github | OSChina 博客 | 腾讯云社区 | 阿里云栖社区 | Facebook | Linkedin | Youtube | 打赏(Donations) | About
知乎专栏多维度架构

1.19. DevOps实施中你可能遇到的问题

1.19.1. 什么是DevOps?

首先DevOps 不是一个产品,其次说它是软件工程方法论也不准确。他是过程、方法和系统的统称,更类似笔者提出的多维度架构思想。

DevOps 这个词是由开发 Development(Dev) 和运维 Operations(Ops) 组成。它包含了三个维度,开发,测试,运维,但在实际工作中,我们也会将产品、设计、运营也纳入其中。

在 DevOps 模式下,产品,设计,开发,测试和运维团队更紧密地结合在一起,贯穿应用程序的整个生命周期。通过自动化工具替代手工操作,实现快速,高效,安全的测试,构建,部署项目。

  1. 可用的软件胜过完备的文档
  2. 团队合作胜过需求文档
  3. 响应变化胜过遵循流程与计划

1.19.2. 为什么会诞生DevOps?

传统软件企业以软件开发为主,开发部是最大的部门,根据项目分组,下设需求,开发,测试等岗位,并没有将运维纳入其中,这种模式已经不适合互联网企业。互联网企业通常是设置产品部,开发部,测试部,运维部,运营部,客服部等部门,但这样的组织架构带来了新的问题。

产品部关注用户体验,不考虑性能与开发合理性。开发部门的驱动力通常是“频繁交付新特性”,完成产品部提出的需求。测试部关注的是产品的BUG以及是否按照需求文档完成所有的功能。运维部更关注7*24小时无故障运行。从产品->开发->测试->运维过程看似完美,但他们目标不匹配,就在这些部门之间造成了鸿沟,从而减慢了交付业务的速度。

随着管理学的不断完善,例如工商管理,被细分为很多纵深领域,行政管理,人事管理,财务管理,营销管理,项目管理……等等。

而软件管理又被细分为:时间管理,范围管理,需求管理,质量管理,风险管理,成本管理......

由于组织架构的需要,又把人分成很多岗位,每个岗位上紧紧需要一种知识体系。企业按照自身的需要只招聘某个领域的人才。

同时我们学校也按照知识体系划分院系,本科教育程专科趋势,不重视通识教育,最终学生紧紧掌握了微观的知识。

如果说哲学是科学的科学,那么 DevOps 就是管理的管理。所以我认为 DevOps 是多维度宏观管理学。

1.19.3. DevOps 虽好,为什么难以普及呢?

实施DevOps 第一个遇到的问题就是人才,DevOps 需要经验丰富的跨界人才。第二个问题就是没有案例可循,无法借鉴和参考。

实施DevOps需要具备管理,开发,测试,运维等等背景的人才。每个领域至少也需要三年的积累,至少需要 3+3+3+3 = 12 年工作经验,多少公司员工都比较年轻,普遍在 3~5年。 一般员工工作10年以上,遍开始转向管理岗位,或者寻找其他出路。即使转管理岗的员工紧紧负责开发管理或者测试管理…… 不太可能10年的开发,转运维部重头开始。

我上面说过我们教育模式有问题,本科教育应该培养 “T” 型人才,专科教育培养 “I” 型人才,本科教育呈专科化。学校只教会学生一项技能(如Java 开发),而没有教会学生如何学习。

在中国企业的年龄歧视 “T” 型人才流失严重。“I”人才只能掌握一项技能解决一个领域的问题,无法完成DevOps 的实施。

DevOps 不是产品,是一种管理思想,每个企业根据自身特点,制定自己的DevOps规范,所以第二个难点就是,没有案例可循,无法参考。

1.19.4. 软件工程的历史与进化

传统软件工程学出现的年代互联网还不普及,主要是单机运行的软件,或者C/S结构的软件,其特点是开发周期长,迭代慢,每半年或者一年交付一次。流程主张:

		
需求->设计->开发->测试->交付
		
		

进入互联网时代,已B/S为主的软件,交付周期缩短到一个月,在传统软件工程做了改进,放弃了瀑布开发模式,提出了快速迭代,螺旋上升,管理上也逐步完善。出现了软件项目管理,CMM5软件开发成熟度模型。

互联网快速发展,使传统软件企业面临挑战,理论上互联网应用程序没有稳定版,新的特性源源不断加入,如果出现稳定版就意味着企业停滞。

互联网企业面临的问题是

  1. 需求频繁变更,一天一个想法,需求尚未成熟就开始投入开发软件生命周期短,以各种活动为例,很多功能是一次性的,软件生命周期可能是几周,几个月。
  2. 频繁交付新特性,不能像传统软件一样几个月甚至几年升级一次,我们需要应对互联网快速变化,可能需要每周升级一次,甚至每天升级数次。
  3. 随时可能回撤,随时做好回撤准备,要支持版本的任意切换
  4. 多项目并行开发,并行开发还会产生耦合依赖,升级顺序限制,集成测试更复杂。

随着Web 2.0 和 云计算思想的提出,软件也在发生变化,软件运行不在限于一台物理机,而是多台服务器的集群中,传统的模块或原件,被独立部署在世界各地。

软件的开发面临前所未有的挑战:

  1. 异构平台,软件不限于那种操作系统,例如Unix,Linux,As/400,windows,Mac
  2. 语言混合开发,不在紧紧使用一种语言开发软件。每一种语言都有他所在领域的优势。
  3. 分布式,软件再也不是只运行在 一个CPU下,软件被分成很多模块被分布式部署到多台服务上。

这时便出现了极限编程,敏捷开发….等等,同时诞生了新的岗位“产品”,新的思想不断提出,但是仍然无法解决面临的问题。

  1. 产品部:需如雪片飞来,需求堆积如山
  2. 开发部:版本延期,质量问题频发,疲于奔命修复 BUG,刚修复了一个, 又出现新的 Bug
  3. 测试部:手工测试,升级后问题爆发,测试环境通过,到生产环境就出问题
  4. 运维部:环境不统一,每次部署都是一场灾难,配置易出错,回撤时间长,
  5. 团队现状:加班严重,效率地下,每天奔波救火

测试环境无法重现,开发人员直接在线上修改代码,跳过测试直接将代码交给运维升级

运维事故严重影响运营和广告投放

人员流动导致代码丢失

问题的原因在于,他们紧紧从各自部门的角度解决问题,同时 KPI 考核也不合理:

  1. 产品从产品的角度解决产品遇到的问题。
  2. 开发从开发的角度解决开发遇到的问题。
  3. 测试从测试的角度解决测试遇到的问题。
  4. 运维从运维的角度解决运维遇到的问题。

实际上现在的软件已经不是当年交付后一个网管就能搞定剩下的工作。同时软件开发交付周期缩的更短,一周甚至每天升级数次,遇到突发事件要做好随时准备升级。

总结这个时期实际上是: 软件项目管理 加 ITSM (IT Service Management) IT服务管理

所以聚焦微观管理解决宏观管理问题的做法是错误的,于是诞生了 DevOps。 DevOps 是多维度宏观管理学,是管理的管理。

1.19.5. 为什么很多企业为什么实施 DevOps 以失败告终?

很多企业实施DevOps 紧紧是软件堆砌,根本没有深入理解 DevOps 思想,仅仅是 devops 相关的软件全部安装上,然后做系统集成。使用时需要打开好几个软件,有些时项目管理软件,有些时代码管理,有些时缺陷管理,有些时持续集成……

这时各部门一片抱怨声:

  1. 管理层说:项目管理工具不好用,我要看甘特图。
  2. 产品说:我不用那个Wiki写需求
  3. 设计说:版本控制对于PSD这种大文件兼容不好,50M的问题每次提交很痛苦。
  4. 开发说:我们不用 Docker,而我们也不用 maven
  5. 测试说:怎么随意部署环境,我们还没有测试完,就清空数据了。
  6. 运维说:生产环境我不敢用你的自动部署。

可能用户需要打开浏览器数个窗口,频繁切换才能完成具体工作。

时不时就能听到有人在公司的QQ群、微信群、钉钉上有人喊,XXXX 环境又挂了。

改变现有的工作方式是非常痛苦的,任何不合理的流程和工作方式已经使用了多年,习惯已经根深蒂固。

实施 devops 需要各部门收集意见,对各个部门培训,改变现有的工作流程,等各部门理解了 DevOps 原理和流程后,才能实施。

1.19.6. CI 持续集成不是DevOps

Jenkins 不是 DevOps

持续集成是一种软件开发实践,即团队开发成员经常集成他们的工作,通常每个成员每天至少集成一次,也就意味着每天可能会发生多次集成。每次集成都通过自动化的构建(包括编译,发布,自动化测试)来验证,从而尽快地发现集成错误。

持续集成只是 DevOps 中的一个小小的环节,并不是最主要的核心工作。

持续集成可以解决什么问题

  1. 能验证代码是否可以正常编译
  2. 验证组件或模块是否能够集成
  3. 验证自动化测试用例是否正常运行
  4. 测试环境的部署

持续集成不能解决什么问题

  1. 生产环境的发布
  2. 部署失败后回撤
  3. 不能/不擅长构建环境,虽然支持 Docker
  4. 构建速度慢

持续集成智能单向操作,例如

		
代码->构建->测试->部署 等等		
		
		

持续集成中我们遇到很多问题

例如就是通过 git hook 触发 Jenkins 实现持续集成,自动构建项目。问题来了,任何提交都会触发一次 pipeline 脚本,当项目频繁提交时,第一个构建过程还未运行完毕,第二个进程便启动。导致构建排队,阻塞,同时 pipeline 可能会争夺资源(多个进程读写同一个文件),产生冲突,轻则稍等片刻,重则测试环境崩溃。

另外通过CI 持续集成部署代码也不靠谱,会出现和上面相同问题,例如第一个进程用 scp 复制 jar 包到远程主机,还未传输完成,第二个进程便做同样的操作。

还有,第一个进程重启 tomcat ,tomcat 还未停止退出,第二个请求便发出。最终导致 tomcat 崩溃。

以上的特性,你敢在生产环境上使用吗?一旦发布失败,或者需要回撤,持续集成并没有很好的解决方案。

我认为,持续集成尚不完善,测试环境玩玩可以,生产环境还是不要了。

1.19.7. CD 持续交付不是 DevOps

持续集成、持续交付、持续部署是一系列的软件工程实践方法,使用自动化手段达到完成软件。

持续交付(Continuous Delivery)和持续部署(Continuous Deployment)的区别

  1. 持续集成(Continuous Integration) 通过将每一次改动都提交到一个模拟产品环境中,使用严格的自动化测试,确保业务应用和服务能符合预期,最终产生构建产物。
  2. 持续交付(Continuous Delivery) 通过持续集成产生构建物,确保让软件产品能够快速、安全的部署到产品环境中。持续交付并不是指软件每一个改动都要尽快的部署到产品环境中。它指的是任何的修改都已证明构建物可以在任何时候实施部署。
  3. 持续部署(Continuous deployment) 是持续交付的更高阶段即生产阶段,就是将最终的产品发布到线上生产环境,给用户使用。所以当业务开发完成时,经过持续集成,持续交付后,你有信心只需要按一次按钮就能将应用快速并安全的部署到产品环境中。

请不要再混淆持续交付与持续部署了。

1.19.8. 自动化部署

我习惯将持续部署(Continuous deployment)称为自动化部署

本章节重点谈自动化部署,每个人对自动化部署都有自己的理解,每个企业对自动化部署的需求也不同。

目前很多云平台开始推出一些列 DevOps 工具,体验了一下,仍然处在初级阶段,也不十分成熟。严格的说他们实现的 CD (持续交付)。

前面讲过持续集成不是 DevOps,这里我要说持续部署也不是 DevOps。自动化部署是从CI/CD中分离出来的,将部署单独提炼出来。

自动化部署远比 CD(Continuous Delivery) 持续交付要复杂,涉及包括

  1. 网络层:网络设备管理,负载均衡切换,路由表管理
  2. 系统层:基础设施,操作系统,软件运行环境,
  3. 应用层:应用软件部署,配置管理,日志管理
  4. 缓存层:缓存的刷新
  5. 搜索层:重建全文索引
  6. 数据层:数据库结构管理,数据库数据管理
  7. 日志层:谁,什么时间,做了什么操作,结果怎样
  8. 除此之外,管理上还需要提案和审批流程等等

所以 CD (持续交付)解决不了企业的生产环境自动化部署需求,CD紧紧是CI (持续集成)运行完成后,将构建物部署到指定的运行环境中。通常CD并不提供回撤功能,所以极少由企业使用 CD 部署生产环境。

		
Git -> 编译 -> 测试 -> 打包 -> 构建物 -> 部署 -> 运行		
		
		

CI/CD 的流水线作业只能部署单一项目,对于大型网站就无能为例

例如很多大型网站

  1. 构建过程非常复杂,不仅仅是一个项目打包, 而是需要多个模块,处理复杂的配置过程。
  2. 一次部署多台服务器,每个服务器可能有多个实例,实例间相互依赖关系
  3. 需要遵守严格的部署和启动顺序
  4. 记录部署日志,文件的新增,覆盖,删除
  5. 部署时间点
  6. 升级不仅仅是代码,还有数据库,缓存,搜索引擎,消息队列……
  7. 需要改变负载均衡设备节点,设置防火墙策略
  8. 需要有完备的回撤方案
  9. 除此之外好虚考虑增量部署和差异部署,例如部署100mb 以上的大文件,甚至GB尺寸的文件

很多 DevOps 方案注重 Docker,K8s解决方案。但实际情况 Docker 并不适用于所有场景,更多是物理服务器,虚拟机,云主机,刀片服务器…

使用 Docker 的前提是,Docker必须部署在宿主主机上,在云主机中部署 Docker 意义不大。

很多企业大量使用云主机,对 Docker 并无强烈的需求。

运维需要怎样的自动化部署工具

  1. 项目管理:升级提案,工作流转,工作审批
  2. 备份管理:任何生产环境部署前都需要备份,必须实现增量备份和差异备份。
  3. 环境管理:环境部署,基础设施管理
  4. 阶段管理:开发,测试,生产
  5. 仓库管理:分支切换,分支保护(例如只允许合并不允许提交)
  6. 配置管理:每个阶段拥有自己的配置
  7. 文件过滤:排除过滤,包含过滤,内容替换,覆盖和删除(覆盖指定文件,删除指定文件)
  8. 内容优化:Grup, Webpack 压缩js, css,html5, 图片雪碧图…..
  9. 自动构建:编译,测试,测试报告,打包,构建物管理
  10. 节点管理:新增节点,删除节点
  11. 部署管理:增量部署,差异部署,md5sum 校验检查
  12. 部署脚本:部署前脚本(停止),部署后脚本(启动)或者环境初始化,解决部署依赖
  13. 时间线:谁,什么时间,做了部署,可以指定时间点随时回撤到指定版本。
  14. 部署日志:谁,什么时间,做了什么操作,产生什么结果
  15. 部署报告:自动创建部署报告(Issue或Ticker)

持续集成与持续交付和持续部署的关系:

		
持续集成(CI) -> 构建物 --> 持续交付(CD) --> 交付验收环境 (Alpha)--> 验收成功
             \                                                    |                     
              \................................................../
                                         |
                                         V
                                      持续部署 ----> 生产环境 (Beta/Preview/Release) ----> 生产环境验收
		
		

1.19.9. 收集各部门问题

实施DevOps前需要收集各部门问题

问题如下

  1. 产品线都多少条?
  2. 同时进行并行开发的多少条?
  3. 怎么进行项目管理?
  4. 产品团队的情况:怎样管理需求文档,多个产品人员怎样协作
  5. 设计团队的情况:都使用什么设计软件,一般文件尺寸多大
  6. 开发团队的情况:使用什么语言,什么框架,开发人员数量,采用哪种版本控制,急需解决的问题?
  7. 测试团队的情况:测试工具,测试的方法,测试用例怎样管理,人员数量,急需解决的问题?
  8. 运维团队的清况:服务器数量,云的使用情况,docker使用情况,运维工具,运维人员,急需解决的问题?
  9. 目前最迫切解决的问题是什么?
  10. 你的企业目前还面临哪些问题(非技术)?

有了这些数据,在DevOps工具选型是,你才能判断是否符合你的需求。例如很多商用工具的 License 是按照用户数收费的。有些则按照部署节点收费。

1.19.9.1. 自运维的需求

例如下面是来自运维的需求

运维团队需要什么呢

  1. 合同管理
  2. 成本管理
  3. 续费管理
  4. 问题管理
  5. 突发事件管理
  6. 环境配置
  7. 设备管理
  8. 配置管理
  9. 自动化部署
  10. 监控和报警
  11. 备份和恢复

上面大部需求以用Issue/Ticket 凑合,但是有几个功能例如,环境配置,自动化部署,监控/报警,备份/恢复,这些就凑合不了,实打实的硬性需求。如果不能实现这些功能,就不能称为 DevOps。

我们就先从监控说起把,你很发现很多 DevOps 的文章中,不会涉及到监控,但是这是运维的重中之重。

1.19.10. 收缩技术栈

技术部门常常会陷入技术思维,恨不得将所有主流技术都使用上,却忽略了他们兼容性,以及对该技术的掌握程度。

当团队没有100%掌握某项技术是,风险是巨大的,我们常常会看到网上有这种文章《XXX踩过的坑》,无疑是拿生产环境练手,为自己的职业生涯打怪升级。

大炮打蚊子,很多需求根本无需使用复杂的技术,最终变成庞然大物。

尽量使用一种技术解决所有问题,而不是使用所有技术解决一种问题。这样技术团队学习起来不会太吃力,且团队人力资源可以共享,测试难度和运维难度都会降低。

1.19.10.1. 模块化思维

技术思维另一个误区就是,拆整为零,模块化。例如,用户中心,商品中心,订单中心,物流中心 ……

			
   用户中心 —---—- 商品中心,
     |  \       /   |
     |    \   /     |
     |      X       |
     |    /  \      |
     |  /      \    |
  订单中心 ——---- 物流中心			
			
			

看这个架构多么清晰

  1. 用户中心: 负责用户注册,登录,找回密码
  2. 商品中心:商品分类,商品搜索,商品列表,商品展示
  3. 订单中心:订单报价,订单合并……
  4. 物流中心:对接物流平台……

技术人员的成就感飘飘然,然票票。运维根据需求将上面四个中心使用四台高配置服务器部署起来。

市场部需求

  1. 用户登录
  2. 浏览商品
  3. 下订单
  4. 走物流
  5. 用户积分+100

平时没有什么问题,订单量一大所有问题都暴漏出来, 积分添加失败,库存数据出错,物流下单失败……

这种模式的问题有很多,例如

  1. 运维复杂,部署复杂,配置管理复杂
  2. 排查问题难度搞
  3. 分离后,通过网络连接,网络存在延迟和超时等等其他不可控因素
  4. 分布式事务处理,复杂且难以保证
  5. 分布式锁,并发的杀手

任何一个系统都不能简单的进行拆分,抓中拆分同样是我们教育的问题,导致思维方式产生问题。

15年前我就意识到这种问题所在,15年后去一下电商公司面试,发现他们仍然在采用这种模式。

1.19.11. 被遗忘的数据库

在持续集成和持续部署中数据库常常被忽略。

实施 DevOps 对于 DBA 都不那些诉求呢?

这里我列举一些DBA的诉求

  • 数据库备份与恢复,备份文件的安全
  • 数据库结构版本控制
  • 数据库快照
  • 注入扫描
  • 撰改报警
  • SQL 审计
  • 数据库监控
  • 脏数据处理

上面每一项都需要单独拿出来分析,例如监控。

数据库监控有可以细分为

  • IP 地址,包括端口,服务
  • 同步状态
  • 连接数
  • 缓存,命中率
  • SQL语句调用统计

等等

总之 DBA 需要知道,谁,什么时候,登陆了数据库服务器,做了什么操作。随时可以备份数据,恢复数据。

另外还有数据文件一致性的需求

什么是数据文件一致性?举一个例子,用户头像是一张图片,存储在用户数据表中如下

		
 ID | USERNAME | ICON
------------------------------
  1 | neo      | /images/neo/Avatar.jpg
		
		

可能存在数据存在,图片找不到;或者有图片,没有数据的情况。这里只是一个例子,实际场景更复杂,例如银行票据,合同等等。

1.19.12. 建立中心仓库

DevOps 需要一个核心仓库,用来管理构开发包,容器,以及建物等等。

仓库可以分为三种类型,分别是

  1. 和基础设施库
  2. 容器仓库
  3. 软件依赖仓库

基础设施库包括: Yum,Apt,Snap

容器仓库包括 Docker, Helm

软件依赖仓库包括

  1. Maven
  2. Gradle
  3. npm
  4. PyPI
  5. Ruby Gems
  6. PHP composer
  7. CPAN

为什么需要建立这些仓库呢?

首先构建物是公司的私有资产,不可能放在开放的仓库内。其次,使用外部仓库严重影响构建速度,例如下来速度慢和一些不可控的因素,挂起,闪断等等。

通常我们将私有自建的仓库和DevOps系统放在一起,以加速构建速度。

1.19.13. 缓存

缓存可以帮助构建程序显著提高执行速度,DevOps 涉及到的缓存包含

  1. 源代码缓存
  2. 软件开发包缓存
  3. 构建物缓存

另外,软件开发包缓存和构建物缓存的版本通常是递增的,所有无需考虑缓存过期的问题,但是需要考虑下载过程中出现的损害。

常见的损坏包括

  1. 源代码版本控制文件损坏,导致代码无法更新
  2. 软件开发包依赖文件损坏,导致无法编译
  3. 构建物损坏,导致无法部署,启动

1.19.14. 安全

DevOps 需要考虑几点安全问题

  1. 隔离安全,构建过程中会将源代码下载的构建服务器,在 Pipeline 中运行脚本,即可拿到其他项目的源码,配置文件。
  2. 环境变量安全,Pipeline 常常会用到环境变量,通常在 Pipeline 中查看所有环境变量,就可以看到其他项目的定义。
  3. 日志安全,运行单元测试,应用产生的日志,也可能泄漏敏感数据。

对于单一用户,这些问题没有那么严重,但是对于多用户系统或基于 SaaS 的 DevOps 的平台来说这就是大问题。 否则会出现 A 用户可以访问 B 用户资源的问题。甚至做出一些恶意操作,下载源码,植入木马等等