【DEVOPS】最佳实践和指导思想

2023-11-21 23:10

本文主要是介绍【DEVOPS】最佳实践和指导思想,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

对DevOps推进过程中的最佳实践和指导思想进行一次穷举,早日形成团队内部共识,将精力尽量集中到做事上来。

0. 目录

      • 1. 前言
      • 2. 细则
        • 2.1 基础设施即代码(Infrastructure as Code - IaC)
        • 2.2 不可变基础设施(Immutable Infrastructure)
        • 2.3 "只生成一次制品"
        • 2.4 对不同环境采用同一种部署方式
        • 2.4 "内建质量"
        • 2.5 一切皆版本控制(配置管理)
        • 2.6 唯一可信任源
        • 2.7 工具的连通性
        • 2.8 随时可发布
        • 2.9 元数据
      • 3. Links

1. 前言

笔者在上一篇博文【DEVOPS】共识中,对于部门内的开发流程中普遍存在的一些认知和举措进行了个人的分析和解读;本文可看作上一篇博文的姊妹篇,意在总结过往多年在沉淀DEVOPS相关理论知识体系的过程中,所了解到的DEVOPS相关最佳实践和指导思想。

2. 细则

2.1 基础设施即代码(Infrastructure as Code - IaC)

这一条指导思想要求我们将应用正常运行所需要的环境,其搭建过程用代码的方式描述到配置文件中,之后将由专门的工具通过读取该配置文件来实现应用环境的构建。

以上看似增加了额外工作量的最佳实践,将让我们获得如下好处:

  1. 环境的搭建过程不再依赖于人,人的经验和责任心并不会影响最终搭建出来的应用运行环境,做到环境的完全独立,进而缩小了系统出现错误时候的排错范围。
  2. 有助于形成完整,规范的安装目录结构,大幅降低沟通成本。因为整个部署过程在一开始的时候就进行了约束并持久化,因此我们很容易就联想到形成默认安装目录结构的团队契约,这在降低沟通成本的同时,也使得基础架构部门在进行重复性工作消除的时候,能够基于共识进行更为激进的封装。
2.2 不可变基础设施(Immutable Infrastructure)

对于基础设施的不可变性,最基本的就是指运行服务的服务器在完成部署后,就不在进行更改。

这一点很重要,但又隐藏地很深,就笔者过往的工作经历而言,一套基础环境经过一系列人工操作配置完成之后,基本陷入两种角色的反复切换:

  1. “生怕磕着碰着的宝贝疙瘩”。我他喵费了九牛二虎之力才整出个可正常运行的系统,谁要是把这环境破坏了,我跟谁拼命!
  2. “任劳任怨的老黄牛”。哎呀,这套系统的基础部署环境搭建起来太费劲了,咱们不是已经有了一套可正常的运行的吗? 我这开发的新功能就在那套环境下测试下得了,你看你这人咋这么不近人情呢,又不会给你搞坏了。

“这种模式中,任何基础设施的实例(包括服务器、容器等各种软硬件)一旦创建之后便成为一种只读状态,不可对其进行任何更改。如果需要修改或升级某些实例,唯一的方式就是创建一批新的实例来替换它。
为什么我会说,不可变基础设施的思想对持续交付的影响非常深远呢?因为不可变的思想正是解决了持续交付一直没有解决的一个难题,即环境、顺序、配置这些基础设施在测试环节和生产环节的不一致性所带来的问题。” — 《极客时间 - 持续交付36讲》

之所以说这个思想隐藏的很深,是因为在没有相关理论和思维的基础支撑,完全靠着本能去行事,非常容易陷入一种"出现不一致情况的主要原因是相关人员缺乏责任心;技能不娴熟;我这次没有投入全部精力来做这件事;这是个小失误,只要再这样这样就解决了,解决起来也耗费不了多长时间"等等。

违反"不可变基础设施"并不会让代价集中式地爆发,以切肤之痛让人对于前辈教诲的幡然醒悟,相反它总是由如"鞋子里的小石子"一样,时不时跳出来膈应你,而且这种"膈应"是被分摊到了团队内部的各个人身上,如果领导人自身都是含糊的,那违反本条最佳实践的反效果,将能陪伴这个团队,不离不弃,至死方休。团队里的每个人都在抱怨,”抱怨系统部署困难”,”抱怨生产环境和测试环境应用表现不一致”,”抱怨同一个系统功能前后表现不一致,上一个版本没有问题的,但因为这次更新是直接在原有版本基础上替换了部分文件,所以这句话无法被证实,最后只能靠谁更自信以及嗓门更大,资历更老了”。

2.3 “只生成一次制品”

只生成一次制品,这是《持续交付》中提到的一个非常重要的实践。

对于同样一份代码,理论上来说,不同的时间段编译打包出来的制品,其所提供的服务应该是完全一致。

但是正如上面所强调的,这都是"理论上的",在这个现实的世界里,你需要面对各类违反常识的现象,因此针对制品生成这一块,为了杜绝相关的不一致问题,根本性地解决方案就是:针对某个时间节点的源代码,只生成一次制品,不同环境下应用的表现不一致的需求,应该交给外部的配置文件来控制,而不是交给源代码的编译过程。

2.4 对不同环境采用同一种部署方式

对不同环境采用同一种部署方式,这也是《持续交付》中提到的另一个非常重要的实践。

实现这一步并不简单,因为要实现将同一制品部署到不同的环境,就必须做到制品与配置的分离。

只有实现了"制品与配置的分离",我们才能实现无人工介入前提下的,可追溯的部署流程。

"制品与配置的分离"实现之后,我们可以针对每类不同的环境来准备一份包含完整配置信息的,只对应相应环境的配置,这样在之后的部署环境,整个部署过程将转变为由自动化流程根据用户所指派的环境,抓取同一份制品包,以及与指定环境相匹配的配置文件包,合并之后部署到对应的环境上。

2.4 “内建质量”

内建质量作用在开发过程中,要求软件生命周期之间参与的各个角色都需要实时的对软件的质量负责。确保软件在交付到下一环节前已经有了基础的质量保证。其核心目的就是减少因为问题发现太晚导致的额外资源成本浪费

在这里插入图片描述
上面这幅图里:

  1. 85%的问题是在编码阶段引入的,如果可以立即得到修复,那么每个问题的成本大约在25$左右。
  2. 但如果这些问题被传递到发布之后,那每个问题的修复成本将暴增到16000$(是前者的 640倍)。

"内建质量"的底层逻辑是**“你想要有一个好的结果,那你必须得先存在一个好的过程”**。

在各种原因造就的粗犷管理之下,事前没有好好规范,事中没有阶段性地检查,然后居然臆想最终下属能够交付上来一个能够让各方都满意的作品,这领导当得未免也太轻松了?

很多时候笔者在想:“为什么每次问题在最终阶段才会大爆发”? 当然了,只有在最终的集成阶段我们才能看到原本被分模块开发的软件真正作为一个整体来运行,也只有这个时候,各个模块之间的相互影响才能看到实际的效果,而这些影响往往就是问题的同义词。

但是,除了以上这个原因之外,笔者不得不稍显恶毒地设想"真是下一站就是最终的客户了,没法再自我催眠我这边没有问题,现在必须要面对现实了",但是往往这个不得不面对的现实后面因为问题被长期隐藏,导致更高的修复成本,"集成地狱"在开发流程中时不时出现就是最好的证明。

"内建质量"要求我们在研发流程的过程中,能够将问题尽早暴露出来,最好在错误发生的地点将错误发现并解决。

为了实现上述目标,我们需要一系列诸如" 测试左移",“质量门禁”的指导思想,以及一系列相应的措施来保证"内建质量"的实现。

  1. 需求评审阶段,我们需要对需求的描述格式,需求优先级等进行一系列检查,确保从源头掐灭一些低级错误。
  2. 代码研发阶段,我们需要从最基本的代码质量检查,团队内部代码规范,单元测试覆盖率等等各个维度将代码低级错误消灭在这个阶段。
  3. 测试阶段,我们需要从测试用例格式,测试代码质量,测试代码业务场景等等多个角度来进行检查。
  4. 部署运维阶段,我们应该指定严格完善的上线/回滚流程,并针对多个维度搭建完善的监控系统,确保系统线上环境的稳定,以及问题的及时发现,系统回滚的快捷。

本小节所描述的"内建质量",作为核心的"内建"说明了这其中的大部分检查工作都应该被自动化流程所完成,确保不能满足基本质量要求的阶段性产物无法流动到下一阶段。

内建质量的两大原则:

  1. 问题发现得越早,修复成本就越低;
  2. 质量是每个人的责任,而不是质量团队的责任。
2.5 一切皆版本控制(配置管理)

“一切皆版本控制”的同义词就是我们经常听到的"配置管理"。

在《持续交付》(2011-10)的第二章配置管理的小结里说到:“配置管理是本书其他内容的基础。没有配置管理,根本谈不上持续集成、发布管理以及部署流水线。它对交付团队内部的协作也会起到巨大的促进作用”。

"一切皆版本控制"这句话里的"一切"已经很说明问题了,对于软件开发整个流程捋下来,从最开始的可行性分析文档开始,我们就应该将其进行版本控制,例如上传SVN,或者用专门的WIKI等。

我们进行版本管理的目的不是为了找个地方把东西存起来,也不是为了未来某一天不小心发生误删或审查需要时候,有所底气;更不是因为别人都做了,所以我们也要做。以上这些都不是做版本控制的主要目的。

我们做版本控制是为了能够精确控制软件开发的整个流程,让整个流程既能够按照实践顺序按部就班地向前迭代,也能够在问题发生或者某些需要的时候,能够稳步地将时光倒流,退回我们期望的那个时间点。

既然是"一切皆版本控制",让我们尝试列举下需要版本管理的:

  1. 需求。
  2. 代码。
  3. 制品。
  4. 部署脚本。
  5. 数据库。
  6. 应用环境相关的安装软件包。
  7. 等等。
2.6 唯一可信任源

关于这一点,其实用一句话就能解释:“我们只对从这里拿到的包负责,不要从那些犄角旮旯踅摸个包告诉我们有问题,我们深受其害,我们以后不想再受伤害”。

"唯一可信任源"隐含了要求将发包权限回收,放到专人手上;其二就是建立双方的契约,断开提供者和实现者的直接接触,通过引入"唯一可信任源"规范化制品的管理。

2.7 工具的连通性

对于持续交付工具链体系来说,工具的连通性是核心要素。

相较于争论为了完成某个任务,是使用现有的工具A,还是新引入更为强力的B,在单个工具上反复拉锯论证,如何在现有研发流程工具集基础上,在最短时间内拉通各个软件,实现研发数据信息的快速流动,才是应该被首先考虑的。

借用政府作部门协同信息化文件中的一句话:“我们要让数据多跑路,群众少跑路”。工具的高效连通能够显著降低研发流程中各部门协作的停滞感,促进价值流的高效流动

2.8 随时可发布

你的软件必须处于随时可发布状态。

这一最佳实践要求软件开发团队至少能够随时提供软件的两类最新版本:

  1. 经过完整测试通过的,能够部署在生产环境下的版本,该版本内拥有所有测试通过的新特性。
  2. 未经过完整测试,可提供给测试人员进行测试的,或者产品/售前部门进行软件演示的,包含了当前最新开发进度成果的。

这一最佳实践展示出来的是对于软件开发流程的最终要求,看似简单的一句话需求背后所隐含的要求却并不简单:

  1. 你的软件要时刻处于等待测试和展示的状态。这要求软件从设计阶段开始,之后的每次状态变更都要经过一些基础的检测, 这样才能将尽量多的问题留在原地,而不是积累到最后需要演示/部署时候才解决。
  2. 你的软件版本管理得规范,你得明确知道当前软件的最新版本号,以及各个版本号对应的需求完成和BUG修复情况。
  3. 你的软件流程得尽量自动化,"随时"的要求决定了我们不可能指望依靠人工来完整这一要求。
2.9 元数据

关于元数据的名词解释这里就不多做描述了,作为"关于数据的数据",元数据的特点决定了其主要作用是对过程和结果进行描述和记录,以方便对相关过程和结果进行反向追溯。

在DevOps流程中,因为大量的工作被机器所取代,增加了效率的同时,也让人增加了对于过程不可控的担忧(当然了这只是出于感性上的直观感觉,其实从理性出发,自动化反而增强了过程的可控性),因此为了能够对过程进行回溯,自动化流程需要在搭建的过程中,在流程的每个阶段尾声,写入关于本阶段的一些元数据作为备份,这样既能够为之后的阶段提供信息参考,也能够可能的问题排查提供追诉依据。

额外提一句的是,其实人工操作也是应该有元数据的,只是人工操作本来工作量就大,你再给加个增加元数据的活,造反和阳奉阴违就并不是什么值得惊讶的事情了。

3. Links

  1. 【DEVOPS】共识
  2. 【DEVOPS】最佳实践践行之“只生成一次制品”
  3. 基础设施即代码(Infrastructure as Code)
  4. 解读基础设施即代码
  5. 云原生定义解析—不可变基础设施 (immutable infrastructure)
  6. 内建质量,你真的了解么?

这篇关于【DEVOPS】最佳实践和指导思想的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/405744

相关文章

Spring Boot集成/输出/日志级别控制/持久化开发实践

《SpringBoot集成/输出/日志级别控制/持久化开发实践》SpringBoot默认集成Logback,支持灵活日志级别配置(INFO/DEBUG等),输出包含时间戳、级别、类名等信息,并可通过... 目录一、日志概述1.1、Spring Boot日志简介1.2、日志框架与默认配置1.3、日志的核心作用

破茧 JDBC:MyBatis 在 Spring Boot 中的轻量实践指南

《破茧JDBC:MyBatis在SpringBoot中的轻量实践指南》MyBatis是持久层框架,简化JDBC开发,通过接口+XML/注解实现数据访问,动态代理生成实现类,支持增删改查及参数... 目录一、什么是 MyBATis二、 MyBatis 入门2.1、创建项目2.2、配置数据库连接字符串2.3、入

Android Paging 分页加载库使用实践

《AndroidPaging分页加载库使用实践》AndroidPaging库是Jetpack组件的一部分,它提供了一套完整的解决方案来处理大型数据集的分页加载,本文将深入探讨Paging库... 目录前言一、Paging 库概述二、Paging 3 核心组件1. PagingSource2. Pager3.

在Java中使用OpenCV实践

《在Java中使用OpenCV实践》用户分享了在Java项目中集成OpenCV4.10.0的实践经验,涵盖库简介、Windows安装、依赖配置及灰度图测试,强调其在图像处理领域的多功能性,并计划后续探... 目录前言一 、OpenCV1.简介2.下载与安装3.目录说明二、在Java项目中使用三 、测试1.测

MyBatis-Plus 自动赋值实体字段最佳实践指南

《MyBatis-Plus自动赋值实体字段最佳实践指南》MyBatis-Plus通过@TableField注解与填充策略,实现时间戳、用户信息、逻辑删除等字段的自动填充,减少手动赋值,提升开发效率与... 目录1. MyBATis-Plus 自动赋值概述1.1 适用场景1.2 自动填充的原理1.3 填充策略

Olingo分析和实践之EDM 辅助序列化器详解(最佳实践)

《Olingo分析和实践之EDM辅助序列化器详解(最佳实践)》EDM辅助序列化器是ApacheOlingoOData框架中无需完整EDM模型的智能序列化工具,通过运行时类型推断实现灵活数据转换,适用... 目录概念与定义什么是 EDM 辅助序列化器?核心概念设计目标核心特点1. EDM 信息可选2. 智能类

Olingo分析和实践之OData框架核心组件初始化(关键步骤)

《Olingo分析和实践之OData框架核心组件初始化(关键步骤)》ODataSpringBootService通过初始化OData实例和服务元数据,构建框架核心能力与数据模型结构,实现序列化、URI... 目录概述第一步:OData实例创建1.1 OData.newInstance() 详细分析1.1.1

Olingo分析和实践之ODataImpl详细分析(重要方法详解)

《Olingo分析和实践之ODataImpl详细分析(重要方法详解)》ODataImpl.java是ApacheOlingoOData框架的核心工厂类,负责创建序列化器、反序列化器和处理器等组件,... 目录概述主要职责类结构与继承关系核心功能分析1. 序列化器管理2. 反序列化器管理3. 处理器管理重要方

虚拟机Centos7安装MySQL数据库实践

《虚拟机Centos7安装MySQL数据库实践》用户分享在虚拟机安装MySQL的全过程及常见问题解决方案,包括处理GPG密钥、修改密码策略、配置远程访问权限及防火墙设置,最终通过关闭防火墙和停止Net... 目录安装mysql数据库下载wget命令下载MySQL安装包安装MySQL安装MySQL服务安装完成

SpringBoot整合(ES)ElasticSearch7.8实践

《SpringBoot整合(ES)ElasticSearch7.8实践》本文详细介绍了SpringBoot整合ElasticSearch7.8的教程,涵盖依赖添加、客户端初始化、索引创建与获取、批量插... 目录SpringBoot整合ElasticSearch7.8添加依赖初始化创建SpringBoot项