BLOG

ブログ

Azure DevOps上でterraformを用いたAzureのIaC管理方法

背景

 クラウドコンピューティングの分野において、AWS と GCP に並ぶ存在として Azure が注目されています。Azure は多様なサービスを提供し、Azure DevOps や Azure Synapse など、AWS や GCP とは異なるツールやサービスがあります。それぞれのサービスごとに、ヘッダーや構成などにも違いがあり、AWS や GCP と比べると微妙に仕様が異なります。
このような状況の中で、Azure の導入にあたり、開発や管理のコストを効果的に削減するためには、Infrastructure as Code (IaC) の導入が有効です。特に、Azure 環境のインフラストラクチャをコードで管理する手段として、Terraform の導入が注目されています。Terraform を利用することで、Azure のリソースを効率的かつ再現性の高い方法で構築、管理することが可能となります。今回はそういったterraformの導入方法をまとめたいと思います。

設計

リポジトリAzure DevOps ReposCloud Source RepositoriesAWS CodeCommit
cicdAzure DevOps PipelinesCloud BuildAWS CodeBuild + AWS CodePipeline
terraform
実行権限主体
AzureアプリGCP Service AccountAWS IAM role
state管理場所Azure Storage Account (container)Cloud StorageAWS S3
環境構築terraformterraformterraform


図1:Blob (オブジェクト) Storage の概要 – Azure Storage | Microsoft Docs

構成を考える上で気になった点は以下の内容である。

  • AWS・GCPとStorageの概念が違い、ストレージアカウント配下にファイル以外にキューなど様々なものが紐づいて管理ができる
  • リポジトリや実行環境はAWS・GCPと同様Azure DevOpsというサービスにまとまっている
  • Azure Resource ManagerというAzure内部に管理サービスを持っており、Azureだけを利用する場合はterraformより優れいてる面もありそうだった

手順

storage周りの準備

 tfstateを管理するstarage周りは先に手動で準備しておく必要があるので、 resource group・strage account・storage containerの3つをコンソールや以下コマンドで準備しておきます。

$ az login
$ az group create --name {RESOURCE_GROUP_NAME} --location japaneast
$ az storage account create --resource-group {RESOURCE_GROUP_NAME} --name {STORAGE_ACCOUNT_NAME} --sku Standard_LRS --encryption-services blob
$ account_key=$(az storage account keys list --resource-group {RESOURCE_GROUP_NAME} --account-name {STORAGE_ACCOUNT_NAME} --query '[0].value' -o tsv)
$ az storage container create --name {CONTAINER_NAME} --account-name {STORAGE_ACCOUNT_NAME} --account-key $account_key
$ az storage container list --account-name {STORAGE_ACCOUNT_NAME} --account-key $account_key --output table

terraform用のアカウント準備


図2:Azure構成概略図

  1. Microsoft Entraセンターの「アプリケーション>アプリの登録」よりterraformで利用するアプリの新規登録を行う
  2. 概要に記載のある「アプリケーション (クライアント) ID」「ディレクトリ (テナント) ID」をメモしておく
  3. 「証明書とシークレット>クライアントシークレット>新しいクライアントシークレット」よりシークレットを作成し、「クライアントシークレット」をメモしておく
  4. サブスクリプションより契約中のプランを選択し、「アクセス制御(IAM)>ロールの割り当て>ロールの割り当ての追加」より作成したアプリにロールを追加する。
  5. 契約中プランの「サブスクリプションID」をメモしておく

Azure DevOps周りの準備


図3:Azure構成概略図

  • Azure DevOps Reposでリポジトリの作成
  • Azure DevOps Pipelinesにてリポジトリを接続し、azure-pipelines.ymlをリポジトリのルートフォルダに作成

リポジトリの中身

  • azure-pipelines.yml:Azure DevOps Pipelineの実行内容を管理
  • /tf:terraformファイルを格納するフォルダ
├── azure-pipelines.yml
└── tf
    ├── backend.tf
    └── variables.tf

azure-pipelines.ymlの中身

  • Azure DevOps Pipeline のライブラリを利用
  • 不要なシークレット払い出しを避けるためAzure DevOpsのService Connectionの利用を推奨している記事も多いですが、terraformの場合はこの認証方法が利用できないため注意が必要です
    • ##[error]Terraform backend initialization for AzureRM only support service principal authorization というエラーが発生する
    • AWS・GCPではサービスに対しては類似の方法ができるため、別の問題でできていない可能性はあります
    • 環境変数にてメモしていたARM_SUBSCRIPTION_ID・ARM_CLIENT_ID・ARM_TENANT_ID・ARM_CLIENT_SECRETを渡すことで認証を通しています
  • The subscription is not registered to use namespace 'Microsoft.Synapse'といったエラーが出ることがあり、リソース プロバイダーの登録エラーの解決が必要な場合があります
trigger:
- main

variables:
- group: sandbox-azure-sinkcapital
- name: TerraformVersion
  value: '1.7.5'
- name: terraformWorkingDirectory
  value: 'tf'

steps:
- task: JasonBJohnson.azure-pipelines-tasks-terraform.azure-pipelines-tasks-terraform-installer.TerraformInstaller@0
  displayName: 'Install Terraform'
  inputs:
    terraformVersion: $(terraformVersion)

- task: TerraformCLI@0
  displayName: 'Terraform Version'
  inputs:
    command: 'version'

# - task: TerraformCLI@0
#   displayName: 'Terraform Format'
#   inputs:
#     workingDirectory: $(terraformWorkingDirectory)
#     command: 'fmt'
#     commandOptions: '-recursive'

- task: TerraformCLI@0
  displayName: 'Run terraform init'
  inputs:
    workingDirectory: $(terraformWorkingDirectory)
    command: 'init'
  env:
    ARM_SUBSCRIPTION_ID: $(azure_subscription_id)
    ARM_CLIENT_ID: $(azure_client_id)
    ARM_TENANT_ID: $(azure_tenant_id)
    ARM_CLIENT_SECRET: $(azure_client_secret)

# - task: TerraformCLI@0
#   displayName: 'Run terraform plan'
#   inputs:
#     command: plan
#     workingDirectory: $(terraformWorkingDirectory)
#   env:
#     ARM_SUBSCRIPTION_ID: $(azure_subscription_id)
#     ARM_CLIENT_ID: $(azure_client_id)
#     ARM_TENANT_ID: $(azure_tenant_id)
#     ARM_CLIENT_SECRET: $(azure_client_secret)

- task: TerraformCLI@0
  displayName: 'Run terraform apply'
  inputs:
    workingDirectory: $(terraformWorkingDirectory)
    command: apply
  env:
    ARM_SUBSCRIPTION_ID: $(azure_subscription_id)
    ARM_CLIENT_ID: $(azure_client_id)
    ARM_TENANT_ID: $(azure_tenant_id)
    ARM_CLIENT_SECRET: $(azure_client_secret)

backend.tfの中身

  • 「storage周りの準備」にて指定したストレージ情報を記載する
terraform {
  required_providers {
    azurerm = {
      source  = "hashicorp/azurerm"
      version = "~> 3.95.0"
    }
  }

  backend azurerm {
    resource_group_name  = "{RESOURCE_GROUP_NAME}"
    storage_account_name = "{STORAGE_ACCOUNT_NAME}"
    container_name       = "{CONTAINER_NAME}"
    key                  = "terraform.tfstate"
  }
}

provider azurerm {
  skip_provider_registration = true
  features {}
}

感想

 今回Azureにてterraform環境を整えましたが、AWS・GCPとはstorageや権限の概念が異なり最初の設定が少し難しかった印象です。 ただterrraformを利用しているので一通り実行できるようになった後は他クラウドと変わらず開発が行えました。 AzureはExcelなどMicrosft製品との連携が強く、今後Microsft製品を多く利用される環境にて導入を進めさせていただければと思います。

参照リンク

SinkCapitalではデータに関する支援を行っています

弊社はスペシャリスト人材が多く在籍するデータ組織です。 データ分析や分析基盤の設計などでお困りの方がいらっしゃれば、 まずは無料で、こちらから各分野のスペシャリストに直接相談出来ます。