EMR管理ポリシーをv1からv2に更新してみた

EMRの管理ポリシーをv1(非推奨化予定)からv2に更新する機会がありました。EMR管理ポリシーのv1とv2でどのような差異があるか、どういった対応を行ったか本記事にまとめます。
2023.01.19

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

こんにちは、福岡オフィスのyoshihitohです。

先日、EMRの管理ポリシーをv1(非推奨化予定)からv2に更新する機会がありました。EMR管理ポリシーのv1とv2でどのような差異があるか、どういった対応を行ったか本記事にまとめます。

前提条件

対象

  • Amazon EMR on EC2 が対象です
  • Amazon EMR on EKSAmazon EMR Serverless は対象外です

システム構成

筆者が運用するシステムではMWAAからEMRクラスタを構築して日次バッチを実行しています。日次バッチはS3に配置したデータを処理して、その結果をGlueのデータカタログに登録しています。このシステムで利用するEMR管理ポリシーをv1からv2に更新しました。

ポリシー更新

ポリシー更新にあたって以下の対応が必要です。

  • EMRクラスタ構築時のリクエスト内容を変更する
  • IAMロールの権限設定を変更する
  • EMR関連リソースにタグを設定する

以降でそれぞれの対応について説明します。なお、更新の詳細や考慮事項については Amazon EMR管理ポリシー のドキュメントに詳細が記載されています。ドキュメントの内容を確認してから作業することをオススメします。

注意事項

・現在のすべてのエンティティから v1 ポリシーをデタッチすると、ポリシーは表示されなくなり、使用できなくなります。

Amazon EMR管理ポリシー のドキュメントに記載されている通り、v1ポリシーを使用するエンティティが無くなるとv1ポリシーは表示されなくなるようです。切り替え作業が終わるまでの間はv1ポリシーが非表示とならないように、何かしらのIAMエンティティにアタッチしておくと良いかもしれません。

EMRクラスタ構築時のリクエスト内容を変更する

RunJobFlow でEMRクラスタを構築するときに、リクエストの Tags に以下の内容を設定してください。

  • Key: for-use-with-amazon-emr-managed-policies
  • Value: true

for-use-with-amazon-emr-managed-policies タグを設定すると、EMRがプロビジョニングするリソースにタグを伝播するようになります。そのため後述するEMR管理ポリシーv2が要求するリソースタグの条件を満たすようになります。

IAMロールの権限設定を変更する

EMRクラスタで使用するIAMロールと、EMRクラスタを構築するアプリケーションで利用するIAMロールについて、アタッチするポリシーの変更が必要です。以下v1とv2の対応表です。

システム ロール種別 v1ポリシー v2ポリシー
アプリケーション フルアクセス AmazonElasticMapReduceFullAccess AmazonEMRFullAccessPolicy_v2
アプリケーション 読み取り専用 AmazonElasticMapReduceReadOnlyAccess AmazonEMRReadOnlyAccessPolicy_v2
EMRクラスタ EMRロール AmazonElasticMapReduceRole AmazonEMRServicePolicy_v2
EMRクラスタ EC2インスタンスプロファイル AmazonElasticMapReduceforEC2Role -
EMRクラスタ Auto Scalingロール AmazonElasticMapReduceforAutoScalingRole AmazonElasticMapReduceforAutoScalingRole (変更なし)

EMR on EC2では用途ごとに複数のロールがあり、それぞれのロールで利用できるEMR管理ポリシーが用意されています。EMRのデフォルトロールでは、以下のポリシーがアタッチされています。

ロール種別 デフォルトロール v1の場合 v2の場合
EMRロール EMR_DefaultRole AmazonElasticMapReduceRole AmazonEMRServicePolicy_v2
EC2インスタンスプロファイル EMR_EC2_DefaultRole AmazonElasticMapReduceforEC2Role -
Auto Scalingロール EMR_AutoScaling_DefaultRole AmazonElasticMapReduceforAutoScalingRole AmazonElasticMapReduceforAutoScalingRole (変更なし)

EMRのデフォルトロールを使用しても良いし、システム固有のロールを作成することもできます。以降はシステム固有のロールを カスタムロール と呼びます。ロール種別の詳細は Amazon EMR で使用される IAM サービスロール を確認してください。

EMR管理ポリシーをv1からv2に変更する場合は以下の対応が必要です。

  • アプリケーションで利用するロールの権限設定を変更する
  • EMRクラスタで利用するロールの権限設定を変更する

それぞれについて説明します。

アプリケーションで利用するロールの権限設定を変更する

EMRはフルアクセス用の管理ポリシーと、読み取り専用の管理ポリシーを用意しています。アプリケーションの目的に適したv2ポリシーをアタッチするように変更します。

  • フルアクセスの場合: AmazonEMRFullAccessPolicy_v2
  • 読み取り専用の場合: AmazonEMRReadOnlyAccessPolicy_v2

EMRクラスタで利用するロールの権限設定を変更する

以下の対応が必要です。

  • EMRロール
    • ロールにアタッチするポリシーを AmazonEMRServicePolicy_v2 に変更する
    • (カスタムロールを利用する場合のみ) EC2インスタンスプロファイル (のロール) を対象とした iam:PassRole を許可するポリシーを追加する
  • EC2インスタンスプロファイル
    • AmazonElasticMapReduceforEC2Role (v1ポリシー)をデタッチする
    • EMRクラスタ上で動作するアプリケーションが必要とする操作権限を持つポリシーを追加する

Auto Scalingロールについてはv1とv2で差異がないため対応不要です。

EMR管理ポリシーはv1とv2で権限設定が大幅に変わっています。以降でEMRロール夜の管理ポリシーととEC2インスタンスプロファイル用の管理ポリシーについて、v1とv2でどのような差異があるか確認していきます。

EMRロール

EMRロール向けの管理ポリシーは、EMRクラスタのリソースをプロビジョニングするために必要な操作を許可しています。v1とv2で対象リソースの条件が変わりました。

  • v1 ( AmazonElasticMapReduceRole )
    • 対象リソースの制限なし
  • v2 ( AmazonEMRServicePolicy_v2 )
    • for-use-with-amazon-emr-managed-policies タグに true を設定したリソースを対象とする
    • for-use-with-amazon-emr-managed-policies タグに true を設定したリクエストを対象とする
    • EMRのデフォルトロール EMR_EC2_DefaultRoleEMR_AutoScaling_DefaultRole を対象とする

リソースのタグについては EMRクラスタ構築時のリクエスト内容を変更するEMR関連リソースにタグを設定する を参照してください。

EC2インスタンスプロファイルもしくはオートスケーリングにカスタムロールを利用している場合、 iam:PassRole でカスタムロールを指定する権限が必要です。この権限を持ったポリシーを作成してEMRロールにアタッチしましょう。

AWSアカウントID 123456789012 の環境で、EC2インスタンプロファイルに ec2-role を、オートスケーリングに autoscaling-role を使用する場合のIAMポリシーを例示します。

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": "iam:PassRole",
      "Resource": "arn:aws:iam::123456789012:role/autoscaling-role",
      "Condition": {
        "StringLike": {
          "iam:PassedToService": "application-autoscaling.amazonaws.com*"
        }
      }
    },
    {
      "Effect": "Allow",
      "Action": "iam:PassRole",
      "Resource": "arn:aws:iam::123456789012:role/ec2-role",
      "Condition": {
        "StringLike": {
          "iam:PassedToService": "ec2.amazonaws.com*"
        }
      }
    }
  ]
}

EC2インスタンスプロファイル

EC2インスタンスプロファイル向けの管理ポリシーは、EMRクラスタ上で動作するアプリケーションが必要とする操作を許可します。v1では管理ポリシー AmazonElasticMapReduceforEC2Role が用意されていましたが、v2は同等の管理ポリシーを用意していません。EMRクラスタ上で動作するアプリケーションが必要とする操作権限を持ったポリシーを作成・アタッチしましょう。また、S3に配置したjarファイルをステップ実行する場合はS3のアクセス権限が必須となることに留意してください。

筆者が運用するシステムはSparkアプリケーションのjarファイルをS3に配置しています。SparkアプリケーションはS3とGlueを操作するため以下のようなポリシーを設定しました。実行するとまずい操作は個別に拒否しています。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Action": "s3:*",
            "Resource": "*",
            "Effect": "Allow"
        },
        {
            "Action": [
                "s3:Create*",
                "s3:DeleteBucket*",
            ],
            "Resource": "*",
            "Effect": "Deny"
        },
        {
            "Action": "glue:*",
            "Resource": "*",
            "Effect": "Allow"
        }
    ]
}

EMR関連リソースにタグを設定する

EMRロール・EC2インスタンスプロファイルの詳細で確認したとおり、EMR管理ポリシーv2を利用する場合は、各リソースの for-use-with-amazon-emr-managed-policies タグに true を設定する必要があります。 EMRクラスタ構築時のリクエスト内容を変更する 対応後にEMRクラスタを起動すると、EMRが自動でほとんどのリソースにタグを伝播してくれます。ただし以下のリソースについては利用者側でタグを設定する必要があります。

  • サブネット
  • セキュリティグループ

セキュリティグループはEMRが自動で作成したものを利用する場合と、利用者が作成したものを利用する場合で扱いが異なります。

  • EMRが自動で生成したものを利用する場合
    • タグ設定不要 (EMRが設定するため)
  • 利用者が作成したセキュリティグループを利用する場合
    • タグ設定が必要

詳細はドキュメント 管理ポリシーを使用するためにリソースにタグを付ける を参照してください。筆者が運用するシステムの場合はEMRが作成したセキュリティグループを利用しているため、サブネットのみタグ設定が必要でした。

変更時にハマったこと

ドキュメントをちゃんと読まずにEMR管理ポリシーをv1からv2に付け替えてみたら盛大にハマりました。具体的には以下のエラーが発生しました。

  • EMRクラスタ起動時に Service role AppServiceRole has insufficient EC2 permissions エラーが発生して起動に失敗する
  • Sparkアプリケーション実行ステップを追加すると、 AmazonS3Exception: Access Denied エラーが発生して異常終了する

それぞれについてトラブルシュート方法とエラーの原因を記載します。

EMRクラスタ起動時に Service role AppServiceRole has insufficient EC2 permissions エラーが発生して起動に失敗する

EMR管理ポリシーをv1からv2に切り替えてからEMRクラスタを作成すると、 Service role AppServiceRole has insufficient EC2 permissions エラーが発生して起動に失敗しました。

トラブルシュート方法

CloudTrailでエラーが発生した操作を特定しました。

  1. イベント履歴を開く
  2. EMRクラスタ作成日時周辺のイベントに絞り込む
  3. エラーが発生した操作を特定する
  4. イベント詳細を確認する
  5. 認証エラーの場合は、STSのDecodeAuthorizationMessage を使って errorMessage の詳細を復号し確認する

エラーの原因

以下の要因でエラーが発生していました。

  • EMRロールEC2インスタンスプロファイルiam:PassRole する権限を許可していなかった
  • EMRが動作するサブネットに for-use-with-amazon-emr-managed-policies タグを設定していなかった

CloudTrailにこのようなエラーが記録されていました。

{
  "eventTime": "2023-01-13T06:14:39Z",
  "eventSource": "ec2.amazonaws.com",
  "eventName": "RunInstances",
  "awsRegion": "ap-northeast-1",
  "sourceIPAddress": "elasticmapreduce.amazonaws.com",
  "userAgent": "elasticmapreduce.amazonaws.com",
  "errorCode": "Client.UnauthorizedOperation",
  "errorMessage": "You are not authorized to perform this operation. Encoded authorization failure message: CDzLM...(以下略)",
}

errorMessage を復号すると、以下のメッセージを確認できました。(抜粋です)

{
  "allowed": false,
  "context": {
    "principal": {
      "id": "XXXXXXXXXXXXXXXXXXXXX:CCSSession",
      "arn": "arn:aws:sts::123456789012:assumed-role/ServiceRole/CCSSession"
    },
    "action": "iam:PassRole",
    "resource": "arn:aws:iam::123456789012:role/JobFlowRole",
    "conditions": {
      "items": [
        {
          "key": "aws:Region",
          "values": { "items": [ { "value": "ap-northeast-1" } ] }
        },
        {
          "key": "aws:Service",
          "values": { "items": [ { "value": "ec2" } ] }
        },
        {
          "key": "aws:Resource",
          "values": { "items": [ { "value": "role/JobFlowRole" } ] }
        }
      ]
    }
  }
}

context セクションの action でエラー要因の操作がわかり、 resource で操作対象のリソースがわかります。この場合は ServiceRole がEC2に JobFlowRoleiam:PassRole しようとしたところ、権限不足で操作が拒否されたことがわかります。

これらのエラーを解消すると、EMRクラスタが起動するようになりました。

Sparkアプリケーション実行ステップを追加すると、 AmazonS3Exception: Access Denied エラーが発生して異常終了する

EMRクラスタが起動するようになった後で、Sparkアプリケーション実行ステップを追加してみました。少し待つと Failed to get main class in JAR with error 'com.amazon.ws.emr.hadoop.fs.shaded.com.amazonaws.services.s3.model.AmazonS3Exception: Access Denied という内容のエラーが発生して異常終了しました。

トラブルシュート方法

EMRのステップを参照してエラーメッセージを確認しました。

ステップの処理まで進むとEMRのコンソール画面から詳細なエラーメッセージを確認できるようになるので対処しやすいですね。

エラーの原因

S3の操作権限がなく、ステップ実行で利用するjarファイルを取得するときに権限エラーとなっていました。

S3の操作権限と、EMRクラスタ上で動作するSparkアプリケーションが必要とする権限を付与して再実行したところ、ステップが正常終了するようになりました。

まとめ

EMR管理ポリシーをv1からv2に更新する場合は以下の対応が必要です。

  • EMRクラスタ構築時のリクエスト内容を変更する
    • RunJobFlow リクエストの Tags{"Key": "for-use-with-amazon-emr-managed-policies", "Value": "true" } を設定する
  • IAMロールの権限設定を変更する
    • 各ロールにアタッチするポリシーをv1からv2に付け替える
    • EC2インスタンスプロファイルで利用するロールに、EMRクラスタ上で動作するアプリケーションが必要とする権限を追加する
  • EMR関連リソースの for-use-with-amazon-emr-managed-policies タグに true を設定する

おわりに

EMR管理ポリシーをv1からv2に移行する際に対応すべき内容と、実際のシステムで起こったエラーの内容について紹介しました。EMR管理ポリシーv2への移行を検討している方々のお役にたてると幸いです。

参考