SQS を活用したイベント駆動型 Glue Crawler の設定方法

SQS を活用したイベント駆動型 Glue Crawler の設定方法

岩佐 孝浩
岩佐 孝浩
5 min read
ETL Glue

はじめに

Glue Crawler は S3 バケットのイベント通知を利用したクロール が可能です。これにより、フルスキャンを回避し、クロールのパフォーマンスとコストの両面で大きなメリットが得られます。

AWS リソースの作成

以下の内容で CloudFormation テンプレートを作成してください。

AWSTemplateFormatVersion: '2010-09-09'
Description: Glue crawler test

Resources:
  SqsQueue:
    Type: AWS::SQS::Queue
    Properties:
      SqsManagedSseEnabled: true
      QueueName: glue-crawler-test-queue

  SqsQueuePolicy:
    Type: AWS::SQS::QueuePolicy
    Properties:
      Queues:
        - !Ref SqsQueue
      PolicyDocument:
        Version: '2008-10-17'
        Id: __default_policy_ID
        Statement:
          - Effect: Allow
            Principal:
              AWS:
                - !Sub arn:aws:iam::${AWS::AccountId}:root
                - !GetAtt IAMRoleGlueCrawler.Arn
            Action: sqs:*
            Resource: !GetAtt SqsQueue.Arn
          - Effect: Allow
            Principal:
              Service: s3.amazonaws.com
            Action: sqs:*
            Resource: !GetAtt SqsQueue.Arn

  S3Bucket:
    Type: AWS::S3::Bucket
    DependsOn: SqsQueuePolicy
    Properties:
      BucketName: !Sub glue-crawler-test-${AWS::AccountId}-${AWS::Region}
      BucketEncryption:
        ServerSideEncryptionConfiguration:
          - ServerSideEncryptionByDefault:
              SSEAlgorithm: AES256
      NotificationConfiguration:
        QueueConfigurations:
          - Event: 's3:ObjectCreated:*'
            Queue: !GetAtt SqsQueue.Arn
      PublicAccessBlockConfiguration:
        BlockPublicAcls: TRUE
        BlockPublicPolicy: TRUE
        IgnorePublicAcls: TRUE
        RestrictPublicBuckets: TRUE

  IAMRoleGlueCrawler:
    Type: AWS::IAM::Role
    Properties:
      Path: /service-role/
      RoleName: !Sub glue-crawler-test-service-role
      AssumeRolePolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Effect: Allow
            Principal:
              Service: glue.amazonaws.com
            Action: sts:AssumeRole
      Policies:
        - PolicyName: cw-logs
          PolicyDocument:
            Version: '2012-10-17'
            Statement:
              - Effect: Allow
                Action:
                  - logs:CreateLogGroup
                  - logs:CreateLogStream
                  - logs:PutLogEvents
                Resource: "*"
        - PolicyName: glue
          PolicyDocument:
            Version: '2012-10-17'
            Statement:
              - Effect: Allow
                Action:
                  - glue:CreateTable
                  - glue:GetDatabase
                  - glue:GetTable
                  - glue:UpdateTable
                Resource: "*"
        - PolicyName: s3
          PolicyDocument:
            Version: '2012-10-17'
            Statement:
              - Effect: Allow
                Action:
                  - s3:GetObject
                  - s3:ListBucket
                  - s3:PutObject
                Resource: '*'

  GlueDatabase:
    Type: AWS::Glue::Database
    Properties:
      CatalogId: !Ref AWS::AccountId
      DatabaseInput:
        Name: glue-crawler-test-db

  GlueTable:
    Type: AWS::Glue::Table
    Properties:
      CatalogId: !Ref AWS::AccountId
      DatabaseName: !Ref GlueDatabase
      TableInput:
        Name: glue-crawler-test-table
        TableType: EXTERNAL_TABLE
        Parameters:
          classification: json
        StorageDescriptor:
          Location: !Sub 's3://${S3Bucket}/'
          Compressed: false
          InputFormat: org.apache.hadoop.mapred.TextInputFormat
          OutputFormat: org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat
          SerdeInfo:
            SerializationLibrary: org.openx.data.jsonserde.JsonSerDe

  GlueCrawler:
    Type: AWS::Glue::Crawler
    Properties:
      Name: glue-crawler-test
      Role: !Sub service-role/${IAMRoleGlueCrawler}
      Targets:
        CatalogTargets:
          - DatabaseName: !Ref GlueDatabase
            Tables:
              - !Ref GlueTable
      SchemaChangePolicy:
        UpdateBehavior: UPDATE_IN_DATABASE
        DeleteBehavior: LOG

<YOUR_CFN_BUCKET> を適切な値に置き換え、以下のコマンドで CloudFormation スタックをデプロイしてください。

STACK_NAME=glue-crawler-test

aws cloudformation package \
  --template-file template.yaml \
  --s3-bucket <YOUR_CFN_BUCKET> \
  --s3-prefix "$STACK_NAME/$(date +%Y)/$(date +%m)/$(date +%d)/$(date +%H)/$(date +%M)" \
  --output-template-file package.template

aws cloudformation deploy \
  --stack-name $STACK_NAME \
  --template-file package.template \
  --capabilities CAPABILITY_NAMED_IAM

Glue Crawler ターゲットテーブル設定の更新

現時点では、CloudFormation で Glue Crawler 用の S3 イベント通知がサポートされていません。そのため、ターゲットテーブルの設定を手動で更新する必要があります。

CloudFormation Support For S3 Event isn’t currently available. S3 Event Crawler’s integration with CloudFormation is in scope and in the works. We plan on releasing this coverage to Cloudformation some later this year. Thank you for patience.

ターゲットテーブルを選択し、Edit をクリックします。

Subsequent crawler runs セクションで Crawl based on events を選択します。

テスト

JSON バージョン 1 による Glue テーブルスキーマの更新

サンプル JSON ファイルをアップロードして S3 イベント通知をトリガーします。

echo '{"message": "Hello World"}' > sample1.json
aws s3 cp sample1.json s3://glue-crawler-test-<ACCOUNT_ID>-<REGION>/

Glue Crawler を開始します。

aws glue start-crawler --name glue-crawler-test

状態が STOPPING になるまでモニタリングします。

$ aws glue get-crawler --name glue-crawler-test | jq -r '.Crawler.State'
STOPPING

更新された Glue テーブルスキーマを確認します。

aws glue get-table \
  --database-name glue-crawler-test-db \
  --name glue-crawler-test-table \
| jq '.Table.StorageDescriptor.Columns'
[
  {
    "Name": "message",
    "Type": "string"
  }
]

JSON バージョン 2 による Glue テーブルスキーマの更新

新しいバージョンの JSON ファイルで同様のプロセスを繰り返します。

echo '{"message": "Hello World", "statusCode": 200}' > sample2.json
aws s3 cp sample2.json s3://glue-crawler-test-<ACCOUNT_ID>-<REGION>/

Glue Crawler を開始します。

aws glue start-crawler --name glue-crawler-test

状態が STOPPING になるまでモニタリングします。

$ aws glue get-crawler --name glue-crawler-test | jq -r '.Crawler.State'
STOPPING

更新された Glue テーブルスキーマを確認します。

aws glue get-table \
  --database-name glue-crawler-test-db \
  --name glue-crawler-test-table \
| jq '.Table.StorageDescriptor.Columns'
[
  {
    "Name": "message",
    "Type": "string"
  },
  {
    "Name": "statuscode",
    "Type": "int"
  }
]

SQS メッセージ数の確認

SQS キューに残っているメッセージがないことを確認します。

$ queue_url=$(aws sqs get-queue-url --queue-name glue-crawler-test-queue | jq -r '.QueueUrl')
$ aws sqs get-queue-attributes \
  --queue-url $queue_url \
  --attribute-names ApproximateNumberOfMessages
{
    "Attributes": {
        "ApproximateNumberOfMessages": "0"
    }
}

クリーンアップ

プロビジョニングした AWS リソースを削除します。

aws s3 rm s3://glue-crawler-test-<ACCOUNT_ID>-<REGION>/ --recursive
aws cloudformation delete-stack --stack-name $STACK_NAME

まとめ

Glue Crawler を S3 イベント通知と SQS を活用して構成することで、フルスキャンを回避し、コスト削減とパフォーマンスの向上を実現できます。このアプローチは、イベント駆動型データパイプラインを実装する際の効率的なソリューションとなります。

Happy Coding! 🚀

岩佐 孝浩

岩佐 孝浩

Software Developer at KAKEHASHI Inc.
AWS を活用したクラウドネイティブ・アプリケーションの要件定義・設計・開発に従事。 株式会社カケハシで、処方箋データ収集の新たな基盤の構築に携わっています。 Japan AWS Top Engineers 2020-2023