基础结构即代码

小窍门

此内容摘自电子书《为 Azure 架构云原生 .NET 应用程序》,可在 .NET 文档 查阅或下载免费的 PDF 离线阅读。

Azure 平台的云原生 .NET 应用电子书封面缩略图。

云原生系统采用微服务、容器和现代系统设计,以实现速度和敏捷性。 它们提供自动化生成和发布阶段,以确保一致和质量的代码。 但是,这只是故事的一部分。 如何预配运行这些系统的云环境?

现代云原生应用程序采用广泛接受的做法:基础设施即代码IaC。 使用 IaC,可以自动执行平台预配。 你基本上将软件工程实践(如测试和版本控制)应用于 DevOps 实践。 基础结构和部署是自动化、一致且可重复的。 正如持续交付自动化了手动部署的传统模型一样,基础结构即代码(IaC)正在不断改进应用程序环境的管理方式。

使用 Azure 资源管理器(ARM)、Terraform 和 Azure 命令行接口(CLI)等工具可以声明方式编写所需的云基础结构的脚本。

Azure 资源管理器模板

ARM 是 Azure Resource Manager(Azure 资源管理器)的缩写。 它是一个 API 预配引擎,内置于 Azure 中,并作为 API 服务公开。 ARM 使你能够在单个协调的作中部署、更新、删除和管理 Azure 资源组中包含的资源。 为引擎提供基于 JSON 的模板,该模板指定所需的资源及其配置。 ARM 按照遵循依赖项的正确顺序自动协调部署。 引擎可确保幂等性。 如果已存在具有相同配置的所需资源,则会忽略预配。

Azure 资源管理器模板是一种基于 JSON 的语言,用于在 Azure 中定义各种资源。 基本架构类似于图 10-14。

{
  "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
  "contentVersion": "",
  "apiProfile": "",
  "parameters": {  },
  "variables": {  },
  "functions": [  ],
  "resources": [  ],
  "outputs": {  }
}

图 10-14 - 资源管理器模板的架构

在此模板中,可以定义资源部分中的存储容器,如下所示:

"resources": [
    {
      "type": "Microsoft.Storage/storageAccounts",
      "name": "[variables('storageAccountName')]",
      "___location": "[parameters('___location')]",
      "apiVersion": "2018-07-01",
      "sku": {
        "name": "[parameters('storageAccountType')]"
      },
      "kind": "StorageV2",
      "properties": {}
    }
  ],

图 10-15 - 资源管理器模板中定义的存储帐户示例

可以使用动态环境和配置信息参数化 ARM 模板。 这样,就可以重复使用它来定义不同的环境,例如开发、QA 或生产环境。 通常,模板会在单个 Azure 资源组中创建所有资源。 如果需要,可以在单个资源管理器模板中定义多个资源组。 可以通过删除资源组本身来删除环境中的所有资源。 还可以在资源组级别运行成本分析,从而快速计算每个环境的成本。

GitHub 上的 Azure 快速入门模板 项目中提供了许多 ARM 模板示例。 它们可以帮助加速创建新模板或修改现有模板。

可以通过多种方式运行资源管理器模板。 也许最简单的方法是将它们粘贴到 Azure 门户中。 对于实验性部署,此方法可能很快。 还可以在 Azure DevOps 中作为生成或发布过程的一部分运行它们。 有一些任务将利用连接到 Azure 来运行模板。 对资源管理器模板的更改会以增量方式应用,这意味着添加新资源只需将其添加到模板即可。 该工具将协调当前资源与模板中定义的资源之间的差异。 然后,将创建或更改资源,使其与模板中定义的资源匹配。

Terraform

云原生应用程序通常构造为 cloud agnostic。 因此,这意味着应用程序不会紧密耦合到特定的云供应商,并且可以部署到任何公有云。

Terraform 是一种商业模板化工具,可以跨所有主要云玩家预配云原生应用程序:Azure、Google Cloud Platform、AWS 和 AliCloud。 它不使用 JSON 作为模板定义语言,而是使用稍微更简洁的 HCL(Hashicorp 配置语言)。

图 10-16 显示了与上一个资源管理器模板(图 10-15)相同的 Terraform 文件示例:

provider "azurerm" {
  version = "=1.28.0"
}

resource "azurerm_resource_group" "testrg" {
  name     = "production"
  ___location = "West US"
}

resource "azurerm_storage_account" "testsa" {
  name                     = "${var.storageAccountName}"
  resource_group_name      = "${azurerm_resource_group.testrg.name}"
  ___location                 = "${var.region}"
  account_tier             = "${var.tier}"
  account_replication_type = "${var.replicationType}"

}

图 10-16 - 资源管理器模板的示例

Terraform 还为问题模板提供直观的错误消息。 还有一个方便的验证任务,可以在生成阶段使用,以提前捕获模板错误。

与资源管理器模板一样,命令行工具可用于部署 Terraform 模板。 Azure Pipelines 中还存在社区创建的任务,这些任务可以验证和应用 Terraform 模板。

有时,Terraform 和 ARM 模板会输出有意义的值,例如新创建的数据库的连接字符串。 此信息可以在生成管道中捕获,并在后续任务中使用。

Azure CLI 脚本和任务

最后,可以利用 Azure CLI 以声明方式编写云基础结构的脚本。 可以创建、找到和共享 Azure CLI 脚本,以预配和配置几乎所有 Azure 资源。 CLI 使用起来非常简单,学习曲线也很平缓。 脚本在 PowerShell 或 Bash 中执行。 它们也易于调试,尤其是在与 ARM 模板相比时。

需要拆解和重新部署基础结构时,Azure CLI 脚本可以正常工作。 更新现有环境可能很棘手。 许多 CLI 命令不是幂等的。 这意味着它们每次运行时都会重新创建资源,即使资源已存在也是如此。 始终可以添加代码,用于在创建资源之前检查每个资源是否存在。 但是,这样做后,脚本可能会膨胀,难以管理。

这些脚本还可以嵌入到 Azure DevOps 的流水线中 Azure CLI tasks。 执行管道会调用脚本。

图 10-17 显示了一个 YAML 代码片段,其中列出了 Azure CLI 的版本和订阅的详细信息。 请注意 Azure CLI 命令如何包含在内联脚本中。

- task: AzureCLI@2
  displayName: Azure CLI
  inputs:
    azureSubscription: <Name of the Azure Resource Manager service connection>
    scriptType: ps
    scriptLocation: inlineScript
    inlineScript: |
      az --version
      az account show

图 10-17 - Azure CLI 脚本

在本文中, 什么是基础结构即代码,作者 Sam Guckenheimer 介绍了如何“实现 IaC 的 Teams 可以快速大规模地提供稳定的环境。 团队通过代码来表示环境的期望状态,从而避免手动配置并强制实施一致性。 使用 IaC 的基础结构部署是可重复的,并防止因配置偏移或缺少依赖项而导致的运行时问题。 DevOps 团队可与一组统一的做法和工具协作,以快速、可靠、大规模地交付应用程序和其支持基础结构。