この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
本ブログでは、GitHub Actionsを使い、main ブランチへの push をトリガーにコンテナイメージをビルドしてコンテナレジストリのAmazon ECRにプッシュし、AWS Lambdaにコンテナイメージをデプロイする方法を紹介します。
実質的にやっていることは、GitHub の ECS 向けドキュメントをベースに、以下の変更を加えています。
- GitHub から AWS への認証に、IAMアクセスキーの代わりに OpenID Connect(OIDC)を利用
- デプロイ先をAmazon ECSからAWS Lambdaへ変更
大前提として、デプロイのゴールはLambda関数のコンテナイメージを更新することにフォーカスしており、Lambda関数の作成、設定変更、Lambda関数を呼び出すリソースのデプロイは本記事のスコープ外です。
0. GitHub レポジトリにアプリケーションを用意
以下のような階層のLambda関数用レポジトリを用意します。
$ tree -a -I '.git'
.
├── .github
│ └── workflows
│ └── aws-lambda-deploy.yml
├── Dockerfile
└── app.py
app.py
import sys
def handler(event, context):
return 'Hello from AWS Lambda using Python' + sys.version + '!'
Dockerfile
FROM public.ecr.aws/lambda/python:3.9
COPY app.py ${LAMBDA_TASK_ROOT}
CMD [ "app.handler" ]
.github/workflows/aws-lambda-deploy.yml
が GitHub Actionsのワークフロー用設定ファイルです。
具体的な内容は ステップ4 で解説しています。
1. Amazon ECR レポジトリの作成
コンテナレジストリ Amazon ECR にレポジトリを作成します。
2. AWS Lambda 関数の作成
ウォークスルー手順簡易化のため、コンテナ版AWS Lambda関数を事前に作成します。
さらに、コンテナイメージURIには既存の URI を指定しておきます。
3. AWS側で OIDC 設定
GitHubからAWSリソースを操作する際に、OIDCで取得した一時トークンを利用します。
AWS側では
- アイデンティティプロバイダー
- GitHubのOIDCがAssumeするIAMロール
を作成します。
これらリソースは各AWSアカウントごとに一つ用意します。
参考 : Configuring OpenID Connect in Amazon Web Services - GitHub Docs
アイデンティティプロバイダー
IAM→アイデンティティプロバイダーから作成します。
以下を指定します。
- Provider type : OpenID Connect
- Provider URL : https://token.actions.githubusercontent.com
- Audience : sts.amazonaws.com
作成されたリソースの ARN を控えます。
IAM ロール
GitHub アクション aws-actions/configure-aws-credentials の GitHub ページに、IAM ロールを作成するCloudFormationテンプレートが用意されています。
このテンプレートを流して、リソース作成します。
スタック作成時に以下を指定します。
- GitHub 組織名
- 先程作成したOIDCプロバイダーのARN
- GitHub レポジトリ名
なお、現時点の CloudFormation テンプレートは以下の通りです。
Parameters:
GitHubOrg:
Type: String
RepositoryName:
Type: String
OIDCProviderArn:
Description: Arn for the GitHub OIDC Provider.
Default: ""
Type: String
Conditions:
CreateOIDCProvider: !Equals
- !Ref OIDCProviderArn
- ""
Resources:
Role:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Statement:
- Effect: Allow
Action: sts:AssumeRoleWithWebIdentity
Principal:
Federated: !If
- CreateOIDCProvider
- !Ref GithubOidc
- !Ref OIDCProviderArn
Condition:
StringLike:
token.actions.githubusercontent.com:sub: !Sub repo:${GitHubOrg}/${RepositoryName}:*
GithubOidc:
Type: AWS::IAM::OIDCProvider
Condition: CreateOIDCProvider
Properties:
Url: https://token.actions.githubusercontent.com
ClientIdList:
- sts.amazonaws.com
ThumbprintList:
- a031c46782e6e6c662c2c87c76da9aa62ccabd8e
Outputs:
Role:
Value: !GetAtt Role.Arn
作成された IAMロールには、ポリシーを追加します。
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "ECR",
"Effect": "Allow",
"Action": [
"ecr:BatchCheckLayerAvailability",
"ecr:CompleteLayerUpload",
"ecr:InitiateLayerUpload",
"ecr:PutImage",
"ecr:UploadLayerPart"
],
"Resource": "*"
},
{
"Sid": "Lambda",
"Effect": "Allow",
"Action": "lambda:UpdateFunctionCode",
"Resource": "*"
}
]
}
許可するActionは要件に合わせて調整してください。
4. GitHub Actions ワークフローを作成
Lambda関数のレポジトリに Lambda デプロイ用のワークフローを追加します。
ファイル冒頭の env
ブロックで定義している変数を環境に合わせて調整してください。
.github/workflows/aws-lambda-deploy.yml
name: Deploy container image to AWS Lambda
on:
push:
branches:
- main
env:
AWS_ACCOUNT_ID: MY_ACCOUNT_ID
AWS_ROLE_NAME: MY_ROLE_NAME
AWS_ROLE_SESSION_NAME: MY_ROLE_SESSION_NAME
AWS_REGION: us-west-1
ECR_REPOSITORY: MY_REPOSITORY_NAME
LAMBDA_FUNCTION_NAME: MY_FUNCTION_NAME
permissions:
id-token: write
contents: read
jobs:
aws-deploy:
name: Push to ECR
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@master
with:
role-to-assume: arn:aws:iam::${{ env.AWS_ACCOUNT_ID }}:role/${{ env.AWS_ROLE_NAME }}
role-session-name: ${{ env.AWS_ROLE_SESSION_NAME }}
aws-region: ${{ env.AWS_REGION }}
- name: Login to Amazon ECR
id: login-ecr
uses: aws-actions/amazon-ecr-login@v1
- name: Build, tag, and push image to Amazon ECR
id: build-image
env:
ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
IMAGE_TAG: ${{ github.sha }}
run: |
# Build a docker container and
# push it to ECR so that it can
# be deployed to Lambda.
docker build -t $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG .
docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG
# Update Lambda configuration
aws lambda update-function-code --function-name $LAMBDA_FUNCTION_NAME --image-uri $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG
ポイントは以下です。
- アクション
aws-actions/configure-aws-credentials
でOIDCトークンを取得 - アクション
aws-actions/amazon-ecr-login
で ECR にログイン - Gitのコミットハッシュ値をイメージタグ(
IMAGE_TAG
)に利用
最後のステップでは API aws lambda update-function-code
を直接呼び出してLambda関数のイメージだけを更新しています。
AWS CDK 等を利用すると、Lambda 関数を使ったサービス全般のデプロイが可能です。
5. 動作確認
GitHub の main ブランチに更新が走ると、今回登録したワークフローが実行されることを確認してください。
GitHub 側でワークフローの実行が成功し、AWS 側で以下を確認できればOKです。
- ECR に新しいイメージのPUSHされている
- Lambda 関数のコンテナイメージが最新のものに変更されている
最後に
AWS Lambdaのコンテナイメージ対応により、CI/CDパイプラインを構築しやすくなりました。
本ブログでは、その一例として、GitHub ActionsとOpenID Connect(OIDC)を利用し、mainブランチへの更新をトリガーに、コンテナLambdaへデプロイする方法を紹介しました。
お使いのLambdaにピッタリなCI/CD環境を構築し、Lambdaの開発サイクルを加速させちゃいましょう!
参考
- GitHub Actions OIDCでconfigure-aws-credentialsでAssumeRoleする | DevelopersIO
- Deploying to Amazon Elastic Container Service - GitHub Docs
- Configuring OpenID Connect in Amazon Web Services - GitHub Docs
- GitHub - aws-actions/configure-aws-credentials: Configure AWS credential environment variables for use in other GitHub Actions.