AWS CodePileLineにてLambdaからCloudFrontのInvalidationを自動実行
はじめに
S3上のコンテンツをCloudFrontを使用し配信している。
参照:独自ドメインを使用してS3上の静的ウェブサイトをRoute53を使用し公開する
また、githubへpushした際、CodePipeLineを使用し自動build、自動deployは対応済
参照:GithubへのpushをトリガーとしてCode PipelineでJekyllをビルドしてS3にデプロイする
S3の更新をトリガーとするとLambdaが必要以上に実行されてしまう
参照:AWS S3更新時にLambdaでCloudFrontのInvalidationを自動実行
その為、CodePileLineの処理の一環として、Lambdaを実行する
パイプライン処理は、CodeCommitにPushしたソースをCodePipelineでS3にデプロイ後、AWS Lambdaを呼び出しLambda FunctionでInvalidatioinとInvalidationのステータスチェックを行い、Invalidationを実行する。
手順
IAM ロールの作成
IAM コンソールから新しいロールを作成する
ロールの作成
を選択
信頼されたエンティティの種類を選択
AWSサービス
選択
ユースケースの選択
Lambda
を選択
次のステップ
を選択
ポリシーの作成
を選択
権限内容は以下の JSON で指定する
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "VisualEditor0",
"Effect": "Allow",
"Action": [
"codepipeline:PutJobFailureResult",
"codepipeline:PutJobSuccessResult",
"cloudfront:CreateInvalidation"
],
"Resource": "*"
},
{
"Sid": "VisualEditor1",
"Effect": "Allow",
"Action": [
"logs:CreateLogStream",
"logs:CreateLogGroup",
"logs:PutLogEvents"
],
"Resource": "arn:aws:logs:*:*:*"
}
]
}
タグ
は任意で必要であれば作成する
名前
も任意で自分のわかりやすい名称をつける
例:lambda_cloud_front_invalidation
先ほど作成したポリシーを検索し、選択
次のステップ
を選択
タグ
は任意で必要であれば作成する
名前
も任意で自分のわかりやすい名称をつける
例:lambda_cloud_front_invalidation
ポリシーと区別する必要もないと考えたので同じ名前
Lambda 関数の作成
Lambda コンソールから新しい関数を作成する
一から作成
を選択
関数名は任意で入力
ランタイムで使用する言語は「Python 3.8」、実行ロールは既存のロールから「先ほど作成した IAM ロール」を指定する
Lambda関数は以下のように記載する
from __future__ import print_function
import boto3
import json
import time
cp = boto3.client('codepipeline')
cf = boto3.client('cloudfront')
# codepipelineへ成功jobを返答する
def put_job_success(job_id):
cp.put_job_success_result(jobId=job_id)
# codepipelineへ失敗jobを返答する
def put_job_failure(job_id, err):
message = 'Function exception: ' + str(err)
cp.put_job_failure_result(
jobId=job_id,
failureDetails={
'type': 'JobFailed',
'message': message
}
)
# lambdaのmain関数
def lambda_handler(event, context):
try:
job_id = event['CodePipeline.job']['id']
job_data = event['CodePipeline.job']['data']
user_parameters = json.loads(
job_data['actionConfiguration']['configuration']['UserParameters']
)
pipeline_name = user_parameters['PipelineName']
distribution_id = user_parameters['DistributionId']
res = cf.create_invalidation(
DistributionId=distribution_id,
InvalidationBatch={
'Paths': {
'Quantity': 1,
'Items': ['/*'],
},
'CallerReference': str(time.time())
}
)
put_job_success(job_id)
except Exception as err:
put_job_failure(job_id, err)
return "Complete."
CodePipeLineの設定
CodePipeLineから呼び出すための設定を行う
Deployを実行した後に呼び出しを行うため、最下段のステージを追加する
を選択
アクション名(任意)、アクションプロバイダはAWS Lambda
、リージョン(任意)、関数名は先ほど作成したLambda関数名、ユーザパラメータはLambdaに渡す引数
ユーザパラメータとしてこのPipeLineの名称と更新するCloudFrontのDistributionIdをjson形式にて記載する
{
"PipelineName": "PipeLineの名称",
"DistributionId": "更新するCloudFrontのDistributionId"
}
おわりに
問題なく実行はされた。これで自動化完了。
PipeLine処理がいつ完了したか取得するため、SNSを用いてSlackへ通知させるようにしたい。
参考
Subscribe via RSS