🍣

GitHub ActionsとTerraformを使ったAzureへの自動デプロイ:トラブルシューティングガイド

2025/03/10に公開

はじめに

クラウドインフラストラクチャをコードとして管理する「Infrastructure as Code(IaC)」の実践において、TerraformとGitHub Actionsの組み合わせは非常に強力です。しかし、特にAzureへのデプロイでは、認証やワークフローの設定に関する様々な課題に直面することがあります。

この記事では、GitHub ActionsとTerraformを使ってAzureリソースを自動デプロイする際に遭遇した問題とその解決策について詳しく解説します。

環境構築

まず、以下の環境を準備しました:

  • GitHubリポジトリ(terraform-multicloud-deploy)
  • Azureアカウントとサブスクリプション
  • Terraformの基本的な構成ファイル(main.tf, variables.tf, outputs.tf, backend.tf)

発生した問題と解決策

1. Azureサービスプリンシパルの作成エラー

問題

az ad sp create-for-rbac \
  --name "terraform-github-actions" \
  --role Contributor \
  --scopes /xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\ 
  --sdk-auth

(MissingSubscription) The request did not have a subscription or a valid tenant level resource provider.

原因
スコープの指定方法が間違っていました。正しいスコープの形式は /subscriptions/<subscription-id> ですが、/subscriptions/ プレフィックスが欠けており、末尾に余分なバックスラッシュがありました。

解決策

# まずAzure CLIでログイン
az login

# 正しいスコープ形式でサービスプリンシパルを作成
az ad sp create-for-rbac \
  --name "terraform-github-actions" \
  --role Contributor \
  --scopes /subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx \
  --sdk-auth

2. Azureストレージアカウント作成エラー

問題

az storage account create \
  --name terraformstate_test \
  --resource-group terraform-state-rg \
  --location japaneast \
  --sku Standard_LRS

(SubscriptionNotFound) Subscription xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx was not found.

原因

  1. ストレージアカウント名にアンダースコア(_)が含まれていましたが、Azureのストレージアカウント名には小文字と数字のみ使用可能です。
  2. Storageリソースプロバイダーが登録されていませんでした。

リソースプロバイダー(Resource Provider)は、Azureにおいて特定の種類のリソースやサービスを提供・管理するためのコンポーネントです。各リソースプロバイダーは、特定のAzureサービスに関連するリソースタイプを作成・管理するためのAPIを提供します。

特にTerraformやその他のIaCツールを使用する場合、リソースプロバイダーの登録状態を事前に確認しておくことで、デプロイ時のエラーを防ぐことができます。また、新しいAzureサービスを使用する際には、対応するリソースプロバイダーの登録が必要になることを覚えておくと良いでしょう。

解決策

# Storageリソースプロバイダーを登録
az provider register --namespace Microsoft.Storage

# 登録状態を確認(Registeredになるまで待つ)
az provider show --namespace Microsoft.Storage --query "registrationState" -o tsv

# 正しい名前形式でストレージアカウントを作成
az storage account create \
  --name terraformstateunique \
  --resource-group terraform-state-rg \
  --location japaneast \
  --sku Standard_LRS

3. Terraformバックエンド設定エラー

問題

Initializing the backend...
Error: Error building ARM Config: Authenticating using the Azure CLI is only supported as a User (not a Service Principal).

原因
バックエンド設定にサブスクリプションIDが指定されておらず、また、コンテナが存在していませんでした。

解決策

  1. backend.tfファイルにサブスクリプションIDを追加:
terraform {
  backend "azurerm" {
    subscription_id      = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
    resource_group_name  = "terraform-state-rg"
    storage_account_name = "terraformstateunique"
    container_name       = "tfstate"
    key                  = "azure/terraform.tfstate"
  }
}
  1. ストレージコンテナを作成:
az storage container create --name tfstate --account-name terraformstateunique --auth-mode login

4. GitHub Actionsでの認証エラー

問題

Run terraform init
Error: Error building ARM Config: Authenticating using the Azure CLI is only supported as a User (not a Service Principal).

原因
GitHub Actionsの環境では、Azure CLIを使用した認証はサービスプリンシパルとして認識されるため、Terraformが認証情報を正しく取得できませんでした。

サービスプリンシパルは、アプリケーションやサービスがAzureリソースにアクセスするための「サービスアカウント」のようなものです。特に自動化ツールやCI/CDパイプラインでは、サービスプリンシパルを使用することで、人間の介入なしにAzureリソースを安全に操作することができます。

解決策
GitHub Actionsのワークフローファイル(.github/workflows/terraform.yml)に環境変数を設定するステップを追加:

- name: Extract Azure Credentials
  run: |
    # JSONからクレデンシャル情報を抽出
    AZURE_CREDS='${{ secrets.AZURE_CREDENTIALS }}'
    echo "ARM_CLIENT_ID=$(echo $AZURE_CREDS | jq -r .clientId)" >> $GITHUB_ENV
    echo "ARM_CLIENT_SECRET=$(echo $AZURE_CREDS | jq -r .clientSecret)" >> $GITHUB_ENV
    echo "ARM_SUBSCRIPTION_ID=$(echo $AZURE_CREDS | jq -r .subscriptionId)" >> $GITHUB_ENV
    echo "ARM_TENANT_ID=$(echo $AZURE_CREDS | jq -r .tenantId)" >> $GITHUB_ENV

- name: Terraform Init
  run: terraform init
  working-directory: ./azure
  env:
    ARM_CLIENT_ID: ${{ env.ARM_CLIENT_ID }}
    ARM_CLIENT_SECRET: ${{ env.ARM_CLIENT_SECRET }}
    ARM_SUBSCRIPTION_ID: ${{ env.ARM_SUBSCRIPTION_ID }}
    ARM_TENANT_ID: ${{ env.ARM_TENANT_ID }}

同様に、Terraform ValidateTerraform PlanTerraform Applyステップにも環境変数を追加しました。

5. Terraformフォーマットエラー

問題

Run terraform fmt -check
terraform fmt -check
backend.tf
main.tf
Error: Terraform exited with code 3.

原因
Terraformファイル(backend.tfとmain.tf)が標準的なフォーマットに従っていませんでした。

terraformの標準的なフォーマットに従わないとは、①インデントが不適切②スペースやタブの使用が一貫していない③改行が不適切④括弧やカンマの配置が標準と異なる等が挙げられる。

解決策
ローカルでterraform fmtコマンドを実行してファイルを修正:

cd terraform-multicloud-deploy/azure
terraform fmt
git add .
git commit -m "Fix Terraform formatting"
git push origin main

6. GitHubへのプッシュエラー

問題

remote: error: File aws/.terraform/providers/registry.terraform.io/hashicorp/aws/5.90.0/darwin_amd64/terraform-provider-aws_v5.90.0_x5 is 669.60 MB; this exceeds GitHub's file size limit of 100.00 MB

原因
.terraformディレクトリがGitリポジトリに含まれており、大きなプロバイダーファイルがGitHubの制限を超えていました。

解決策

  1. .gitignoreファイルを更新:
# Local .terraform directories
**/.terraform/*

# .tfstate files
*.tfstate
*.tfstate.*
  1. 大きなファイルをGitの履歴から削除:
git rm -r --cached aws/.terraform/
git commit -m "Remove .terraform directories and update .gitignore"
git push origin main

ベストプラクティスと教訓

  1. 適切な認証方法の選択

    • ローカル開発ではaz loginを使用
    • CI/CD環境ではサービスプリンシパルと環境変数を使用
  2. リソースプロバイダーの確認

    • 新しいリソースタイプを使用する前に、対応するプロバイダーが登録されているか確認
  3. 命名規則の遵守

    • Azureリソース名の制約(小文字、数字のみなど)を理解する
  4. バージョン管理のベストプラクティス

    • .gitignoreファイルで大きなファイルや機密情報を除外
    • Terraformの状態ファイルはリモートバックエンドに保存
  5. 環境変数の適切な設定

    • GitHub Actionsでは、ARM_CLIENT_IDARM_CLIENT_SECRETARM_SUBSCRIPTION_IDARM_TENANT_IDの4つの環境変数が必要

まとめ

GitHub ActionsとTerraformを使ったAzureへの自動デプロイは、いくつかの落とし穴がありますが、適切な設定と理解があれば非常に効率的なワークフローを構築できます。

特に重要なのは、認証情報の適切な管理と、GitHub Actionsの環境でTerraformが正しく動作するための環境変数の設定です。また、Azureリソースの命名規則やリソースプロバイダーの登録状態にも注意が必要です。

これらの問題を理解し、適切に対処することで、安定した自動デプロイパイプラインを構築することができます。

最後に

私は2つのプラットフォームで生成AIに関する発信を行なっております。

生成AIサービスの考察を見たい方へ

生成AIサービスの動向やや具体的な内容は、noteで詳しく解説しています。

noteプロフィール: @mizupee

日々の生成AI分析を追いたい方へ

毎日1つの生成AIサービスを分析するTwitter投稿「#100DaysofAI」もぜひフォローください。簡潔なポイント分析とアイデア共有を継続中です。

Twitter: @mizupee

Discussion