大部分的软件环境管理问题,原因都在这里
专栏策划|雅纯
自愿编辑|jimmy、吕瑞星
软件交给的终态是提供安稳可预期的系统,要做到这一点,咱们需求确保:一、软件制品的共同性;二、运转环境的共同性。
第3讲咱们分享了怎么确保软件制品的共同性,这一讲咱们来谈谈怎么确保环境的共同性。
运转环境共同性的目标是环境可预期、安稳、低本钱。其间低本钱比较要害,因为环境资源的本钱一般比较高。
咱们能够将运转环境分为3部分:制品、履行引擎和编列规矩。
要确保制品的共同性,第一是确保代码及其依靠的共同性;第二是确保构建环境的共同性;最后是确保构建脚本的共同性。确保环境的共同性,也包括了三点:
- 运用的共同性,比方共同的容器镜像;
- 容器运转所需的上下文的共同性,比方共同的数据装备等;
- 编列规矩的共同性,需求确保编列履行相同的规矩,比方相同容器布置规矩、相同节点散布规矩、相同备份规矩等。
确保这3点,布置完成之后才会构成共同的可运转环境。但是现实当中,环境还是会有许多其它的问题,比方:
- 装备文件中有许多监控之类的装备,关于运用者来说,不知道装备的详细效果,需求修正时不知怎么设置。
- 测验的时分依靠的环境经常发生问题,消耗大量等待和排查时刻。比方说依靠的API经常出问题,排查修正或许需求等待依靠方好久,导致测验作业无法继续进行。
- 新环境的建立很耗时。建立一个新的环境是很苦楚的工作,比方国际化团队,经常要建立新的站点,而每搭一个新的环境就要消耗一整天的时刻是很苦楚的。
- 运用在本地无法运转。比方因为缺某个资源导致运用无法正常运转。
- 装备环境需求当心翼翼,或许呈现装备遗失。每次配环境的时分需求很当心,特别是当环境装备由多人配合时,会呈现装备抵触,导致程序无法运转,需求全链路排查处理。
这里咱们简略列了五个常见的问题,它们的根源都是环境缺少明晰的界说:不清楚环境的详细内容、对环境建立过程的认知模糊。
环境的明晰界说,包括环境包括什么制品、这些制品怎么布置等。那么环境办理的终态是什么呢?
当制品相同、运转上下文相同,而且资源数据是相同的情况下,根据相同的编列规矩,环境就应该是共同的。一同,环境能够由软件来界说和声明。这是咱们以为的环境办理的终态,简略来说,即软件界说的不可变环境。软件界说的不可变环境,能够归入版别办理,确保环境首要是界说清晰的,其次是有清晰版别的。
环境办理的3个阶段
阶段一:阐明书
环境办理的第一个阶段是阐明文档,这点相信许多人都经历过。当咱们在做一个项目或产品时,会写整个产品的布置阐明书、阐明文档、晋级文档等各种文档。但文档很难确保实用,也纷歧定是最新的、精确的。每次咱们去现场交给时,都会遇到一些文档里没有描绘的问题。这时分还得打电话承认,是否有遗失什么。用文档或阐明书去办理环境,存在很大的坏处,所以咱们想到了用指令的方法去办理。
阶段二:指令
第二阶段,咱们经过指令的方法,写了各种shell、Python脚本,把相关指令组合在一同。之前咱们在做一个产品的私有化交给的时分,一开始的做法便是用脚本去办理环境,因为敞开一个新环境实在太苦楚了,需求花许多时刻改参数、找包、配IP等,效率太低。所以咱们写了脚本来办理,用脚本代替了文档。
但是用脚本办理环境也存在许多问题。咱们要应对各式各样的环境,同一个任务在不同的场景里,指令组合或许是不相同的,所以脚本会越来越多,保护脚本的本钱也越来越高。
阶段三:声明
为了处理指令脚本的保护和安稳性问题,咱们进入了第三个阶段,声明式——经过装备的方法表达环境,把环境界说出来。声明式的描绘提供了环境的确定性表达。
以k8s为例,咱们以一个比方来看,怎么做环境声明
上图是K8S的简略架构,左上角是K8S的master,左下角是node,master有好几个组件:scheduler、ControllerManager、APIserver,以及Etcd。Etcd是一个散布式存储,装备信息都在Etcd里边。Node是物理机或者虚拟机,在每一个Node上面会有多个pod,上面会运转许多的容器。
咱们知道K8S的最小单元是pod,里边有容器,还有各种网络存储等,经过pod声明去描绘。声明被apply后,详细的工作在controller里边处理。
经过sidecar别离重视点
咱们写一个运用,这个运用里边大量的代码其实与事务无关,而是包括许多服务办理的代码,例如日志、监控、限流、熔断等。这些代码占了很大的比重,而且这些代码的保护者和运用开发者纷歧定是同一批人。服务办理相关的代码,在许多企业会有专门的团队担任保护和晋级,相似阿里的中间件团队。传统的情况下,咱们需求晋级并重新布置运用才干晋级服务办理能力。但是在云原生年代,运用开发者期望仅重视运用事务代码,服务办理相关的代码放在其他的容器里边,事务容器和服务办理容器通常会编列在同一个pod里边,但是服务办理容器的办理、开发、发布都跟运用开发者没有联系,这些便是sidecar容器。sidecar容器完成了重视点的别离,运用的开发者和中间件的开发者以及运维相关的开发者,都能够有自己的重视点。
咱们以两个人物为例,一是事务的开发者,重视的是运用的容器,所以发布的时分,他的重视点都在运用容器这一块。二是企业的SRE,他的重视点往往在sidecar的各种服务办理容器上,比方logagent的日志等级和采样率是否合理等。
经过sidecar,事务开发者和SRE的重视点就别离了。这样别离还有一个优点,便是中间件下沉,都以sidecar的方法办理。一旦遇到相应的中间件需求晋级,事务代码不需求做任何的改动和发布,只需求做sidecar的发布就好了。
咱们前面说到,共同的环境需求有3个组成部分:相同的制品、相同的运转上下文以及相同的编列规矩。相同的运转上下文,实质便是里边的装备要共同。最早咱们是用文档告知咱们怎么把环境办理起来,之后用脚本,最后用环境声明。
但是,用声明式的方法界说环境也并不完美。举个详细的比方,在运用运转的时分需求有一些相应的装备,中间件、基础资源、CPU、存储等都需求装备,这样会面对一个很大的问题——环境相关的装备太多了。
环境相关的装备太多,该怎么办理好呢?
经过IaC来界说环境
为了处理这个问题,业界采用了IaC的概念(InfrastructureasCode)。早期在云机房上架的时分会用到IaC,比方有一个新的机器过来,要装成centos7的系统,里边要配特定的DNS服务等等。这是就会界说一个声明文件,发送给saltstack这样的工具。现在整个环境都是经过基础设施来描绘出来的,所以整个环境包括中间件的资源都是基础设施了,在范围上比原先要广的多。
从装备的角度,咱们有运用装备、运维装备、基础设施运维装备,乃至软件生产过程的装备。咱们把运用代码和IaC代码,放在两个库里边(也有放到一个库里边的,各有利弊,在此咱们不展开也不评价)。
比方上图中,在IaCRepo里咱们放了动态装备(即运转时的装备)、BaaS装备(基础设施,如数据库、中间件存储、音讯行列等)、监控装备(如监控粒度、采样频率)、发布装备等。一切的装备都声明在代码库里边,根据该声明编列的一切环境就都是共同的了。
任何工作都是有利有弊,用IaC的方法办理环境又会带来什么新的应战呢?
首要是“灵活的代价”。因为一切的装备都是松散的文本,缺少一致的聚合根,导致修正者需求自己了解这些装备背后对应的依靠联系。比方某个装备项设置为on会敞开限流,但是必须配合特定的configMap一同运用;比方敞开了一个Ingress插件,但如果另一个Rollout插件没有敞开,会无法正常作业;再比方HPA和CronHPA无法一同运用,会发生抵触。因为编写的灵活性,会导致无穷的组合方法,其组合发生的后果往往在运转时才会发现。
其次是知识的本钱。IaC将一个环境一切的装备都以文本的界面给到了开发者,但是许多装备项是需求专业背景的,比方运维相关的战略、比方监控的装备方法等等,价值IaC自身的学习本钱,往往让许多开发者望而生畏。
为了处理这个问题,阿里联合微软一同发布了OAM模型,以运用为一致维度,将IaC包括的各类资源和人物进行了分类和聚合。
首要,OAM引入了运用(Application)的概念,将运用的各类IaC装备都聚合在一同,处理其依靠问题。
其次,OAM将IaC的运用者别离为:运用开发者、运用运维、基础设施运维三大人物,彼此的重视点进行了别离。
OAM笼统和简化了IaC的界说和保护方法,降低开发者的学习和运用本钱。
总结一下,咱们以为,环境办理的终态是软件界说的不可变环境,而当下,它的最佳实践咱们以为是根据OAM模型的、以运用为核心的IaC声明。
我有话说: