0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

AWS CDK + GitHub Actionsで作るLambdaコンテナCI/CDパイプライン(3/4)

Last updated at Posted at 2025-07-03

1.はじめに

1.1.まえがき

本ブログは以下項目の4つに分かれており、本ブログはその3つ目になります。

※ 本ハンズオンの全コードはこちらのGitHubリポジトリで参照できます。

項番 ブログタイトル 概要
1 概要とAWS事前準備編 Lambdaコンテナの仕組みと環境準備
2 アプリケーションとCDK実装編 LambdaアプリとCDKコードの解説
3 GitHub Actions設定とデプロイ・挙動確認編(本ブログ) CI/CDパイプライン構築
4 トラブルシューティング集 ハマりポイントと解決方法まとめ

1.2.今回の内容

今回は CI/CDパイプライン部分を構築します。
GitHub Actionsの設定から、実際のデプロイ、そして動作確認まで進めていきます。

今回でやること:

  1. GitHub Actionsワークフローの作成:push時に自動実行されるCI/CDパイプライン
  2. 実際のデプロイと動作確認:CodeDeployによるカナリアリリースを体験
  3. GitHubシークレットの設定:安全な認証情報管理

前提条件:

以下が完了していることを前提とします:

2.ハンズオン

2.1.前提

2.1.1.実行環境

2.1.2.全体のファイル構成

  • 以下のファイル構成をAmazo SageMaker Studio Code Editor(IDE)で構築する

■ 本手順の最終的なファイル構成

your-app/
├── .gitignore              #【前回作成】
├── .github/
│   └── workflows/
│       └── deploy.yml      #【★今回作成★】GitHub Actions ワークフロー定義
├── app/
│   ├── app.py              #【前回作成】
│   └── Dockerfile          #【前回作成】
└── cdk/                    # AWS CDK アプリケーション (Python)
    ├── app.py              #【前回作成】 CDK エントリーポイント
    ├── cdk.json            #【前回作成】 CDK 設定ファイル
    ├── requirements.txt    #【前回作成】 CDK 依存関係
    ├── .venv/              # Python 仮想環境
    └── pipeline_stack/     # スタック定義を置くディレクトリ
        ├── __init__.py     #【前回作成】
        └── pipeline_stack.py #【前回作成】 CDK スタック定義 (Python)

2.1.3.アプリケーションの説明

  • 機能: HTTP GETリクエストを受け取ると、事前に設定されたメッセージと、現在実行されているLambda関数のバージョン情報、リクエストIDをJSON形式で返却する。
  • CI/CDパイプライン構築が目的のため、アプリケーション自体のロジックは最小限にしている。

2.1.4.インフラの説明

  • AWS上にサーバーレスなAPIバックエンドと、そのCI/CDパイプラインを構築する。

■ 利用するリソース

項番 提供元 リソース名 概要
1 AWS AWS Lambda アプリケーションコード(コンテナイメージ)を実行するコンピューティングサービス。
2 AWS Amazon ECR Lambda関数で利用するDockerコンテナイメージを保存・管理するためのプライベートリポジトリです。GitHub Actionsでビルドしたイメージがここにプッシュされる。
3 AWS Amazon API Gateway Lambda関数を外部(インターネット)からHTTPリクエストで呼び出すためのエンドポイントを作成
4 AWS AWS CodeDeploy Lambda関数の新しいバージョンを安全にデプロイするためのサービスです。今回 カナリアリリース戦略を採用する。
5 AWS IAM GitHub ActionsがAWSリソース(ECRへのプッシュ、CDKによるデプロイなど)を操作するため、またLambda関数やCodeDeployが必要な権限で動作するためのロールとポリシーを作成・管理。OIDC (OpenID Connect) を利用してGitHub ActionsとAWS間の安全な認証連携を実現する。
6 AWS AWS CDK (Cloud Development Kit) 上記のAWSリソース構成をPythonコードで定義し、CloudFormationスタックとしてプロビジョニング(作成・更新)する。
7 GitHub GitHub Actions GitHubリポジトリへのコードプッシュをトリガーとして、アプリケーションのビルド(Dockerイメージ作成)、ECRへのプッシュ、CDKによるAWS環境へのデプロイを自動化するCI/CDパイプラインを構築。
2.1.5.本項目での構築箇所

image.png

2.2.Github Actions作成

  • CI/CDパイプラインの中心となるコード
  • GitHubにプッシュされることで自動的に実行され、ビルド - デプロイまでを処理する。

2.2.1.GitHub Actionsワークフローの構成

  • このワークフローは大きく以下4つの処理ステップに分かれている。
  1. 環境セットアップ:Python/Node.js/AWS CDK
  2. AWS認証:OIDCを使って安全にAWSにアクセス
  3. コンテナビルド & プッシュ:DockerイメージをECRに配置
  4. CDKデプロイ:クラウドインフラを自動デプロイ

2.2.3.Qualifierの取得

スタック定義で必要なECRリポジトリ名にはQualifierが含まれます。
以下のコマンドをCloudShell環境で実行して、自身の環境の値を取得しコード内 # 環境変数定義 の ECR_REPOSITORYを修正

# CDKが作成したS3バケット名を取得
BUCKET_NAME=$(aws cloudformation describe-stack-resources --stack-name CDKToolkit --query "StackResources[?ResourceType=='AWS::S3::Bucket'].PhysicalResourceId" --output text --region us-east-1)

# Qualifierを抽出(バケット名のパターン:cdk-{QUALIFIER}-...)
YOUR_QUALIFIER=$(echo "$BUCKET_NAME" | cut -d'-' -f2)

# 確認出力
echo $YOUR_QUALIFIER

2.2.4.ワークフローファイルの作成

# ファイル作成
mkdir -p your-app/.github/workflows

# デプロイワークフローの作成
cat > your-app/.github/workflows/deploy.yml << 'EOF'
name: Deploy Lambda Container via CDK (Python)

# トリガー設定:masterブランチプッシュ時に実行
on:
  push:
    branches:
      - master # masterブランチへのプッシュでトリガー

# 権限設定(OIDC認証に必要)
permissions:
  id-token: write # OIDC トークンを発行するために必要
  contents: read  # リポジトリのコンテンツを読み取るために必要

jobs:
  deploy:
    runs-on: ubuntu-latest

    # 環境変数定義
    env:
      AWS_REGION: us-east-1 # 対象のAWSリージョン
      CDK_STACK_NAME: LambdaPipelineStackPy    # CDKスタック名 (app.pyのスタックIDと合わせる)
      ECR_REPOSITORY: cdk-★★自身の Qualifier★★-container-assets-${{ secrets.AWS_ACCOUNT_ID }}-us-east-1

    steps:
      # Step 1: ソースコード取得
      - name: Checkout code
        uses: actions/checkout@v4

      # Step 2: 環境セットアップ
      - name: Set up Python
        uses: actions/setup-python@v5
        with:
          python-version: '3.10' # CDKとLambdaで使うPythonバージョン

      # Node.js 環境のセットアップ
      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: '20'

      # AWS CDK CLI (npm) のインストール
      - name: Install AWS CDK CLI via npm
        run: npm install -g aws-cdk

      # Step 3: AWS認証(OIDC経由)
      - name: Configure AWS credentials
        uses: aws-actions/configure-aws-credentials@v4
        with:
          role-to-assume: arn:aws:iam::${{ secrets.AWS_ACCOUNT_ID }}:role/GitHubAction-AssumeRoleWithAction
          aws-region: ${{ env.AWS_REGION }}

      # Step 4: ECRログイン
      - name: Login to Amazon ECR
        id: login-ecr
        uses: aws-actions/amazon-ecr-login@v2

      # Step 5: Python依存関係インストール
      - name: Install Python dependencies
        working-directory: ./cdk
        run: |
          python -m pip install --upgrade pip
          pip install -r requirements.txt

      # Step 6: イメージタグ決定(Gitコミットハッシュ使用)
      - name: Set Image Tag
        id: image_tag
        run: echo "tag=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT

     # Step 7: Dockerイメージビルド & ECRプッシュ
      - name: Build, tag, and push image to Amazon ECR
        id: build-image
        env:
          ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }} # 例: 123456789012.dkr.ecr.us-east-1.amazonaws.com
          IMAGE_TAG: ${{ steps.image_tag.outputs.tag }}
        run: |
          ECR_IMAGE_URI="$ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG"
          docker build -t $ECR_IMAGE_URI app
          docker push $ECR_IMAGE_URI
          echo "ecr_image_uri=$ECR_IMAGE_URI" >> $GITHUB_OUTPUT # 完全なURIを出力

      # Step 8: CDKデプロイ実行
      - name: Deploy CDK Stack
        working-directory: ./cdk
        env:
          CDK_DEFAULT_REGION: ${{ env.AWS_REGION }}
        run: |
          echo "--- Running CDK deploy with image URI: ${ECR_IMAGE_URI} ---"
          # -c オプションでコンテキストとしてイメージタグを渡す
          cdk deploy ${{ env.CDK_STACK_NAME }} --require-approval never -c image_tag=${{ steps.image_tag.outputs.tag }} -vvv
EOF

3.CDKアプリ実行

  • 今まで作ったコードを全てGitHubにプッシュすることで、これ以降プッシュされると GitHub Actionsが自動でビルド・デプロイを実行する。

3.1.デプロイの実行

プロジェクトをGitHubにプッシュすると、先ほど作成したGitHub Actionsワークフローが自動で起動します。

# Git初期化(初回のみ)
git init

# 全ファイルを追加
git add .

# コミット(最初のコミット)
git commit -m "Initial commit with Lambda container and CDK setup"

# GitHubリポジトリをリモートに追加 (初回のみ)
# git remote add origin https://github.com/YOUR_GITHUB_USERNAME/YOUR_REPO_NAME.git

# masterブランチにプッシュ(GitHub Actionsがトリガされる)
git push -u origin master # または main

3.2.GitHubでの確認画面への遷移

  • GitHub画面で「Update」の文字が表示される、押下することで「Details」が表示される。
    image.png

  • 「Details」を押下して以下、ビルド・デプロイまでのフローが表示される
    image.png

3.2.1.カナリアリリースによる挙動の違い

  • CodeDeployのカナリアリリース戦略を用いているため、以下のような挙動をする。

    • 1.新バージョンに10%のトラフィックを流す(5分間様子見)
    • 2.問題なければ100%切り替え
    • 3.エラーがあれば自動ロールバック
  • 初回デプロイ: 約2分(リソース作成のみ)
    image.png

  • 2回目以降のデプロイ: 約7分(リソース更新 + CodeDeploy カナリアリリース待機時間 5分設定)
    image.png

3.3.デプロイ後の動作確認

  • デプロイ完了後、実際にAPIエンドポイントに CloudShell でアクセスして動作確認を実施します。

3.3.1.APIエンドポイントの確認

# スタック名を変数に設定
STACK_NAME="LambdaPipelineStackPy"

# CloudFormationスタックの出力からApiEndpointの値を取得
API_ENDPOINT=$(aws cloudformation describe-stacks --stack-name $STACK_NAME --query "Stacks[0].Outputs[?OutputKey=='ApiEndpoint'].OutputValue" --output text --region us-east-1)

# 取得したURLを確認
echo "取得した API エンドポイント URL: $API_ENDPOINT"

# エンドポイントへアクセス
curl "$API_ENDPOINT"

# 想定レスポンス:以下のようなレスポンスが Lambdaより返却される
{"message": "Hello from CDK !", "version_id": "3", "aws_request_id": "968a21ba-6f15-4cc7-bc15-a54e1b1a522d"}

3.3.2.設定変更の動作確認

  • カナリアリリースを体験するために、アプリケーション設定を変更する。
項目 変数名 変更前 変更後
タイムアウト LAMBDA_TIMEOUT 30 60
メッセージ LAMBDA_MESSAGE "Hello from CDK !" Hello from Lambda !

your-app/cdk/pipeline_stack/pipeline_stack.pyを編集後、再度Git commitとpushを実行します

# 変更をコミット
git add .
git commit -m "Update Lambda settings: timeout and message"
git push

3.3.3.変更結果の確認

■ タイムアウト確認

# タイムアウト取得
aws lambda list-functions \
    --query 'Functions[?contains(FunctionName, `LambdaPipelineStackPy-MyLambdaFunction`)].[Timeout]' \
    --output text \
    --region us-east-1

# 変更前: 30
# 変更後: 60  ←正しく更新されている!

■ メッセージ確認(カナリアリリース)
version_idも、新バージョンでは1つカウントアップされる

# 継続的にAPIにアクセス
curl "$API_ENDPOINT"

# 最初の5分間:新旧メッセージが混在!
{"message": "Hello from CDK !", "version_id": "3", ...}    # 90%の確率
{"message": "Hello from Lambda !", "version_id": "4", ...} # 10%の確率

# 5分経過後:新メッセージのみ
{"message": "Hello from Lambda !", "version_id": "4", ...} # 100%

4.クリーンアップ

  • ハンズオンで作成した AWS リソースを手動で削除します。
項番 リソース 作業手順 注意点
1 CloudFormation: CDKToolkit マネジメントコンソール > CloudFormation > スタック 依存リソースがある場合は削除失敗します
2 S3: cdk--assets-... マネジメントコンソール > S3 > バケット バケット内のオブジェクトも全削除が必要
3 ECR: cdk--container-assets-... マネジメントコンソール > ECR > リポジトリ コンテナイメージ代は日々課金されるため重要
4 IAM: GitHubAction-AssumeRoleWithAction マネジメントコンソール > IAM > ロール アタッチ済みポリシーも確認
5 IAM: GitHubAction-AssumeCdkRoles マネジメントコンソール > IAM > ポリシー このポリシーを使用中のロールがないか確認
6 IAM: IDプロバイダ token.actions.githubusercontent.com マネジメントコンソール > IAM > IDプロバイダ OIDC認証の設定
7 GitHub: シークレット AWS_ACCOUNT_ID GitHub > リポジトリ > Settings > Secrets セキュリティ対策として削除

5.おわりに

今回は第3回 GitHub Actions設定とデプロイ・挙動確認編を記載しました。

今回実施したことサマリ:

  • GitHub Actionsワークフロー作成:自動CI/CDパイプラインを構築
    • OIDCベース認証設定:セキュアなAWS認証を実現
    • コンテナイメージビルド:DockerコンテナをECRへ自動プッシュ
    • CDK自動デプロイ:インフラを自動でプロビジョニング
    • CodeDeployカナリアリリース設定:安全な本番更新方法を確認
  • 動作確認と設定変更テスト:機能の検証

次回は実際のトラブルシューティング集で今回発生したエラーについてまとめたいと思います。

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?