皆様こんにちは、
NTTデータ先端技術の尾崎遼太郎と申します。
業務としては、主にクラウド上にビッグデータ分析基盤を作る案件に携わっており、
最近は、AWSマネージドサービス(SageMaker, Glue, QuickSight, Lambda)を使ったデータ分析環境を提供する業務をしていました。
今回は、昨年(2022年)末に開催されたAWSイベント「AWS Re:Invent 2022」で公開された新機能である、
「Amazon SageMaker Role Manager」を試してみましたので、ご紹介します。
新サービスを触るのはワクワクしますね。
それでは本編です。
SageMaker Role Managerの背景
機能の内容に入る前に、まずはこの機能が必要となる背景から考えていきましょう。(あくまでも尾崎個人の見解です。)
企業において機械学習PJを進める際に、セキュリティ・ガバナンスは非常に重要 です。
その中でも、データのセキュリティは特に重要となるポイントです。
機械学習のために扱うデータにはお客様の情報が含まれる場合も多いかと思います。
情報漏洩はあってはならないことで、そのためにはデータ・リソースに対する適切なアクセス制御が必要となります。
しかしながら、アクセス制御というのは非常に煩雑になることも多く、多くの企業で苦労がかかるポイントです。
特に、大企業においてはどうしてもPJに携わる人の数が多くなりがちで、各メンバーに適切な権限を付与することに手間がかかってしまいます。
実際に私も、大企業においてSageMaker向けの権限制御に関する業務に携わった経験がありますが、
必要以上に強い権限を付与すればセキュリティリスクとなってしまい、逆に弱すぎる権限の場合は操作でエラーが出るなど、運用には苦労した経験があります。
そういった課題の解消のために、SageMakerのロール管理を簡素化するサービスとして生まれたのがSageMaker Role Managerです。
機能の概要
SageMaker Role Managerは、簡単なGUIによってSageMaker用のIAMロールを作成することができる機能です。
AWS re:Invent2022において、「SageMaker向けガバナンスツール」が複数個発表されており、
こちらの機能はその中の一つとして発表されました。
本機能で作成されたIAMロールは、主にSageMaker Studioにおいて利用されることが想定されているようです。
また、ロールを作成する際に「ペルソナ」と呼ばれる標準セットのようなものが用意されており、
そちらをベースに用途に合わせてカスタマイズする使い方が可能になっています。
使ってみる
では、実際に使ってみましょう。
その前にまずは事前準備です。
1. 事前準備
機能を試す前に、機能を使う上で必要な事前準備をしていきます。
今回の機能と直接関係するものではありませんので、詳細な手順は割愛します。
※いずれの操作もアカウントの管理者権限で実行しています。
1-1. S3バケットの作成
SageMakerで利用するS3バケットを事前に作成しておく必要があります。
すでにS3バケットが存在する場合はそちらを使っても問題ありませんが、今回は作成することにします。
「test-bucket-<乱数>
」という名前のS3バケットを作成しました。
1-2. ECRリポジトリの作成
同じように、イメージをプルするためのリポジトリも事前に作成しておく必要があります。
こちらも、今回は新規で作成します。
「test-repo
」という名前のECRリポジトリを作成しました。
1-3. (任意)VPCの作成
VPCは作成しなくてもSageMaker Role Managerの機能を利用することはできますが、
「リソースの作成を特定のVPCに制限する」という機能があるようなので、今回はテスト用のVPCを作成しておきます。
以下のように、4つのサブネット(Public×2, Private×2)を持つVPCを作成しました。
- VPC:SageMaker-RoleManager-test-vpc
- Subnet:
- SageMaker-RoleManager-test-subnet-public1-ap-northeast-1a
- SageMaker-RoleManager-test-subnet-public2-ap-northeast-1c
- SageMaker-RoleManager-test-subnet-private1-ap-northeast-1a
- SageMaker-RoleManager-test-subnet-private2-ap-northeast-1c
また、PrivateSubnetにはそれぞれNAT Gatewayをつけました。
実際の環境ではプロキシなどを挟むことも多いかと思いますが、今回はシンプルな構成とするためにNAT直つなぎです。
1-4. SecurityGroupの作成
上記と同じように、「リソースの作成を特定のSGに制限する」という機能のテストのために、先ほど作ったVPC内にSecurityGroup(以下SGと呼称)を追加します。
以下のSGを作りました。
- SG:sagemaker-rolemanager-test-sg
※インバウンド・アウトバウンドルールはすべてのトラフィックを許可しています。
実際の環境では、適切なアクセス制御を設定することをお勧めします。
1.5 SageMakerドメインの作成
この辺りは自分もAWS側の設計思想を読み解けているのか自信がないですが、
SageMaker Role Managerで作成したロールが登場するのはあくまでもユーザープロファイルに対してになるようですので、
ドメイン自体は新機能は使わずに事前作成してしまおうと思います。
VPC・SGを設定すること以外は特にデフォルト設定で作成します。
デフォルトのロールについては、AmazonSageMakerFullAccessを付与したロールを利用しています。
また、NWについて今回は簡単のため、「パブリックインターネットのみ」を選択しています。
- ドメイン名:rolemanager-test-domain
- 認証:IAM
- デフォルトの実行ロール:新規作成(AmazonSageMakerFullAccess)
- スペースのデフォルトの実行ロール:新規作成(AmazonSageMakerFullAccess)
- VPC・Subnet・SG:先ほど作成したプライベートサブネットとSGを選択。「パブリックインターネットのみ」を選択。
- 暗号化キー:カスタム暗号化なし
- それ以外の項目:いずれもデフォルトのまま
こちらで、権限以外のSageMaker関連のインフラがあらかた完成したかなと思います。
ようやく準備が完了しましたので、実際にSageMaker Role Managerの機能を試していきましょう。
2. SageMaker Role Managerを使ってみる。
SageMaker Role Manager はIAMロールを作成する機能ですので、
この機能自体を利用する権限はそれなりに強い権限を持った担当者が実施することになるかなと思います。
(SageMaker環境自体の管理者の役割の方が作業することになるかなと思います。)
今回はアカウント管理者の権限でそのまま進めてしまいます。
ここでポイントになるのは、
- 事前に SageMakerのサービス側(例えば、ジョブやインスタンスなど)が引き受けるロール を作成し、
- その後、 利用者(SageMakerドメインにおけるプロファイル)が利用するロール を作成する
という順序で作業することです。
これはこの後の手順を見ていただいたほうがわかりやすいと思いますが、
利用者のロール権限に、「どのロールを渡せるか」という権限をつけるために、事前にロールが必要となります。
補足:公式ドキュメントの記載では「新しいサービスロールを作成することも可能」という風にも読み取れたのですが、
私が試した限りではロールが空の場合は作成できなかったので、事前作成は必要のようです。
2-1. SageMaker Role Managerの画面へのアクセス
SageMaker Role Managerは左メニューの「開始方法」というところからアクセスします。
右側に「SageMaker を初めて使用しますか?」という表示がある場合は、その下の「今すぐ始める」というところからもアクセスできそうです。
「開始方法」という画面の、「ロールを設定」という部分が今回追加されたRole Managerのことのようですね。
早速「ロールを作成」ボタンをクリックしてみます。
2-2. SageMakerのサービスが引き受けるロールを作成する
では、まずはSageMakerのサービス側(ジョブやインスタンス)が引き受けるロールを作成していきます。
2-2-1. ロール情報を入力
ここでロールを作成することができます。
-
ロール名のサフィックス
単にロール名ではなく「ロール名のサフィックス」というのが不思議ですが、頭に「SageMaker-」というプレフィックスが付与されるようですね。
今回は以下のサフィックスで作成します。
「TestRoleForSageMakerComputing
」 -
説明
説明が入れられるようですが、今回は空欄のままにしておきます。 -
ペルソナ
ここが本機能の重要なところです。
利用者に付与する権限を、以下のセットから選択します。2023/03時点では以下を選択できます。- カスタムロールの設定
- データサイエンティスト
- MLオペレーション
- SageMaker コンピューティングロール
カスタムロールを利用することで細かな設定もできそうですが、今回は作成済みのペルソナを使ってみましょう。
まずは「SageMaker コンピューティングロール」を選択します。 -
ネットワーク条件
オプションの項目ですが、今回は有効にしてみましょう。
「VPCサブネット」「セキュリティグループ」に、それぞれ先ほど作ったサブネット・SGを入れていきます。
サブネットとしては、プライベートサブネットの二つを指定します。
(雑談)現在のUIだとサブネット名が見れず、サブネットID・リージョン・CIDRしか見れないようですね。
今後改善されるかもしれませんが、今のところは別画面でサブネットIDを控えておく必要がありそうです。
- 暗号化の条件
暗号化に関するオプションも指定できそうですが、今回は特に指定しないままにしておきます。
すべてを入力したら次へ進みます。
2-2-2. 機械学習アクティビティを設定
実際に作成されるロールの設定画面のようです。
-
新しいロールを設定
新しく作成するロールへの権限を選択する部分です。
注意事項に以下の記載があります。Amazon SageMaker Role Manager では、ステップ 1 で選択したペルソナに基づいて選択した機械学習アクティビティが推奨されます。
機械学習アクティビティを削除または追加するには、以下のチェックボックスにチェックを入れてください。ということで、選んだペルソナに対すおすすめの権限が推奨される仕組みのようですね。
今回のケースだと、先ほど「SageMaker コンピューティングロール」のペルソナを選択したので、
推奨されたアクティビティのための権限(一番上の一つだけ)があらかじめ選択済みになっていました。 -
必要なAWSサービスへのアクセス
ここは選択したアクティビティによって違うようですね。
今回のアクティビティの場合は、「S3バケット」「ECRリポジトリ」の二つが必要になります。
それぞれ、事前準備で作成したものを設定します。
次へ進みましょう。
2-2-3. ポリシーとタグをさらに追加
-
このロールに IAM ポリシーをさらに追加
あとからポリシーを追加できるようですが、今回は特に追加せずに進みます。 -
タグ
タグの付与もスキップします。
この画面は特に指定せず、次へ進みます。
2-2-4. ロールを確認
確認画面です。
設定値を確認し、「送信」ボタンを押します。
すると、すぐに「ロールが正常に作成されました」という表示が出ました。
作成されたロールを確認します。
- ロール名:「SageMaker-TestRoleForSageMakerComputing」
- ポリシー:「SM_ComputeExecutionRole_VPC_1679206034750」
ということで、選択した設定値に基づいてポリシーが自動生成され、ロールが作られているようです。
2-3. 利用者向けのロールを作成する
SageMakerのサービスに付与するロールが完成したので、つづいて利用者向けのロールも作成しましょう。
先ほどと同様に、ペルソナだけを変えて作成します。
2-3-1. ロール情報を入力
ロール名のサフィックスを「TestRoleForDataScientist
」とし、
ペルソナを「データサイエンティスト」にする以外は先ほどと同じです。
2-3-2. 機械学習アクティビティを設定
今回はデータサイエンティストを選択したので、先ほどよりも多くのアクティビティが選択されています。
そのため、選択が必要なAWSリソースも変わっており、IAMロールおよびS3バケットのを選択する必要があります。
IAMロールは先ほど作った 「SageMaker-TestRoleForSageMakerComputing」
S3バケットは先ほど選択したのと同様に事前作成したバケットを選択します。
実際の運用においては、「MLジョブで利用するロール」と「モデル管理で必要なロール」では権限が異なる場合もありますので、
必要に応じてロールを分けるなどご検討ください。
今回は同じロールを設定しています。
選択して次へを押します。
2-3-3. ポリシーとタグをさらに追加
ここはそのままで次へ進みます。
2-3-4. ロールを確認
確認し、「送信」を押します。
こちらもすぐにロールが正常に作成されますので、確認しましょう。
- ロール名:「SageMaker-TestRoleForDataScientist」
- ポリシー:
- SageMakerS3BucketPolicyTemplate_1679208137687
- SM_CommonJobManagement_VPC_1679208137687
- SM_ExperimentsManagement_1679208137687
- SM_ExperimentsVisualization_1679208137687
- SM_ModelManagement_VPC_1679208137687
- SM_StudioAppPermissions_1679208137687
ポリシーが複数付与された、ロールが新規作成されているのが確認できますね。
3. 作成されたロールを使ってみる
では、RoleManagerを利用して新規作成したロールを、実際に使ってみましょう。
事前準備で作成したSageMakerドメインに対して、ユーザープロファイルを作成します。
3.1 プロファイルの作成
ユーザープロファイルを作成する際の実行ロールとして、
先ほど作成した「SageMaker-TestRoleForDataScientist
」を選択します。
他の設定は任意で設定してください。
3.2 SageMaker Studioへの接続
先ほど作成したユーザプロファイルでSageMaker Studioに接続します。
SageMaker Studioの画面はかっこいいですね。
3.3 機械学習のトレーニングジョブで挙動を確認する
では、先ほど作成したロールの挙動を確認してみましょう。
今回は、二種類のトレーニングジョブ作成用ノートブックファイルを用意して挙動の違いを確認します。
- ①ジョブ作成が失敗するパターン:
ノートブック内でSageMakerの機械学習トレーニングジョブを作成する際、VPCの設定を 行わないで ジョブを作成します。 - ②ジョブ作成が成功するパターン:
ノートブック内でSageMakerの機械学習トレーニングジョブを作成する際、VPCの設定を 行って ジョブを作成します。
補足:今回 SageMaker Role Managerを利用してロールを作成する際、VPCの設定を強制するオプションを有効化しているため、
VPCやSGなどのNW設定をしない場合はジョブ作成に失敗し、設定すれば成功することが期待されます。
①VPC設定を行わないジョブ作成処理
以下の設定で学習ジョブを作成します。
- ジョブが利用するS3バケット:先ほど事前準備で作成したS3バケット
- ジョブが利用するIAMロール:先ほどSageMaker Role Managerで作成したSageMakerComputing用ロール
- ジョブのサブネット・SG:指定しない (コメントアウトしてある箇所です。)
※ジョブの重要な設定項目だけ抜粋したものが以下です。
bucket_name = 'test-bucket-j9a4dug6'
role = 'arn:aws:iam::353645643161:role/service-role/SageMaker-TestRoleForSageMakerComputing'
xgb = sagemaker.estimator.Estimator(
xgboost_container
, role
, instance_count=1
, instance_type='ml.m4.xlarge'
, output_path='s3://{}/{}/output'.format(bucket_name, prefix)
, sagemaker_session=sess
#, subnets=[
# 'subnet-09aa82239a7ff433c'
# , 'subnet-0406d0af4ef85e719'
#]
#, security_group_ids=[
# 'sg-0fd75ec9f56e544bd'
#]
)
すると、以下のようなエラーメッセージが出ました。
ClientError: An error occurred (AccessDeniedException) when calling the CreateTrainingJob operation: User: arn:aws:sts::353645643161:assumed-role/SageMaker-TestRoleForDataScientist/SageMaker is not authorized to perform: sagemaker:CreateTrainingJob on resource: arn:aws:sagemaker:ap-northeast-1:353645643161:training-job/xgboost-2023-03-28-20-27-52-674 because no identity-based policy allows the sagemaker:CreateTrainingJob action
必要なNW設定をしていない場合にジョブ作成が失敗するのは期待していた通りの挙動 といえます。
続いて、NW設定をした場合を見てましょう。
②VPC設定を行ったジョブ作成処理
以下の設定で学習ジョブを作成します。
- ジョブが利用するS3バケット:先ほど事前準備で作成したS3バケット
- ジョブが利用するIAMロール:先ほどSageMaker Role Managerで作成したSageMakerComputing用ロール
- ジョブのサブネット・SG: 今回作成し、SageMaker Role Managerでも指定したSubnet・SGを指定する
※ジョブの重要な設定項目だけ抜粋したものが以下です。
bucket_name = 'test-bucket-j9a4dug6'
role = 'arn:aws:iam::353645643161:role/service-role/SageMaker-TestRoleForSageMakerComputing'
xgb = sagemaker.estimator.Estimator(
xgboost_container
, role
, instance_count=1
, instance_type='ml.m4.xlarge'
, output_path='s3://{}/{}/output'.format(bucket_name, prefix)
, sagemaker_session=sess
, subnets=[
'subnet-09aa82239a7ff433c'
, 'subnet-0406d0af4ef85e719'
]
, security_group_ids=[
'sg-0fd75ec9f56e544bd'
]
)
こちらを実行すると、今度はエラーなく成功する……と思ったのですが、
以下のようなエラーメッセージが出ました。
ClientError: An error occurred (AccessDeniedException) when calling the DescribeLogStreams operation: User: arn:aws:sts::353645643161:assumed-role/SageMaker-TestRoleForDataScientist/SageMaker is not authorized to perform: logs:DescribeLogStreams on resource: arn:aws:logs:ap-northeast-1:353645643161:log-group:/aws/sagemaker/TrainingJobs:log-stream: because no identity-based policy allows the logs:DescribeLogStreams action
エラーではありますが、先ほどとはエラーの内容が変わっており、CloudWatch Logs関連の権限不足のエラーのようです。
SageMakerコンソールに戻り、トレーニングジョブのページを見てみましょう。
すると、ステータスがCompletedになっていることが確認できました。
そのため、一応こちらのジョブは作成に成功しているようです。
このことから、
「 ジョブ自体の作成には成功したが、ログ/メトリクス関連で情報取得の権限が不足しており状況確認の処理がエラーになっている 」
という状況と推測しています。
なので、今回試したかった「SageMaker Role Managerで作成したロールでNW関連の制御ができているか」は確認できていそうですね。
記事が長くなってきてしまったので、今回の作業はいったんこの辺りでストップさせていただき、
ログ関連の権限不足エラーは今回の機能とは直接関係ない部分であるため、これ以上の深堀調査は割愛させていただこうと思います🙇
SageMaker Role Managerを使ってみた感想
こちらは私の意見ですが、今回SageMaker Role Managerを触ってみて、以下のように感じました。
😀良かった点
- GUIで簡単にIAMロール・ポリシーが作成できること。
- ペルソナが初めから用意されていることで、標準的な権限を簡単に作成できること。
🤔今後に期待したい点
- 現状はIAMロールの新規作成しかできなそうで、作成したIAMロールの管理はできなそうであること。
※例えば、一度作ったロールの権限を追加するなどは、IAM側の画面から作業が必要なようです。 - 私の環境では、作成したロールでも権限不足エラー(CloudWatch Logs関連の権限不足)が発生したこと。
※あくまでも権限付与をアシストするものであり、「これを使えば権限エラーがなくなる」というわけではないと認識すべきと思います。 - 依存リソースの事前作成などが必要であること。
※仕様上仕方のないことですが、依存リソースの事前作成が必要な点は利用タイミングの制約にもなりそうです。
全体的には、新しいサービスということでまだまだ粗削りな印象を受けましたが、
「SageMaker利用時の権限管理の煩雑さを解消したい」という課題感自体は非常に共感できるものですので、
今後に期待したいサービスであると感じています!
おわりに
今回は、AWS SageMakerの新サービスである SageMaker Role Manager を触ってみました。
実運用に組み込むには用途が限られそうなものの、今後の機能拡充に非常に期待が持てるサービスという印象を受けました。
自分としても注目したいサービスの一つですので、またアップデートがあればぜひ触ってみたいと思いました。
データ分析用のツールを導入するうえで、セキュリティ・ガバナンスの観点は非常に重要ですが難しいポイントですので、
AWS側でどんどん機能をアップデートして、そういった課題が改善されていくのは大変ありがたいと感じています。
それでは、今回は以上にしたいと思います。
お読みいただきありがとうございました。
皆様もよきAWSライフをお過ごしください。
参考文献
補足
SageMaker Studioで動かした機械学習のコードです。
以下のチュートリアルを参考に、環境向けに書き換えを行っています。
# import libraries
import boto3, re, sys, math, json, os, sagemaker, urllib.request
from sagemaker import get_execution_role
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from IPython.display import Image
from IPython.display import display
from time import gmtime, strftime
from sagemaker.predictor import csv_serializer
# Define IAM role
#role = get_execution_role()
role = 'arn:aws:iam::353645643161:role/service-role/SageMaker-TestRoleForSageMakerComputing'
prefix = 'sagemaker/DEMO-xgboost-dm'
my_region = boto3.session.Session().region_name # set the region of the instance
# this line automatically looks for the XGBoost image URI and builds an XGBoost container.
xgboost_container = sagemaker.image_uris.retrieve("xgboost", my_region, "latest")
print("Success - the MySageMakerInstance is in the " + my_region + " region. You will use the " + xgboost_container + " container for your SageMaker endpoint.")
bucket_name = 'test-bucket-j9a4dug6' # <--- CHANGE THIS VARIABLE TO A UNIQUE NAME FOR YOUR BUCKET
s3 = boto3.resource('s3')
#try:
# if my_region == 'us-east-1':
# s3.create_bucket(Bucket=bucket_name)
# else:
# s3.create_bucket(Bucket=bucket_name, CreateBucketConfiguration={ 'LocationConstraint': my_region })
# print('S3 bucket created successfully')
#except Exception as e:
# print('S3 error: ',e)
try:
urllib.request.urlretrieve ("https://d1.awsstatic.com/tmt/build-train-deploy-machine-learning-model-sagemaker/bank_clean.27f01fbbdf43271788427f3682996ae29ceca05d.csv", "bank_clean.csv")
print('Success: downloaded bank_clean.csv.')
except Exception as e:
print('Data load error: ',e)
try:
model_data = pd.read_csv('./bank_clean.csv',index_col=0)
print('Success: Data loaded into dataframe.')
except Exception as e:
print('Data load error: ',e)
train_data, test_data = np.split(model_data.sample(frac=1, random_state=1729), [int(0.7 * len(model_data))])
print(train_data.shape, test_data.shape)
pd.concat([train_data['y_yes'], train_data.drop(['y_no', 'y_yes'], axis=1)], axis=1).to_csv('train.csv', index=False, header=False)
boto3.Session().resource('s3').Bucket(bucket_name).Object(os.path.join(prefix, 'train/train.csv')).upload_file('train.csv')
s3_input_train = sagemaker.inputs.TrainingInput(s3_data='s3://{}/{}/train'.format(bucket_name, prefix), content_type='csv')
sess = sagemaker.Session()
xgb = sagemaker.estimator.Estimator(
xgboost_container
, role
, instance_count=1
, instance_type='ml.m4.xlarge'
, output_path='s3://{}/{}/output'.format(bucket_name, prefix)
, sagemaker_session=sess
, subnets=[
'subnet-09aa82239a7ff433c'
, 'subnet-0406d0af4ef85e719'
]
, security_group_ids=[
'sg-0fd75ec9f56e544bd'
]
)
xgb.set_hyperparameters(
max_depth=5,
eta=0.2,
gamma=4,
min_child_weight=6,
subsample=0.8,
silent=0,
objective='binary:logistic',
num_round=100
)
xgb.fit({'train': s3_input_train})
なお、本記事のための環境はAWSアカウントごと新規でSandbox環境を作成しているため、
検証完了後にアカウントごとリソースをすべて削除しております。
(AWSアカウントの発行はAWS Organizationsを利用して簡単に行えるのが便利ですね!)
本記事にはアカウントIDやリソースID等の情報が含まれていますが、いずれも削除済みですのでご安心ください。
以上、お読みいただきありがとうございました。