练习 - 预配 Azure 资源

已完成

在本练习中,你将配置自动化工作流以预配 Terraform 资源。

访问示例应用程序

在本练习中,你将通过一个模板来创建 GitHub 存储库,该模板包含预配 Terraform 的所有代码。

  1. 在 GitHub 上,转到存储库的主页:

    https://github.com/MicrosoftDocs/mslearn-java-petclinic-simplified
    
  2. 在文件列表上方,选择“使用此模板”,然后选择“创建新存储库”。

    Screenshot of the

  3. 在“存储库名称”框中,为你的存储库输入独一无二的名称。 请务必遵循 GitHub 存储库的命名约定。

  4. 确保选中“专用”选项,然后选择“创建存储库”。

    Screenshot of the

Workflow

在你刚才创建的存储库的项目目录中,你会看到一个名为 terraform 的目录,其中有一个名为 main.tf 的文件。

下面,让我们看看几个可以用来定义模块配置的部分:

  • 提供程序:Terraform 配置文件从提供程序的规范开始。 使用 Azure 时,你在提供程序块中指定 Azure 提供程序 (azurerm)。
  • Terraform:正在使用的 Terraform 版本。
  • 数据:从现有服务中获取数据。
  • 局部变量:使用函数和表达式生成新变量。
  • 资源:描述资源和依赖项。
  • 模块:可重用性和复杂性抽象。

若要预配应用程序和数据库,只需包括“提供程序”和“资源”部分即可。

接下来,打开 main.tf 文件,并查看大纲和注释:

provider "azurerm" {
  version = "=2.20.0"
  features {}
}

# Creates a resource group
resource "azurerm_resource_group" "main" {
  name     = var.resource_group
  location = var.location

  tags = {
    "Terraform" = "true"
  }
}

resource "random_password" "password" {
  length = 32
  special = true
  override_special = "_%@"
}

# Creates a MySQL server
resource "azurerm_mysql_server" "main" {
  name                              = "${azurerm_resource_group.main.name}-mysql-server"
  location                          = azurerm_resource_group.main.location
  resource_group_name               = azurerm_resource_group.main.name

  administrator_login               = "petclinic"
  administrator_login_password      = random_password.password.result

  sku_name   = "B_Gen5_1"
  storage_mb = 5120
  version    = "5.7"
  auto_grow_enabled                 = true
  backup_retention_days             = 7
  geo_redundant_backup_enabled      = false
  infrastructure_encryption_enabled = false
  public_network_access_enabled     = true
  ssl_enforcement_enabled           = true
  ssl_minimal_tls_version_enforced  = "TLS1_2"
}

# The database that your application will use
resource "azurerm_mysql_database" "main" {
  name                = "${azurerm_resource_group.main.name}_mysql_db"
  resource_group_name = azurerm_resource_group.main.name
  server_name         = azurerm_mysql_server.main.name
  charset             = "utf8"
  collation           = "utf8_unicode_ci"
}

# Enables the 'Allow access to Azure services' check box
resource "azurerm_mysql_firewall_rule" "main" {
  name                = "${azurerm_resource_group.main.name}-mysql-firewall"
  resource_group_name = azurerm_resource_group.main.name
  server_name         = azurerm_mysql_server.main.name
  start_ip_address    = "0.0.0.0"
  end_ip_address      = "0.0.0.0"
}

# Creates the plan that the service uses
resource "azurerm_app_service_plan" "main" {
  name                = "${var.application_name}-plan"
  location            = azurerm_resource_group.main.location
  resource_group_name = azurerm_resource_group.main.name
  kind                = "Linux"
  reserved            = true

  sku {
    tier = "PremiumV2"
    size = "P1v2"
  }
}

# Creates the service definition
resource "azurerm_app_service" "main" {
  name                = var.application_name
  location            = azurerm_resource_group.main.location
  resource_group_name = azurerm_resource_group.main.name
  app_service_plan_id = azurerm_app_service_plan.main.id
  https_only          = true

  site_config {
    always_on        = true
    linux_fx_version = "JAVA|8-jre8"
  }

  # Contains application-specific environment variables
  app_settings = {
    "WEBSITES_ENABLE_APP_SERVICE_STORAGE" = "false"

    "SPRING_PROFILES_ACTIVE"     = "mysql"
    "SPRING_DATASOURCE_URL"      = "jdbc:mysql://${azurerm_mysql_server.main.fqdn}:3306/${azurerm_mysql_database.main.name}?useUnicode=true&characterEncoding=utf8&useSSL=true&useLegacyDatetimeCode=false&serverTimezone=UTC"
    "SPRING_DATASOURCE_USERNAME" = "${azurerm_mysql_server.main.administrator_login}@${azurerm_mysql_server.main.name}"
    "SPRING_DATASOURCE_PASSWORD" = azurerm_mysql_server.main.administrator_login_password
  }
}

通过 Terraform 设置 GitHub Actions 工作流

让我们向你的 GitHub 工作流提供对你的 Azure 帐户的访问权限。

在 Azure CLI 中,运行以下命令来创建一个服务主体:

重要

将 <yourServicePrincipalName> 替换为要使用的服务主体名称。

az ad sp create-for-rbac --name "<yourServicePrincipalName>" --role contributor --scopes /subscriptions/<subscriptionId> --sdk-auth

前面的命令会返回以下 JSON。 复制它供下一步使用:

{
  "clientId": "XXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXXX",
  "clientSecret": "XXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
  "subscriptionId": "XXXXXXXXX-XXXXX-XXXX-XXXX-XXXXXXXXXXXXX",
  "tenantId": "XXXXXXXX-XXXXX-XXXX-XXXX-XXXXXXXXXXX",
  ...
}

GitHub 机密

GitHub 存储库有一项称为“机密”的功能,你可以使用该功能存储 Terraform 用来向 Azure 进行身份验证的敏感信息。

在前面的步骤中创建所需的 ID 和机密后,本单元中的下一步是将它们添加到 GitHub 项目中的“机密”存储。

对于本练习,你需要存储以下机密:

  • AZURE_CLIENT_ID
  • AZURE_CLIENT_SECRET
  • AZURE_SUBSCRIPTION_ID
  • AZURE_TENANT_ID

若要存储机密,请转到你的已分支的 GitHub 存储库,选择“设置”,选择“机密和变量”,然后在左侧窗格中选择“操作”。

使用创建服务主体时返回的值创建四个机密。

请确保在不带引号 (" ") 的情况下存储机密,如以下屏幕截图所示:

Screenshot showing stored secrets on the Secrets pane under GitHub Settings.

工作流文件

你的项目目录中有一个名为 .github/workflows 的目录,其中有一个名为 main.yml 的文件。

main.yml 文件是一个 GitHub 工作流。 它使用你刚才配置的机密将应用程序部署到 Azure 订阅。

在 main.yml 工作流文件中,你将发现以下内容:

name: TERRAFORM

on:
  push:
    branches: [ main ]
    paths:
    - 'terraform/**'
  pull_request:
    branches: [ main ]
    paths:
    - 'terraform/**'

  workflow_dispatch:
jobs:
  terraform:
    runs-on: ubuntu-latest

    env:
      ARM_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
      ARM_CLIENT_SECRET: ${{secrets.AZURE_CLIENT_SECRET}}
      ARM_SUBSCRIPTION_ID: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
      ARM_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}

    defaults:
      run:
        working-directory: ./terraform
    steps:
      - uses: actions/checkout@v2

      - name: Setup Terraform
        uses: hashicorp/setup-terraform@v1

      - name: Terraform Init
        run: terraform init

      - name: Terraform Plan
        run: terraform plan

      - name: Terraform Apply
        run: terraform apply -auto-approve

此工作流执行以下操作:

  • 检查配置格式是否正确。
  • 为每个拉取请求生成一个计划。
  • 在你更新 terraform 目录中的文件时触发配置。

注意

通过转到“操作”,然后选择 Terraform 工作流和“重新运行现有作业”,也可触发 GitHub Actions 工作流。

触发工作流

接下来,在存储库中通过以下操作来触发 GitHub 操作:

  1. 在内置的 GitHub 文本编辑器或你选择的编辑器中,按照以下说明编辑 terraform/variables.tf:

    a. 将 "CHANGE_ME_RESOURCE_GROUP" 更改为你所需的资源组名称。
    b. 将 "CHANGE_ME_APP_NAME" 更改为你所需的应用程序名称。 确保应用程序名称独一无二。

    variable "resource_group" {
      description = "The resource group"
      default = "CHANGE_ME_RESOURCE_GROUP"
    }
    
    variable "application_name" {
      description = "The Spring Boot application name"
      default     = "CHANGE_ME_APP_NAME"
    }
    
    variable "location" {
      description = "The Azure location where all resources in this example should be created"
      default     = "westeurope"
    }
    
  2. 提交更改。

验证 GitHub Actions 生成

  1. 在你的存储库中选择“操作”,然后在左窗格中选择 TERRAFORM 工作流。

  2. 在步骤列表中,验证是否已触发“Terraform 初始化”、“Terraform 计划”和“Terraform 验证”。

    Screenshot displaying the results of the Terraform workflow run.

  3. 在步骤列表中,展开“Terraform 应用”,并验证:

  • Terraform 是否已创建资源并显示 Azure 实例 URL。

  • 你的 Azure 应用实例是否公开可用。

    Screenshot showing that the Azure app instance is publicly available.

后续步骤

在下一个练习中,你将使用 GitHub Actions 部署 Spring Boot 示例应用程序。

设置应用程序名称和 Azure 资源组

在 GitHub 存储库中,通过执行以下操作来编辑 Azure 资源名称:

  1. 在内置的 GitHub 文本编辑器或你选择的编辑器中,按照以下说明编辑 terraform/variables.tf:

    a. 将 "<CHANGE_ME_RESOURCE_GROUP>" 更改为你所需的资源组名称。
    b. 将 "<CHANGE_ME_APP_NAME>" 更改为你所需的应用程序名称。 确保应用程序名称独一无二。

    variable "resource_group" {
      description = "The resource group"
      default = "<CHANGE_ME_RESOURCE_GROUP>"
    }
    
    variable "application_name" {
      description = "The Spring Boot application name"
      default     = "CHANGE_ME_APP_NAME"
    }
    
    variable "location" {
      description = "The Azure location where all resources in this example should be created"
      default     = "westeurope"
    }
    
  2. 提交更改

创建 Azure 管道以预配 Terraform 资源

在我们的 Azure DevOps 项目中,我们将创建两个单独的管道用于预配和生成并部署。 预配管道创建将在稍后通过“生成并部署”管道发布的 Azure 资源。

让我们创建第一个预配管道:

  1. 选择你的组织,然后选择“新建项目”。

  2. 指定下列参数。

    参数 说明
    项目名称 必需
    说明 可选
    能见度 选择“专用”
    高级
    版本控制 选择“GIT”
    工作项进程 选择“基本”
  3. 选择“创建项目”,创建项目并打开欢迎页。

Screenshot displaying the new Azure Project form.

设置 Azure 管道服务连接

让我们为 Azure 管道授予对 Azure 帐户的访问权限。

  1. 在 Azure DevOps 中,从项目设置页打开“Service connections”页

  2. 依次选择“创建服务连接”、“Azure 资源管理器”和“下一步”。

  3. 依次选择“服务主体(自动)”和“下一步”。

  4. 指定下列参数。

    参数 说明
    范围级别 选择 Azure 订阅
    订阅 选择你的现有 Azure 订阅
    资源组 留空以允许用户访问订阅中定义的所有资源
    连接名称 必需。 在任务属性中引用此服务连接时将使用的名称。 此名称不是 Azure 订阅的名称。
  5. 选择保存创建连接。

创建预配管道

重要

此模块的先决条件要求安装 Terraform Azure Pipelines 扩展。 如果尚未安装,则管道将无法运行。

设置项目并连接到 Azure 后,需要创建一个 Azure 管道来预配 terraform 资源。

在 Azure DevOps 中,转到你的项目,在左侧菜单中选择“管道”,然后选择“创建管道”。

  1. 在“连接”选项卡上,选择“GitHub”(YAML 文件)。
  2. 如果系统提示你授权 GitHub 访问权限,请输入 GitHub 凭据并使用请求的权限批准对 Azure Pipelines 的访问权限。
  3. 在“选择”选项卡上,选择包含模板的 GitHub 存储库。
  4. 在“清单”选项卡上,选择“配置管道”。
  5. 在“配置”选项卡上,选择以使用“现有的 Azure Pipelines YAML 文件”。
  6. 在路径中,选择“/azuredevops/provision.yml”
  7. 选择“继续”以转到“查看”选项卡并查看你的管道。

Screenshot displaying the new Azure Pipeline form.

在“Review your pipeline YAML”屏幕上,让我们检查要用于创建管道的 YAML 文件。

name: Provision Resources

trigger: none

pool:
  vmImage: 'ubuntu-latest'

steps:

# Initialize the Terraform environment and bind to your Service Connection
- task: TerraformTaskV1@0
  inputs:
    provider: 'azurerm'
    command: 'init'
    workingDirectory: $(Build.Repository.LocalPath)/terraform
    backendServiceArm: $(serviceConnection)
    backendAzureRmResourceGroupName: $(serviceConnection)
    backendAzureRmStorageAccountName: $(serviceConnection)
    backendAzureRmContainerName: 'tfstate'
    backendAzureRmKey: 'tf/terraform.tfstate'

# Apply the Terraform config and deploy to Azure
- task: TerraformTaskV1@0
  inputs:
    provider: 'azurerm'
    command: 'apply'
    workingDirectory: $(Build.Repository.LocalPath)/terraform
    backendAzureRmContainerName: 'tfstate'
    backendAzureRmKey: 'tf/terraform.tfstate'
    environmentServiceNameAzureRM: $(serviceConnection)

让我们来看看我们在配置中使用的一些字段:

  • serviceConnection:你以前设置的 Azure 管道服务连接
  • command:Terraform 工作流命令 - init 或 apply
  • backendAzure:团队环境中存储共享状态所需的必填字段。\

在保存和运行管道之前,需要添加将绑定到服务连接的变量:

  1. 选择“变量”(右上角)并添加一个名为“serviceConnection”的变量,其值作为服务连接的名称。
  2. 选择“确定”(右下角)保存变量。

Screenshot displaying the new Service Principal variable.

最后,选择“run”(右上角)保存并运行管道

监视管道运行

在“Jobs”下,跟踪生成过程的每个步骤。

当管道运行时,观察第一个 Terraform init 阶段和第二个 apply 阶段从蓝色(正在运行)变为绿色(已完成)。 你可以选择各个阶段来观察管道的运行情况。

Screenshot displaying the new Azure Pipeline run.

提示

查看电子邮件。 你可能已收到包含运行结果的生成通知。 你可以使用这些通知来了解每个生成是通过还是失败。

后续步骤

在下一练习中,你将使用 Azure Pipelines 来生成和部署示例 Spring Boot 应用程序。