AWS CodePipelineを使ったCI/CDパイプライン構築

はじめに

現代のソフトウェア開発では、継続的インテグレーション/継続的デリバリー(CI/CD)の実践が不可欠となっています。AWSは、CodePipelineをはじめとする一連のサービスを提供し、クラウドネイティブなCI/CDパイプラインの構築を強力にサポートしています。

本記事では、AWS CodePipelineを中心としたCI/CDパイプラインの構築方法について、基本的な概念から実践的な手順、応用例まで詳しく解説します。

CI/CDとは

始めに、CI/CDの基本概念を簡単におさらいしておきましょう。

  • 継続的インテグレーション(CI): 開発者がコードの変更を頻繁に共有リポジトリにマージし、自動的にビルドとテストを実行することで、早期に問題を発見する手法
  • 継続的デリバリー(CD): ビルドとテストを通過したコードを自動的に本番環境に近い環境にデプロイし、いつでもリリース可能な状態を維持する手法
  • 継続的デプロイメント(CD): さらに踏み込んで、変更を自動的に本番環境にデプロイする手法

AWS CI/CDサービスの概要

AWSのCI/CDサービスには主に以下のものがあります:

  • AWS CodePipeline: パイプラインの定義と管理、各ステージの連携を担当
  • AWS CodeCommit: Gitベースのプライベートリポジトリサービス
  • AWS CodeBuild: ソースコードのビルドとテストを行うフルマネージドサービス
  • AWS CodeDeploy: さまざまな環境へのデプロイを自動化するサービス
  • AWS CodeStar: 上記サービスを統合したプロジェクト管理サービス
  • AWS CodeArtifact: プライベートなアーティファクトリポジトリサービス

これらを組み合わせることで、コードのコミットからテスト、デプロイまでを自動化する完全なCI/CDパイプラインを構築できます。

CodePipelineの基本

AWS CodePipelineは、CI/CDパイプラインの定義、視覚化、自動化を行うサービスです。主な特徴は以下の通りです:

  • ステージベースのワークフロー: ソース取得、ビルド、テスト、デプロイなど、複数のステージで構成
  • 豊富な統合: AWSサービスだけでなく、GitHub、Jenkins、Spinnaker等のサードパーティーツールとも連携可能
  • 並列アクション: 同じステージ内で複数のアクションを並列実行可能
  • 承認アクション: 人による手動承認ステップの追加が可能
  • 可視化: パイプラインの実行状況をコンソールで視覚的に確認可能

CI/CDパイプライン構築の例

それでは実際に、AWSのサービスを使ったCI/CDパイプラインの構築手順を見ていきましょう。この例では、以下のフローを実装します:

  1. GitHubからソースコードを取得
  2. CodeBuildでビルドとテストを実行
  3. テスト環境へのデプロイ
  4. 手動承認
  5. 本番環境へのデプロイ

前提条件

  • AWSアカウント
  • GitHubアカウントとリポジトリ
  • AWS CLIのセットアップ(任意)
  • デプロイ対象のアプリケーション

手順1:必要なIAMロールの作成

まず、CodePipelineとCodeBuildが使用するIAMロールを作成します。AWSマネジメントコンソールから作成する方法と、AWS CloudFormationテンプレートを使用する方法があります。

CodePipeline用IAMロール(AWSコンソール)

  1. IAMコンソールを開き、「ロール」→「ロールの作成」をクリック
  2. 「AWSサービス」を選択し、「CodePipeline」を選択して「次へ」
  3. 「AWSCodePipelineServiceRole」ポリシーを選択して「次へ」
  4. ロール名(例: CodePipelineServiceRole)を入力して「ロールの作成」をクリック

CodeBuild用IAMロール(AWSコンソール)

  1. IAMコンソールで「ロール」→「ロールの作成」をクリック
  2. 「AWSサービス」を選択し、「CodeBuild」を選択して「次へ」
  3. 「AmazonS3FullAccess」と「AWSCodeBuildAdminAccess」ポリシーを選択して「次へ」
  4. ロール名(例: CodeBuildServiceRole)を入力して「ロールの作成」をクリック

手順2:アーティファクト保存用のS3バケットを作成

CodePipelineは、各ステージ間でアーティファクトを受け渡すためのS3バケットを必要とします。

aws s3 mb s3://my-codepipeline-artifacts-bucket --region ap-northeast-1

または、AWSコンソールからS3バケットを作成します。

手順3:CodeBuildプロジェクトの作成

次に、ソースコードのビルドとテストを行うCodeBuildプロジェクトを作成します。

  1. CodeBuildコンソールを開き、「ビルドプロジェクトを作成する」をクリック
  2. プロジェクト名(例: MyAppBuild)を入力
  3. ソースプロバイダーを設定(この時点では任意の設定で可、後でパイプラインから上書きされる)
  4. 環境設定:
    • マネージドイメージを選択(例: Amazon Linux 2、標準)
    • サービスロールには先ほど作成した「CodeBuildServiceRole」を選択
  5. Buildspec:
    • 「buildspec.ymlを使用する」を選択(または、インラインでコマンドを定義)
  6. アーティファクト:
    • タイプ: 「Amazon S3」を選択
    • バケット名: 先ほど作成したS3バケットを選択
    • 名前: BuildOutputなどと入力
  7. 「ビルドプロジェクトの作成」をクリック

手順4:buildspec.ymlの作成

アプリケーションのリポジトリにbuildspec.ymlファイルを作成します。これはCodeBuildが実行する命令を定義するファイルです。以下は、Node.jsアプリケーションの例です:

version: 0.2

phases:
  install:
    runtime-versions:
      nodejs: 16
    commands:
      - echo Installing dependencies...
      - npm install
  pre_build:
    commands:
      - echo Running tests...
      - npm test
  build:
    commands:
      - echo Building the application...
      - npm run build
  post_build:
    commands:
      - echo Build completed on `date`

artifacts:
  files:
    - build/**/*
    - node_modules/**/*
    - scripts/**/*
    - appspec.yml
    - package.json
  discard-paths: no

手順5:CodePipelineの作成

いよいよ、CodePipelineを作成します。

  1. CodePipelineコンソールを開き、「パイプラインの作成」をクリック
  2. パイプライン名(例: MyAppPipeline)を入力して「次へ」
  3. サービスロールは先ほど作成した「CodePipelineServiceRole」を選択
  4. アーティファクトストアとして、先ほど作成したS3バケットを選択して「次へ」

ソースステージの設定:

  1. ソースプロバイダーとして「GitHub(バージョン2)」を選択
  2. 「接続」で「Connect to GitHub」をクリックし、認証を行う
  3. リポジトリとブランチを選択
  4. 変更検出オプションとして「GitHub Webhooks」を選択して「次へ」

ビルドステージの設定:

  1. ビルドプロバイダーとして「AWS CodeBuild」を選択
  2. リージョンを選択
  3. 先ほど作成したビルドプロジェクト「MyAppBuild」を選択して「次へ」

デプロイステージ(テスト環境)の設定:

  1. デプロイプロバイダーとして「AWS CodeDeploy」を選択
  2. リージョンを選択
  3. CodeDeployアプリケーション名とデプロイグループ名を入力(未作成の場合は先に作成が必要)
  4. 「次へ」をクリックし、設定内容を確認して「パイプラインの作成」をクリック

手順6:手動承認ステージの追加

テスト環境へのデプロイ後、本番環境へのデプロイ前に手動承認を追加します。

  1. 作成したパイプラインの詳細ページで「編集」をクリック
  2. テスト環境デプロイステージの後に「+ステージを追加」をクリック
  3. ステージ名(例: Approval)を入力して「ステージを追加」
  4. 追加したステージ内で「+アクションを追加」をクリック
  5. アクション名(例: ManualApproval)を入力
  6. アクションプロバイダーとして「手動承認」を選択
  7. 通知オプションとして、必要に応じてSNSトピックを設定
  8. 「完了」をクリックし、「保存」をクリック

手順7:本番環境デプロイステージの追加

手動承認ステージの後に、本番環境へのデプロイステージを追加します。

  1. 承認ステージの後に「+ステージを追加」をクリック
  2. ステージ名(例: Production)を入力して「ステージを追加」
  3. 「+アクションを追加」をクリック
  4. アクション名(例: DeployToProduction)を入力
  5. アクションプロバイダーとして「AWS CodeDeploy」を選択
  6. 本番環境用のCodeDeployアプリケーションとデプロイグループを選択
  7. 「完了」をクリックし、「保存」をクリック

手順8:CodeDeployのセットアップ

CodeDeployを使用するには、デプロイ先の環境設定とappspec.ymlファイルの作成が必要です。

appspec.ymlの例(EC2デプロイの場合):

version: 0.0
os: linux
files:
  - source: /
    destination: /var/www/html/my-app
hooks:
  BeforeInstall:
    - location: scripts/before_install.sh
      timeout: 300
      runas: root
  AfterInstall:
    - location: scripts/after_install.sh
      timeout: 300
      runas: root
  ApplicationStart:
    - location: scripts/application_start.sh
      timeout: 300
      runas: root

EC2インスタンスのセットアップ:

  1. CodeDeployエージェントをインストール
  2. IAMインスタンスプロファイルを設定
  3. タグを設定(CodeDeployデプロイグループの対象特定用)

CI/CDパイプラインの応用例

基本的なパイプラインの構築方法を理解したところで、いくつかの応用例を紹介します。

1. マルチ環境デプロイメント

開発、ステージング、本番環境など、複数の環境へ段階的にデプロイするパイプラインを構築できます。

GitHub → Build → Dev Deploy → Dev Tests → Staging Deploy → Staging Tests → Approval → Production Deploy

2. パラレルテスト実行

ビルド後に複数のテストを並列で実行し、効率的に品質を確保するパイプラインです。

GitHub → Build → [Unit Tests, Integration Tests, Security Scans] → Deploy

3. ブルー/グリーンデプロイメント

CodeDeployのブルー/グリーンデプロイメント機能を活用し、ダウンタイムなしでの安全なデプロイを実現します。

GitHub → Build → Test → Blue/Green Deploy → Traffic Shift → Terminate Old Version

4. クロスアカウントデプロイメント

開発アカウントと本番アカウントを分離し、セキュリティを強化したパイプラインです。

[開発アカウント] GitHub → Build → Test → [本番アカウント] Production Deploy

5. インフラストラクチャのCI/CD

AWS CloudFormationやTerraformを使用して、インフラストラクチャのCI/CDを実現します。

GitHub → Validate Templates → Create Change Sets → Approval → Apply Changes

AWS CloudFormationによるパイプラインの自動化

これまでの手順をAWS CloudFormationテンプレートで自動化することもできます。以下は、簡略化したテンプレートの例です:

AWSTemplateFormatVersion: '2010-09-09'
Description: 'CI/CD Pipeline with AWS CodePipeline, CodeBuild, and CodeDeploy'

Parameters:
  GitHubOwner:
    Type: String
  GitHubRepo:
    Type: String
  GitHubBranch:
    Type: String
    Default: main
  GitHubToken:
    Type: String
    NoEcho: true

Resources:
  # アーティファクトバケット
  ArtifactBucket:
    Type: AWS::S3::Bucket
    Properties:
      VersioningConfiguration:
        Status: Enabled
      
  # CodePipelineサービスロール
  CodePipelineServiceRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Effect: Allow
            Principal:
              Service: codepipeline.amazonaws.com
            Action: 'sts:AssumeRole'
      ManagedPolicyArns:
        - 'arn:aws:iam::aws:policy/AWSCodeStarFullAccess'
  
  # CodeBuildプロジェクト
  CodeBuildProject:
    Type: AWS::CodeBuild::Project
    Properties:
      Name: !Sub ${AWS::StackName}-Build
      ServiceRole: !GetAtt CodeBuildServiceRole.Arn
      Artifacts:
        Type: CODEPIPELINE
      Environment:
        Type: LINUX_CONTAINER
        ComputeType: BUILD_GENERAL1_SMALL
        Image: aws/codebuild/amazonlinux2-x86_64-standard:3.0
      Source:
        Type: CODEPIPELINE
        BuildSpec: buildspec.yml
  
  # CodeBuildサービスロール
  CodeBuildServiceRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Effect: Allow
            Principal:
              Service: codebuild.amazonaws.com
            Action: 'sts:AssumeRole'
      ManagedPolicyArns:
        - 'arn:aws:iam::aws:policy/AmazonS3FullAccess'
        - 'arn:aws:iam::aws:policy/AWSCodeBuildAdminAccess'
  
  # CodePipeline
  Pipeline:
    Type: AWS::CodePipeline::Pipeline
    Properties:
      RoleArn: !GetAtt CodePipelineServiceRole.Arn
      ArtifactStore:
        Type: S3
        Location: !Ref ArtifactBucket
      Stages:
        # ソースステージ
        - Name: Source
          Actions:
            - Name: Source
              ActionTypeId:
                Category: Source
                Owner: ThirdParty
                Provider: GitHub
                Version: '1'
              Configuration:
                Owner: !Ref GitHubOwner
                Repo: !Ref GitHubRepo
                Branch: !Ref GitHubBranch
                OAuthToken: !Ref GitHubToken
              OutputArtifacts:
                - Name: SourceCode
        
        # ビルドステージ
        - Name: Build
          Actions:
            - Name: BuildAndTest
              ActionTypeId:
                Category: Build
                Owner: AWS
                Provider: CodeBuild
                Version: '1'
              Configuration:
                ProjectName: !Ref CodeBuildProject
              InputArtifacts:
                - Name: SourceCode
              OutputArtifacts:
                - Name: BuildOutput
        
        # デプロイステージ(テスト環境)
        - Name: DeployToTest
          Actions:
            - Name: DeployAction
              ActionTypeId:
                Category: Deploy
                Owner: AWS
                Provider: CodeDeploy
                Version: '1'
              Configuration:
                ApplicationName: !Ref ApplicationName
                DeploymentGroupName: !Ref TestDeploymentGroup
              InputArtifacts:
                - Name: BuildOutput

Outputs:
  PipelineURL:
    Description: URL to the CodePipeline Console
    Value: !Sub https://console.aws.amazon.com/codepipeline/home?region=${AWS::Region}#/view/${Pipeline}

パイプラインのモニタリングと分析

CI/CDパイプラインの効率性と信頼性を向上させるためには、モニタリングと分析が重要です。

CloudWatchによるモニタリング

CodePipelineは、パイプラインの実行状況をCloudWatchに自動的に送信します。これを活用して、以下のようなモニタリングが可能です:

  • パイプライン実行の成功率/失敗率
  • 各ステージの実行時間
  • ビルドの成功/失敗
  • デプロイの成功/失敗

CloudWatch Dashboardの作成

以下のような指標を含むダッシュボードを作成することで、パイプラインの健全性を一目で確認できます:

  • パイプライン実行数(成功/失敗)
  • 平均実行時間
  • コミットからデプロイまでのリードタイム
  • 障害発生後の平均復旧時間(MTTR)

アラートの設定

重要な問題を早期に検知するために、以下のようなアラートを設定することをお勧めします:

  • パイプライン実行失敗時のアラート
  • パイプライン実行時間閾値超過時のアラート
  • 手動承認待ち状態が一定時間継続した場合のアラート

セキュリティのベストプラクティス

CI/CDパイプラインのセキュリティを強化するための重要なベストプラクティスをいくつか紹介します:

  1. 最小権限の原則: 各サービスに必要最小限の権限のみを付与する
  2. 機密情報の保護: パスワードやAPIキーなどの機密情報はAWS Secrets Managerで管理する
  3. コード品質のチェック: SonarQubeなどのツールを統合し、セキュリティ脆弱性を検出する
  4. イメージスキャン: コンテナイメージの脆弱性スキャンを実施する
  5. インフラストラクチャのコード化: CloudFormationやTerraformを使用し、インフラストラクチャをコード管理する
  6. 監査ログの有効化: AWS CloudTrailを有効化し、API呼び出しを記録する

CI/CDパイプラインの最適化

パイプラインのパフォーマンスと効率を最適化するためのポイントをいくつか紹介します:

  1. ビルドキャッシュの活用: CodeBuildのキャッシュ機能を使用して、依存関係のダウンロード時間を短縮
  2. 並列処理の活用: 独立したタスクは並列実行することで全体の実行時間を短縮
  3. テストの最適化: テストを重要度に応じて分類し、クリティカルなテストを優先して実行
  4. アーティファクトサイズの最適化: 必要なファイルのみをアーティファクトに含める
  5. デプロイ戦略の最適化: 適切なデプロイ戦略(ローリング、ブルー/グリーンなど)を選択

トラブルシューティング

CI/CDパイプラインで発生しやすい問題とその解決策を紹介します:

  1. パイプライン実行失敗:
    • CodePipelineコンソールでエラーメッセージを確認
    • 各ステージのログを詳細に調査
    • IAM権限の問題がないか確認
  2. ビルド失敗:
    • CodeBuildのログを確認
    • buildspec.ymlの構文エラーがないか確認
    • 依存関係の問題がないか確認
  3. デプロイ失敗:
    • CodeDeployのログを確認
    • appspec.ymlの構文エラーがないか確認
    • デプロイスクリプトのエラーがないか確認
    • ターゲット環境のアクセス権限を確認
  4. パフォーマンス問題:
    • 各ステージの実行時間を分析
    • キャッシュの活用を検討
    • 並列処理の可能性を検討

まとめ

AWS CodePipelineを中心としたCI/CDパイプラインの構築について、基礎から応用まで解説しました。AWSの各種サービスを組み合わせることで、コードのコミットから本番環境へのデプロイまでを自動化し、開発プロセスの効率と品質を向上させることができます。

基本的なパイプラインから始めて、徐々に機能を追加していくアプローチがお勧めです。また、定期的にパイプラインの効率と信頼性を評価し、継続的に改善していくことで、より効果的なCI/CD環境を構築できるでしょう。

参考リソース

コメント

タイトルとURLをコピーしました