エンジョイ AWS!
サーバーワークス エンジニアの伊藤Kです。
実に1年ぶりのブログ投稿です。
今回のお題は「Amazon Neptune」。グラフデータベースを提供するAWSのフルマネージドサービスです。
Neptune・・・ローマ神話の神であり、海王星も意味します。我々おっさん世代だとマスクのコレクションが好きな超人が頭に浮かびます。
それはよいとして、グラフデータベースとは、「グラフモデル」を効率的に格納し、検索するデータベースのことです。
そしてここで言うグラフは、「グラフ理論」という、数学の理論が元になったモデルです。一般的に「グラフ」と聞いて思いつく、棒グラフや折れ線グラフとは、起源は同じですが、ちょっと種類が違うものとなります。
今回は、Amazon Neptune のインスタンス構築について書きます。
お手軽に構築するには
AWS公式ドキュメント の CloudFormation テンプレートを使うと、インスタンス、Neptune Workbench、アクセスするツールをインストールするためのEC2インスタンスなど、一通り構築できます。
それらのネットワーク基盤となるVPCも同時に作成され、3つのAZに各2つのサブネット、Elastic IPとNAT Gatewayも構成されます。
今回は、VPCとサブネットは既に作ったものを利用したかったのと、1つ1つ順を追って構築することで理解を深める狙いで、上記テンプレートをベースに要素ごとに分けた CloudFormation テンプレートを作成、構築します。
目指す最終形の図
VPC、サブネット、NAT Gatewayは既に存在するものとします。
ひとまずのゴールとしては、マネジメントコンソールから Neptune Workbench を動かし、 Neptune インスタンスのデータを操作する環境を構築する、までとします。
その後時間ができたら、EC2インスタンスを立てて、何らかのツールで Neptune インスタンスのデータを操作することまでやれればと。(願望)
今回は、図の紫枠の部分を構築します。
インスタンスを構築するCloudFormationテンプレート(サンプル)
私の記事では毎度のお約束、「Description」で記述している怪しげな英語には目をつぶってください。
また、サンプルなのでご自分の要件に合わせてカスタマイズしてご利用ください。
AWSTemplateFormatVersion: "2010-09-09" Description: "Custom Template to create Neptune inside a VPC" Parameters: VPC: Description: 'VPC' Default: "vpc-xxxxxxxxxxxx" Type: AWS::EC2::VPC::Id SubnetA: Description: 'Subnet AZ-a' Default: "subnet-xxxxxxxxxxxx" Type: AWS::EC2::Subnet::Id SubnetC: Description: 'Subnet AZ-c' Default: "subnet-xxxxxxxxxxxx" Type: AWS::EC2::Subnet::Id ApplicationTagValue: Description: 'Application Tag Value' Default: "Test" Type: String NeptuneDBSubnetGroupName: Description: 'DBSubnetGroup Name (Lowercase letters Only)' Default: "test-neptune-dbsubnet" Type: String NeptuneDBSGName: Description: 'SG Name for Neptune DB' Default: "test-neptune-sg" Type: String NeptuneDBClusterParameterGroupName: Description: 'DBClusterParameterGroup Name' Default: "Test-Neptune-DBClusterParameterGroup" Type: String NeptuneQueryTimeout: Description: Neptune Query Time out (in milliseconds) Default: 20000 Type: Number NeptuneDBParameterGroupName: Description: 'DBParameterGroup Name (Lowercase letters Only)' Default: "test-neptune-dbparametergroup" Type: String NeptuneDBClusterName: Description: 'DBCluster Name' Default: "Test-Neptune-DBCluster" Type: String NeptuneDBEngineVersion: Description: 'DBCluster Engine Version (e.g. 1.0.5.1)' Default: "1.0.5.1" Type: String DBClusterPort: Description: 'DB Port (default 8182)' Default: 8182 Type: String DBClusterBackupWindow: Description: 'Cluster BackupWindow HH:MI-HH:MI (UTC)' Default: "15:00-15:30" Type: String DBClusterMaintenanceWindow: Description: 'Cluster MaintenanceWindow [Sun to Sat]:HH:MI-[Sun to Sat]HH:MI' Default: "Sat:15:30-Sat:16:00" Type: String DBMaintenanceWindow: Description: 'DB MaintenanceWindow [Sun to Sat]:HH:MI-[Sun to Sat]HH:MI' Default: "Sun:15:30-Sun:16:00" Type: String DbInstanceType: Description: 'Neptune DB instance type' Type: String Default: db.t3.medium AllowedValues: - db.t3.medium - db.r4.large - db.r4.xlarge - db.r4.2xlarge - db.r4.4xlarge - db.r4.8xlarge - db.r5.large - db.r5.xlarge - db.r5.2xlarge - db.r5.4xlarge - db.r5.8xlarge - db.r5.12xlarge NeptuneDBInstanceName: Description: 'DBInstance Name (Lowercase letters Only)' Default: "test-neptune-dbinstance" Type: String IAMRoleName: Description: 'IAM Role Name for LoadFromS3' Default: "Role-NeptuneLoadFromS3" Type: String IAMPolicyName: Description: 'IAM Policy Name for LoadFromS3' Default: "Policy-NeptuneLoadFromS3" Type: String Resources: NeptuneLoadFromS3Role: Type: 'AWS::IAM::Role' Properties: RoleName: !Ref IAMRoleName AssumeRolePolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Principal: Service: - rds.amazonaws.com Action: - 'sts:AssumeRole' Path: / NeptuneLoadFromS3Policy: Type: 'AWS::IAM::Policy' Properties: PolicyName: !Ref IAMPolicyName PolicyDocument: Statement: - Effect: Allow Action: - 's3:Get*' - 's3:List*' Resource: '*' Roles: - !Ref NeptuneLoadFromS3Role NeptuneSG: Type: 'AWS::EC2::SecurityGroup' Properties: VpcId: !Ref VPC GroupDescription: "Allow Access" GroupName: !Ref NeptuneDBSGName SecurityGroupIngress: - FromPort: '22' ToPort: '22' IpProtocol: tcp CidrIp: 0.0.0.0/0 Description: ssh from anywhere - FromPort: !Ref DBClusterPort ToPort: !Ref DBClusterPort IpProtocol: tcp CidrIp: 0.0.0.0/0 Description: http access Tags: - Key: "Name" Value: !Ref NeptuneDBSubnetGroupName - Key: "Application" Value: !Ref ApplicationTagValue NeptuneDBSubnetGroup: Type: 'AWS::Neptune::DBSubnetGroup' Properties: DBSubnetGroupDescription: "Neptune DB subnet group" DBSubnetGroupName: !Ref NeptuneDBSubnetGroupName SubnetIds: - !Ref SubnetA - !Ref SubnetC Tags: - Key: "Name" Value: !Ref NeptuneDBSubnetGroupName - Key: "Application" Value: !Ref ApplicationTagValue NeptuneDBClusterParameterGroup: Type: 'AWS::Neptune::DBClusterParameterGroup' Properties: Family: "neptune1" Description: "neptune-db-cluster-parameter-group-description" Name: !Ref NeptuneDBClusterParameterGroupName Parameters: neptune_enable_audit_log: 0 Tags: - Key: "Name" Value: !Ref NeptuneDBClusterParameterGroupName - Key: "Application" Value: !Ref ApplicationTagValue NeptuneDBParameterGroup: Type: 'AWS::Neptune::DBParameterGroup' Properties: Family: "neptune1" Description: "neptune-db-parameter-group-description" Name: !Ref NeptuneDBParameterGroupName Parameters: neptune_query_timeout: !Ref NeptuneQueryTimeout Tags: - Key: "Name" Value: !Ref NeptuneDBParameterGroupName - Key: "Application" Value: !Ref ApplicationTagValue NeptuneDBCluster: Type: 'AWS::Neptune::DBCluster' Properties: DBClusterIdentifier: !Ref NeptuneDBClusterName EngineVersion: !Ref NeptuneDBEngineVersion DBSubnetGroupName: !Ref NeptuneDBSubnetGroup DBClusterParameterGroupName: !Ref NeptuneDBClusterParameterGroup IamAuthEnabled: false AssociatedRoles: - RoleArn: !GetAtt NeptuneLoadFromS3Role.Arn StorageEncrypted: true KmsKeyId: '' Port: !Ref DBClusterPort PreferredBackupWindow: !Ref DBClusterBackupWindow PreferredMaintenanceWindow: !Ref DBClusterMaintenanceWindow VpcSecurityGroupIds: - !Ref NeptuneSG Tags: - Key: "Name" Value: !Ref NeptuneDBClusterName - Key: "Application" Value: !Ref ApplicationTagValue DependsOn: - NeptuneDBSubnetGroup - NeptuneDBClusterParameterGroup NeptuneDBInstance: Type: 'AWS::Neptune::DBInstance' Properties: DBInstanceIdentifier: !Ref NeptuneDBInstanceName DBClusterIdentifier: !Ref NeptuneDBCluster DBInstanceClass: !Ref DbInstanceType DBParameterGroupName: !Ref NeptuneDBParameterGroup PreferredMaintenanceWindow: !Ref DBMaintenanceWindow Tags: - Key: "Name" Value: !Ref NeptuneDBInstanceName - Key: "Application" Value: !Ref ApplicationTagValue DependsOn: - NeptuneDBCluster - NeptuneDBParameterGroup
ポイント解説
サブネットについて
- ここではAZ-A、AZ-Cのセットにしているが、別々の2つのAZであれば違う組み合わせでも可。
- Neptune用のDBサブネットグループを作成し、2つのサブネットを所属させる。
- Neptune インスタンスのみを置くのであれば、インターネットへの接続ルートがないプライベートサブネットで可。
Neptune DBのエンジンバージョンについて
- 執筆時の最新は"1.1.0.0"。ここでは元にしたテンプレートでデフォルト値として指定されていた"1.0.5.1"を使用。
インスタンスタイプについて
IAMロール、IAMポリシーについて
- Neptune インスタンスにアタッチする。バルクロードのためにS3へアクセスするときの権限を指定する。テンプレート内ではS3の全バケットを対象としているが、特定のバケットのみ使用する場合はより権限を絞るのもよい。
Parameters | |
---|---|
VPC | SecurityGroup の作成で使う。Neptune インスタンスの作成には使用しない。 |
SubnetA | Neptune インスタンスを所属させる、AZ-Aに属するサブネットを指定する。 |
SubnetC | Neptune インスタンスを所属させる、AZ-Cに属するサブネットを指定する。 |
ApplicationTagValue | リソース共通で"Application" タグを作成するので、その値を指定する(任意の値)。利用料の把握などに使用。 |
NeptuneDBSubnetGroupName | Neptune用のDBサブネットグループを作成するので、その名前を入力する(任意の値)。アルファベットは全て小文字を指定すること。大文字を混ぜても自動的に小文字に変換されて作成され、インスタンスの作成時にエラーとなる(後述)。 |
NeptuneDBSGName | Neptune用のセキュリティグループを作成するので、その名前を入力する(任意の値)。このセキュリティグループは後々クライアントとなるインスタンスからの接続に使用する。 |
NeptuneDBClusterParameterGroupName | Neptune クラスター用のパラメーターグループを作成するので、その名前を入力する(任意の値)。 |
NeptuneQueryTimeout | Neptune におけるクエリのタイムアウト値を、ミリ秒で指定する。 |
NeptuneDBParameterGroupName | Neptune インスタンス用のパラメーターグループ(クラスター用とは別)を作成するので、その名前を入力する(任意の値)。アルファベットは全て小文字を指定すること。大文字を混ぜても自動的に小文字に変換されて作成され、インスタンスの作成時にエラーとなる(後述)。 |
NeptuneDBClusterName | Neptune クラスターの名前を入力する(任意の値)。 |
NeptuneDBEngineVersion | Neptune DBのエンジンバージョンを指定する。 |
DBClusterPort | Neptune クラスターが使用するポートを指定する。特別な要件が無ければ、デフォルトの8182が無難。 |
DBClusterBackupWindow | Neptune クラスターが自動バックアップ(スナップショット生成)を実施する時間帯。Descriptionに記された形式で、UTCで入力する。 |
DBClusterMaintenanceWindow | Neptune クラスターのメンテナンスウィンドウ時間帯。Descriptionに記された形式で、UTCで入力する。 |
DBMaintenanceWindow | Neptune インスタンスのメンテナンスウィンドウ時間帯(クラスターとは別に指定)。Descriptionに記された形式で、UTCで入力する。 |
DbInstanceType | Neptune インスタンスのインスタンスタイプを指定する。"AllowedValues"の中から選択する。 |
NeptuneDBInstanceName | Neptune インスタンスの名前を入力する(任意の値)。アルファベットは全て小文字を指定すること。大文字を混ぜても自動的に小文字に変換されて作成される。 |
IAMRoleName | Neptune インスタンスにアタッチするIAMロールを作成するので、その名前を入力する(任意の値)。 |
IAMPolicyName | IAMロールにアタッチするIAMポリシーを作成するので、その名前を入力する(任意の値)。 |
Resources | |
NeptuneLoadFromS3Role | Neptune インスタンスにアタッチするIAMロールを作成。 |
NeptuneLoadFromS3Policy | 上記IAMロールにアタッチするIAMポリシーを作成。's3:Get*'、's3:List*'権限を割り当ててている。 |
NeptuneSG | Neptune インスタンスにアタッチするセキュリティグループを作成。 |
NeptuneDBSubnetGroup | Neptune用のDBサブネットグループを作成。 |
NeptuneDBClusterParameterGroup | Neptune クラスター用のパラメーターグループを作成。ここでは、"neptune_enable_audit_log: 0" を固定で設定している。元ネタのCloudFormationテンプレートではパラメータで指定する記述となっている。"Family" は "neptune1" で固定(ユーザーガイドより)。 |
NeptuneDBParameterGroup | Neptune インスタンス用のパラメーターグループを作成。"neptune_query_timeout" にパラメーターで指定した値を設定している。こちらも"Family" は "neptune1" で固定(ユーザーガイドより)。 |
NeptuneDBCluster | Neptune クラスターを作成。EngineVersionやPortなど、パラメーターで指定した値を設定している。ここでは、"IamAuthEnabled: false"を固定で設定。 "StorageEncrypted: true" と "KmsKeyId: ''" をセットで設定することで、暗号化を有効にし、KMSキーは"aws/rds" を設定できる。DependsOn でDBサブネットグループとクラスター用のパラメーターグループを指定している。 |
NeptuneDBInstance | Neptune インスタンスを作成。クラスターと結び付けている。DependsOn でクラスターとインスタンス用のパラメーターグループを指定している。 |
テンプレートによる作成後、マネジメントコンソールから確認
クラスターとデータベースインスタンスが作成されています。まだこの時点では、中のデータを確認する術がありません。
ハマりどころ
「ポイント解説」に書きましたが、DBサブネットグループ名のパラメーターに大文字を入力してしまい、これが自動的に小文字として作成されるので、クラスター作成時に「そんなサブネットグループは存在しない」というエラーが発生しました。
気になる利用料は
料金表は こちら
インスタンス料金 | 東京リージョン db.t3.medium で 0.15USD/時間 |
---|---|
ストレージ料金 | 東京リージョン 0.12USD/GB/月 |
I/O 料金 | 東京リージョン 0.24USD/100万リクエスト |
→ ストレージ1GB以内、I/Oは100万リクエスト以内に収まると仮定して、1月分を計算して日本円で換算すると、おおよそ 11,920円/月
ぼやきなど
時代は Infrastructure as Code や! (もう古い?) と CloudFormation テンプレートを作り始めたはいいものの、なかなか思うように通らず、しかも大量に構築する要件も特になかったので、「マネコンポチポチでよかったかな・・・」と何度もテンプレートを作らない方向に流れそうになりましたが、何となくやりきりました。
それでは、楽しいAWSライフを!