写点什么

FreeWheel 云环境治理实践:运维体系设计

彭潇、张成、姜冰

  • 2021-08-16
  • 本文字数:5134 字

    阅读完需:约 17 分钟

FreeWheel云环境治理实践:运维体系设计

前言

随着各大云厂商竞争愈发激烈,云计算产业正在快速崛起。云计算正在影响整个信息产业,其可靠性、灵活性、按需计费的高性价比等优势已经让很多厂商把“上云”列入到了战略计划中。

 

相对传统运维,云计算为我们节省了很多硬件、网络、甚至一些基础服务的维护成本。与此同时也把运维模式从传统的静态化变成了动态化,如何管理多样化的动态资源、构建弹性化服务、实现异地切换与备份、管控内外部安全、优化成本等等挑战应运而生。

 

本文将分享 FreeWheel 基于 AWS 云服务的运维生态体系设计思路:面对内部众多团队,如何在保持“底线”的同时,给用户提供灵活的可变空间、实现裸资源交付与管理。

不以规矩 不能成方圆

古人云,工欲善其事必先利其器。让我们先来定定规矩,制定内部标准“白皮书”。

命名标准与组织关系定义

传统运维中的 CMDB 是一个绕不开的话题。不过 AWS 丰富的 API 已经帮我们封装好了各种接口,这些基础信息都可以通过 API 实时查询。我们要做的是把各个服务模块通过多种维度描述出来。

 

我们将服务树服务作为公司内部统一入口,用来描述和维护所有资源的组织关系,虽然服务本身很轻量化,但却是整个运维生态系统的基石。

 

服务树需要怎么设计?这个并没有标准答案,需要综合公司实际情况反复地推敲与验证才能定制出合理的方案。

 

虽然是开放性设计,但还是需要满足一些基本要求:

 

  • 最小服务单元唯一性

注册在服务树里面的节点必须是唯一的,这个就像传统的硬件资源管理,大到一个机柜,小到一根内存,每个硬件都是唯一并且真实存在的。

 

  • 灵活并尽可能的小巧

这里需要考虑维度问题,服务树既是给自动化代码读的,也是给人看的。不同角色需要不同的维度,所以这里一定要按需制定好标准规范,以后公司内部的沟通与开发、部署、维护等都会围绕这个体系运转。

 

  • 与业务关联

先顺应公司当前的产品线思路去设计。梳理清楚当前的业务结构,了解未来的发展计划和趋势,需要考虑的因素包括产品线定位、人员安排等等。

 

然后要考虑当前底层基础服务情况。比如我们的大部分业务都运行在 AWS 上,需要利用 AWS 原生服务的特性来支撑设计需求。

 

最后要兼顾底层载体的基本特性,其初期交付、中后期的部署与配置管理,以及后期的下线等都需要通过服务树来管理。

 

在此抛砖引玉一下,我们的设计是以 Project(项目) 、 Application(应用) 、Service(服务,即最小服务单元)为主的三层结构(以下简称 P-A-S 模型),小巧且可以灵活覆盖业务。

 

根据这三层结构,我们定义出了不同的维度便于生态管理,即:

  • P 节点:项目层,包括下面所有 P-A 及 P-A-S 资源

  • P-A 节点:应用层,包括 P-A 下面的所有资源

  • P-A-S 节点:单服务层,仅仅包括对应的单一服务单元

  • P-*-S 节点:通配服务层,该项目下所有应用的特定服务单元,适用于内部多租户的越界管理

 

下图简单介绍了服务树的层级与 AWS 一些资源的对应关系:

 


同时面对多租户及中台性质的这些服务,我们的服务树也会基于应用层来显性地指明对应关系,如下图所示:

  • 中台性质的服务,S 层所属统一项目,并跨 P 或 A 层节点提供业务支持。

  • 多租户性质的服务,A 层可根据需求,映射到不同的 P 或者 A 节点,这可以灵活地实现费用分析以及人员的管理等。

 


基于服务树,我们把 AWS 的资源均对号入座打上 P-A-S 的 TAG,看下服务树帮我们解决了哪些问题:

 

  • 命名标准:

  • 通过命名的标准化,很好地统一了内部沟通语言,包括工作和机器语言。

  • P 和 A 层资源信息(命名、节点位置、人员信息等)固化在服务树里,剩下的 S 层相对灵活,通过流程确保服务树“源”的权威性。

  • 对于 AWS 的资源,把服务树节点信息与 TAG 绑定,对支持自定义化的 ARN 资源,也会基于服务树节点固化 ARN。

  • 组织关系:

  • 资源相关的信息,都可以通过不同节点位置或者用定义好的不同维度来查询。

  • 费用分析:

  • 将 P-A-S 设定为 AWS Billing TAG,这样我们可以从 AWS cost explorer 或者 billing raw data 里方便地统计出各个维度的费用明细。

  • 针对中台或者多租户平台的费用追踪,我们提出了一个 budget entity 的概念,即通过 P-A-S 不同维度的组合,可以预定义出不同范畴的“预算组合集”。

  • 通过费用明细和监控数据的关联分析,可以给容量评估和优化提供很好的参考数据。

  • 访问控制:

  • 针对于业务层面,基础的 IAM 和 Security Group 均基于服务树节点进行通配或精准授权。

  • 针对于人员和工具层面,比如报警组、权限申请、pipeline 等都可基于服务树进行授权和隔离。

  • 自动化运维:

  • 服务树的设计理念为实现统一的、标准的自动化运维平台打下了坚实的基础, 例如上述的命名标准,访问控制都是自动化运维平台里不可或缺的部分。

云原生服务的标准定义

完成了组织结构的规范和标准,接下来就要标准化原生服务的使用与管理方案。

 

为什么要规范云原生服务的使用呢?

 

公有云服务往往需要兼顾多样化的用户场景,所以服务设计得非常灵活,内部多租户模式给管理带来了很多痛点:

 

  • 不同团队使用相同服务、解决不同问题,或使用不同服务、解决相同问题,过多的差异化难以维护。

  • 往往一个参数的差异,就会导致误把资源发布到公网或者内部权限越界,存在很多安全隐患。

  • 公有服务迭代快,学习成本高。

 

我们本着“在同构中求异构,不在异构中求同构”的原则,尽可能最大化复用资源。像部署发布这种琐碎重复的事情交给底层基础服务去完成就好了,所以我们在支撑众多业务团队时候需要尽可能做到:事做一遍、坑踩一次、快速迭代。

 

在 AWS 上,对于最底层裸资源我们大概划分成这几类:

EC2层

以虚拟机为主的传统生态

Docker容器层

基于EKS或ECS的容器生态

Serverless层

以Lambda为主的无服务器生态

Database层

以RDS,DDB为主的数据库生态

AWS其他原生服务层

开箱即用服务,包括认证鉴权、网络、存储、数据分析、中间件等等原生生态

除 AWS 开箱即用的原生服务,其他服务均需要额外的工具来构建其生态,因篇幅有限,今天我们先不做深入讨论。

 

在 AWS 各种白皮书和最佳实践文档的基础上,我们根据公司实际情况,针对大部分常用服务制定了公司内部的“最佳实践”,主要包括:

  • 原生服务的应用场景的制定,固定需求的统一解决方案,原生服务选型等标准;

  • 扩展性、安全性、可管理性、费用成本评估等标准;

  • 权限、属性等配置约束;

  • Tag、ARN 等命名约束;

 

当然,标准不意味着技术锁定,对于“老”技术需要不断更新迭代,对于“新”技术,在积极拥抱的同时更需要理智地评估,而不是一味赶“时髦”。

基础设施的标准定义

无标准不成自动化,到此,我们有了足够详细的标准化参考,接下来我们就要思考如何确保各种标准可以准确地应用到生产之中。

 

在底层基础实施技术栈的选型上,我们主要考量以下几个方面:

  • 可管理 AWS 资源

  • 可支持多用户或团队协同工作

  • 可扩展

  • 可维护

 

AWS 作为一个很成熟的公有云,很多商业化或开源的厂商都在其之上提供了完整解决方案,相关的技术选型是个仁者见仁智者见智的问题,找到适合的就可以。

 

我们最终选择了 Terraform 的开源方案,在此简单介绍下 Terraform(以下简称 TF)的优势:

  • Infrastructure as Code 模式;

  • 执行计划提示,即应用新代码前可显示“dry run”结果,对幂等性管理比较友好;

  • 一键执行,TF 会根据代码的修改自动编排对 AWS API 的调用;

  • 较丰富的组件支持,除 AWS 外还支持很多流行工具,同时产品迭代也跟的上 AWS 的进度(AWS 的更新速度真的很快)。

 

TF 作为一个 Infrastructure as Code 的框架,虽然有诸多优势,但是如何将它用好仍然是我们需要去解决的问题,尤其是在多团队合作参与 AWS 环境治理的的情况下, 如何保证整套治理体系的可维护性、安全性、幂等性、唯一性等等。

 

鉴于此,我们打造了一个支持 TF 的自动化运维平台(将在下一篇文章中详细介绍)作为 AWS 环境治理的统一入口,通过平台介入来实现下图中左侧往右侧的转变, 并解决上述几个问题:

 

可维护性:保障代码风格和结构一致性,保证代码库始终处于可维护的健康状态

  1. 针对 AWS 的各项原生服务,基于上文确定的“内部最佳实践”,我们将对应的实践固化成 TF 模块,并加入显性的版本控制,便于灵活管理模块,使其与应用代码解耦,实现私有化模块注册功能;

  2. 私有化模块库在公司内部以开源项目的模式管理,集大家的力量和经验来扩大和提升“最佳实践”的范围;

  3. 降低用户对 TF 的学习成本,通过可视化前端来生成和维护代码,用户只需在界面选择自己需要的私有化模块版本,根据引导输入简单的变量,运维平台会负责自动生成 TF 代码,并进入 pull request(以下简称 PR)阶段,从而保证代码风格和结构的一致性。

安全性:保障修改后的代码平稳应用到线上

  1. 准确性,利用自动化运维平台结合 TF 的 Dry run 功能保证用户提交代码的准确性,包括语法和预定义的语义检查,以及提交资源修改前的二次确认:

  2. 运维平台支持暂存当前工作目录状态,便于执行 TF dry run 和不合法修改再编辑等功能;

  3. 运维平台根据我们的最佳实践定义了一些语义检查规则,补足了 TF dry run 无法实现的一些检查点。比如,IAM policy 的内容会结合预定的黑名单,初筛一些权限越界的修改;

  4. TF dry run 结果会提示用户此次资源变更的具体信息和细节, 用户确认此次提交的影响是否符合预期后,变更才会正式进入 PR 阶段。

  5. 合法性,用户提交的任何关于资源变更的修改,上线之前都会经过审核人员(SRE 团队)的评估。

  6. 可审计性,任何关于 AWS 资源的变更都会被详细记录下来,便于变更追溯和第三方审计。

  7. 隔离性,基于服务树的设计,可以灵活地把任意节点和下面的子节点定义为一个租户,每个租户都为其创建单独的 pipeline 进行权限和网络的隔离。通过权限边界的隔离,一是便于组织租户内的资源,二是可以止损一些泛事件的影响,比如极端 bug、恶性行为等。

幂等性:保障代码可一次或多次按需应用变更

  1. 维护好 TF 的状态信息,即 TF 的 state 信息。TF 每次运行都会用对比 AWS 资源实际状态和 state 里记录的状态,若发现不一致的情况,TF 会以自己的 state 信息为基准去纠正实际状态。所以 state 信息需要独立维护,并且做好备份。目前我们采取的方案是 state 信息独立存储在 S3 里,并且开启 object version 来备份每次更新,同时在异地备份,避免一些灾难性的不可逆事故。

  2. 处理好资源依赖。服务的部署通常比较复杂,有先后顺序、输入输出等等依赖关系,所以小到模块内部,大到整套 TF 代码,都需要确保这些关系是正确的,这样代码就可以到处部署了。

  3. 通过 TF 模块化的结构来限制一些变更。先解释下哪些属于重要参数,因为一些 AWS 原生设计的特性,一些服务一旦创建出来,有些参数就无法修改了,或者修改后不会影响现有资源,只有下次创建新资源才会生效。TF 不但会继承这些特性,在有些场景还会强制植入些新的逻辑。举个简单的例子,比如修改 EC2 的初始化 user data,因服务特性,只有在创建实例的时候才会运行一次,针对现有 EC2,再怎么修改这些参数也不会触发 user data 重新执行,但是如果通过 TF 去管理,当修改 user data 后,TF 会自动为我们销毁当前实例,并发布新的实例,以这样的方式强制 user data 更新。因为云的特性,这种案例有很多,但是在大部分场景下我们可能不需要这样的“硬操作”,所以之前提到的“内部最佳实践”都会对参数和使用场景等等进行评估和设计。

唯一性:保障代码做为“源”,而不是环境影响代码

  1. 最小化授权,无论人员还是服务,只授权需要的的权限。原理很简单,但是实现起来还是有些难度,需要沉淀出各种场景的权限模板供大家参考与使用,主要原因如下:

  2. AWS IAM policy 的学习成本高,涉及服务种类多,每个服务下面又有很多 action,还需要配置很多条件才可实现最小化授权,最终的结果是一个较复杂的组合。

  3. 用户往往可以描述出清晰的使用场景,但是不清楚所依赖的 AWS 服务和具体 action。

  4. 若资源被 TF 维护,那修改的途径也要通过 TF,否则就会产生歧义,到底该以环境状态还是代码状态为准。

  5. 尽量使用 AWS 原生服务来管理动态资源,支持动态扩展的原生服务已经为我们造好轮子了,除非功能不能满足我们需求。另外 TF 管理资源其实是非动态的,它需要记录在管的每个资源的生命周期状态,并且基于这些对应的状态才能做出决策。举个简单的例子,我们需要根据业务不同的时间段,来扩展集群里 EC2 的数量,如果直接使用 TF 管理每一个 EC2,那我们就只能频繁地调整代码了。换个角度,如果利用 TF 直接管理 Auto Scaling group(以下简称 ASG),所有 EC2 托管于 ASG,非 TF 直接管理,这样的话我们只需要维护 ASG 的 schedule policy 和 EC2 的 launch template 即可优雅地固化 TF 代码。

  6. 监控方面,通过 TF 的 plan 功能进行异步检查,判断当前 TF 代码是否与线上环境一致。一旦检查到非一致的资源,主动发送报告给对应的负责人,由负责人修复。

结语

标准定义是一个团队持续思考与沉淀的过程,也是不断迭代与试错的过程,更是获得宝贵经验财富的过程。但是有了标准,如果没有强有力的执行,那么标准就失去了应有的意义。下一篇文章,我们将重点介绍 FreeWheel 在标准化过程中的实践,以及运维平台如何发挥它的作用。

 

作者介绍:

 

彭潇:Lead SRE,任职于 FreeWheel OPS 团队,致力于 AWS 云上环境治理相关工作。

 

张成:Senior Manager,任职于 FreeWheel OPS-DEV 团队,负责自动化运维平台的建设和开发工作。

 

姜冰:Software Architect,任职于 FreeWheel Data 团队,负责数据平台的建设和开发工作。

2021-08-16 08:004560

评论

发布
暂无评论
发现更多内容

vivo商城前端架构升级-总览篇

vivo互联网技术

node.js Vue 大前端 架构设计

Java中强、软、弱、虚四种引用详解

古月木易

Java

高效程序员的45个习惯:敏捷开发修炼之道(7)

石云升

敏捷开发 晨会

鲲鹏迁移第一批吃螃蟹的人,践行技术国际化

华为云开发者联盟

鲲鹏920 服务器 华为云 ARM芯片 X86

35K成功上岸华为商城事业部,只因学透了这几个开源的商城项目

Java迁哥

Java 华为 源码 资料 商城项目

JVM中unsafe.cpp源码

Darren

c++ 源码 JVM unsafe

LeetCode题解:84. 柱状图中最大的矩形,双循环暴力,JavaScript,详细注释

Lee Chen

大前端 LeetCode

CPU中的程序是怎么运行起来的(预告篇)

良知犹存

cpu

java安全编码指南之:Mutability可变性

程序那些事

Java java安全编码 编码指南 可变性

【运维探讨】RPA落地实践,提升IT运维工作效能!

嘉为蓝鲸

RPA 运维自动化 标准化 系统运维 流程

【API进阶之路】破圈,用一个API代替10人内容团队

华为云开发者联盟

内容 编辑 API 华为云 文本摘要

面经手册 · 第9篇《队列是什么?什么是双端队列、延迟对列、阻塞队列,全是知识盲区!》

小傅哥

数据结构 小傅哥 队列 ArrayDeque

架构设计复杂度来源

escray

学习 从零开始学架构 架构师预科班

ArCall远比你想象的要强大的多

anyRTC开发者

WebRTC 在线教育 直播 RTC 安卓

2019年我最喜欢的三款数码产品。

徐说科技

手机 苹果

程序员如何获取一份高薪工作?阿里P8大牛给你一些中肯的建议

Java迁哥

Java 华为 程序员 面试 资料

区块链支付系统源码开发,USDT承兑支付平台

13530558032

一条龙!CI / CD 、打造小团队前端工程化服务

久违

Vue 大前端 jenkins React

分析HiveQL 生成的MapReduce执行程序

任小龙

花两个半月吃透这份Java手打面经,成功从外包上岸到京东

Java迁哥

Java 学习 腾讯 面试 资料

9块钱,构建个私有网盘,关键不限速

华为云开发者联盟

网站 OBS 在线网盘 华为云 云存储

week12 homework

burner

Java创建对象的方法有哪些?

古月木易

Java

Docker 网络模式详解及容器间网络通信

哈喽沃德先生

Docker 容器 微服务

为什么阿里巴巴的程序员成长速度这么快,看完他们的内部资料我明白了

Java迁哥

Java 阿里巴巴 程序员 成长 笔记

区块链交易所开发源码,数字货币交易所app开发

13530558032

拥抱K8S系列-01-CentOS7安装docker

张无忌

Docker centos 运维

JDK8 Unsafe.java 源码

Darren

源码 并发 CAS 代码注释 unsafe

实战案例丨使用云连接CC和数据复制服务DRS实现跨区域RDS迁移和数据同步

华为云开发者联盟

迁移 灾备 数据复制 云连接 数据同步

Java创建对象的方法有哪些?

奈学教育

Java

Java中强、软、弱、虚四种引用详解

奈学教育

Java

FreeWheel云环境治理实践:运维体系设计_语言 & 开发_InfoQ精选文章