GitHub Actions workflowを使用してLambdaリソースを管理する
はじめに
AWS上のLambdaに直接ソースコードを入力して運用すると、GitHubのソースコードも適宜修正する必要があり、管理の手間が増します。
こうした課題を解決するのが、GitHub Actionsのワークフローです。
GitHub Actionsを活用すれば、ソースコードの管理をGitHub内で一元化できるだけでなく、CI/CDの自動化などさまざまなメリットを享受できます。
GitHub Actions workflowとは
GitHub Actions Workflow は、GitHub リポジトリ内で 自動化された処理(CI/CDパイプラインなど) を定義し、実行できる機能です。
ビルド・テスト・デプロイなどの作業を、コードのプッシュやプルリクエスト(PR)作成時に 自動実行することができます。
料金
- パブリックリポジトリの場合
- 無料で使用できます。
- プライベートリポジトリの場合
- アカウントの利用プランに応じてGitHubホステッドランナーの利用を対象とした課金があります。
- 一定量の無料使用時間とストレージが割り当てられています。
利用料金と制限事項については下記のドキュメントをご参照ください。
https://docs.github.com/ja/actions/administering-github-actions/usage-limits-billing-and-administration
前提
手順の実施前に以下が作成されていることを確認してください。
・GitHubにリポジトリが作成されていること
・GithubからAWSへアクセスするための認証情報(OIDC[OpenID Connect])
・AWS上に管理対象となるLambdaが事前に作成されていること
手順
- IAM IDプロバイダの登録
- IAMポリシーの登録
- IAMロールの登録
- GitHub Actionsにシークレットを登録
- Yamlファイルの作成
- ワークフローの実行
IAM IDプロバイダの登録
GitHub ActionsからAWSへアクセスするためのOIDC認証を設定します。
デプロイ側の環境(AWS)
AWS側でIDプロバイダを作成します。
IAM > IDプロバイダ > プロバイダを追加
プロバイダのタイプ:OpenID Connect
プロバイダのURL:token.actions.githubusercontent.com
対象者:sts.amazonaws.com
上記の通り入力します。
サムプリントを取得してプロバイダを追加します。
IAMポリシーの登録
AWSのコンソールからIAMを開きます。
左タブのアクセス管理>ポリシーから「ポリシーの作成」を押下します。
ポリシーエディタでJSONを選択し下記を貼り付けます。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"lambda:UpdateFunctionCode"
],
"Resource": "{更新したいLambda関数のARNを指定 ※複数指定可}"
}
]
}
「次へ」を押下し、
ポリシー名を入力後「ポリシーの作成」を押下します。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"lambda:UpdateFunctionCode"
],
"Resource": [
"arn:aws:lambda:ap-northeast-1:{ACCOUNT_ID}:function:{ワークフロー名}"
]
}
]
}
IAMロールの登録
左タブからロールを開きます。
「ロールの作成」を押下し信頼されたエンティティタイプはカスタム信頼ポリシーを選択します。
下記ステートメントを適宜書き換えてから貼り付けて「次へ」を押下します。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Federated": "arn:aws:iam::{ACCOUNT_ID}:oidc-provider/token.actions.githubusercontent.com"
},
"Action": "sts:AssumeRoleWithWebIdentity",
"Condition": {
"StringEquals": {
"token.actions.githubusercontent.com:aud": "sts.amazonaws.com"
},
"StringLike": {
"token.actions.githubusercontent.com:sub": "repo:{対象レポジトリ}:*"
}
}
}
]
}
許可ポリシーは作成したIAMポリシーを選択し「次へ」を押下します。
ロール名を入力後、「ロールを作成」を押下します。
GitHub Actionsにシークレットを登録
Githubの対象リポジトリ画面を開き、[Settings] > [Environments] を開きます。
「New Environment」で対象のブランチ名を入力し新しいEnvironmentを作成してください。
対象の「Environment」画面内の[New repository secret]を押下します。「Add Environment secrets」から下記ロールを追加してください。
Name | Value |
---|---|
AWS_LAMBDA_WORKFLOW_ROLE_ARN | 作成したLambdaのIAMロール名 |
workflow実行用Yamlファイルの作成
.github/workflows/配下にymlファイルを新規作成します。
下記ソースファイルをコピーし貼り付けてください。
対象パス、対象ブランチ名はご自身の環境に合わせて記載してください。
.github/workflows/lambda-workflow.yml
name: lambda-workflow
# 指定したブランチのプルリクエスト時に、対象パス配下のファイルで変更があったとき、ワークフローが実行
on:
pull_request:
types:
- closed
paths:
- '{対象パス}/**'
branches:
- {対象ブランチ名}
jobs:
build_and_deploy_lambda:
if: ${{ github.event.pull_request.merged == true }}
runs-on: ubuntu-latest
permissions:
id-token: write
contents: read
# ブランチ名から環境GitHubの環境変数を指定
environment: ${{ github.event.pull_request.base.ref }}
# リポジトリをチェックアウト
steps:
- name: Checkout Code
uses: actions/checkout@v3
with:
fetch-depth: 0
# AWS CLI を設定
- name: Configure AWS CLI
uses: aws-actions/configure-aws-credentials@v2
with:
role-to-assume: ${{ secrets.AWS_LAMBDA_WORKFLOW_ROLE_ARN }}
aws-region: ap-northeast-1
# 変更があったファイルのディレクトリのみ抽出
- name: Find Changed Lambda Directories
id: find_changed_dirs
run: |
if [ -z "${{ github.event.pull_request.base.sha }}" ] || [ -z "${{ github.sha }}" ]; then
echo "Error: Commit SHA is missing."
exit 1
fi
BASE_COMMIT=$(git merge-base "${{ github.event.pull_request.base.sha }}" "${{ github.sha }}")
echo "Base Commit: $BASE_COMMIT"
CHANGED_FILES=$(git diff --name-only "$BASE_COMMIT" "${{ github.sha }}")
CHANGED_DIRS=$(echo "$CHANGED_FILES" | grep '^{対象パス}/' | cut -d'/' -f3 | sort | uniq | tr '\n' ' ')
CHANGED_DIRS=$(echo "$CHANGED_DIRS" | tr -d '"')
if [ -z "$CHANGED_DIRS" ]; then
echo "No Lambda directories changed."
echo "LAMBDA_DIRS=" >> $GITHUB_ENV
else
echo "Changed Lambda Directories: $CHANGED_DIRS"
echo "LAMBDA_DIRS=$CHANGED_DIRS" >> $GITHUB_ENV
fi
# Lambda のデプロイ
- name: Deploy Changed Lambda Functions
if: env.LAMBDA_DIRS != ''
run: |
echo "Changed Lambda Directories: $LAMBDA_DIRS"
for dir in $LAMBDA_DIRS; do
# 変更があったファイルのディレクトリをzip化する
echo "Processing directory: $dir"
cd {対象パス}/$dir
zip -r lambda_function.zip .
FUNCTION_NAME="$dir"
# デプロイ前に現在のバージョンを保存する
echo "Publishing current version for Lambda function: $FUNCTION_NAME"
aws lambda publish-version --function-name $FUNCTION_NAME
# zipしたファイルをデプロイする
echo "Deploying Lambda function: $FUNCTION_NAME"
aws lambda update-function-code --function-name $FUNCTION_NAME --zip-file fileb://lambda_function.zip
cd - > /dev/null
done
今回のワークフローで実現できる要件は以下の通りです。
・ワークフローが実行されるのは「対象パス配下でファイルの変更があったとき」かつ「対象ブランチにプルリクエストされたとき」をトリガーとする
・対象パス配下で、変更があったファイルのディレクトリのみデプロイ
・デプロイされる前にAWS上のソースコードを保存
ワークフローの実行
対象パス配下のソースファイルを更新し、作業ブランチにプッシュします。
対象ブランチでプルリクエストしマージが完了すると、Github Actionのワークフローが実行されます。AWSコンソールからLambdaのソースファイルの内容が新しく置き換わっていること、バージョンが発行されデプロイ前のソースコードが保存されていることを確認してください。
まとめ
GitHub Actionsを利用してLambdaへの自動デプロイを実装することができました。
ソースコードをアレンジすれば、他にもさまざまなワークフローの要件を実現できるので、引き続き検証してみようと思います。
Discussion