【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

相关文章

基于MySQL Binlog的Elasticsearch数据同步实践

一、为什么要做 随着马蜂窝的逐渐发展,我们的业务数据越来越多,单纯使用 MySQL 已经不能满足我们的数据查询需求,例如对于商品、订单等数据的多维度检索。 使用 Elasticsearch 存储业务数据可以很好的解决我们业务中的搜索需求。而数据进行异构存储后,随之而来的就是数据同步的问题。 二、现有方法及问题 对于数据同步,我们目前的解决方案是建立数据中间表。把需要检索的业务数据,统一放到一张M

系统架构师考试学习笔记第三篇——架构设计高级知识(20)通信系统架构设计理论与实践

本章知识考点:         第20课时主要学习通信系统架构设计的理论和工作中的实践。根据新版考试大纲,本课时知识点会涉及案例分析题(25分),而在历年考试中,案例题对该部分内容的考查并不多,虽在综合知识选择题目中经常考查,但分值也不高。本课时内容侧重于对知识点的记忆和理解,按照以往的出题规律,通信系统架构设计基础知识点多来源于教材内的基础网络设备、网络架构和教材外最新时事热点技术。本课时知识

如何确定 Go 语言中 HTTP 连接池的最佳参数?

确定 Go 语言中 HTTP 连接池的最佳参数可以通过以下几种方式: 一、分析应用场景和需求 并发请求量: 确定应用程序在特定时间段内可能同时发起的 HTTP 请求数量。如果并发请求量很高,需要设置较大的连接池参数以满足需求。例如,对于一个高并发的 Web 服务,可能同时有数百个请求在处理,此时需要较大的连接池大小。可以通过压力测试工具模拟高并发场景,观察系统在不同并发请求下的性能表现,从而

Prometheus与Grafana在DevOps中的应用与最佳实践

Prometheus 与 Grafana 在 DevOps 中的应用与最佳实践 随着 DevOps 文化和实践的普及,监控和可视化工具已成为 DevOps 工具链中不可或缺的部分。Prometheus 和 Grafana 是其中最受欢迎的开源监控解决方案之一,它们的结合能够为系统和应用程序提供全面的监控、告警和可视化展示。本篇文章将详细探讨 Prometheus 和 Grafana 在 DevO

springboot整合swagger2之最佳实践

来源:https://blog.lqdev.cn/2018/07/21/springboot/chapter-ten/ Swagger是一款RESTful接口的文档在线自动生成、功能测试功能框架。 一个规范和完整的框架,用于生成、描述、调用和可视化RESTful风格的Web服务,加上swagger-ui,可以有很好的呈现。 SpringBoot集成 pom <!--swagge

vue2实践:el-table实现由用户自己控制行数的动态表格

需求 项目中需要提供一个动态表单,如图: 当我点击添加时,便添加一行;点击右边的删除时,便删除这一行。 至少要有一行数据,但是没有上限。 思路 这种每一行的数据固定,但是不定行数的,很容易想到使用el-table来实现,它可以循环读取:data所绑定的数组,来生成行数据,不同的是: 1、table里面的每一个cell,需要放置一个input来支持用户编辑。 2、最后一列放置两个b

【HarmonyOS】-TaskPool和Worker的对比实践

ArkTS提供了TaskPool与Worker两种多线程并发方案,下面我们将从其工作原理、使用效果对比两种方案的差异,进而选择适用于ArkTS图片编辑场景的并发方案。 TaskPool与Worker工作原理 TaskPool与Worker两种多线程并发能力均是基于 Actor并发模型实现的。Worker主、子线程通过收发消息进行通信;TaskPool基于Worker做了更多场景化的功能封装,例

vue2实践:第一个非正规的自定义组件-动态表单对话框

前言 vue一个很重要的概念就是组件,作为一个没有经历过前几代前端开发的我来说,不太能理解它所带来的“进步”,但是,将它与后端c++、java类比,我感觉,组件就像是这些语言中的类和对象的概念,通过封装好的组件(类),可以通过挂载的方式,非常方便的调用其提供的功能,而不必重新写一遍实现逻辑。 我们常用的element UI就是由饿了么所提供的组件库,但是在项目开发中,我们可能还需要额外地定义一

《C++中的移动构造函数与移动赋值运算符:解锁高效编程的最佳实践》

在 C++的编程世界中,移动构造函数和移动赋值运算符是提升程序性能和效率的重要工具。理解并正确运用它们,可以让我们的代码更加高效、简洁和优雅。 一、引言 随着现代软件系统的日益复杂和对性能要求的不断提高,C++程序员需要不断探索新的技术和方法来优化代码。移动构造函数和移动赋值运算符的出现,为解决资源管理和性能优化问题提供了有力的手段。它们允许我们在不进行不必要的复制操作的情况下,高效地转移资源

使用Azure Devops Pipeline将Docker应用部署到你的Raspberry Pi上

文章目录 1. 添加树莓派到 Agent Pool1.1 添加pool1.2 添加agent 2. 将树莓派添加到 Deployment Pool2.1 添加pool2.2 添加target 3. 添加编译流水线3.1 添加编译命令3.2 配置触发器 4. 添加发布流水线4.1 添加命令行4.2 配置artifact和触发器 5. 完成 1. 添加树莓派到 Agent Pool