IAM Roleを割り当てたEC2インスタンスからEMRを起動する

いろいろとハマったのでメモ.

サマリ

  • IAM Roleは3種類必要
    • EMRをキックするインスタンス用の通常IAM Role
    • EMRのservice role
    • EMRで起動されるEC2用のjobflow role
  • service / jobflow roleはdefaultを自動生成できるので使うべし
    • 必要に応じて後からカスタムすれば良い
    • AWS SDKからEMRを起動するときにservice / jobflow roleを指定する
  • AWSのドキュメントは英語版を見る方が結果的に早そう
    • 日本語版は情報が古い

やろうとしていること

cronでデイリーにEMRを起動してS3のデータを集計する. 元々はサーバにAWSのトークン情報を抱かせて環境変数経由で渡して動いていたものを,IAM Roleを使う方式に変更することが目的.

条件は下記の通り.

  • AWS
    • Tokyo Region
    • EMR AMI Version 2.4.2
    • AWS SDK for Ruby version 1.48.1
  • サーバ(EC2)
    • EMRをAWS SDK for Ruby経由で起動する
    • IAM Role (emr-kicker) 割当済み
  • EMR Job
    • S3のbucket Aにあるデータを入力
    • 集計結果は別のbucket Bに保存される

やったこと

emr-kickerだけを設定 → 失敗

サーバのIAM Roleであるemr-kickerに必要な権限(EMR/EC2/S3など)を全て割り当てた. これでEMRを起動しようとすると

/path/to/vendor/bundle/ruby/2.1.0/gems/aws-sdk-1.48.1/lib/aws/core/client.rb:375:in 'return_or_raise': 
Service role and InstanceProfile are required for calls made with temporary credentials provided by STS (AWS::EMR::Errors::ValidationException)

となってコマンドが失敗する.

公式ドキュメントのAmazon EMR に IAM ロールを設定するから起動時にjobflow-roleを設定できることを知り,emr-jobflowというIAM Roleを新たに自前で作成してみるも,同じメッセージで起動できなかった.

よく見たらこのドキュメントにはIAM ロールでclusterを起動する方法は、現在 Amazon EMR コンソールではサポートされていませんなどと書いてあった...

自前で用意したjobflow / service roleも設定 → 失敗

日本語のドキュメントでは情報が見つからなかったが,ググっているうちにDefault IAM Roles for Amazon EMRに当たった.

ここのデフォルト設定を元に,カスタムしたroleをそれぞれ(emr-service, emr-instance)作成し,service-role, jobflow-roleに設定するとコマンドは成功.

しかしAWS Consoleを見ると

Terminated with errors
EMR service role arn:aws:iam::***************:role/emr-service is invalid

となって起動できていなかった.

default roleを生成してそのまま利用 → 成功

Default IAM Roles for Amazon EMRの末尾にある

  • Create Default Roles with the CLI

を参考に,AWS CLIから下記コマンドでdefault roleを作成.

$ aws emr create-default-roles

このコマンドの結果,EMR_DefaultRoleEMR_EC2_DefaultRoleがIAM Roleに追加される. service-roleにEMR_DefaultRole, jobflow-roleにEMR_EC2_DefaultRoleを指定したところ,上述のTerminated with errosが出なくなり集計処理を実行することができた.

自前設定のroleで失敗して,デフォルトのroleだと成功した原因

IAM RoleのPermissionとは別の設定項目であるTrust Relationshipが正しく設定できていなかったためだった.

jobflow-roleをカスタム

EMR_EC2_DefaultRoleはS3やDynamoDBフルアクセスなど,かなり強い権限を持った状態なので,こちらは自前設定して必要範囲に絞った権限で利用することにした.