Aurora Serverlessの説明
一言でいうと自動でスケールして、アクセスがなければ勝手に停止するAWSのMySQL/PostgreSQLインフラです
2018年に一般公開された比較的新しいサービスで2020年になってもアップデートが続いています
Aurora Serverlessの利用用途
こちらの記事をご覧になると概要がわかると思います
https://dev.classmethod.jp/articles/lessons-learned-from-up-and-running-aurora-serverless/
通常のAuroraとのコスト比較はこちらの記事にあります
https://dev.classmethod.jp/articles/calculate-amazon-aurora-serverless-costs/
たまにしか接続しない開発環境のDBや、アクセス傾向が不規則なワークロードに適しています
ただ、常時稼働させてしまうと同スペックのDBインスタンスに対して60%割高になるため、安定したアクセスが常時続くのであれば通常のAuroraのほうが適しています
また、停止状態からの稼働に60秒ほどかかるため、本番アクセスでは最低ACU(Aurora Capacity Unit)を1以上にしたいです
DBスナップショットを取ることでAurora Serverless/非Serverlessの移行やリージョン移行なども行えるため、柔軟に対応できます
コスト
https://aws.amazon.com/jp/rds/aurora/pricing
ACUに対する課金が支配的です
1ACUあたりのコストはバージニア0.06$/hourに対して東京0.10$/hourと東京は66%割高です
東京からus-west-2へのレイテンシは100msくらいですので
https://dev.classmethod.jp/articles/hongkong-ec2-s3-rtt/
これが許容できるのであればus-west-2とかに置くのもありです
データ転送コストは0.09USD/GBなので、よほどの量でなければ大した額にならないはずです
利用方法
Aurora Serverlessへのアクセス
mysql通信などの普通のDB通信の他にData APIという接続方法も利用できます
接続情報をSecret Managerに格納した上でIAM認証で接続するため接続周りがすっきりします
また、HTTPSエンドポイントから接続するためLambdaなどからでも利用しやすいです
Data APIを利用するにはコンソールから有効化する必要があります
(CloudFormationからはできなかった)
https://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/AuroraUserGuide/data-api.html
https://speakerdeck.com/iwatatomoya/aurora-serverlessfalsedata-apinituite
Boto3からの利用としては、下記のようにexecute_statementにクエリを渡して実行します
https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/rds-data.html#RDSDataService.Client.execute_statement
DataAPI経由であれば異なるAWSアカウント間の通信もPrivateLinkが使えるそうです
https://dev.classmethod.jp/articles/rds-data-api-now-supports-aws-privatelink/
Aurora Serverlessの管理
AWSコンソールからクエリを叩けるのですが、コンソールのタイムアウトが短く、内部でクエリは実行されるがコンソールから見るとタイムアウトになるというようなことが起こります
mysql通信などの普通のDB通信ができるので、ローカルマシンのDBクライアントから接続するのが良さそうです
私はSequel Proを使っています(後継のSequel Aceで接続できないパターンがある)
Session Manager経由で接続するとハマりどころがあったので書きました
https://qiita.com/elyunim26/items/d987827a7b6189815c3a
感想
停止状態からの稼働に60秒かかることが少しネックで、周知が必要だったり、アプリケーションコード内のリトライで対応したり、本番環境で停止しにくかったりします。
しかし特にPoCなどの開発段階では、使わなければ勝手に止まってコストを抑えてくれるのは頼りになります
min, maxのACU設定だけでスケールしてくれるというのは運用負荷が減り、またその気になればスケールできるという安心感があります
(同時に、スケールできてしまうためコストが上る可能性もあるということですが)
また(Serverlessに関わらず)Auroraの特徴としてDB容量は設定せずとも勝手に増えてくれます
この点も運用面で安心感があります
https://aws.amazon.com/jp/premiumsupport/knowledge-center/view-storage-aurora-cluster/
メリット・デメリットを見極めて使えば役に立ちそうです
Cloud Formation サンプル
下記のようなテンプレートで作成できます
AWSTemplateFormatVersion: 2010-09-09
Description: Build AWS Batch environment
Parameters:
VpcStackName:
Type: String
MiddleStackName:
Type: String
EnvType:
Description: Environment type.
Default: test
Type: String
AllowedValues:
- prod
- test
ConstraintDescription: must specify prod or test.
RdsDBClusterIdentifier:
Description: DBClusterIdentifier
Type: String
AllowedPattern: ^[a-zA-Z0-9\-]*$
MinLength: 1
MaxLength: 60
RdsDbMasterUserName:
Description: RdsDbMasterUserName
Type: String
RdsDbMasterUserPassword:
Description: RdsDbMasterUserPassword
Type: String
NoEcho: true
MachineUserName:
Type: String
BucketName:
Type: String
Conditions:
IsProd: !Equals [ !Ref EnvType, prod ]
Resources:
#####
# IAM
#####
RDSDataApiUsePolicy:
Type: AWS::IAM::Policy
Properties:
PolicyName: RDSDataApiUsePolicy
PolicyDocument:
# https://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/AuroraUserGuide/data-api.html
Version: '2012-10-17'
Statement:
- Sid: SecretsManagerDbCredentialsAccess
Effect: Allow
Action:
- secretsmanager:GetSecretValue
- secretsmanager:PutResourcePolicy
- secretsmanager:PutSecretValue
- secretsmanager:DeleteSecret
- secretsmanager:DescribeSecret
- secretsmanager:TagResource
Resource: arn:aws:secretsmanager:*:*:secret:rds-db-credentials/*
- Sid: RDSDataServiceAccess
Effect: Allow
Action:
- secretsmanager:CreateSecret
- secretsmanager:ListSecrets
- secretsmanager:GetRandomPassword
- tag:GetResources
- rds-data:BatchExecuteStatement
- rds-data:BeginTransaction
- rds-data:CommitTransaction
- rds-data:ExecuteStatement
- rds-data:RollbackTransaction
Resource: "*"
Users:
- !Ref MachineUserName
RdsS3WritableRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Principal:
Service:
- rds.amazonaws.com
Action:
- sts:AssumeRole
Policies:
-
PolicyName: "S3WritableForRds"
PolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: "Allow"
Action: "s3:*"
Resource: !Sub arn:aws:s3:::{$BucketName}
#####
# Subnet Group
#####
RdsDbSubnetGroup:
Type: AWS::RDS::DBSubnetGroup
Properties:
DBSubnetGroupDescription: Database subnets for RDS
SubnetIds:
Fn::Split:
- ','
# Suppose access from data api.
# It can connect through iam auth from internet.
- Fn::ImportValue: !Sub ${VpcStackName}-SubnetsPrivate
#####
# aurora
#####
RdsDbClusterParameterGroup:
Type: AWS::RDS::DBClusterParameterGroup
Properties:
Description: CloudFormation Aurora Cluster Parameter Group
Family: aurora5.6
Parameters:
server_audit_logging: 0
time_zone: Asia/Tokyo
# https://qiita.com/msykd/items/f6ef3f7c137c7778fa70
character_set_client: utf8mb4
character_set_connection: utf8mb4
character_set_database: utf8mb4
character_set_results: utf8mb4
character_set_server: utf8mb4
innodb_large_prefix: 1
innodb_file_format: Barracuda
innodb_file_per_table: 1
# https://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/AuroraUserGuide/AuroraMySQL.Integrating.SaveIntoS3.html
aurora_select_into_s3_role: !GetAtt RdsS3WritableRole.Arn
aws_default_s3_role: !GetAtt RdsS3WritableRole.Arn
RdsDbCluster:
Type: AWS::RDS::DBCluster
Properties:
BackupRetentionPeriod: 7
DBClusterIdentifier: !Ref 'RdsDBClusterIdentifier'
DBClusterParameterGroupName: !Ref 'RdsDbClusterParameterGroup'
DBSubnetGroupName: !Ref 'RdsDbSubnetGroup'
DeletionProtection: false
Engine: aurora
EngineMode: serverless
EngineVersion: 5.6.10a
MasterUsername: !Ref 'RdsDbMasterUserName'
MasterUserPassword: !Ref 'RdsDbMasterUserPassword'
Port: 3306
PreferredBackupWindow: 15:25-15:55
PreferredMaintenanceWindow: Tue:16:05-Tue:16:35
ScalingConfiguration:
MinCapacity: 1
AutoPause: true
MaxCapacity: 4
SecondsUntilAutoPause: 1800
StorageEncrypted: true
VpcSecurityGroupIds:
- !Ref RdsSecurityGroup
RdsSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
VpcId:
Fn::ImportValue: !Sub ${VpcStackName}-VPC
GroupDescription: Allow MySQL (TCP3306)
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 3306
ToPort: 3306
Tags:
- Key: Name
Value: !Sub ${AWS::StackName}-mysql
Outputs:
RdsDbClusterEndpoint:
Value: !GetAtt 'RdsDbCluster.Endpoint.Address'