🎉

AWS×GitHub Actionsで実践するIaCデプロイ自動化:トラブルシューティング編

2025/03/10に公開

はじめに

クラウドインフラストラクチャの構築・管理において、Infrastructure as Code(IaC)とCI/CDパイプラインの組み合わせは現代のベストプラクティスとなっています。

今回は、AWS環境をTerraformで構築し、GitHub Actionsを用いて自動デプロイする過程で遭遇した様々なエラーと、その解決方法について詳しく解説します。

実際のプロジェクト進行では、理想通りに進まないことがほとんどです。

この記事では特に 「失敗から学ぶ」 という観点から、私が直面した問題とその解決策を共有します

プロジェクト概要

今回のプロジェクトでは、以下の技術スタックを使用しました:

  • インフラ定義: Terraform
  • クラウドプロバイダ: AWS(Amazon Web Services)
  • CI/CD: GitHub Actions
  • バージョン管理: Git/GitHub

目標は、コードをプッシュするだけでAWS環境が自動的に構築・更新される仕組みを作ることでした。

遭遇したエラー①:AWS認証情報の問題

エラー内容

最初に遭遇したのは、GitHub Actionsのワークフロー実行時に発生したAWS認証エラーでした。

Run terraform fmt -check
/home/runner/work/_temp/5d7b0f66-6c5e-4010-ad77-73ef92e81c1b/terraform-bin fmt -check
backend.tf
main.tf
Error: Terraform exited with code 3.
Error: Process completed with exit code 1.

一見するとフォーマットエラーのように見えますが、実際には認証情報の問題が根本原因でした。

原因分析

調査の結果、以下の問題が見つかりました:

  1. 無効なAWSアクセスキー: GitHub Secretsに設定したAWSアクセスキーが無効または期限切れでした
  2. S3バケット設定の問題: Terraformのバックエンドとして使用するS3バケットが正しく設定されていませんでした
  3. DynamoDBテーブルの権限不足: 状態ロック用のDynamoDBテーブルを作成する権限がありませんでした

解決策

  1. AWS IAMで新しいアクセスキーを作成
    • IAMコンソールから専用のデプロイ用ユーザーを作成
    • 必要最小限の権限を持つポリシーを作成・アタッチ
    • 新しいアクセスキーをGitHub Secretsに設定

こちらの記事を参考にアクセスキーを作成しました。
https://zenn.dev/fumi_mizu/articles/a9d67f2d687cf5

  1. S3バケットの正しい設定

    terraform {
      backend "s3" {
        bucket  = "terraform-state-fumipen-123" # 実際に作成したバケット名
        key     = "aws/terraform.tfstate"
        region  = "ap-northeast-1"
        encrypt = true
      }
    }
    
  2. DynamoDBテーブルの設定を一時的に削除

    • 権限の問題を回避するため、DynamoDBによる状態ロックを一時的に無効化

遭遇したエラー②:GitHubの大容量ファイル制限

エラー内容

Terraformの設定が完了し、コードを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
remote: error: GH001: Large files detected. You may want to try Git Large File Storage - https://git-lfs.github.com.
To https://github.com/fumifumi0831/terraform-multicloud-deploy.git
 ! [remote rejected] main -> main (pre-receive hook declined)
error: failed to push some refs to 'https://github.com/fumifumi0831/terraform-multicloud-deploy.git'

原因分析

Terraformを初期化すると、.terraformディレクトリにプロバイダーのバイナリファイルがダウンロードされます。AWSプロバイダーは特に大きく、669.60MBもあり、GitHubの制限(100MB)を大幅に超えていました。

さらに問題だったのは、このファイルが誤ってGitの追跡対象になっていたことです。.gitignoreファイルが適切に設定されていなかったため、Terraformの一時ファイルやバイナリがリポジトリに含まれてしまいました。

解決策

  1. 適切な.gitignoreファイルの作成

    # Local .terraform directories
    **/.terraform/*
    
    # .tfstate files
    *.tfstate
    *.tfstate.*
    
    # Crash log files
    crash.log
    crash.*.log
    
    # Exclude all .tfvars files
    *.tfvars
    *.tfvars.json
    
    # Ignore override files
    override.tf
    override.tf.json
    *_override.tf
    *_override.tf.json
    
    # Ignore CLI configuration files
    .terraformrc
    terraform.rc
    
    # Ignore lock files
    .terraform.lock.hcl
    
    # macOS
    .DS_Store
    
  2. 既に追跡されているファイルの削除

    git rm -r --cached aws/.terraform
    git commit -m "Remove .terraform directories from git"
    
  3. Gitの履歴からも大きなファイルを削除

    git filter-branch --force --index-filter "git rm --cached --ignore-unmatch aws/.terraform/providers/registry.terraform.io/hashicorp/aws/5.90.0/darwin_amd64/terraform-provider-aws_v5.90.0_x5" --prune-empty --tag-name-filter cat -- --all
    git gc --prune=now
    git push origin main --force
    

この一連の操作により、大きなファイルをGitの履歴から完全に削除し、リポジトリのサイズを適切に保つことができました。

gitの追跡ファイルの削除やGitの履歴からも削除する方法についてはこちらに方法を詳しく載せてます。
https://zenn.dev/articles/dd3fb628a182f5/edit

学んだ教訓

1. 事前準備の重要性

  • 適切な.gitignoreの設定: プロジェクト開始時に適切な.gitignoreファイルを用意することで、多くの問題を未然に防げます
  • 権限の最小化: 必要最小限の権限を持つIAMユーザーを使用することでセキュリティリスクを低減できます

2. トラブルシューティングのアプローチ

  • エラーメッセージの正確な理解: 表面的なエラーメッセージだけでなく、根本原因を特定することが重要です
  • 段階的な検証: 小さな変更を加えて検証することで、問題の切り分けがしやすくなります

3. CI/CDパイプラインの設計

  • 環境変数とシークレットの管理: 認証情報は必ずGitHub Secretsなどの安全な方法で管理する
  • ワークフローの分割: 複雑なワークフローは小さく分割し、各ステップで適切な検証を行う

GitHub Actionsワークフローの最終形

最終的に完成したGitHub Actionsのワークフローは以下のようになりました:

name: Multi-Cloud Terraform Deployment

on:
  # プッシュ時に実行
  push:
    branches: [ main ]
    paths:
      - 'aws/**'
      - '.github/workflows/**'
  
  # プルリクエスト時に実行
  pull_request:
    branches: [ main ]
    paths:
      - 'aws/**'
      - '.github/workflows/**'
  
  # 手動実行
  workflow_dispatch:
    inputs:
      deploy_target:
        description: 'デプロイターゲット'
        required: true
        default: 'aws'
        type: choice
        options:
          - aws

jobs:
  # 変更されたディレクトリを検出するジョブ
  detect-changes:
    runs-on: ubuntu-latest
    outputs:
      aws_changed: ${{ steps.filter.outputs.aws }}
    
    steps:
    - name: Checkout
      uses: actions/checkout@v3
      with:
        fetch-depth: 0
    
    - name: Filter paths
      uses: dorny/paths-filter@v2
      id: filter
      with:
        filters: |
          aws:
            - 'aws/**'

  # AWS デプロイジョブ
  deploy-aws:
    needs: detect-changes
    if: |
      github.event_name == 'workflow_dispatch' && github.event.inputs.deploy_target == 'aws' ||
      github.event_name != 'workflow_dispatch' && needs.detect-changes.outputs.aws_changed == 'true'
    runs-on: ubuntu-latest
    environment: aws-deployment
    
    steps:
    - name: Checkout
      uses: actions/checkout@v3

    - name: Setup Terraform
      uses: hashicorp/setup-terraform@v2
      with:
        terraform_version: 1.5.0

    - name: Configure AWS Credentials
      uses: aws-actions/configure-aws-credentials@v2
      with:
        aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
        aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
        aws-region: ap-northeast-1

    - name: Terraform Init
      run: terraform init
      working-directory: ./aws

    - name: Terraform Format
      run: terraform fmt -check
      working-directory: ./aws

    - name: Terraform Validate
      run: terraform validate
      working-directory: ./aws

    - name: Terraform Plan
      run: terraform plan
      working-directory: ./aws
      if: github.event_name == 'pull_request'

    - name: Terraform Apply
      run: terraform apply -auto-approve
      working-directory: ./aws
      if: github.event_name == 'push' || github.event_name == 'workflow_dispatch'

まとめ

AWS環境をTerraformとGitHub Actionsで自動デプロイする過程では、様々な問題に直面しました。特に認証情報の管理や大きなファイルの取り扱いには注意が必要です。

しかし、これらの問題を一つずつ解決していくことで、堅牢なCI/CDパイプラインを構築することができました。失敗から学ぶことで、より深い知識と経験を得ることができたと感じています。

IaCとCI/CDの組み合わせは、現代のクラウドインフラ管理において非常に強力なアプローチです。初期設定に手間がかかることもありますが、一度構築してしまえば、インフラの変更を安全かつ迅速に行うことができます。

皆さんもぜひ、この記事で紹介したトラブルシューティングの知識を活かして、自分だけのIaCパイプラインを構築してみてください。

今回私が作成したリソースはこちらです。
https://github.com/fumifumi0831/terraform-multicloud-deploy.git

最後に

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

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

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

noteプロフィール: @mizupee

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

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

Twitter: @mizupee

参考リソース


この記事が皆さんのクラウドインフラ自動化の旅に役立つことを願っています。質問やフィードバックがあれば、コメント欄でお待ちしています!

Discussion