Amazon Neptune の構築 - インスタンス

記事タイトルとURLをコピーする

エンジョイ 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 インスタンスのデータを操作することまでやれればと。(願望)

f:id:swx-kenichi-ito:20220120230731p:plain
今回は、図の紫枠の部分を構築します。
f:id:swx-kenichi-ito:20220120230751p:plain

インスタンスを構築する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"を使用。
  • インスタンスタイプについて

    • 使用できるインスタンスタイプは料金表 から確認できる。
    • インスタンスタイプごとのスペックはRDSと共通なので、こちら で確認する。
  • 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 でクラスターとインスタンス用のパラメーターグループを指定している。

テンプレートによる作成後、マネジメントコンソールから確認

クラスターとデータベースインスタンスが作成されています。まだこの時点では、中のデータを確認する術がありません。

f:id:swx-kenichi-ito:20220120232032p:plain

ハマりどころ

「ポイント解説」に書きましたが、DBサブネットグループ名のパラメーターに大文字を入力してしまい、これが自動的に小文字として作成されるので、クラスター作成時に「そんなサブネットグループは存在しない」というエラーが発生しました。 f:id:swx-kenichi-ito:20220120230832p:plain

気になる利用料は

料金表は こちら

インスタンス料金 東京リージョン 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ライフを!
f:id:swx-kenichi-ito:20220120230902p:plain

伊藤K (記事一覧)

おっさんエンジニア。

SREと名前のつく部門にいますがやっていることはSREではないです。

甘いお菓子が大好きですが、体重にDirect Connectなので控えています。

「エンジョイ AWS」を合言葉に、AWSを楽しむことを心がけています。