65.9K
CodeProject 正在变化。 阅读更多。
Home

基础设施即代码简介(第二部分):使用 Azure Resource Manager 模板进行 IaC 实践

2022 年 6 月 10 日

CPOL

7分钟阅读

viewsIcon

4346

如何使用 Bicep 语言和 Terraform HCL 语法创建模板。

本系列的第一篇文章 解释了基础设施即代码 (IaC) 的基本概念及其解决的问题。我们学习了如何区分供应商特定和多云 IaC 工具以及它们支持的模板语言。

本文介绍了 Azure ARM 模板,并解释了 JSON 和 Bicep 语法之间的区别。然后,我们将使用 Bicep 语法,通过创建几个虚拟机 (VM) 和一个 PostgreSQL 数据库来分步创建用于 Web 应用的资源配置模板。到本文结束时,我们将在 Azure 上创建一个完全配置的基础设施。

请按照本教程的步骤操作,让您的 Azure 部署正常运行,并访问此 GitHub 存储库 查看最终的 IaC 模板。

要求

要学习本教程,请确保您

  • 如果您还没有 Azure 订阅,请按照 说明 部分创建免费的 Azure 帐户。
  • 在您的计算机上安装 Azure CLI

ARM 模板、JSON 语法和 Bicep 语法

Azure 中最基础的 IaC 编程是使用 Azure 资源管理器 (ARM) 模板。ARM 模板是 JSON 文件,用于定义在 Azure 上配置资源的结构和配置。

ARM 模板使用声明式语法,这意味着它们描述了部署应如何进行,而不是使用一系列命令来执行部署操作。ARM 模板指定要部署的资源及其属性。

ARM 模板依赖于 JSON 文件,这些文件通常很难阅读。幸运的是,Microsoft 推出了另一种声明式语言 Bicep,它与基于 JSON 的 ARM 模板功能相同,但语法更简洁。鉴于其优势,Microsoft 建议您在为项目创建自动化 Azure 部署时使用 Bicep 而不是 JSON。虽然您不需要处理 JSON 文件,但部署会自动将 Bicep 文件转换为 ARM 模板。

Bicep 具有语法和类型检查功能,并支持代码重用。其模板语法支持强大的功能,包括数据类型、参数、变量、子资源、模块、输出、循环和条件。

Bicep 是对 JSON 模板的重大改进,因为它能跟上每一个升级或新增资源。Azure 资源管理器上的每个新资源发布都已在 Bicep 语法中可用。

创建用于配置 VM 和 PostgreSQL 数据库的 ARM 模板

在本教程中,我们将使用 Bicep 语言创建一个模板,该模板将为 Web 应用配置基础设施,方法是创建几个 VM 和一个 PostgreSQL 数据库,如下图所示

我们的目标是创建两种类型的资源:VM(多个)和 Azure PostgreSQL 数据库。但是,这些资源依赖于我们必须创建的辅助资源,如下面的图所示

构建 Bicep 文件

打开您的开发终端并运行 install 子命令来安装 Bicep CLI。

> az bicep install

然后,运行以下命令启动 login 会话。

> az login

接下来,定义您的活动 subscription

> az account set --subscription "YOUR-SUBSCRIPTION-NAME"

声明资源组

在 Azure 中,资源组 (RG) 是一个容器,有助于管理解决方案的相关资源。例如,假设您在 Azure 中有三个不同的应用程序。您可以将您的资源组织到三个不同的资源组中,这样在处理每个应用程序的资源时就不会感到困惑。

让我们创建一个包含以下代码的 main.bicep 文件。

targetScope = 'subscription'

resource rg 'Microsoft.Resources/resourceGroups@2021-01-01' = {
  name: 'bicep-rg'
  location: 'eastus'
}

module vmAndPostgreSQLModule 'VMAndPostgreSQL.bicep' = {
  name: 'VMAndPostgreSQL'
  scope: rg
}

上面的代码定义了目标范围,并声明了一个资源和一个模块。默认情况下,代码将 Bicep 文件范围限定为资源组。但由于我们使用 Bicep 创建资源组,因此我们将范围更改为定位我们的活动订阅。

接下来,我们使用 resource 关键字添加资源声明。我们为名为 bicep-rg 的资源组设置符号名称 rg,并将位置设置为 East US。就像命令式编程语言中的变量名一样,我们使用此符号名称在 Bicep 文件的其他部分稍后引用该资源。

上面的代码的最后一部分是模块声明。VMAndPostgreSQL.bicep 模块是从 main.Bicep 文件部署的 Bicep 文件。通过模块,我们可以将配置逻辑分解成更小的文件。简单的模块有利于提高可读性,并在不同的部署中重用。

接下来,让我们创建一个新的 VMAndPostgreSQL.bicep 文件,其中包含我们部署逻辑的其余部分。VMAndPostgreSQL.bicep 文件以以下代码开头。

@description('Number of Virtual Machines to Provision')
param virtualMachineCount int = 3

@description('Location for all resources.')
param location string = resourceGroup().location

上面的描述装饰器允许您解释如何使用参数。装饰器可以为您的声明添加元数据。例如,Azure 门户会向用户显示描述。

virtualMachineCount 参数定义了我们要配置多少 VM 实例,而 location 参数存储了模块中定义的资源组的位置。

声明网络安全组

网络安全组 (NSG) 会过滤进出虚拟网络中 Azure 资源的流量。网络安全组规则允许或拒绝我们创建的 VM 和数据库资源的入站或出站流量。规则将使我们能够指定源、目标、端口和协议。

resource networkSecurityGroup 'Microsoft.Network/networkSecurityGroups@2021-02-01' = {
  name: 'b1c3p-nsg'
  location: location
  properties: {
    securityRules: [
      {
        name: 'SSH'
        properties: {
          priority: 1001
          direction: 'Inbound'
          access: 'Allow'
          protocol: 'Tcp'
          sourcePortRange: '*'
          destinationPortRange: '22'
          sourceAddressPrefix: '*'
          destinationAddressPrefix: '*'
        }
      }
    ]
  }
}

声明虚拟网络

虚拟网络 (VNet) 使我们的 VM 和数据库服务器能够安全地相互通信,与 Internet 通信,以及与本地网络通信。要创建虚拟网络,请将此代码添加到您的 Bicep 模块。

resource virtualNetwork 'Microsoft.Network/virtualNetworks@2021-02-01' = {
  name: 'b1c3p-vn'
  location: location
  properties: {
    addressSpace: {
      addressPrefixes: [
        '10.0.0.0/16'
      ]
    }
    subnets: [
      {
        name: 'b1c3p-sn'
        properties: {
          addressPrefix: '10.0.0.0/24'
          networkSecurityGroup: {
            id: networkSecurityGroup.id
          }
        }
      }
    ]
  }
}

声明公共 IP

VM 依赖于网络接口,而网络接口依赖于公共 IP (PIP) 地址。要创建公共 IP 地址,请在您的 Bicep 模块中声明以下资源。

resource publicIPAddresses 'Microsoft.Network/publicIPAddresses@2021-02-01' = 
  [for i in range(0, virtualMachineCount): {
  name: 'b1c3p-ip-${i}'
  location: location
  properties: {
    publicIPAddressVersion: 'IPv4'
    publicIPAllocationMethod: 'Dynamic'
  }
}]

我们可以使用“for”语法迭代集合中的项来创建多个资源。在上面的代码中,我们使用整数索引来创建多个公共 IP 地址实例。range 函数创建一个从 0virtualMachineCount 参数的数组。

声明网络接口

网络接口将 VM 与底层软件网络连接起来。在这里,我们声明了一个具有动态公共 IP 地址的网络接口集合。

resource networkInterfaces 'Microsoft.Network/networkInterfaces@2020-08-01' = 
  [for i in range(0, virtualMachineCount): {
  name: 'b1c3p-nic-${i}'
  location: location
  properties: {
    ipConfigurations: [
      {
        name: 'ipconfig1'
        properties: {
          publicIPAddress: {
            id: publicIPAddresses[i].id
          }
          privateIPAllocationMethod: 'Dynamic'
          subnet: {
            id: resourceId('Microsoft.Network/virtualNetworks/subnets', 
                            virtualNetwork.name, 'b1c3p-sn')
          }
        }
      }
    ]
  }
}]

声明虚拟机

声明了辅助资源后,我们终于可以声明一个 VM 集合了。请务必确定 您的订阅可以使用哪些 VM 大小。幸运的是,有一个 Azure CLI 命令可以做到这一点。例如,由于我将 VM 托管在 East US 区域,我可以运行以下命令并选择一个 Restrictions 列值为 None 的 VM 大小。

> az vm list-skus --location eastus  --all --output table   
Name                       Zones    Restrictions
-------------------------  -------  -----------------------------------
Standard_B2s               1,2,3    None
Standard_B4ms              1,2,3    None
Standard_D1                3        ['NotAvailableForSubscription, ... 
Standard_D11               3        ['NotAvailableForSubscription, ...

现在,您可以定义具有适当 VM 大小的 VM 资源。在本例中,我选择了 Standard_B2s,因为它在 East US 区域的订阅中可用。请注意,您可能需要选择其他 VM 大小,以考虑其他 VM 属性,如存储配置文件、操作系统和网络配置文件。

resource virtualMachines 'Microsoft.Compute/virtualMachines@2021-03-01' = 
    [for i in range(0, virtualMachineCount): {
    name: 'b1c3p-vm-${i}'
    location: location
    properties:{
      hardwareProfile: {
        vmSize:'Standard_B2s'
      }
      storageProfile: {
        osDisk: {
          createOption: 'FromImage'
          managedDisk: {
            storageAccountType: 'Standard_LRS'
          }
        }
        imageReference: {
          publisher: 'Canonical'
          offer: 'UbuntuServer'
          sku: '18.04-LTS'
          version: 'latest'
        }       
      }
      osProfile: {
        computerName: 'b1c3p-vm-${i}'
        adminUsername: 'azureuser'
        adminPassword: 'Adm1nP@55w0rd'
      }
      networkProfile: {
        networkInterfaces: [
          {
            id: networkInterfaces[i].id
          }
        ]
      }
    }
  }]

声明 Azure PostgreSQL 数据库

Web 应用程序使用关系数据库是很常见的。因此,我们还将在本教程的配置中创建一个。

我们声明一个 Azure PostgreSQL 数据库资源,它是一个关系型数据库即服务,基于 PostgreSQL 数据库引擎。我们定义了 SKU 标识符、属性以及数据库运行所在的虚拟网络。

resource server 'Microsoft.DBforPostgreSQL/servers@2017-12-01' = {
  name: 'b1c3ppostgresql'
  location: location
  sku: {
    name: 'GP_Gen5_2'
    tier: 'GeneralPurpose'
    capacity: 2
    size: '51200'
    family: 'Gen5'
  }
  properties: {
    createMode: 'Default'
    version: '11'
    administratorLogin: 'MyAdministrator'
    administratorLoginPassword: 'Adm1nP@55w0rd'
    storageProfile: {
      storageMB: 51200
      backupRetentionDays: 7
      geoRedundantBackup: 'Disabled'
    }
  }

  resource virtualNetworkRule 'virtualNetworkRules@2017-12-01' = {
    name: 'AllowSubnet'
    properties: {
      virtualNetworkSubnetId: virtualNetwork.properties.subnets[0].id
      ignoreMissingVnetServiceEndpoint: true
    }
  }
}

使用 Bicep 文件部署

要使用 main.bicep 文件在订阅范围内创建部署,请运行以下命令。

az deployment sub create --template-file main.bicep --location eastus

最终配置的基础设施

现在,让我们看看我们在 Azure 上完全配置的基础设施是什么样的。

在 Azure 门户中,打开 bicep-rg 资源并单击 **资源可视化工具** 菜单。资源可视化工具允许我们查看和理解使用 Bicep 模板部署的组件。

转到 **Azure 门户** 主页,然后单击 **所有资源** 以获取已配置资源的更详细视图。

后续步骤

在本文中,我们介绍了 Azure ARM 模板,并解释了 JSON 和 Bicep 语法之间的区别。然后,我们使用 Bicep 语法创建了一个模板,该模板通过创建几个 VM 资源及其依赖项以及一个 PostgreSQL 数据库来配置 Web 应用的基础设施。我们看到了如何声明变量,将模板分解为模块,以及如何使用 Bicep 语言迭代数字范围来配置多个 VM。最后,我们在 Azure 上实现了一个完全配置的基础设施。

本系列的第三篇也是最后一篇文章 解释了如何创建用于使用 Terraform 语言配置资源的声明,并将其过程与使用 ARM 模板的过程进行比较。

要了解更多关于如何使用 Bicep 定义 Azure 网络资源的信息,请参阅资源使用 Bicep 创建虚拟网络资源

© . All rights reserved.