背景

我们对于云上资源的部署,部分工作是通过控制台选择特定资源规格参数进行创建,还有一部分是使用 CLI或者 SDK 直接调用接口封装成定制化的平台来创建资源。但是随着企业数字化转型的加速,公司业务上云规模的持续增长和云资源的不断更新,同时又为了满足跨云基建的快速交付和容灾能力建设需求。我们也不可避免遇到行业内频繁提出的以下问题:

  • 效率: 对于创建单个种类的资源来说控制台创建或者定制化平台创建的方式很简单,但在做整个云上基建层基础设施交付时,由于资源之间有种种依赖关系,这时候会发现控制台方式需要在不同的产品之间来回切换,而定制化平台的方式要时刻关注创建进度及依赖资源的信息循环等待结果,才能再去创建下一个依赖资源,整个过程耗时耗力。
  • 复制: 针对不同的环境(如测试、预发和生产)、不同地域(如杭州、上海)需要创建完全相同的基础设施,控制台或者定制化平台的方式又需要重复之前的步骤一步步地进行操作和等待,无法复制。
  • 多云: 往往我们需要在多个云上部署资源,以实现跨云的容灾备份和资源优化等目标,因此控制台的切换和定制化平台也变得更加复杂。
  • 标准: 手动创建还有一个非常大的问题,那就是非常容易出现配置是否符合相同的标准,保证两套环境中各个资源配置完全是同一个标准,也会变得更难以统一。

总之在业务多云环境成为常态的当下,为了能更好地享受云计算带来的弹性扩展、按需付费、高可用性等优势,实现跨云跨地域基础设施的一键交付,加强云上容灾能力,寻求更为合理的基础设施交付手段成为我们迫切需要解决的问题。

相关概念

IaC

  • 基础设施即代码(Infrastructure as Code 或称IaC):通过代码而非手动流程来管理和置备基础设施的方法。

Terraform

  • 基础设施即代码 (IaC) 工具: Terraform是一个开源的基础设施即代码工具,允许用户使用声明性配置语言定义和管理基础设施资源。

Terraform的优势

  • 跨云兼容性:Terraform支持多种云服务商(如AWS、Azure、GCP、阿里云、华为云、腾讯云等,是目前对阿里云、腾讯云、华为云等支持度最高的IaC工具)以及本地数据中心。
  • 版本控制与审计:通过将基础设施配置保存在代码库中,Terraform实现了配置的版本控制和审计追踪,提升了安全性和合规性。
  • 自动化与可重复性:通过编写可复用的Terraform模板,可以快速、准确地部署和更新云资源,提高部署效率和减少人为错误。
  • 声明式配置:Terraform采用声明式配置方式,只需描述希望达到的状态,Terraform将自动完成资源的创建、更新和销毁,简化配置过程。

架构

Git模版管理: 开发者将模版代码推送到代码仓库,形成tag或者commit版本控制。

BPM审批流: 完成对于审批后,由bpm调用回调接口触发资源交付任务。

Terraform封装: 交付异步任务触发调用Terraform,执行基础设施的创建或更新操作。

消息通知: 企微机器人通知。

模块组成

基础设施交付主要分为5个部分组成:

  • 项目: 资源支撑的业务场景集合名称(具备名称、描述、标签、维护人、时间等基本属性)。
  • 分组: 针对项目下设的资源分组集合,主要是为了区分环境和用途功能(具备id,名称,描述,编排任务,资源模版,时间等基本属性)。
  • 模版: 分组资源集合的分类模版,包含基础资源或者是抽象资源(例如服务器集群),设定特定的资源规格,具备可复制性和高移植性。
  • 任务: 选定模版和任务形成的唯一对应关系进行编排执行的产物。
  • 参数: 在形成任务前,针对模版进行填充的参数数据集合。

实践

1. 技术选型 在平台建设的调研期间,我们也考虑使用社区目前普遍推荐的与gitlab结合来触发terraform的编排任务,并且在demo中也是以这种方式作为测试基础。但是因为以下的几点考虑,我们并没有结合gitlab或者Jenkins,而是自建了一个更加轻量化和定制化的任务执行流水线。

  • 整个交付的过程能在一个平台上去追溯,不期望从自己的平台跳转gitlab去做查看和操作。
  • 如果使用gitlab的流水线,我们不仅要开发模版代码,同时还需要提供定制的gitlab yml或者jenkinsfile。
  • 对接gitlab仍然需要在平台内额外对接gitlab api,并没有工作量上的缩减,另外关联系统更多,稳定性难以保障。
  • 使用gitlab的流水线还需要额外提供runner,exec runner或者docker runner的各种稳定性难以保证,且问题排障比较困难。

2. 模版存储 实际开发中,我们并没有完全舍弃gitlab,仍然还是将terraform模版代码文件存放在gitlab中,让gitlab帮我们管理模版版本的追踪进行模版存储。在模版存储上,我们使用master分支作为可使用模版文件分支,而其他的分支作为模版开发和测试分支,仓库中以云商code(如aliyun、huaweicloud等)作为云商模版的集合,当我们在平台选用模版文件时,结合gitlab api来调用master分支下aliyun的子文件夹名称来进行模版的选择。

实际代码仓库代码文件结构如下:

在平台上我们可以动态选择到需要的模版文件:

3. 执行流程 资源编排是作为某个业务项目下具体环境分组的资源交付任务执行的集合,也是我们对terraform进行封装集成的关键,在执行一次资源编排任务之前,我们需要先在项目环境分组下创建一个资源编排。


在资源编排创建之后,根据terraform采用声明式配置方式,我们针对资源编排,根据实际业务的需要,进行参数的填充和更新。下面是一个新建虚拟交换机的场景tf模版代码,其中availability_zone作为交换机的可用区参数。

// variable声明的是参数类型声明// availability_zone是参数名称variable "availability_zone" {  description = "虚拟交换机的可用区参数."  type        = list(string)  default     = []}
// resource描述的是我们想要得到的基础资源声明// alicloud_vswitch是具体的资源类型// vswitches是资源的描述// zone_id是指创建的虚拟交换机所在的可用区// var.availability_zone 我们可以通过这种方式使用上面定义好的参数`availability_zone`resource "alicloud_vswitch" "vswitches" {  for_each     = toset([for idx in range(length(var.vswitch_cidrs)) : tostring(idx)])  vpc_id       = alicloud_vpc.vpc.id  cidr_block   = element(var.vswitch_cidrs, tonumber(each.key))  zone_id      = var.availability_zone[tonumber(each.key) % length(var.availability_zone)]  vswitch_name = format("%s%02d", var.vswitch_name_prefix, tonumber(each.key) + 1)  tags         = var.tags}

在平台上可以修改任务的availability_zone参数来控制最终交换机所处的可用区信息。

最终平台会将参数组合形成一个标准json。

{   "availability_zone": [      "cn-hongkong-b",      "cn-hongkong-c",      "cn-hongkong-d"   ]}

在命令组合的类方法里,组合好的标准参数json会被拼接到terraform的执行命令中,供后续任务触发后进行调用。


class TerraformCommandManager(object):    def __init__(self, terraform_bin=None):        self.terraform_bin = terraform_bin or '/usr/local/bin/terraform'
    def init(self, *args):        return [self.terraform_bin, 'init', '-no-color', '-reconfigure'] + list(args)
    def plan(self, *args):        return [self.terraform_bin, 'plan', '-no-color'] + list(args)
    def apply(self, *args):        return [self.terraform_bin, 'apply', '-auto-approve', '-no-color'] + list(args)

资源编排任务的流程如下:

4. 页面展示

4.1 任务详情页面

展示资源编排任务的各节点执行详情及耗时,并且展示本次任务变更涉及的资源数量。

4.2资源详情页面

当任务执行成功后,点击资源管理,跳转到资源详情页面,可查看本次变更在云上产生的资源详情列表,并展示了各类型数量,方便校验云上资源的数量。

注意事项

安全配置: 使用合适的方法来管理密码和密钥保护敏感信息。测试和验证: 所有的资源都会以最终的参数作为目标,在正式部署之前,要进行充分的测试和验证,确保参数的准确性,同时模版在正式使用之前也要做相应的测试和验证。

结语

当我们对云上资源制定了较为完整的标准,结合terraform的编排能力,可以轻松做到在10几分钟内,跨多个云和可用区部署完全相同的海量基础设施服务,会对我们的云上容灾能力建设有很大帮助。


参考: https://www.redhat.com/zh/topics/automation/what-is-infrastructure-as-code-iac https://developer.hashicorp.com/terraform?product_intent=terraform https://cloud.google.com/docs/terraform/best-practices-for-terraformhttps://juejin.cn/post/7115993352209694751

作者介绍

Nanliao,现任后端研发专家

青州,现任前端研发专家