前言
云计算架构作为一种基础设施服务几乎已经成为了现代Web开发的标配,它显著地降低了 DevOps(Development and Operations)的门槛,通过云服务商提供的管理平台,Web应用开发人员可以轻松地在云上搭建自己的系统。作为一名云时代的全栈开发工程师,了解云计算架构背后的机制可以让我们更好地利用这个强大的基础设施,在设计、开发、部署和维护应用程序时做出更明智的决策。同时云计算是互联网技术的延伸,通过学习云计算架构,可以更深入地掌握互联网基础知识,这对于个人的技术水平也是一个很大的提升。
为了对云计算有一个全面的了解,最近在读 《图解云计算架构——基础设施和API》 一书,这本书主要以OpenStack和AWS为例,通过API来重点讲解IaaS云服务的本质。下面是边读边整理的学习笔记,一方面可以随时回顾,另一方面希望通过输出来促进自己思考。
正文
前面分别介绍了云计算的虚拟机、存储、网络组件资源。在此基础上,能不能更进一步,自动定义资源间的关系呢?答案就是云计算编排(Cloud Orchestration)。
1. 编排的基础知识和模板语法
云计算编排(Cloud Orchestration)是指通过自动化工具和技术来协调、管理和优化云环境中各种资源和服务的过程。它不仅涉及到虚拟机、存储和网络等基础设施资源的调度,还包括应用程序组件之间的交互以及服务级别的管理。云计算编排的目标是简化复杂的IT操作,提高资源利用率,并确保业务应用能够高效、可靠地运行。
基础设施即代码
之所以把基础设施看成代码,是因为云计算编排和自动化使我们能够以便于人类阅读的纯文本格式(比如YAML或JSON)定义云基础设施与系统状态,并通过编排工具、API、脚本语言及自动化工具的组合,最终可以像处理程序代码一样地处理云基础设施。
幂等性:通过编排和自动化,无论用户执行了多少次,都能复现相同环境,保持一致性。
实现方式:
- 声明式工具:如 Terraform,让用户描述期望的状态,然后工具负责实现该状态;
- 命令式工具:如 Ansible、Chef、Puppet,需要用户编写一系列指令来逐步达到目标状态。
AWS CloudFormation和OpenStack Heat都是典型的声明式功能,AWS CloudFormation中使用的是JSON模板,OpenStack Heat使用的是YAML或JSON模版。
编排功能中的资源集合的概念
前面几节我们介绍了通过REST API分别操作服务器、块存储和网络等资源,随着资源数的增长, API的调用也会增加且变得复杂,难以管理。使用云计算编排意味着将以往基于各独立资源的操作API的搭建方案切换成基于资源组设计的搭建方案,完全以ROA(面向资源的架构)的角度考虑如何设计和操作。
在云计算编排中,资源的集合称为栈(stack),以栈为单位来调用API操作资源集合。
使用API操作云计算编排
以OpenStack Heat为例,介绍与栈相关的基本操作。
- 创建栈: 调用create stack API,将事先定义了资源配置的YAML或JSON文件作为查询参数。创建成功后,会将预先定义的栈名和栈ID分配给栈。
- 删除栈:调用delete stack API,向指定栈ID的URI发送DELETE请求
- 更新栈:调用update stack API,向指定栈ID的URI发送PUT请求
模板的整体定义
编排模板起源于AWS CloudFormation,下面介绍使用JSON定义的AWS CloudFormation模板。
模板由多个元素(section)构成:
- 模板版本:模板也有版本的概念。
- 元数据(metadata):描述了关于模板本身的信息,如名称、版本、作者、描述等
- 映射(Mappings):以键值对的形式指定资源查找表,常用于多区域或多环境部署中,为不同地区或环境提供定制化的配置选项。
- 条件(Conditions):允许基于某些逻辑判断是否创建特定资源或应用特定配置。
- 资源(Resources):必选,模板的核心部分。列出了所有要创建的云资源及其属性,如虚拟机、存储卷、安全组、负载均衡器、数据库实例等。
- 参数(Parameters):定义了用户在部署时可以使用的变量,例如实例类型、区域、密钥对、网络设置等。
- 输出(Outputs):定义了在资源部署完成后可以公开访问的信息,比如公共IP地址、DNS名称、API端点等。
验证模板
我们需要通过一些方法从逻辑上验证的复杂模板,不同的云环境都有通过相应的验证API。注意,这种验证方法只能检查模板的语法是否正确,不能保证资源或属性在实际环境中的有效性。
模板的兼容性
理想情况下,模板的大部分元素在云环境中是通用的。但是由于资源和模板的兼容性,可能无法在某个云环境下直接使用另一个云环境定义的基础设施。为了实现跨云环境模板兼容性,可以考虑使用多云编排工具,或者编写脚本,将各个云的API和对应的客户端整合起来。
执行中的状态和故障排除
云计算编排是资源的集合,在创建过程中如果出现错误或耗时过多,就很难确认执行情况或排除故障。为此,云计算编排功能提供了用于查看各资源或事件状况的API。
根据现有资源自动创建模板
AWS CloudFormation提供给的CloudFormer功能可以将现有环境中的资源信息作为元数据收集起来,然后将其转换成模板。
模板的可视化
JSON和YAML格式的模板虽然使用了人类可阅读的声明式语法,但在复杂模板场景中可读性还是比较差。AWS CloudFormation Designer功能提供了一套可视化的工具,可以通过GUI的方式选定资源,从而简化维护过程。
2. 使用云计算编排的好处
环境搭建阶段
通过云计算编排可以进一步实现搭建过程的自动化,优化操作过程,降低误操作的可能性,提升效率
运维阶段
运维阶段的评价标准主要在于减少运维的工作量和预防误操作这两方面。
- 定义了资源间的依赖关系:资源会按照预定义的依赖关系创建
- 定义了自动扩容/缩容与自动修复:通过与监控服务器、监控API联动,即可将系统异常状态的报警作为触发器,执行资源的自动重新部署处理。
通过复用模版来复制环境
我们可以通过编排功能将定义环境的模板导出为JSON文件,然后以它为蓝本调用创建API复制出多个相同的环境。基于这种方式,我们可以:
- 实现不可变基础设施:搭建多个版本的线上环境来切换现有环境的模式
- 根据需要部署测试环境,开展AB实验
- 灾难恢复:指定不同区域作为参数,将模板用于灾难恢复
持续集成
云计算编排实现了基础设施即代码,这是DevOps中持续集成(CI)的基础。
CI的目的在于提升应用程序的发布效率,缩短发布的声明周期,从而提升服务交付的竞争力。借助云计算编排,我们可以将服务器、存储、网络等基础设施也指定为资源,并将其纳入CI的对象,带来额外的好处:
- 基础设施的变更与应用程序的发布同时进行:通过执行同时含有应用程序和基础设施的栈,可以在一体化的环境中进行测试,然后再以相同的栈将两者部署到线上环境,从而避免因应用程序和基础设施不匹配而产生的缺陷。实践中常用的方法是将应用程序的执行体存储至机器镜像或Git等代码仓库中,待资源启动时从中调用。
- 结合预估的业务量对资源进行合理的微调:基于编排具备自动扩容/缩容与自动修复等自动扩充的功能
- 应用云中的新功能:在云环境中,为了扩充功能,经常需要添加组件或资源。通过利用编排功能可以逐步应用这些新功能。包括基础设施的CI是一种主要用于Google、Amazon、Facebook等大型服务企业的高级更新手段。使用了编排功能的CI还衍生出一种新概念,即先局部复制环境再进行环境切换的“不可变基础设施”。
配置管理、逆向工程
- 配置管理:作为模板的JSON文件本身就相当于资源的集合,可以结合各种可视化工具呈现配置信息,进行配置管理
- 逆向工程:逆向工程一般是指根据现有环境或程序自动生成结构图或设计文档,以提升文档生成效率及标准化程度的过程。编排功能就包含了逆向工程的要素:使用编排功能部署环境使我们可以基于模板管理已固定下来的配置信息。
3. 编排的使用方法
从面向动作到面向资源的设计模式
使用编排功能之后,对云的操作管理从面向动作转换成面向资源,这是一种不同的设计模式
注意事项
从使用原则上,编排功能有三点注意事项:
- 不要使用资源的操作API来变更通过栈创建的资源:如果另外通过API来操作,可能导致栈内资源的实际状态与原始模板不一致,无法确定资源实际处于什么状态。这违反了幂等性和配置管理的思路
- 资源变更时要确认资源的状态:有些资源在变更后会被重新创建,在变更期间就会产生短暂的服务停止时间(downtime),这是需要考虑的。如果要避免这种情况,可以考虑使用不可变基础设施,即在另一个栈中重新创建一套环境,然后把现有系统切过去。
- 事先确认不支持编排功能的组件和资源:如果编排功能的模板不支持新增的组件、资源和属性,此时将无法将这些新增内容导入到编排功能中。导入新内容前需要先确认是否支持。
栈的分解
系统规模越大,资源的数量就越多,而且往往会出现资源发布频率或服务等级不同的系统群。这时候就要考虑栈的分解了。
栈的分解粒度可以使用多种模式,基本思路就是“依照系统设计上的通用元素与子系统划分的原则”。如果子系统都变成了栈,就会形成一种低耦合的架构,从而降低子系统之间的依赖,提升发布速度。由此就产生了划分子系统的倾向,而这正是微服务的概念。
比如以下几个栈就是在AWS CloudFormation中,从子系统分解出来的典型通用元素:
- 前端(DMZ)
- 数据存储区(DB Storage)
- 认证(IAM)
- 网络(VPC)
- 运维通用服务
把栈分解之后,有时还需要在栈之间传递数据:
- 先在发送栈中通过“输出”元素输出数据
- 然后在接收栈中通过“参数”元素获取数据
栈的嵌套
在AWS CloudFormation中,我们可以将多个栈嵌套起来,通过更新被包含的栈来使模板内的资源变更生效。在模板中指定类型为栈的资源即可实现栈的嵌套。
4. 编排的基本操作和API
OpenStack Heat由Heat API和Heat引擎两部分组成。
- Heat API既可以接收来自客户端的API请求,又可以向其他API发送请求并接收响应。Heat API就是用于整合资源的API。
- Heat引擎:通过Heat API接收到模板后,Heat引擎会将定义在模板中的状态视为资源集合加以管理。如果有需要,Heat引擎会向Heat API发送要求操作资源的请求。
Heat处理模板的基本流程:
- 接收模板:用户通过API或命令行工具提交Heat模板。
- 验证模板:对模板进行语法检查,验证参数是否正确设置,以及必需的字段是否存在,确保其符合预期的结构和规范。
- 解析模板:解析模板中的资源定义、参数、输出和其他元素。确定哪些资源需要创建,并理解它们之间的依赖关系。
- 初始化栈(Stack):创建一个新的栈对象来表示这次部署操作。栈包含了所有将要创建的资源及其状态信息。
- 准备环境:
- 如果模板中包含条件语句或其他逻辑控制结构,此时会根据提供的参数值评估这些表达式。
- 准备任何必要的前置条件,例如网络配置、安全组规则等。
- 资源创建:
- Heat引擎根据模板中的定义,依次创建每个资源。
- 对于具有依赖关系的资源,会按照正确的顺序进行创建,确保依赖项先于其所依赖的对象被创建。
- 使用OpenStack API调用相应的服务(如Nova、Neutron、Cinder等)来实际创建资源。
- 如果剩余资源不足以维持预定义的状态,则栈创建失败
- 监控资源状态
- 在资源创建过程中,Heat引擎持续监控每个资源的状态,直到它们全部成功部署或遇到错误。
- 如果某个资源创建失败,Heat引擎可以根据预设策略尝试重试或者回滚整个栈。
- 更新栈状态
- 当所有资源都成功创建后,更新栈的状态为“CREATE_COMPLETE”。
- 如果任何一个步骤失败,则更新栈的状态为“CREATE_FAILED”,并且可能启动回滚过程以清理部分创建的资源
- 输出结果
- 提供最终的输出信息,如公共IP地址、DNS名称、API端点等。
- 这些输出值可以通过API查询,也可以作为后续操作的一部分使用。
小结
随着基础设施即代码实现门槛的降低,云计算编排功能、面向资源、幂等性的概念也渐渐成为了一切的基础,我们能够通过模板定义基于REST API的面向资源的架构。