Aurora ServerlessのData APIを有効化してEC2(AWS CLI)とLambda(Boto3)から接続する
以下のページで、Aurora Serverlessの基本的な事項について取り上げました。
Aurora Serverless v1の特徴の1つに、Data APIがあります。
Aurora Serverless v1 の Data API を使用すると、Aurora Serverless v1 DB クラスターへのウェブサービスインターフェイスを操作できます。Data API は、DB クラスターへの永続的な接続を必要としません。代わりに、セキュア HTTP エンドポイントおよび AWS SDK との統合を利用できます。
Aurora Serverless v1 の Data API の使用
本ページでは、Data APIを使用して、EC2インスタンスおよびLambda関数からAurora Serverlessに接続します。
構築する環境
VPC内に3つのサブネットを作成します。
いずれもインターネットにアクセス不可なプライベートサブネットとします。
Aurora Serverlessを作成し、AZが異なる2つのサブネットと関連付けます。
MySQLタイプの最新のバージョンを指定します。
Data APIを有効化します。
EC2インスタンスを作成します。
Aurora Serverlessに接続するクライアントです。
OSは最新版のAmazon Linux 2とします。
SSM用のエンドポイントを作成します。
SSM Session Managerを使用して、EC2インスタンスにリモートアクセスするためです。
RDS Data用のエンドポイントも作成します。
Data APIを使用して、EC2インスタンスからAurora Serverlessに接続するためです。
VPC外にLambda関数を作成します。
こちらもAurora Serverlessに接続するクライアントです。
ランタイム環境にPython3.8を選択し、Function URLを有効化します。
CloudFormationテンプレートファイル
上記の構成をCloudFormationで構築します。
以下のURLにCloudFormationテンプレートを配置しています。
https://github.com/awstut-an-r/awstut-fa/tree/main/059
テンプレートファイルのポイント解説
本ページはAurora ServerlessのData APIを有効化し、EC2/Lambdaから接続する方法を取り上げます。
Aurora Serverlessに関する基本的な事項については、冒頭にご紹介したページをご確認ください。
セキュリティグループ
Resources:
InstanceSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupName: !Sub "${Prefix}-InstanceSecurityGroup"
GroupDescription: Deny All.
VpcId: !Ref VPC
DBSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupName: !Sub "${Prefix}-DBSecurityGroup"
GroupDescription: DBSecurityGroup.
VpcId: !Ref VPC
# SecurityGroupIngress:
# - IpProtocol: tcp
# FromPort: !Ref MySQLPort
# ToPort: !Ref MySQLPort
# SourceSecurityGroupId: !Ref InstanceSecurityGroup
EndpointSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupName: !Sub "${Prefix}-EndpointSecurityGroup"
GroupDescription: Allow HTTPS from InstanceSecurityGroup.
VpcId: !Ref VPC
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: !Ref HTTPSPort
ToPort: !Ref HTTPSPort
SourceSecurityGroupId: !Ref InstanceSecurityGroup
Code language: YAML (yaml)
3つのセキュリティグループを定義します。
1つ目はEC2インスタンス用です。
冒頭でご紹介したページと同様に、今回の構成でも、インスタンスに対するインバウンド通信は発生しません。
ですから何もインバウンド通信を許可しません。
2つ目はAurora Serverless用です。
こちらも何もインバウンド通信を許可しません。
今回はData APIを使ってAurora Serverlessに接続するため、MySQLポートを解放する必要はありません。
またData APIでの接続はHTTPS通信によって実行されますが、この通信はAurora ServerlessからData API用エンドポイント向けにアウトバウンド通信のため、こちらもセキュリティグループで許可する必要はありません。
3つ目はVPCエンドポイント用です。
今回はSSM用およびRDS Data用で合計4つのエンドポイントを作成します。
いずれもインスタンスからのHTTPS通信が流れますので、それを反映する内容です。
Aurora Serverless
Resources:
DBCluster:
Type: AWS::RDS::DBCluster
Properties:
DatabaseName: !Ref DBName
DBClusterIdentifier: !Ref DBClusterIdentifier
DBSubnetGroupName: !Ref DBSubnetGroup
EnableHttpEndpoint: true
Engine: !Ref DBEngine
EngineMode: serverless
EngineVersion: !Ref DBEngineVersion
MasterUsername: !Ref DBMasterUsername
MasterUserPassword: !Ref DBMasterUserPassword
StorageEncrypted: true
VpcSecurityGroupIds:
- !Ref DBSecurityGroup
Code language: YAML (yaml)
ポイントはEnableHttpEndpointプロパティです。
Aurora ServerlessでData APIを有効化するためには、本プロパティに「true」を設定します。
この設定によってData API用のHTTPエンドポイントが用意されます。
他は特別な設定は不要です。
Secrets Manager
Resources:
Secret:
Type: AWS::SecretsManager::Secret
Properties:
Name: !Sub "${Prefix}-Secret"
SecretString: !Sub '{"username":"${DBMasterUsername}","password":"${DBMasterUserPassword}"}'
Code language: YAML (yaml)
Data APIを使用してAurora Serverlessに接続するためには、Sercrets Managerを使用する必要があります。
Data API は AWS Secrets Manager に保存されたデータベース認証情報を使用するため、ユーザーは Data API の呼び出しで認証情報を渡す必要はありません。
Aurora Serverless v1 の Data API の使用
具体的には、Aurora DBクラスターを定義時に設定したマスターユーザーとパスワードに関する情報からシークレットを作成します。
SecretStringプロパティに、JSON形式でシークレット文字列を定義します。
2つの情報はそれぞれussername、passwordの値として設定します。
VPCエンドポイント
Resources:
RDSDataEndpoint:
Type: AWS::EC2::VPCEndpoint
Properties:
PrivateDnsEnabled: true
SecurityGroupIds:
- !Ref EndpointSecurityGroup
ServiceName: !Sub "com.amazonaws.${AWS::Region}.rds-data"
SubnetIds:
- !Ref PrivateSubnet1
VpcEndpointType: Interface
VpcId: !Ref VPC
#S3Endpoint:
# Type: AWS::EC2::VPCEndpoint
# Properties:
# RouteTableIds:
# - !Ref PrivateRouteTable
# ServiceName: !Sub "com.amazonaws.${AWS::Region}.s3"
# VpcId: !Ref VPC
Code language: YAML (yaml)
Data APIを使用してAurora Serverlessに接続するためには、Data API用HTTPエンドポイント向けに通信を行います。
プライベートサブネット内のEC2インスタンスが、同エンドポイント向けに通信を行うためには、RDS Data用VPCエンドポイントを作成する必要があります。
詳細につきましては、以下のAWS公式ページをご確認ください。
なお冒頭でご紹介したページとは異なり、S3用VPCエンドポイントは作成しません。
本エンドポイントは、プライベートサブネット上のインスタンスが、S3上に構築されたyumリポジトリにアクセスし、MySQLクライアントパッケージをインストールするために使用しました。
しかし今回はMySQL通信ではなく、HTTPS通信によってAurora Serverlessと通信します。
ですからクライアントパッケージは不要となり、本エンドポイントも不要となります。
EC2インスタンス
Resources:
Instance:
Type: AWS::EC2::Instance
Properties:
IamInstanceProfile: !Ref InstanceProfile
ImageId: !Ref ImageId
InstanceType: !Ref InstanceType
NetworkInterfaces:
- DeviceIndex: 0
SubnetId: !Ref PrivateSubnet
GroupSet:
- !Ref InstanceSecurityGroup
#UserData: !Base64 |
# #!/bin/bash -xe
# yum update -y
# yum install -y mariadb
Code language: YAML (yaml)
Data APIを使用して、Aurora Serverlessに接続するクライアントとしてのEC2インスタンスです。
先述の通り、MySQLクライアントは不要ですので、ユーザーデータを使用したパッケージのインストールは実行しません。
Lambda関数
Resources:
Function:
Type: AWS::Lambda::Function
Properties:
Environment:
Variables:
DBCLUSTER_ARN: !Ref DBClusterArn
DBNAME: !Ref DBName
DBTABLE: !Ref DBTableName
REGION: !Ref AWS::Region
SECRET_ARN: !Ref SecretArn
Code:
ZipFile: |
import boto3
import json
import os
dbcluster_arn = os.environ['DBCLUSTER_ARN']
dbname = os.environ['DBNAME']
dbtable = os.environ['DBTABLE']
region = os.environ['REGION']
secret_arn = os.environ['SECRET_ARN']
sql = 'select * from {table};'.format(table=dbtable)
client = boto3.client('rds-data', region_name=region)
def lambda_handler(event, context):
response = client.execute_statement(
database=dbname,
resourceArn=dbcluster_arn,
schema='mysql',
secretArn=secret_arn,
sql=sql
)
return {
'statusCode': 200,
'body': json.dumps(response, indent=2)
}
FunctionName: !Sub "${Prefix}-function"
Handler: !Ref Handler
Runtime: !Ref Runtime
Role: !GetAtt FunctionRole.Arn
Code language: YAML (yaml)
Data APIを使用して、Aurora Serverlessに接続するクライアントとしてのLambda関数です。
インライン表記で実行するコードを定義します。
詳細については、以下のページをご確認ください。
Environmentプロパティで、環境変数として、DBクラスターやSecrets Managerシークレット等のパラメータを設定します。
コード内では、os.envrionで環境変数にアクセスします。
Boto3を使用して、RDS Data用クライアントオブジェクトを作成します。
execute_statementを実行して、Aurora Serverlessに接続します。
先述の各種パラメータを引数として渡します。
なお実行するSQL分ですが、特定のテーブル(Pets)内のテーブルを取得する内容です。
SQLの実行結果を関数の実行結果として返します。
Function URLを有効化します。
特定のURLからLambda関数を実行できる機能です。
Function URLの詳細については、以下のページをご確認ください。
IAMロール
Resources:
InstanceRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Action: sts:AssumeRole
Principal:
Service:
- ec2.amazonaws.com
ManagedPolicyArns:
- arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore
FunctionRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Action: sts:AssumeRole
Principal:
Service:
- lambda.amazonaws.com
ManagedPolicyArns:
- arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
AuroraServerlessDataAPIPolicy:
Type: AWS::IAM::Policy
Properties:
PolicyName: !Sub "${Prefix}-AuroraServerlessDataAPIPolicy"
PolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Action:
- secretsmanager:GetSecretValue
Resource:
- !Ref SecretArn
- Effect: Allow
Action:
- rds-data:BatchExecuteStatement
- rds-data:BeginTransaction
- rds-data:CommitTransaction
- rds-data:ExecuteStatement
- rds-data:RollbackTransaction
Resource:
- !Ref DBClusterArn
Roles:
- !Ref FunctionRole
- !Ref InstanceRole
Code language: YAML (yaml)
EC2インスタンスおよびLambda関数用のIAMロールを作成します。
両者に共通する権限は、IAMポリシーとして定義します。
ポイントは2つです。
1つ目はSecrets Managerへのアクセスです。
先述のシークレットにアクセスする権限を与えます。
2つ目はData APIを使用するための権限です。
先述のAurora Server DBクラスターに対して、SQLを実行するための最低限の権限を与えます。
なお今回の設定は以下のページを参考に設定しました。
https://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/AuroraUserGuide/data-api.html#data-api.access
環境構築
CloudFormationを使用して、本環境を構築し、実際の挙動を確認します。
CloudFormationスタックを作成し、スタック内のリソースを確認する
CloudFormationスタックを作成します。
スタックの作成および各スタックの確認方法については、以下のページをご確認ください。
各スタックのリソースを確認した結果、今回作成された主要リソースの情報は以下の通りです。
- EC2インスタンス:i-02b21e07f33a5074c
- Lambda関数:fa-059-function
- Lambda関数のFunction URL:https://7vgt4c3bmf7n3xp7htprqdhi5u0tfdms.lambda-url.ap-northeast-1.on.aws/
- Aurora Serverlessに作成するデータベース名:testdb
- Aurora Serverlessのデータベースに作成するテーブル名:Pets
- Aurora Serverless DBクラスターのARN:arn:aws:rds:ap-northeast-1:[account-id]:cluster:fa-059-dbcluster
- Secrets ManagerシークレットのARN:arn:aws:secretsmanager:ap-northeast-1:[account-id]:secret:fa-059-Secret-poaIGs
AWS Management ConsoleからもAurora Serverlessの作成状況を確認します。
正常にAurora Serverlessが作成されています。
そしてData APIが有効化されていることも確認できます。
動作確認
EC2インスタンス
準備が整いましたので、EC2インスタンスにアクセスします。
インスタンスへのアクセスはSSM Session Managerを使用します。
% aws ssm start-session --target i-02b21e07f33a5074c
Starting session with SessionId: root-0815f8b32141bb9b4
sh-4.2$
Code language: Bash (bash)
SSM Session Managerの詳細につきましては、以下のページをご確認ください。
AWS CLIからData APIを使用して、Aurora Serverlessに接続します。
まずAurora ServerlessのデータベースにPetsテーブルを作成します。
sh-4.2$ aws rds-data execute-statement \
--resource-arn "arn:aws:rds:ap-northeast-1:[account-id]:cluster:fa-059-dbcluster" \
--schema "mysql" \
--secret-arn "arn:aws:secretsmanager:ap-northeast-1:[account-id]:secret:fa-059-Secret-poaIGs" \
--region ap-northeast-1 \
--sql "create table Pets(id varchar(200), type varchar(200), price float)" \
--database "testdb"
{
"numberOfRecordsUpdated": 0,
"generatedFields": []
}
Code language: Bash (bash)
正常に実行されました。
次に作成したテーブルにレコードを追加します。
sh-4.2$ aws rds-data execute-statement \
--resource-arn "arn:aws:rds:ap-northeast-1:[account-id]:cluster:fa-059-dbcluster" \
--schema "mysql" \
--secret-arn "arn:aws:secretsmanager:ap-northeast-1:[account-id]:secret:fa-059-Secret-poaIGs" \
--region ap-northeast-1 \
--sql "insert into Pets values (111, 'dog', 123)" \
--database "testdb"
{
"numberOfRecordsUpdated": 1,
"generatedFields": []
}
Code language: YAML (yaml)
こちらも正常に実行されました。
追加されたレコードを確認します。
sh-4.2$ aws rds-data execute-statement \
--resource-arn "arn:aws:rds:ap-northeast-1:[account-id]:cluster:fa-059-dbcluster" \
--schema "mysql" \
--secret-arn "arn:aws:secretsmanager:ap-northeast-1:[account-id]:secret:fa-059-Secret-poaIGs" \
--region ap-northeast-1 \
--sql "select * from Pets" \
--database "testdb"
{
"records": [
[
{
"stringValue": "111"
},
{
"stringValue": "dog"
},
{
"doubleValue": 123.0
}
]
],
"numberOfRecordsUpdated": 0
}
Code language: JavaScript (javascript)
保存されたレコードを取得することができました。
以上の通り、EC2インスタンスにおいて、Data APIを使用して、AWS CLIからAurora Serverlessに接続することができました。
Lambda関数
関数の実行はFunction URLにアクセスして行います。
以下が実行結果です。
こちらも正常に実行されました。
以上の通り、Lambda関数において、Data APIを使用して、Aurora Serverlessに接続することができました。
まとめ
Aurora ServerlessでData APIを有効化する方法を確認しました。
EC2インスタンスおよびLambda関数からData APIを使用する方法も確認しました。