Glue CrawlerをAurora MySQLへ向けて実行してみる
こんにちは、データ事業本部のキタガワです。
Glue CrawlerをAurora MySQLに対して実行し、テーブル情報をGlue Data Catalogに登録する手順をまとめました。
前提条件
この記事を理解するには、以下の知識と権限が必要です。
- AWSの基本的な知識(VPC、IAM、RDS、Glueなど)
- IAMユーザーに適切な権限(CloudFormation、RDS、Glue、VPC、IAMの操作権限)
- MySQLの基本的な知識
稼働中のAurora MySQLがすでにある状態を想定しています。
前提としては以下の通りです。
- Aurora MySQLクラスターが稼働していること
- VPCとサブネットが設定済みであること
- 以下の情報が手元にあること
- Aurora MySQLのエンドポイント
- データベース名
- 接続ユーザー名
- 接続パスワード
- VPCのID
- プライベートサブネットのID
今回やりたいことの簡単なイメージ図はこんな感じです。
CloudFormationテンプレートの概要
今回は前提となるAurora MySQLのデータベースとその他のリソースをCloudFormationを用いて作成します。
このテンプレートでは以下のリソースを作成します。
-
ネットワークリソース
- VPC: Aurora MySQLとGlue Crawlerを実行するためのネットワーク環境
- プライベートサブネット: Aurora MySQLとGlue Crawlerを配置するためのサブネット
- ルートテーブル: プライベートサブネットのルーティング設定
- VPCエンドポイント: S3、SSM、SSMメッセージング用のエンドポイント
-
セキュリティリソース
- セキュリティグループ: Aurora MySQL、SSM、SSM Bastion用のセキュリティグループ
- IAMロール: SSM Bastion用のIAMロール
-
データベースリソース
- Aurora MySQLクラスター: メインのデータベース
- パラメータグループ: データベースの設定
- Secrets Manager: データベースの認証情報
-
Glueリソース
- Glueデータベース: クローリング結果を格納するデータベース
-
踏み台サーバ
- SSM Bastion: プライベートサブネット内の踏み台サーバ
- セッションマネージャー経由でアクセス: 踏み台サーバへのアクセスはSSMセッションマネージャーを使用します
以下が使用したテンプレートです。
template-infra.yaml
AWSTemplateFormatVersion: '2010-09-09'
Description: CloudFormation template for Aurora MySQL and related resources for Glue Crawler
Parameters:
VpcCIDR:
Description: CIDR block for the VPC
Type: String
Default: 10.0.0.0/16
PrivateSubnet1CIDR:
Description: CIDR block for Private Subnet 1
Type: String
Default: 10.0.1.0/24
PrivateSubnet2CIDR:
Description: CIDR block for Private Subnet 2
Type: String
Default: 10.0.2.0/24
DBName:
Description: Database name
Type: String
Default: mydb
DBUsername:
Description: Database admin username
Type: String
Default: admin
NoEcho: true
DBInstanceClass:
Description: Database instance class
Type: String
Default: db.t3.medium
Resources:
VPC:
Type: AWS::EC2::VPC
Properties:
CidrBlock: !Ref VpcCIDR
EnableDnsSupport: true
EnableDnsHostnames: true
Tags:
- Key: Name
Value: !Sub ${AWS::StackName}-VPC
# Subnets
PrivateSubnet1:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref VPC
AvailabilityZone: !Select
- 0
- !GetAZs ''
CidrBlock: !Ref PrivateSubnet1CIDR
Tags:
- Key: Name
Value: !Sub ${AWS::StackName}-PrivateSubnet1
PrivateSubnet2:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref VPC
AvailabilityZone: !Select
- 1
- !GetAZs ''
CidrBlock: !Ref PrivateSubnet2CIDR
Tags:
- Key: Name
Value: !Sub ${AWS::StackName}-PrivateSubnet2
# Route Tables
PrivateRouteTable:
Type: AWS::EC2::RouteTable
Properties:
VpcId: !Ref VPC
Tags:
- Key: Name
Value: !Sub ${AWS::StackName}-PrivateRouteTable
PrivateSubnet1RouteTableAssociation:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
RouteTableId: !Ref PrivateRouteTable
SubnetId: !Ref PrivateSubnet1
PrivateSubnet2RouteTableAssociation:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
RouteTableId: !Ref PrivateRouteTable
SubnetId: !Ref PrivateSubnet2
# Security Groups
AuroraSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: Security group for Aurora MySQL
VpcId: !Ref VPC
Tags:
- Key: Name
Value: !Sub ${AWS::StackName}-AuroraSecurityGroup
SSMSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: Security group for SSM endpoints
VpcId: !Ref VPC
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 443
ToPort: 443
CidrIp: !Ref VpcCIDR
Tags:
- Key: Name
Value: !Sub ${AWS::StackName}-SSMSecurityGroup
SSMBastionSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: Security group for SSM Bastion
VpcId: !Ref VPC
Tags:
- Key: Name
Value: !Sub ${AWS::StackName}-SSMBastionSecurityGroup
# Security Group Rules
AuroraIngressFromSSMBastion:
Type: AWS::EC2::SecurityGroupIngress
Properties:
GroupId: !Ref AuroraSecurityGroup
IpProtocol: tcp
FromPort: 3306
ToPort: 3306
SourceSecurityGroupId: !Ref SSMBastionSecurityGroup
Description: Allow MySQL access from SSM Bastion
AuroraIngressSelfReference:
Type: AWS::EC2::SecurityGroupIngress
Properties:
GroupId: !Ref AuroraSecurityGroup
IpProtocol: tcp
FromPort: 0
ToPort: 65535
SourceSecurityGroupId: !Ref AuroraSecurityGroup
Description: Allow all inbound traffic from the same security group
# IAM Roles
SSMInstanceProfile:
Type: AWS::IAM::InstanceProfile
Properties:
Path: /
Roles:
- !Ref SSMInstanceRole
SSMInstanceRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Principal:
Service: ec2.amazonaws.com
Action: sts:AssumeRole
ManagedPolicyArns:
- arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore
- arn:aws:iam::aws:policy/CloudWatchAgentServerPolicy
# Secrets Manager
AuroraSecret:
Type: AWS::SecretsManager::Secret
DeletionPolicy: Delete
UpdateReplacePolicy: Delete
Properties:
Name: !Sub ${AWS::StackName}/aurora/credentials
Description: Aurora database credentials
GenerateSecretString:
SecretStringTemplate: !Sub '{"username": "${DBUsername}"}'
GenerateStringKey: "password"
PasswordLength: 32
ExcludeCharacters: '"@/\'
# Aurora Subnet Group
DBSubnetGroup:
Type: AWS::RDS::DBSubnetGroup
Properties:
DBSubnetGroupDescription: Subnet group for Aurora MySQL
SubnetIds:
- !Ref PrivateSubnet1
- !Ref PrivateSubnet2
Tags:
- Key: Name
Value: !Sub ${AWS::StackName}-DBSubnetGroup
# Aurora Parameter Groups
AuroraClusterParameterGroup:
Type: AWS::RDS::DBClusterParameterGroup
Properties:
Description: Parameter group for Aurora MySQL cluster
Family: aurora-mysql8.0
Parameters:
character_set_server: utf8mb4
collation_server: utf8mb4_unicode_ci
AuroraInstanceParameterGroup:
Type: AWS::RDS::DBParameterGroup
Properties:
Description: Parameter group for Aurora MySQL instances
Family: aurora-mysql8.0
Parameters:
max_connections: 1000
# Aurora Cluster
AuroraCluster:
Type: AWS::RDS::DBCluster
DeletionPolicy: Delete
UpdateReplacePolicy: Delete
Properties:
Engine: aurora-mysql
EngineVersion: 8.0.mysql_aurora.3.08.1
DatabaseName: !Ref DBName
MasterUsername: !Sub '{{resolve:secretsmanager:${AuroraSecret}:SecretString:username}}'
MasterUserPassword: !Sub '{{resolve:secretsmanager:${AuroraSecret}:SecretString:password}}'
DBSubnetGroupName: !Ref DBSubnetGroup
VpcSecurityGroupIds:
- !Ref AuroraSecurityGroup
DBClusterParameterGroupName: !Ref AuroraClusterParameterGroup
BackupRetentionPeriod: 1
Tags:
- Key: Name
Value: !Sub ${AWS::StackName}-AuroraCluster
AuroraPrimaryInstance:
Type: AWS::RDS::DBInstance
DeletionPolicy: Delete
UpdateReplacePolicy: Delete
Properties:
Engine: aurora-mysql
DBClusterIdentifier: !Ref AuroraCluster
DBInstanceClass: !Ref DBInstanceClass
DBParameterGroupName: !Ref AuroraInstanceParameterGroup
DBSubnetGroupName: !Ref DBSubnetGroup
PubliclyAccessible: false
Tags:
- Key: Name
Value: !Sub ${AWS::StackName}-AuroraPrimaryInstance
# Glue Resources
GlueDatabase:
Type: AWS::Glue::Database
Properties:
CatalogId: !Ref AWS::AccountId
DatabaseInput:
Name: !Join ['_', !Split ['-', !Sub '${AWS::StackName}_db']]
# VPC Endpoints
S3VPCEndpoint:
Type: AWS::EC2::VPCEndpoint
Properties:
ServiceName: !Sub com.amazonaws.${AWS::Region}.s3
VpcId: !Ref VPC
VpcEndpointType: Gateway
RouteTableIds:
- !Ref PrivateRouteTable
SSMVPCEndpoint:
Type: AWS::EC2::VPCEndpoint
Properties:
ServiceName: !Sub com.amazonaws.${AWS::Region}.ssm
VpcId: !Ref VPC
VpcEndpointType: Interface
PrivateDnsEnabled: true
SubnetIds:
- !Ref PrivateSubnet1
- !Ref PrivateSubnet2
SecurityGroupIds:
- !Ref SSMSecurityGroup
SSMMessagesVPCEndpoint:
Type: AWS::EC2::VPCEndpoint
Properties:
ServiceName: !Sub com.amazonaws.${AWS::Region}.ssmmessages
VpcId: !Ref VPC
VpcEndpointType: Interface
PrivateDnsEnabled: true
SubnetIds:
- !Ref PrivateSubnet1
- !Ref PrivateSubnet2
SecurityGroupIds:
- !Ref SSMSecurityGroup
# SSM Bastion
SSMBastionInstance:
Type: AWS::EC2::Instance
Properties:
InstanceType: t3.micro
ImageId: '{{resolve:ssm:/aws/service/ami-amazon-linux-latest/al2023-ami-kernel-6.1-x86_64}}'
SubnetId: !Ref PrivateSubnet1
IamInstanceProfile: !Ref SSMInstanceProfile
SecurityGroupIds:
- !Ref SSMBastionSecurityGroup
Tags:
- Key: Name
Value: !Sub ${AWS::StackName}-SSMBastion
またこのテンプレートをデプロイ後にAurora MySQLのデータベースに接続して、テーブルとGlue Crawlerのためのユーザーを作成しておきます。
簡単に手順を記します。
作成されたEC2にセッションマネージャー経由で接続して、以下のコマンドを実行してください。
- mysqlクライアントのインストール
sudo dnf -y update
sudo dnf -y install mariadb105
- データベースに接続
mysql -h <Aurora MySQLクラスターエンドポイント> -u admin -p
その後パスワードの入力を求められるので、先程のテンプレートで作成したAuroraSecretのパスワードを入力してください。
- テーブルの作成
USE mydb;
CREATE TABLE employees (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(100),
department VARCHAR(100)
);
INSERT INTO employees (name, department) VALUES
('山田太郎', '営業部'),
('鈴木花子', '開発部'),
('佐藤一郎', '人事部'),
('田中美咲', '営業部'),
('高橋健一', '開発部'),
('伊藤香澄', '経理部'),
('渡辺翔太', '人事部'),
('小林優子', '開発部');
CREATE TABLE departments (
id INT AUTO_INCREMENT PRIMARY KEY,
department_name VARCHAR(100),
location VARCHAR(100)
);
INSERT INTO departments (department_name, location) VALUES
('営業部', '東京本社'),
('開発部', '大阪支社'),
('人事部', '東京本社'),
('経理部', '名古屋支社');
- Glue Crawlerのためのユーザーの作成
この例では、employees
テーブルのみを読み取り専用でアクセスできるユーザーを作成します。
これにより、Glue Crawlerは必要なデータのみにアクセスでき、他のテーブルにはアクセスできません。
CREATE USER 'glue_crawler' IDENTIFIED BY 'password';
GRANT SELECT ON mydb.employees TO 'glue_crawler';
Glue Crawler設定手順
おおきく分けて以下の4つの手順です。
- セキュリティグループの設定
- VPCエンドポイントの設定
- Glue Connectionの作成
- Glue Crawlerの作成
それでは詳しく見ていきます。
1. セキュリティグループの設定
Glue Crawlerは複数のコンポーネントで構成されており、それらが相互に通信する必要があります。そのため、セキュリティグループには自己参照ルールが必要です。また、Aurora MySQLへのアクセスも必要です。
1.1 Glue Crawler用セキュリティグループの作成
VPCコンソールからセキュリティグループ作成画面を開いてください。
以下項目を埋めて作成してください。
- セキュリティグループ名: 任意の名前
- 説明: 任意の説明
- VPC: Aurora MySQLが存在するVPCを選択
続いて、先ほど作成したセキュリティグループに自己参照のインバウンドルールを追加してください。
- タイプ: すべてのTCP
- ソース: このセキュリティグループ自身
この自己参照ルールは、Glue Crawlerの各コンポーネントが相互に通信するために必要です。
1.2 Aurora MySQL側のセキュリティグループの設定
Aurora MySQLのセキュリティグループにGlue Crawler用セキュリティグループからのインバウンドルールを追加してください。
- タイプ: MYSQL/Aurora (3306)
- ソース: Glue Crawler用セキュリティグループ
この時、Aurora MySQL自身をソースとする自己参照のインバウンドルールも追加されていることを確認してください。
設定されていなければ上記セキュリティグループに加えて設定してください。
AWS Glue から Amazon RDS データストアに JDBC 接続するための Amazon VPC の設定 - AWS Glue
2. VPCエンドポイントの設定
Glue Crawlerはメタデータや一時ファイルの保存など、内部的にさまざまな理由でS3を使用します。
これらの操作はすべてプライベートネットワーク内で行う必要があるため、S3VPCエンドポイントが必要です。
ただしすでにS3VPCエンドポイントが存在する場合は、このセクションをスキップして次に進むことができます。
冒頭で示したテンプレートにはEC2にパッケージをインストールする必要がある都合上、すでにS3VPCエンドポイントが存在します。
詳しくは以下ページをご覧ください。
インターネットにアクセスせずに AL1 または AL2 EC2 インスタンスの yum を更新する | AWS re:Post
2.1 S3用のVPCエンドポイントの作成
VPCコンソールのエンドポイントセクションを開き、エンドポイント作成画面を開いてください。
以下の項目を入力してエンドポイントを作成してください。
- サービス:
com.amazonaws.region.s3
を選択- エンドポイントのタイプは
Gateway
を指定
- エンドポイントのタイプは
- VPC: Aurora MySQLが存在するVPCを選択
- ルートテーブル: Aurora MySQLのプライベートサブネットに紐づくルートテーブルを選択
- (オプション)リソースベースポリシーの設定
3. Glue Connectionの作成
AWS Glueコンソールを開いてください。左メニューから「Connections」を選択して「Create connection」をクリックしてください。
データソースの選択画面でAmazon Auroraを選択し、接続情報を入力してください。
- Connection details
- Database instances: 対象のAuroraクラスタ
- Database name: Glue Crawlerを実行する対象のデータベース名
- Credential type: Username and password
- Username: データベースのユーザー名
- Password: データベースのパスワード
- Network options:
- VPC: Aurora MySQLが存在するVPCを選択
- Subnet: Aurora MySQLのプライベートサブネットを選択
- Security groups: Glue Crawler用セキュリティグループを選択
続いてプロパティ情報を入力してください。
- Name: 任意のコネクション名
- (オプション) DescriptionやTagの入力
続いてレビュー画面で問題がなければ「Create connection」をクリックしてください。
4. Glue Crawlerの作成
AWS Glueコンソールを開いてください。左メニューから「Crawlers」を選択して「Create crawler」をクリックしてください。
続いてGlue Crawler情報を入力してください。
- Name: 任意の名前
- (オプション) DescriptionやTagの入力
続いてデータストアの設定を行ってください。
- Data source configuration: Not yet
- Data sources: Add a data sourceをクリック
- Data source: 「JDBC」を選択
- Connection: 作成したConnectionを選択
- Include path:
DatabaseName/%
を入力(DatabaseNameはConnectionで指定したデータベース名) - 「Add a JDBC data source」をクリック
- 「Next」をクリック
- Include path:
続いてIAMロールの設定を行ってください。
- 新規作成または既存のロールを選択
- 必要な権限:
AWSGlueServiceRole
: Glue Crawlerの基本的な操作(S3へのアクセス、CloudWatch Logsへのログ出力など)に必要です- Aurora MySQLへの接続権限(rds-db:connectの許可): Aurora MySQLに接続するために必要です
必要な権限は次の公式ドキュメントの通りです。
IAM データベースアクセス用の IAM ポリシーの作成と使用 - Amazon Aurora
どうやらIAMロールでは接続許可までをコントロールし、その後の権限(参照できるデータの範囲の制限など)はデータベースユーザー側で行えるようですね。
今回はAWSマネージドの AWSGlueServiceRole
に加え、インラインポリシーで rds-db:connect
を設定しています。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"rds-db:connect"
],
"Resource": [
"arn:aws:rds-db:REGION:ACCOUNT_ID:dbuser:*/glue_crawler"
]
}
]
}
続いて出力の設定を行ってください。
- Database: データを格納するGlue Databaseを選択
- Prefix added to tables: 任意のプレフィックス(例:
aurora_
)
必要であればスケジュールの設定を行い、最後に「Create crawler」をクリックしてください。
5. Glue Crawlerの実行
作成したGlue Crawlerを選択し、「Run crawler」をクリックしてください。
Glue Crawlerが完了するとGlue Data Catalogで登録されたテーブルを確認できます。
Glue Data Catalogに登録されたテーブルの一覧。
employees
テーブルのみが登録されていることがわかります。
employees
テーブルのスキーマ情報。
Glue Crawlerによって正しくメタデータが取得されています。
mydb
には employees
と departments
の2つのテーブルが作成されていますが、Glue Data Catalogには employees
のみが登録されています。
接続に使用しているデータベースユーザーの権限が適用された上で、メタデータの取得ができていることがわかりますね。
トラブルシューティング
Glue Crawlerの設定中に発生する可能性のある一般的な問題と解決策をまとめました。
1. VPCエンドポイントの検証に失敗する
症状: Glue Connectionの作成時に「VPC S3 エンドポイントの検証に失敗しました」というエラーが表示される。
原因: S3VPCエンドポイントが正しく設定されていない、またはルートテーブルにS3VPCエンドポイントへのルートが追加されていない。
解決策:
- S3VPCエンドポイントが存在することを確認する
- プライベートサブネットのルートテーブルにS3VPCエンドポイントへのルートが追加されていることを確認する
- 必要に応じて、S3VPCエンドポイントを再作成する
2. データベースへの接続に失敗する
症状: Glue Crawlerの実行時にデータベースへの接続に失敗する。
原因: セキュリティグループの設定が不適切、またはデータベースユーザーの権限が不足している。
解決策:
- Aurora MySQLのセキュリティグループにGlue Crawler用セキュリティグループからのインバウンドルールが追加されていることを確認する
- データベースユーザーに適切な権限が付与されていることを確認する
- 必要に応じて、セキュリティグループの設定やデータベースユーザーの権限を修正する
3. IAMロールの権限が不足している
症状: Glue Crawlerの実行時にIAMロールの権限が不足しているというエラーが表示される。
原因: IAMロールに必要な権限が付与されていない。
解決策:
- IAMロールに
AWSGlueServiceRole
が付与されていることを確認する - IAMロールにAurora MySQLへの接続権限(rds-db:connect)が付与されていることを確認する
- 必要に応じて、IAMロールに必要な権限を追加する
まとめ
この記事ではAurora MySQLに対してGlue Crawlerを実行するための手順をまとめました。
今回は検証していませんがAurora MySQL以外のデータソースに関してもGlue Connectionさえ作成できればCrawlerでは適切な権限の付与のみで対応できると思います。
設定することや考慮事項が多く、煩雑に感じるかもしれませんが、1つずつ確認していけばきちんと設定できます。
それではまた次の記事でお会いしましょう。
参考
- AWS Glue から Amazon RDS データストアに JDBC 接続するための Amazon VPC の設定 - AWS Glue
- インターネットにアクセスせずに AL1 または AL2 EC2 インスタンスの yum を更新する | AWS re:Post
- IAM データベースアクセス用の IAM ポリシーの作成と使用 - Amazon Aurora
- Systems Manager のために VPC エンドポイントを使用して EC2 インスタンスのセキュリティを強化する - AWS Systems Manager
- AWS Glue CrawlerでRedshiftをクロールするための設定をしてみた | DevelopersIO
- AWS Glue での「VPC S3 エンドポイントの検証に失敗しました」というエラーをトラブルシューティングする | AWS re:Post
- AWS Glue のための開発用ネットワークの設定 - AWS Glue
- AWS Glue を使用してオンプレミスのデータストアにアクセスし分析する方法 | AWS ビッグデータブログ