【AWS】CodePipelineの最後にCloudFrontのキャッシュを消すLambdaを配置する

今回はCodePipelineの最後にCloudFrontのキャッシュを削除するLambdaを配置したいと思います。 CodePipelineでいい感じにCI/CDを組んだものの、CloudFront側でキャッシュされていると更新がクライアントに反映されないケースがあるため、その対応策となります。

前提

下地として、下記記事を参考にしています。

この記事の中で、CoudFrontのキャッシュを消すLambdaが紹介されています。 素直にこれをCodePipelineに組み込めばいいやと思いきや、多少改造が必要でした。

Lambda

下記が今回使用するLambdaになります。 このLambdaの実行ロールには、通常の権限に加えて"cloudfront:*"CloudFrontに関する操作権限を、"codepipeline:*"CodePipelineに関する操作権限を与えています。

また、環境変数としてDISTRIBUTION_IDを用いており、ここに削除したいCloudFrontのディストリビューションを指定しています。

削除後は、呼び出し元であるCodePipelineに処理成功を伝えるためput_job_success_resultを実行しています。 ※これがないとCodePipeline上は失敗になります。

from __future__ import print_function
import os
import boto3
import time
import json

def lambda_handler(event, context):
    # 削除対象となるCloudFrontのディストリビューションを取得
    target = os.environ['DISTRIBUTION_ID']
    client = boto3.client('cloudfront')
    codepipeline = boto3.client('codepipeline')
    # 削除したいパスに合わせてキャッシュ削除を構成
    # ここでは全てのキャッシュを削除したいので'/*'を指定している
    invalidation = client.create_invalidation(DistributionId=target,
        InvalidationBatch={
            'Paths': {
                'Quantity': 1,
                'Items': ['/*']
        },
        'CallerReference': str(time.time())
    })
    # CodePipelineに完了を伝達する
    codepipeline.put_job_success_result(jobId = event['CodePipeline.job']['id'])
    
    return {
        'statusCode': 200,
        'body': json.dumps('Hello from Lambda!')
    }

Pipelineへの組み込み

今回もCDKで設定を行います。 作成したパイプラインのstagesの中の最後にLambdaInvokeActionを作成し、実行するLambdaを指定しましょう。

import * as cdk from 'aws-cdk-lib';
import * as codepipeline from 'aws-cdk-lib/aws-codepipeline';
import * as actions from 'aws-cdk-lib/aws-codepipeline-actions';
import * as lambda from 'aws-cdk-lib/aws-lambda';

const lambdaArn = '【先ほど作成したLambdaのARN】';

// CodePipelineの設定
const pipeline = new codepipeline.Pipeline(this, `SamplePipeline`, {
    pipelineName: `SamplePipeline`,
    // パイプラインの各ステージを設定
    stages: [
        // ソース取得・ビルド・デプロイ等は割愛...
        // キャッシュ削除
        {
            stageName: 'DeleteCache',
            actions: [
                new actions.LambdaInvokeAction({
                    actionName: "deleteCache",
                    lambda: lambda.Function.fromFunctionArn(this, 'deleteCacheLambda', lambdaArn)
                })
            ]
        }
    ]
});

これでパイプラインの最後にこのLambdaが走り、配信したソースのキャッシュが削除されるため、最新のソースを配信することができます。

まとめ

今回はCodePipelineの最後にLambdaを実行させて、CloudFront上のキャッシュを削除する方法について紹介しました。 ReactVueをフロントエンドに使っている場合S3にビルド結果を格納して、それをCloudFrontを使って配信するような手法がサーバレスとなり、低コストで実現できます。

その際につい忘れがちなCDNのキャッシュ削除までCI/CDの中に組み込むことで、クライアントに迅速に更新を反映できるので役立つケースが多いかと思います。

今回の内容が役立ちましたら幸いです。

参考

SNSでシェアする