演習 - Azure リソースをプロビジョニングする

完了

この演習では、Terraform リソースをプロビジョニングする自動ワークフローを構成します。

サンプル アプリケーションにアクセスする

この演習では、テンプレートから GitHub リポジトリを作成します。そこには Terraform のプロビジョニング用のすべてのコードが含まれます。

  1. GitHub で、リポジトリのメイン ページに移動します。

    https://github.com/MicrosoftDocs/mslearn-java-petclinic-simplified
    
  2. ファイル リストの上にある [このテンプレートを使用する] を選んでから、[新しいリポジトリの作成] を選択します。

    mslearn-java-petclinic-simplified のメイン ページにある [Use this template]\(このテンプレートを使用する\) ボタンのスクリーンショット。

  3. [Repository name](リポジトリ名) ボックスに、レポジトリの一意の名前を入力します。 GitHub リポジトリの名前付け規則に従ってください。

  4. [プライベート] オプションが選択されていることを確かめてから、[リポジトリを作成する] を選択します。

    [Create a new repository from ...]\(... から新しいリポジトリを作成\) ページの [Create repository from template]\(テンプレートからリポジトリを作成\) ボタンのスクリーンショット。

ワークフロー

作成したリポジトリのプロジェクト ディレクトリ内に terraform という名前のディレクトリがあり、その中に main.tf という名前のファイルがあります。

モジュールの構成を定義するために使用する可能性のあるいくつかのセクションを見てみましょう。

  • プロバイダー: Terraform 構成ファイルは、プロバイダーの指定で始まります。 Azure を使用する場合は、provider ブロックで Azure プロバイダー (azurerm) を指定します。
  • Terraform: 使用している Terraform のバージョン。
  • データ:既存のサービスからデータを取得します。
  • ローカル:関数と式を使用して新しい変数を生成します。
  • Resource:リソースと依存関係について記述します。
  • モジュール:再利用性および複雑さの抽象化。

アプリケーションとデータベースをプロビジョニングする場合、含める必要があるのはプロバイダーリソースのセクションだけです。

次に、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 リポジトリに移動し、[設定] を選択してから、左ペインで [シークレットと変数][アクション] の順に選択します。

サービス プリンシパルの作成時に返された値を使用して、4 つのシークレットを作成します。

次のスクリーンショットに示すように、必ず引用符 (" ") を付けずにシークレットを格納してください。

GitHub の [Settings]\(設定\) の [Secrets]\(シークレット\) ペインで格納されたシークレット示すスクリーンショット。

ワークフロー ファイル

プロジェクト ディレクトリ内には .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

このワークフローにより、次の操作が実行されます。

  • 構成が正しい形式になっているかどうかが確認されます。
  • すべての pull request に対してプランが生成されます。
  • terraform ディレクトリ内のファイルを更新すると、構成がトリガーされます。

Note

[Actions](アクション) に移動し、Terraform ワークフローを選択して、[Re-run existing Jobs](既存のジョブを再実行する) を選択することによっても、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. リポジトリで、[Actions](アクション) を選択してから、左側のペインで [TERRAFORM] ワークフローを選択します。

  2. ステップの一覧で、Terraform InitTerraform PlanTerraform Validate がトリガーされていることを確認します。

    Terraform ワークフローの実行結果を表示するスクリーンショット。

  3. ステップの一覧で、Terraform Apply を展開し、次のことを確認します。

  • Terraform によってリソースが作成され、Azure インスタンスの URL が表示されている。

  • Azure アプリ インスタンスが一般公開されている。

    Azure アプリ インスタンスが一般公開されていることを示すスクリーンショット。

次のステップ

次の演習では、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. 変更をコミットする

Terraform リソースをプロビジョニングするための Azure パイプラインを作成する

Azure DevOps プロジェクトで、プロビジョニングと、ビルドおよびデプロイ用に 2 つの異なるパイプラインを作成します。 プロビジョニング パイプラインにより、後でビルドおよびデプロイのパイプラインを介してリリースされる Azure リソースが作成されます。

最初のプロビジョニング パイプラインを作成しましょう。

  1. 組織を選択し、[新しいプロジェクト] を選択します。

  2. 次のパラメーターを指定します。

    パラメーター 説明
    プロジェクト名 必須
    説明 省略可能
    視程 [非公開] を選択
    上級
    バージョン コントロール [Git] を選択
    作業項目プロセス [基本] を選択
  3. [プロジェクトの作成] を選択してプロジェクトを作成し、ようこそページを開きます。

新しい Azure プロジェクト フォームを表示するスクリーンショット。

Azure パイプライン サービス接続を設定する

Azure パイプラインに Azure アカウントへのアクセスを許可しましょう。

  1. Azure DevOps で、プロジェクト設定ページから [サービス接続] ページを開きます

  2. [サービス接続の作成] を選び、[Azure Resource Manager][次へ] の順に選択します。

  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. [続行] を選択して [レビュー] タブに移動し、ご自分のパイプラインを確認します。

新しい Azure パイプライン フォームを表示するスクリーンショット。

[パイプライン 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. [OK] (右下隅) を選択して、変数を保存します。

新しいサービス プリンシパル変数を表示するスクリーンショット。

最後に、[実行] (右上隅) を選択して、パイプラインを保存して実行します

パイプラインの実行を監視する

[ジョブ] の下で、ステップごとにビルド プロセスをトレースします。

パイプラインが実行されると、Terraform の 1 番目の init ステージ、次に 2 番目の apply ステージが、青色 (実行中) から緑色 (完了) に移行するのを監視します。 ステージを選択して、パイプラインの動作を監視することができます。

新しい Azure パイプライン実行を表示するスクリーンショット。

ヒント

メールを確認します。 実行の結果が記載されたビルド通知を既に受信している可能性があります。 これらの通知を使用して、各ビルドの成功または失敗を知ることができます。

次のステップ

次の演習では、Azure Pipelines を使用して、サンプルの Spring Boot アプリケーションをビルドしてデプロイします。