Amazon Web Services ブログ

AWS Systems Manager を使用して RStudio で Amazon EMR エッジノードをデプロイする



RStudio は、統計計算とグラフィックスのための言語と環境である R の統合開発環境 (IDE) です。データサイエンティストとして、R と Spark (ビッグデータ処理フレームワーク) を統合して、大規模なデータセットを分析できます。sparklyr と呼ばれる R パッケージを使用して、大規模なデータセットのフィルタリングと集計を R スクリプトから Spark にオフロードし、R のネイティブの強度を使用して、Spark からの結果をさらに分析および視覚化できます。

RStudio で実行されている R スクリプトは、sparklyr を使用して Spark ジョブをクラスターに送信します。通常、R スクリプトは (sparklyr とともに)、Spark を実行する (Amazon EMR の) マシンのクラスターとは別のマシンにインストールされている RStudio 環境で実行されます。sparklyr が Spark ジョブを送信できるようにするには、RStudio マシンと Spark を実行しているクラスターの間にネットワーク接続を確立する必要があります。そのための 1 つの方法は、RStudio をエッジノードで実行することです。これは、クラスターのプライベートネットワークの一部であり、RStudio などのクライアントアプリケーションを実行するマシンです。エッジノードを使用すると、Hadoop のコアサービスを実行するノードとは別にクライアントアプリケーションを実行できます。エッジノードは、ローカルの Spark および Hive シェルへの便利なアクセスも提供します。

ただし、エッジノードのデプロイは簡単ではありません。それらのエッジノードには、Hadoop クラスターと同じバージョンの Hadoop、Spark、Java、およびその他のツールが必要であり、クラスター内のノードと同じ Hadoop 構成が必要です。

この投稿では、AWS Systems Manager を使用して RStudio がインストールされたエッジノードを自動作成する方法を示します。

EMR クラスターのエッジノードのデプロイ

エッジノードをデプロイする 1 つの方法としては、EMR マスターノードから直接 Amazon EC2 AMI を作成することが挙げられます。詳細については、Amazon EMR のエッジノードを起動して RStudio を実行するをご覧ください。この投稿では、オンデマンドエッジノードのデプロイを簡素化する SSM 自動化ドキュメントを提供しています。Systems Manager は、AWS インフラストラクチャの可視性と制御を提供し、Systems Manager Automation は、エッジノードのオンデマンドの作成などの一般的で反復的なタスクを安全に自動化します。

この投稿では、SSM ドキュメントをインストールするプロセスと、ドキュメントを使用してエッジノードを作成する方法について説明します。コードの詳細については、GitHub リポジトリを参照してください。

自動化ドキュメントの作成

まず、Terraform を使用して自動化ドキュメントを作成します。Terraform は、Terraform のウェブサイトからダウンロードできます。あるいは、AWS CloudFormation も同様に機能します。

Terraform をインストールした後、リポジトリを複製したディレクトリに移動し、vars.tf のファイルを編集します。詳細については、GitHub リポジトリをご覧ください。このファイルはいくつかの入力パラメータを定義しており、ファイル内のコメントのとおりです。vars.tf でデフォルト値を提供するか、サポートされている他の手法のいずれかを使用してオーバーライドできます。詳細については、Terraform のウェブサイトの Input Variables を参照してください。

次に、以下のコードを入力します。

tf init # 一度のみ
tf apply

コードは、Terraform プランを実行してドキュメントを作成します。この時点で、以下を行う権限を持つ AWS アカウントにアクセスするように環境が設定されている必要があります。

今後、Terraform プランを更新するには、Terraform の共有状態機能を使用します。詳細については、Terraform のウェブサイトの Remote State を参照してください。

Terraform プランは、ローカルテンプレートファイルから自動化ドキュメントを読み込み、それを Systems Manager に登録します。次のコードを参照してください。

# テンプレートからドキュメントを読み込み、いくつかの変数を置き換えます。
data "template_file" "ssm_doc_edge_node" {
  template = "${file("${path.module}/ssm_doc_edge_node.tpl")}"

  vars = {
    SSMRoleArn = "${aws_iam_role.ssm_automation_role.arn}"
    InstanceProfileArn = "${aws_iam_instance_profile.edge_node_profile.arn}"
    PlaybookUrl = "s3://${var.bucket}/init.yaml"
    Environment = "${var.environment}"
    Project = "${var.ProjectTag}"
    region = "${var.region}"
  }
}

# ドキュメントのコンテンツを SSM に登録します
resource "aws_ssm_document" "create_edge_node" {
  name          = "create_edge_node"
  document_type = "Automation"
  document_format = "YAML"
  tags = {
    Name = "create_edge_node"
    Project = "${var.ProjectTag}"
    Environment = "${var.environment}"
  }

  content = "${data.template_file.ssm_doc_edge_node.rendered}"
}

Terraform プランの残りの部分では、次のことを行います。

  • 使用する SSM ドキュメントの Ansible テンプレートをアップロードする
  • Systems Manager と新しいエッジノードが適切な権限を引き受けるようにする IAM ロールとポリシーを設定する

自動化ドキュメントに含まれるもの

自動化ドキュメントには、主に 3 つのステップがあります。まず、既存の EMR マスターノードから新しい AMI を作成して起動します。次のコードを参照してください。

- name: create_ami
  action: aws:createImage
  maxAttempts: 1
  timeoutSeconds: 1200
  onFailure: Abort
  inputs:
    InstanceId: "{{MasterNodeId}}"
    ImageName: AMI Created on{{global:DATE_TIME}}
    NoReboot: true
    
- name: launch_ami
  action: aws:runInstances
  maxAttempts: 1
  timeoutSeconds: 1200
  onFailure: Abort
  inputs:
    ImageId: "{{create_ami.ImageId}}"
  ...

次に、SSM エージェントを更新し、Ansible プレイブックを実行して RStudio をインストールします。GitHub で Ansible プレイブックを調べることができます。RStudio と依存関係をインストールし、初期設定を処理します。次のコードを参照してください。

- name: updateSSMAgent
  action: aws:runCommand
  inputs:
    DocumentName: AWS-UpdateSSMAgent
    InstanceIds:
    - "{{launch_ami.iid}}"
- name: installPip
  action: aws:runCommand
  inputs:
    DocumentName: AWS-RunShellScript
    InstanceIds:
    - "{{launch_ami.iid}}"
    Parameters:
        commands: 
        - pip install ansible boto3 botocore
- name: runPlaybook
  action: aws:runCommand
  inputs:
    DocumentName: AWS-RunAnsiblePlaybook
    InstanceIds:
    - "{{launch_ami.iid}}"
    Parameters:
      playbookurl: "${PlaybookUrl}"

最後に、Amazon CloudWatch アラームを追加して、エッジノードに障害が発生した場合に EC2 インスタンスのリカバリをトリガーします。次のコードを参照してください。

- name: add_recovery
  action: aws:executeAwsApi
  inputs:
    Service: cloudwatch
    Api: PutMetricAlarm
    AlarmName: "Recovery for edge node {{ launch_ami.iid }}"
    ActionsEnabled: true
    AlarmActions: 
    - "arn:aws:automate:${region}:ec2:recover"

自動化ドキュメントの使用

自動化ドキュメントの使用を開始するには、以下の手順を実行します。

  1. Systems Manager コンソールで、[自動化] を選択します。
  2. [オートメーションの実行] を選択します。
  3. [自己の所有] タブで、create_edge_node のドキュメントを選択します。
  4. [次へ] をクリックします。

    次のページでは、3 つの情報を入力する必要があります。クラウド運用チーム、または EMR クラスターを管理している人からアドバイスを受けたい場合もあることでしょう。最新の EMR バージョンと Spark でクラスターを作成する手順については、サンプルの Amazon EMR クラスターの起動を参照してください。
  5. [入力パラメータセクション] で、次の情報を入力します。
    • [MasterNodeId] には、接続する EMR クラスターのマスターノードの EC2 インスタンス ID を入力します。ほとんどの場合、運用チームはこの情報を提供できますが、EMR クラスターの [ハードウェア] タブに移動し、マスターノードグループにドリルすることにより、インスタンス ID を見つけることもできます。RStudio で sparklyr を使用するため、EMR クラスターには Spark がインストールされている必要があります。次のスクリーンショットは、[ハードウェア] タブの EC2 インスタンス ID の場所を示しています。
    • [SubnetId] には、エッジノードが存在するサブネットを入力します。運用チームがこの情報を提供できます。または、EMR クラスターの [概要] タブで確認できます。エッジノードは、クラスターと同じ VPC に存在する必要があります。Session Manager 経由で接続するため、パブリックサブネットに存在する必要はありません。次のスクリーンショットは、クラスターの [概要] タブのサブネット ID の場所を示しています。
    • [QuickIdentifier] には、このエッジノードを思い出しやすいようにわかりやすい名前を入力します。たとえば、Edge Node with RStudio です。

実行が完了すると、次のスクリーンショットのように、完了したステップが表示されます。

リストの最後のステップ (ステップ 8) を選択すると、新しいエッジノードの DNS 名と EC2 インスタンス ID が表示されます。次のスクリーンショットを参照してください。

これで、Systems Manager の別の機能である Session Manager を使用して、このエッジノードに接続できます。Session Manager を使用すると、SSH キーを使用したり、SSH ポートをインターネットに公開したりすることなく、ポート転送用の SSH トンネルを開くことができます。ポート転送セッションを開く手順については、セッションの開始 (ポート転送) を参照してください。ローカルにインストールされた Session Manager プラグインが必要です。次のコードを参照してください。

aws ssm start-session \
  --target instance-id \ # 自動化ドキュメントの出力からこれを取得します
  --document-name AWS-StartPortForwardingSession \
  --parameters '{"portNumber":["8787"], "localPortNumber":["8787"]}'

詳細については、AWS CLI 用の Session Manager プラグインのインストールを参照してください。

これで、http://localhost:8787 から RStudio にアクセスできるようになりました。次のスクリーンショットを参照してください。

また、ノードに直接アクセスして、Session Manager コンソールからローカルの Hive シェルと Spark シェルを使用することもできます。

この投稿では、SSM ドキュメントを設定して、シングルユーザーエッジノードを作成します。RStudio にログインするためのデフォルトのユーザー名は ruser です。RStudio はデフォルトで PAM 認証を使用するため、オペレーティングシステムで ruser アカウントのパスワードを直接変更してパスワードを設定する必要があります。詳細については、RStudio サーバーのユーザー名は何ですか? を参照してください。 パスワードを変更するには、別の Session Manager セッションを開き、次のコードを入力します。

aws ssm start-session \
  --target instance-id \ # 自動化ドキュメントの出力からこれを取得します

$ sudo passwd ruser # 任意のパスワードを入力して確認します

R スクリプトなどの重要なファイルはすべて GitHub リポジトリに保存し、出力データを S3 バケットに保存して、長期的な永続性を確保する必要があります。

セキュリティの設定

Terraform プランは、3 つの重要な IAM ロールを設定します。

  • 自動化ドキュメントの実行時に Systems Manager が引き受けるロール。このロールは、新しい AMI、CloudWatch、Systems Manager の作成など、Amazon EC2 でアクションを実行する必要があります。
  • エッジノードの EC2 インスタンスプロファイル。プロファイルには、SSM エージェントを実行し、エッジノードが EMR ノードの一般的なタスクを実行するために必要なアクセス許可があります。
  • CloudWatch がインスタンスのリカバリを実行するためのロール。

ご使用の環境では、IAM ロールとポリシーを確認し、タグやその他の条件に基づいてそれらの範囲を厳しくすることができます。

まとめ

この投稿では、SSM ドキュメントを使用して RStudio で EMR エッジノードをデプロイする自動化された方法について説明しました。RStudio の EMR エッジノードを使用すると、使い慣れた作業環境で、Spark および sparklyr を介して大規模なデータセットにアクセスできます。新しいエッジノードをデプロイし、AWS CloudFormation テンプレートを使用して必要な Hadoop ライブラリをインストールする方法については、Amazon EMR でエッジノードを起動して RStudio を実行するをご覧ください。

 


著者について

Randy DeFauw 氏は、アマゾン ウェブ サービスのプリンシパルソリューションアーキテクトです。 彼は、お客様が AWS を使用するに際して、ソリューションの価値の向上に役立てていただくために、AWS のお客様と協力してデータベースプロジェクトの指導や技術支援を行っています。