Amazon Neptune の構築 - Neptune Workbench

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

エンジョイ AWS!
サーバーワークス エンジニアの伊藤Kです。

前回記事 の続きです。
「Amazon Neptune」の、Neptune インスタンス(クラスター)を構築したので、インスタンスのデータをマネジメントコンソールから操作できるように、Neptune Workbench を構築します。

ワークベンチ、また一部のDIY好き以外にはなじみの薄い用語が出てきましたね。 用語のイメージとしてはこんな感じです。 f:id:swx-kenichi-ito:20220129223915p:plain
workbench とは、作業台、仕事台という意味の英単語で、ITの分野では、あるサービスなどの作業を支援するツール群を指すようです。覚えておこう。
Neptune Workbench は、マネジメントコンソールからのアクセスで操作でき、Neptune インスタンスにいろいろなクエリを発行したり、結果を可視化したりできます。 公式ドキュメント

VPC、サブネット、NAT Gateway、前回記事で構築した Neptune クラスターは既に存在するものとします。

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

Neptune Workbenchを構築するCloudFormationテンプレート(サンプル)

私の記事では毎度のお約束、「Description」で記述している怪しげな英語には目をつぶってください。
また、サンプルなのでご自分の要件に合わせてカスタマイズしてご利用ください。

AWSTemplateFormatVersion: "2010-09-09"
Description: A template to deploy Neptune Notebooks using CloudFormation resources
Parameters:
  NeptuneClusterVpc:
    Description: 'Neptune Cluster VPC'
    Default: "vpc-xxxxxxxxxxxxxxxxxx"
    Type: AWS::EC2::VPC::Id
  ApplicationTagValue:
    Description: 'Application Tag Value'
    Default: "Test"
    Type: String
  SageMakerSecurityGroupName:
    Description: 'SG Name for NeptuneNotebook'
    Default: "Test-SageMaker-SG"
    Type: String 
  NotebookInstanceName:
    Description: 'NeptuneNotebook Instance Name (Must start with "aws-neptune-")'
    Default: "aws-neptune-notebook"
    Type: String 
  NotebookInstanceType:
    Description: >-
      SageMaker Notebook instance type. Please refer
      https://aws.amazon.com/sagemaker/pricing/ for uptodate allowed instance
      type in aws region and https://aws.amazon.com/neptune/pricing/ for
      pricing.
    Type: String
    Default: ml.t3.medium
    AllowedValues:
      - ml.t2.medium
      - ml.t2.large
      - ml.t2.xlarge
      - ml.t2.2xlarge
      - ml.t3.medium
      - ml.t3.large
      - ml.t3.xlarge
      - ml.t3.2xlarge
      - ml.m4.xlarge
      - ml.m4.2xlarge
      - ml.m4.4xlarge
      - ml.m4.10xlarge
      - ml.m4.16xlarge
      - ml.m5.xlarge
      - ml.m5.2xlarge
      - ml.m5.4xlarge
      - ml.m5.12xlarge
      - ml.m5.24xlarge
      - ml.c4.large
      - ml.c4.xlarge
      - ml.c4.2xlarge
      - ml.c4.4xlarge
      - ml.c4.8xlarge
      - ml.c5.xlarge
      - ml.c5.2xlarge
      - ml.c5.4xlarge
      - ml.c5.9xlarge
      - ml.c5.18xlarge
      - ml.c5d.xlarge
      - ml.c5d.2xlarge
      - ml.c5d.4xlarge
      - ml.c5d.9xlarge
      - ml.c5d.18xlarge
      - ml.p3.2xlarge
      - ml.p3.8xlarge
      - ml.p3.16xlarge
      - ml.p2.2xlarge
      - ml.p2.8xlarge
      - ml.p2.16xlarge
  NotebookInstanceConfigName:
    Description: 'NeptuneNotebook Instance Config Name'
    Default: "notebook-instance-config-name"
    Type: String 
  NotebookInstanceSubnet:
    Description: 'NeptuneNotebook Instance Subnet'
    Default: "subnet-xxxxxxxxxxxxxxxx"
    Type: AWS::EC2::Subnet::Id
  EnableIamAuthOnNeptune:
    Description: 'NeptuneNotebook Instance Enable IAMRole'
    Default: 'false'
    Type: String 
  NeptuneLoadFromS3RoleArn:
    Description: 'NeptuneLoadFromS3Role ARN'
    Default: "arn:aws:iam::xxxxxxxxxxxx:role/Role-NeptuneLoadFromS3"
    Type: String 
  NeptuneClusterEndpoint:
    Description: 'NeptuneCluster Endpoint'
    Default: "test-neptune-dbcluster.cluster-xxxxxxxxxxx.ap-northeast-1.neptune.amazonaws.com"
    Type: String 
  NeptuneClusterPort:
    Description: 'NeptuneCluster Port'
    Default: 8182
    Type: String 
  NeptuneClusterId:
    Description: 'Neptune ClusterId'
    Default: "test-neptune-dbcluster"
    Type: String 
  NeptuneClusterResourceId:
    Description: 'NeptuneCluster ResourceId'
    Default: "cluster-xxxxxxxxxxxxxxxxxxxxxxxxx"
    Type: String 
  NeptuneExportApiUri:
    Description: '(Option) Neptune Export API URI'
    Default: ""
    Type: String 
  NeptuneMLIAMRoleArn:
    Description: '(Option) SageMaker IAM Role'
    Default: ""
    Type: String 
Conditions:
  EnableIAMAuth: !Equals 
    - !Ref EnableIamAuthOnNeptune
    - 'true'
Resources:
  ExecutionRole:
    Type: 'AWS::IAM::Role'
    Properties:
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Principal:
              Service:
                - sagemaker.amazonaws.com
            Action:
              - 'sts:AssumeRole'
      Path: /
      Policies:
        - PolicyName: SagemakerNotebookNeptunePolicy
          PolicyDocument:
            Version: 2012-10-17
            Statement:
              - Effect: Allow
                Action:
                  - 'cloudwatch:PutMetricData'
                Resource: !Sub >-
                  arn:${AWS::Partition}:cloudwatch:${AWS::Region}:${AWS::AccountId}:*
              - Effect: Allow
                Action:
                  - 'logs:CreateLogGroup'
                  - 'logs:CreateLogStream'
                  - 'logs:DescribeLogStreams'
                  - 'logs:PutLogEvents'
                  - 'logs:GetLogEvents'
                Resource: !Sub 'arn:${AWS::Partition}:logs:${AWS::Region}:${AWS::AccountId}:*'
              - Effect: Allow
                Action: 'neptune-db:*'
                Resource: !Sub >-
                  arn:${AWS::Partition}:neptune-db:${AWS::Region}:${AWS::AccountId}:${NeptuneClusterResourceId}/*
              - Effect: Allow
                Action:
                  - 's3:Put*'
                  - 's3:Get*'
                  - 's3:List*'
                Resource: !Sub 'arn:${AWS::Partition}:s3:::*'
              - Effect: Allow
                Action: 'execute-api:Invoke'
                Resource: !Sub >-
                  arn:${AWS::Partition}:execute-api:${AWS::Region}:${AWS::AccountId}:*/*
              - Effect: Allow
                Action:
                  - 'sagemaker:CreateModel'
                  - 'sagemaker:CreateEndpointConfig'
                  - 'sagemaker:CreateEndpoint'
                  - 'sagemaker:DescribeModel'
                  - 'sagemaker:DescribeEndpointConfig'
                  - 'sagemaker:DescribeEndpoint'
                  - 'sagemaker:DeleteModel'
                  - 'sagemaker:DeleteEndpointConfig'
                  - 'sagemaker:DeleteEndpoint'
                Resource: !Sub >-
                  arn:${AWS::Partition}:sagemaker:${AWS::Region}:${AWS::AccountId}:*/*
  SageMakerSecurityGroup:
    Type: 'AWS::EC2::SecurityGroup'
    Properties:
      GroupDescription: "Allow Access"
      GroupName: !Ref SageMakerSecurityGroupName
      VpcId: !Ref NeptuneClusterVpc
      Tags:
        - Key: "Name"
          Value: !Ref SageMakerSecurityGroupName
        - Key: "Application"
          Value: !Ref ApplicationTagValue
  NeptuneNotebookInstanceLifecycleConfig:
    Type: 'AWS::SageMaker::NotebookInstanceLifecycleConfig'
    Properties:
      NotebookInstanceLifecycleConfigName: !Ref NotebookInstanceConfigName
      OnStart:
        - Content: !Base64 
            'Fn::Join':
              - ''
              - - |
                  #!/bin/bash
                - |+
                  sudo -u ec2-user -i <<'EOF'

                - !If 
                  - EnableIAMAuth
                  - |
                    echo "export GRAPH_NOTEBOOK_AUTH_MODE=IAM" >> ~/.bashrc
                  - |
                    echo "export GRAPH_NOTEBOOK_AUTH_MODE=DEFAULT" >> ~/.bashrc
                - |
                  echo "export GRAPH_NOTEBOOK_IAM_PROVIDER=ROLE" >> ~/.bashrc
                - |
                  echo "export GRAPH_NOTEBOOK_SSL=True" >> ~/.bashrc
                - echo "export GRAPH_NOTEBOOK_HOST=
                - !Ref NeptuneClusterEndpoint
                - |
                  " >> ~/.bashrc
                - echo "export GRAPH_NOTEBOOK_PORT=
                - !Ref NeptuneClusterPort
                - |
                  " >> ~/.bashrc
                - echo "export NEPTUNE_LOAD_FROM_S3_ROLE_ARN=
                - !Ref NeptuneLoadFromS3RoleArn
                - |
                  " >> ~/.bashrc
                - echo "export AWS_REGION=
                - !Ref 'AWS::Region'
                - |+
                  " >> ~/.bashrc

                - echo "export NEPTUNE_ML_ROLE_ARN=
                - !Ref NeptuneMLIAMRoleArn
                - |+
                  " >> ~/.bashrc

                - echo "export NEPTUNE_EXPORT_API_URI=
                - !Ref NeptuneExportApiUri
                - |+
                  " >> ~/.bashrc

                - 'aws s3 cp s3://'
                - 'aws-neptune-notebook'
                - |
                  /graph_notebook.tar.gz /tmp/graph_notebook.tar.gz
                - |
                  rm -rf /tmp/graph_notebook
                - |
                  tar -zxvf /tmp/graph_notebook.tar.gz -C /tmp
                - |+
                  /tmp/graph_notebook/install.sh

                - EOF
  NeptuneNotebookInstance:
    Type: 'AWS::SageMaker::NotebookInstance'
    Properties:
      InstanceType: !Ref NotebookInstanceType
      NotebookInstanceName: !Ref NotebookInstanceName
      SubnetId: !Ref NotebookInstanceSubnet
      SecurityGroupIds:
        - !Ref SageMakerSecurityGroup
      RoleArn: !GetAtt ExecutionRole.Arn
      LifecycleConfigName: !Ref NotebookInstanceConfigName
      Tags:
        - Key: "Name"
          Value: !Ref NotebookInstanceName
        - Key: "Application"
          Value: !Ref ApplicationTagValue
        - Key: "aws-neptune-cluster-id"
          Value: !Ref NeptuneClusterId
        - Key: "aws-neptune-resource-id"
          Value: !Ref NeptuneClusterResourceId

ポイント解説

  • Neptune インスタンスとの関連付けに必要な値の確認について
    • マネジメントコンソールから確認する場合、下図の値を各パラメーターに入力する

f:id:swx-kenichi-ito:20220129224027p:plain f:id:swx-kenichi-ito:20220129224040p:plain f:id:swx-kenichi-ito:20220129224053p:plain

  • IAMロール、インラインポリシーについて
    • Neptune Workbench にアタッチする。元ネタ (前回の記事参照) のCloudFormationの権限をそのまま使用
    • CloudWatch Logs、S3、SageMaker の権限が書かれている
Parameters
NeptuneClusterVpc 接続する Neptune クラスターが構築されているVPCを指定する。SecurityGroup の作成で使う。Neptune Workbenchの作成には使用しない。
ApplicationTagValue リソース共通で"Application" タグを作成するので、その値を指定する(任意の値)。利用料の把握などに使用。
SageMakerSecurityGroupName Neptune Workbench 用のセキュリティグループを作成するので、その名前を入力する(任意の値)。インバウンドルールは後々クライアントとなるインスタンスからの接続に使用する。アウトバウンドルールは全て許可としているので、前述の"直接インターネットアクセス"が無効の場合でも、NAT Gateway経由でインターネットアクセスが可能となる。
NotebookInstanceName Neptune Workbench の名前を入力する。接頭辞として "aws-neptune-" で始めること(理由は後述)。その後は任意の値。
NotebookInstanceType Neptune Workbench のインスタンスタイプを指定する。"AllowedValues"の中から選択する。
NotebookInstanceConfigName Neptune Workbench は内部的には Amazon SageMaker のノートブックとして作成される。そのライフサイクル設定の名前を入力する(任意の値)。
NotebookInstanceSubnet Neptune Workbench を所属させるサブネットを指定する。今回はNeptune インスタンスが使用する2つのサブネットのうち一つに相乗り。
EnableIamAuthOnNeptune Neptune Workbench への接続にIAM Roleによる認証を用いる場合に "true" を指定する。ここでの動作確認は "false" で実施。
NeptuneLoadFromS3RoleArn 接続する Neptune インスタンスの構築時(前回の記事)に同時に作成した、Neptune インスタンスからS3へアクセスするためのIAMロールのARNを入力する。
NeptuneClusterEndpoint 接続する Neptune インスタンス のクラスターエンドポイント名を入力する。
NeptuneClusterPort 接続する Neptune インスタンス のポートを入力する。
NeptuneClusterId 接続する Neptune インスタンス のクラスターIDを入力する。
NeptuneClusterResourceId 接続する Neptune インスタンス のクラスターリソースIDを入力する。
NeptuneExportApiUri (オプション) "NotebookInstanceConfigName" の項に記載したライフサイクル設定の中で実行されるスクリプトの "export NEPTUNE_EXPORT_API_URI=" に埋め込めるURI。ここでは特に指定しない。
NeptuneMLIAMRoleArn (オプション) "NotebookInstanceConfigName" の項に記載したライフサイクル設定の中で実行されるスクリプトの "export NEPTUNE_ML_ROLE_ARN=" に埋め込めるURI。ここでは特に指定しない。
Resources
ExecutionRole Neptune Workbench にアタッチするIAMロールを作成。ポリシーは "SagemakerNotebookNeptunePolicy" という名前のインラインポリシーとして記載されている
SageMakerSecurityGroup Neptune Workbench にアタッチするセキュリティグループを作成。
NeptuneNotebookInstanceLifecycleConfig Neptune Workbench (SageMaker のノートブック) のライフサイクル設定を作成する。ここでは元ネタ (前回の記事参照) のCloudFormationの記載をほぼそのまま使用。
NeptuneNotebookInstance Neptune Workbench インスタンスを作成。作成するライフサイクル設定と結び付けている。
  • Neptune Workbench (SageMaker のノートブックインスタンス)がマネジメントコンソール Neptune の「Notebook」として表示される条件。以下を全て満たす必要がある。

    • インスタンス名が 接頭辞として "aws-neptune-" で始まっている
    • インスタンスのタグに以下2点が付帯されている
      • Key : "aws-neptune-cluster-id" 、 Value : <接続する Neptune インスタンス のクラスターID>
      • Key : "aws-neptune-resource-id" 、 Value : <接続する Neptune インスタンス のクラスターリソースID>
  • "直接インターネットアクセス"について

    • SageMaker Notebook の設定で、インターネットアクセスを SageMaker から直接行うか、VPC内に作成されたSageMaker の ENI からNAT Gateway等を通して行うかを選択できる
    • CloudFormation テンプレートの "Type: 'AWS::SageMaker::NotebookInstance'" では "DirectInternetAccess" という項目で有効無効を指定できる
    • 上記サンプルテンプレートでは項目自体を記載していないため、デフォルトの "Enabled" が適用される
    • そのため、Neptune Workbench からインターネットや、またS3などへアクセスする場合はインターネットアクセスは SageMaker の直接接続機能経由となり、Neptune インスタンスへのアクセスはVPC内に作成された SageMaker の ENI から行われる
    • このあたりについて書かれている公式ドキュメント : VPC インターフェイスエンドポイントを介してノートブックインスタンスに接続する

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

Neptune Workbench が作成されています。
f:id:swx-kenichi-ito:20220129224130p:plain

Gremlin形式のクエリでアクセスしてみます。
f:id:swx-kenichi-ito:20220129224156p:plain

ハマりどころ

”took longer than 5 minutes" エラー

以下のエラーメッセージが出て、Workbench インスタンスの構築に失敗する事象がなかなか解消できませんでした。

Notebook Instance Lifecycle Config 'arn:aws:sagemaker:ap-northeast-1:xxxxxxxxxxxx:notebook-instance-lifecycle-config/notebook-instance-config-name' for Notebook Instance 'arn:aws:sagemaker:ap-northeast-1:xxxxxxxxxxxx:notebook-instance/notebook-for-neptune' took longer than 5 minutes. Please check your CloudWatch logs for more details if your Notebook Instance has Internet access.

原因としてはライフサイクル設定部分の、以下の記載を誤っていました。

                - 'aws s3 cp s3://'
                - 'aws-neptune-notebook'
                - |
                  /graph_notebook.tar.gz /tmp/graph_notebook.tar.gz

元ネタのテンプレートがパラメータによって分岐していたところをシンプルに書き換えようとして、連結がうまくできなかったようです。
CloudWatch Logsでこの次のコマンドに失敗している旨のメッセージが出ていたところから、このあたりの記述を再度見直して解決しました。

"Notebook" の一覧に表示されない

Neptune の "Notebook" の一覧に作成した Workbench インスタンスが表示されない現象が発生しました。
f:id:swx-kenichi-ito:20220129224216p:plain

SageMaker のインスタンスとしては登録されています。
f:id:swx-kenichi-ito:20220129224234p:plain

これは、「ポイント情報」に記載した、 "Neptune Workbench (SageMaker のノートブックインスタンス)がマネジメントコンソール Neptune の「Notebook」として表示される条件" を満たしていないことが原因でした。
特に、「インスタンス名を "aws-neptune-" で始める」ことにはなかなか気づけませんでした。

気になる利用料は

Neptune Workbench は SageMaker のノートブックインスタンス なのでその利用料がかかります。
料金表は こちら
"オンデマンドノートブックインスタンス" です。

インスタンス料金 東京リージョン ml.t3.medium で 0.065 USD/時間

→ 1か月分を計算して日本円で換算すると、おおよそ 5,148円/月

ぼやきなど

さあ構築できた、次はデータを作ってみよう、と思っていたら、ナイスガイ篠﨑さんに先を越されました。
Amazon Neptuneにデータを入れて可視化してみたい① ~準備・データ追加編~

「データの取得」回と「可視化」回が楽しみです。
やはりグラフDBの楽しさは、可視化してこそですよね!(圧力)



それでは、楽しいAWSライフを!
f:id:swx-kenichi-ito:20220129225143p:plain

伊藤K (記事一覧)

おっさんエンジニア。

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

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