データアナリティクス事業本部の鈴木です。
Amazon AuroraのテーブルからAWS GlueのSparkジョブでデータを取得し結合する処理を作りたかったので、簡単な処理ですが試したのでご紹介します。
Auroraの検証環境を作ったことがなかったので、Aurora Serverless v1環境の準備からしてみました。
検証したいこと
Aurora Serverless v1のテーブルからGlue Jobでデータを取得して、S3バケットに保存するまでの環境構築とGlue Jobの作成がこの記事で検証したい内容です。
Auroraからは2テーブルからデータを取得し、結合してS3バケットに保存してみました。
Auroraは、Amazon Aurora Serverlessをv1からv2にアップグレードしてみた | DevelopersIOのどのAmazon Auroraを使う?に選び方の目安の記載があったので参考にしつつ、特にバージョン自体にはこだわりがなかったので、Aurora Serverless v1にしてみました。
環境構築
1. ネットワークの構築
以下のようなネットワーク構成を作成するはCloudFormationテンプレートを作成し、デプロイしました。
エンドポイントは以下の2つを作成します。
# | サービス | 種類 | 用途 |
---|---|---|---|
1 | com.amazonaws.ap-northeast-1.s3 |
ゲートウェイ型 | Glueジョブで処理した結果を保存する |
2 | com.amazonaws.ap-northeast-1.secretsmanager |
インターフェース型 | Auroraのデータベースアクセス時にクレデンシャルを取得する |
また、図中に表現していませんが、以下のセキュリティグループも作成します。
# | 論理ID | 説明 | 備考 |
---|---|---|---|
1 | GlueConnectionSecurityGroup | Glue接続用のセキュリティグループ | 今回はエンドポイントにもこのセキュリティグループを適用しました |
2 | AuroraSecurityGroup | Aurora用のセキュリティグループ |
テンプレートは以下です。
AWSTemplateFormatVersion: "2010-09-09"
Parameters:
EnvironmentName:
Type: String
VPCCIDR:
Type: String
Default: 10.192.0.0/16
PrivateSubnetCIDR1:
Type: String
Default: 10.192.0.0/24
PrivateSubnetCIDR2:
Type: String
Default: 10.192.1.0/24
Resources:
VPC:
Type: AWS::EC2::VPC
Properties:
CidrBlock: !Ref VPCCIDR
EnableDnsSupport: true
EnableDnsHostnames: true
Tags:
- Key: Name
Value: !Sub ${EnvironmentName}-VPC
# Private Subnetのネットワーク設定
PrivateSubnet1:
Type: AWS::EC2::Subnet
Properties:
AvailabilityZone: !Select [0, !GetAZs ""]
CidrBlock: !Ref PrivateSubnetCIDR1
VpcId: !Ref VPC
Tags:
- Key: Name
Value: !Sub ${EnvironmentName}-PrivateSubnet1
PrivateRouteTable1:
Type: AWS::EC2::RouteTable
Properties:
VpcId: !Ref VPC
Tags:
- Key: Name
Value: !Sub ${EnvironmentName}-PrivateRouteTable1
PrivateSubnetRouteTableAssociation1:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId: !Ref PrivateSubnet1
RouteTableId: !Ref PrivateRouteTable1
# Private Subnetのネットワーク設定
PrivateSubnet2:
Type: AWS::EC2::Subnet
Properties:
AvailabilityZone: !Select [1, !GetAZs ""]
CidrBlock: !Ref PrivateSubnetCIDR2
VpcId: !Ref VPC
Tags:
- Key: Name
Value: !Sub ${EnvironmentName}-PrivateSubnet2
PrivateRouteTable2:
Type: AWS::EC2::RouteTable
Properties:
VpcId: !Ref VPC
Tags:
- Key: Name
Value: !Sub ${EnvironmentName}-PrivateRouteTable2
PrivateSubnetRouteTableAssociation2:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId: !Ref PrivateSubnet2
RouteTableId: !Ref PrivateRouteTable2
# セキュリティグループ
GlueConnectionSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: GlueConnectionSecurityGroup
VpcId: !Ref VPC
Tags:
- Key: Name
Value: !Sub ${EnvironmentName}-GlueConnectionSecurityGroup
SelfRefGlueConnectionSecurityGroupIgress:
Type: AWS::EC2::SecurityGroupIngress
Properties:
GroupId: !GetAtt GlueConnectionSecurityGroup.GroupId
IpProtocol: tcp
FromPort: "0"
ToPort: "65535"
SourceSecurityGroupId: !GetAtt GlueConnectionSecurityGroup.GroupId
AuroraSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: AuroraSecurityGroup
VpcId: !Ref VPC
Tags:
- Key: Name
Value: !Sub ${EnvironmentName}-AuroraSecurityGroup
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 5432
ToPort: 5432
SourceSecurityGroupId: !Ref GlueConnectionSecurityGroup
# エンドポイントの設定
EndpointS3:
Type: AWS::EC2::VPCEndpoint
Properties:
RouteTableIds:
- !Ref PrivateRouteTable1
- !Ref PrivateRouteTable2
ServiceName: !Sub com.amazonaws.${AWS::Region}.s3
VpcEndpointType: Gateway
VpcId: !Ref VPC
EndpointSecretManager:
Type: AWS::EC2::VPCEndpoint
Properties:
VpcEndpointType: Interface
ServiceName: !Sub com.amazonaws.${AWS::Region}.secretsmanager
VpcId: !Ref VPC
PrivateDnsEnabled: True
SubnetIds:
- !Ref PrivateSubnet1
- !Ref PrivateSubnet2
SecurityGroupIds:
- !Ref GlueConnectionSecurityGroup
Glue接続用のセキュリティグループには、自己参照ルールを作成しています。これはAWS Glue 用 JDBC データストアに接続するための VPC の設定 - AWS Glueに記載があります。CloudFormationでの自己参照ルールはAWS CloudformationでSecurity Groupの自己参照の設定を行う - YOMON8.NETを参考にしました。
テンプレートのVPC部分は[小ネタ]Session ManagerでアクセスできるEC2を1発で作成するCloudFormationテンプレート作ってみた | DevelopersIOを参考にしました。
2. Aurora Serverless v1 クラスターの準備
Amazon RDSのコンソールでデータベース
からデータベースの作成
を押しました。
以下はデータベースの作成画面です。選択した箇所を説明します。
標準作成
でAurora (PostgreSQL Compatible)
を選び、利用可能なバージョンからAurora PostgreSQL (Compatible with PostgreSQL 11.16)
としました。テンプレートは開発/テスト
としました。
インスタンスの設定
でDBインスタンスクラスはサーバーレス
を選びました。検証のためなので、容量の範囲は最小AUCは2、最大AUCは4としました。
VPCおよびセキュリティグループは先に作成したものを選択しました。
クエリエディタを使いたかったので、Data APIは有効化しました。
ページ右下のデータベースの作成
を押して利用可能
となるのを待ちました。
3. データベースとテーブルの作成
Glueジョブからデータを取得できるよう、検証用のデータベースとユーザーおよびテーブルを作成しましたのでサンプルを紹介します。
アクション
のクエリ
からクエリエディタを起動しました。
データベースに接続します
ポップアップが出るので、マスターユーザーでpostgres
データベースに接続しました。このときに画面の表示に従ってシークレットマネジャーにシークレットを作成しました。
クエリエディタで以下のSQL文を順に実行し、glue_user
ユーザーとglue_sample_database
データベースを作成し、ユーザーにデータベースへのアクセス権を付与しました。
-- パスワードの文字列は自分のものに変更してください。
CREATE USER glue_user WITH PASSWORD 'パスワードの文字列';
CREATE DATABASE glue_sample_database;
GRANT ALL PRIVILEGES ON DATABASE glue_sample_database TO glue_user;
ユーザーが作成できたら、glue_user
ユーザーでglue_sample_database
データベースに接続しました。このときに画面の表示に従ってシークレットマネジャーにシークレットを作成しました。
テーブルを作成し、サンプルデータを入れておきました。
CREATE TABLE name (
id INTEGER PRIMARY KEY,
name VARCHAR(255) NOT NULL
);
CREATE TABLE price (
id INTEGER PRIMARY KEY,
price INTEGER NOT NULL
);
INSERT INTO name (id, name) VALUES
(1, 'Apple'),
(2, 'Orange'),
(3, 'Grape'),
(4, 'Pineapple'),
(5, 'Peach');
INSERT INTO price (id, price) VALUES
(1, 150),
(2, 120),
(3, 390),
(4, 400),
(5, 350);
以下のようにデータが格納されました。
4. Glue接続の作成
まずGlue接続の作成からです。AWS GlueのコンソールでData Connections
よりCreate connection
を選びました。
以下のように設定を入力しました。ポイントは以下の3点です。
JDBC URL
は、AWS Glue 接続プロパティ - AWS GlueのPostgreSQLに沿うようにしました。Credential type
はSecret
として、先に作成したglue_user
ユーザーのシークレットを指定しました。Network options
は、先に作成したVPC・サブネット・セキュリティグループを指定しました。
5. Glue Job用サービスロールの作成
以下のテンプレートを使ってGlue Job用のサービスロールを作成しました。
※ もし使われる際は、ロール名はAWSGlueServiceRole-Studio-CM-nayuts
にハードコードしてあるので適当に変更してください。
Auroraから取得して加工したデータをPUTするS3バケットおよびシークレットへのアクセス権を定義しました。Auroraのデータベース自体へのアクセスは、既に作成したGlue接続およびGlue用ユーザーにて制御しています。
AWSTemplateFormatVersion: "2010-09-09"
Description: Creating Glue Studio Execution Role for Aurora Data
Parameters:
MartBucketName:
Description: Backet Name for Data Mart.
Type: String
SecretARNforAuroraUser:
Description: Secret ARN for Aurora User .
Type: String
Resources:
GlueStudioExecutionRole:
Type: AWS::IAM::Role
Properties:
# Role名はAWSGlueServiceRole-Studio-から始まる名前に変更してください。
RoleName: AWSGlueServiceRole-Studio-CM-nayuts
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Principal:
Service: glue.amazonaws.com
Action: "sts:AssumeRole"
Path: "/"
Policies:
- PolicyName: GlueStudioS3AccessPolicy
PolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: "Allow"
Action: [
"s3:*"
]
Resource: [
!Sub "arn:aws:s3:::${MartBucketName}",
!Sub "arn:aws:s3:::${MartBucketName}/*"
]
- PolicyName: GlueStudioSecretManagerAccessPolicy
PolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: "Allow"
Action: [
"secretsmanager:GetSecretValue"
]
Resource: [
!Sub "${SecretARNforAuroraUser}"
]
ManagedPolicyArns:
- arn:aws:iam::aws:policy/service-role/AWSGlueServiceRole
MartBucketName
に名前を入れるS3バケットは、今回はあらかじめ作ってあった検証用のS3バケットを使用しました。S3バケットに関しては作成自体は例えばマネジメントコンソールなどから簡単にできます。
Glueジョブの作成と実行
Glueジョブの作成
今回はGlue Studioでジョブを作成してみました。ノードをいくつか作っているので、ある程度の粒度に分けて記載します。
全体像
まず全体像ですが、以下のようなジョブを作成しました。
2テーブルのデータを取得して、片方のテーブルはJOINのため絡む名を変更しておきました。JOINした後、不要なカラムを落としてS3に保存しました。
テーブルからの読み出し
まずname
テーブルからの読み出し設定です。
Node properties
タブではノード名を入力し、Node type
をPostgres
としました。
Data source properties - PostgreSQL
タブにて、JDBC source
でJDBC connection details
を選び、Connection name
で先ほど作成したGlue接続を指定しました。Table name
にてテーブルも指定しました。
Output schema
タブではEdit
からSchemaを設定しました。
price
テーブルからの読み出し設定も同様に行いました。
JOIN
name
テーブルはJOINのためRename field
の変換でカラム名を変更しました。
Join
の変換で2テーブルを結合しました。
結合キーは片方しか要らなかったので、不要なテーブル分は落としておきました。
S3への保存
最後にS3への保存設定をしました。今回はCSV形式としました。
Glueジョブの実行
エディタ右上の Save
ボタンでジョブを保存し、同じ並びのRun
ボタンでジョブを実行しました。
以下のようにS3バケットの指定したパスにファイルが出力されました。
念の為Athenaからテーブルを作成して検索すると、期待通りデータが作成されていることが確認できました。
最後に
今回はAmazon AuroraのテーブルからAWS GlueのSparkジョブでデータを取得し結合する処理を作成してみました。
Sparkジョブを作るだけだと比較的手軽な検証なのですが、VPCから全部作るとなるといろいろ知識が必要なので大変ですね。この記事では簡単にではありますが、VPCの作成からAurora Serverless v1クラスターの作成、Glue接続の設定なども盛り込んでみました。
参考になりましたら幸いです。