AWS Glue crawler のクロールが終わったら Lambda を実行する

本記事では AWS Glue crawler のクロールが終わったら Lambda を実行する構成を作ります。 データ処理の自動化の参考になれば幸いです。
2024.04.01

目的

本記事では AWS Glue crawler のクロールが終わったら Lambda を実行する構成を作ります。
だいたい以下のような構成となります。
blog_glue_trigger_architecture_diagram

また、本記事は AWS の公式ブログ "Event-driven refresh of SPICE datasets in Amazon QuickSight"[1]を参考にしています。
構築はほとんど CDK で行います。

前提条件・知識

  • AWS アカウントを作成済み
  • (ざっくりですが)IAM Role, Policy, EC2 インスタンスを作成できる権限がある
  • 使いたいAWS アカウントのリージョンで cdk bootstrap コマンドを実行済み
  • IAM Role, Policy を作って EC2 インスタンスにロールをアタッチする方法、Session Manager, aws cli の使い方

手順

まずは CDK を実行するための環境を EC2 インスタンス上に準備します。
本記事と環境を揃えるための手順なので、もし手元に cdk や諸々の権限のあるコンピューターがあれば、
後ろの方の S3 bucket, Glue Crawler, EventBridge Rule, CloudWatch logs, Lambda function を作成 から開始しても大丈夫です。

EC2 インスタンスにアタッチするロール・EC2インスタンスを作成

以下のポリシーを関連付けたロールを作成します。
このロールはあとで EC2 インスタンスにアタッチします。
⚠️ 最小権限ではありません。実際のプロジェクトで使うときは、最小権限を設定したほうが良いです。

  • AmazonSSMManagedInstanceCore: Session Manager で EC2 インスタンスに接続するためです。
  • AmazonS3FullAccess: S3 にオブジェクトをアップロード、削除するためです。
  • 以下の Inline Policy:cdk のデプロイに必要な権限[2]、Glue クローラーを開始、CloudWatch Logs を tail 、 CloudFormation の Stack を Describe する権限です。
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "sts:AssumeRole"
            ],
            "Resource": [
                "arn:aws:iam::*:role/cdk-*"
            ]
        },
        {
            "Sid": "StartCrawler",
            "Effect": "Allow",
            "Action": [
                "glue:StartCrawler"
            ],
            "Resource": [
                "*"
            ]
        },
        {
            "Sid": "TailLog",
            "Effect": "Allow",
            "Action": [
                "logs:StartLiveTail",
                "logs:FilterLogEvents"
            ],
            "Resource": [
                "*"
            ]
        },
        {
            "Sid": "CfnDescribe",
            "Effect": "Allow",
            "Action": [
                "cloudformation:DescribeStacks"
            ],
            "Resource": [
                "*"
            ]
        }
    ]
}

そして、作成したロールをアタッチして EC2 インスタンスを作成します。
私の場合以下のような設定でインスタンスを作成しました。

  • OS: AL2023
  • インスタンスタイプ:t2.micro
  • サブネット:public サブネット
  • Public IPの割り当て:有効
  • Security group:全ポートを閉じてます。Session Manager で接続するため、ポートを開ける必要がないためです。

EC2 インスタンス上で CDK の実行に必要なパッケージをインストール

作成した EC2 インスタンスに Session Manager で接続して、以下のコマンドを実行します。
マネジメントコンソールから接続する場合は、 EC2 > 作成したインスタンスを選択 > Connect > Session Manager をクリックします。

cd ~
sudo dnf install -y git
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash  # [3] を参考にしてます。
source ~/.bashrc
nvm install --lts
npm -g install typescript aws-cdk

git は後でプロジェクトを clone するために、 node.js と typescript, aws-cdk は CDK コマンドを実行するためにインストールします。
エラーがなければ準備完了です。

S3 bucket, Glue Crawler, EventBridge Rule, CloudWatch logs, Lambda function を作成

ここから本題に入ります。

Session Manager で接続して、以下のコマンドを実行します。
私が作成した本ブログ用のリポジトリ(https://github.com/yuta-cmth/blog-glue-trigger)の clone と、必要なパッケージをインストールします。

cd ~
git clone https://github.com/yuta-cmth/blog-glue-trigger.git
cd blog-glue-trigger
npm i

続いて、cdk コマンドを使ってリソースを作成します。

# リソース作成
cdk deploy --require-approval never

コマンド実行後、ターミナルで以下のような出力があれば成功です。

✨ Total time: 110.1s

上記のコマンドで作成されたリソースは主に以下の画像のとおりです。

blog_glue_trigger_architecture_diagram

実際に作成されたリソースを確認したい場合、マネジメントコンソールで各サービスを確認したり、CloudFormation の Stack の中を見ることで確認できます。

このあとは、

  1. Crawler を実行する
  2. Crawler の実行が完了すると、EventBridge rule がイベントをキャッチして Lambda を呼び出す
  3. Lambda が CloudWatch Logs にログを書き込む(Lambda の中身は こちら で確認できます。)
  4. CloudWatch Logs にログが書き込まれていることを確認する

の流れで動作を確認していきます。

クローリングのあとに Lambda が動くことを確認

まずは、以下のコマンドで CloudFormation から必要なリソースの名前を取得します。

# クロールする S3 bucket、クローラー、クローラー実行後に実行される Lambda のログを保存するロググループ名を取得します。
# CloudFormation の Outputs から取得しています。
bucket_name=$(aws cloudformation describe-stacks --stack-name BlogGlueTriggerStack --output text --query 'Stacks[0].Outputs[?OutputKey==`BlogGlueCrawlerBucketName`].OutputValue')
crawler_name=$(aws cloudformation describe-stacks --stack-name BlogGlueTriggerStack --output text --query 'Stacks[0].Outputs[?OutputKey==`BlogGlueCrawlerName`].OutputValue')
log_group_name=$(aws cloudformation describe-stacks --stack-name BlogGlueTriggerStack --output text --query 'Stacks[0].Outputs[?OutputKey==`BlogGlueCrawlerEventHandlerLogGroupName`].OutputValue')

次に以下のコマンドで S3 にファイルをアップロード後、Glue のクローラーを実行します。
さらに aws logs コマンドを実行しておいて、クローリングが完了したら実行される Lambda のログを tail します。

aws s3 cp ./s3_test_data/data "s3://${bucket_name}/data" --recursive
aws glue start-crawler --name "${crawler_name}"
aws logs tail --follow "${log_group_name}"

クローリングが多分 1分くらいで終わるのでしばらく待ちます。
以下のように Lambda のログが出力されれば、クローリング完了後に Lambda が実行できていることが分かります。

blog_glue_trigger_log

リソースの削除

以下のコマンドで cdk で作成したリソースを削除します。

aws s3 rm "s3://${bucket_name}" --recursive
cdk destroy --force

s3 rm を実行しているのは、S3 bucket にオブジェクトが入っていると cdk destroy コマンドで bucket を削除できないためです。

最後に

本記事では、AWS Glue Crawler のクロール完了後に Lambda を実行する構成を構築する方法を解説しました。
データ処理の自動化の参考になれば幸いです。

参考

[1] Event-driven refresh of SPICE datasets in Amazon QuickSight. (2020, October 12). Amazon Web Services. https://aws.amazon.com/blogs/big-data/event-driven-refresh-of-spice-datasets-in-amazon-quicksight/
[2] Kay, A. (n.d.). What IAM permissions are needed to use CDK Deploy? Stack Overflow. Retrieved March 27, 2024, from https://stackoverflow.com/questions/57118082/what-iam-permissions-are-needed-to-use-cdk-deploy
[3] Tutorial: Setting Up Node.js on an Amazon EC2 Instance. (n.d.). AWS SDK for JavaScript. Retrieved March 29, 2024, from https://docs.aws.amazon.com/sdk-for-javascript/v2/developer-guide/setting-up-node-on-ec2-instance.html