Xでポストされていたこちらを紹介します。
素敵です。
GitHubはこちらです。
特徴
デフォルトVPCを使用してSageMaker StudioとCode Editorを構築するCloudFormationテンプレートが提供されています。
未使用時に自動で停止するスクリプトが組み込まれていますので、Cloud9のような使い勝手で利用が可能です。
早速やってみた。
バージニア北部リージョンで試しました。
-
マネジメントコンソールにログインします
-
別タブを開き、GitHubのリポジトリ( https://github.com/aws-samples/sagemaker-studio-code-editor-template )にアクセスします
-
「Deployment (1-click)」のセクションを表示します
使用するAWSリージョンの横の「Launch Stack」ボタンをクリックします -
CloudFormationのスタック作成画面が開きます
「次へ」をクリックします -
スタックの詳細を指定します
指定できるパラメーターは以下のとおりですパラメーター名 内容 AutoStopIdleTimeInMinutes Code Editorの自動停止までのアイドル時間。0の場合は無効になります (これは、ターミナルのアクティビティではなく、ファイルの変更に基づきます。このパラメーターは作成後に更新できません。) EbsSizeInGb Code EditorのEBSボリュームサイズ (このパラメーターは作成後に減らすことはできません。) InstanceType Code Editorのインスタンスタイプ (高速起動は、ml.t3.medium、ml.t3.large、ml.m5.large、ml.m5.2xlarge、ml.c5.large でサポートされています。) パラメーターを指定した後、「次へ」をクリックします
-
スタックオプションの設定画面では設定の変更はしないので、画面下部の「次へ」をクリックします
-
確認して作成画面です
最下部にある「AWS CloudFormation によって IAM リソースがカスタム名で作成される場合があることを承認します。」にチェックをいれ、「送信」ボタンをクリックします
-
CloudFormationスタックの作成が始まります
-
10分ほど待つと、スタックの作成が完了します
(StackSet-AWS-QuickSetupで始まるスタックが2つ増えていますが、これは気にしないでください) -
「出力」タブに表示されているURLをクリックします
-
SageMaker Studioが表示されます
Code Editorにアクセスする
-
「Skip Tour for now」をクリックし、モーダルを閉じます
左に並んだアイコンの「Code Editor」をクリックします -
「default」をクリックします
-
「Open Code Editor」をクリックします
Cloud9との違い
-
自動起動はない
自動停止はありますが、自動起動はありません。SageMaker Studioの画面にて起動する必要があります
SageMaker Studioの画面へは、以下のいずれかの方法でアクセスします -
OSの種類
Cloud9はAmazon Linux 2、Amazon Linux 2023、Ubuntu 22.04ですが、SageMaker Studio Code EditorはUbuntu 22.04です。
おまけ:自動停止はどういう仕組でできているの?
CloudFormationスタックを作成した際に、SageMaker Studioのライフサイクル設定が作成されます。
ライフサイクル設定では、PHPやJava、Dockerなどインストールが行われます。
他に、Cronもインストールされ、2分ごとにPythonスクリプトが実行されるように設定されます。
*/2 * * * * /bin/bash -ic '$CONDA_HOME/python $PYTHON_SCRIPT_PATH --time 600 --region $AWS_DEFAULT_REGION >> $LOG_FILE'
PythonスクリプトはこちらのGitHubリポジトリで公開されている「auto_stop_idle.py」です。
「auto_stop_idle.py」では、ディレクトリの最終更新日をチェックし、利用中かどうかを判定する「check_user_activity」関数が用意されています。
def check_user_activity(workspace_dir, idle_threshold):
# Get the timestamp of the most recently modified file or folder
recent_item = max(
(os.path.join(root, file) for root, _, files in os.walk(workspace_dir) for file in files),
key=lambda x: os.lstat(x).st_mtime,
default=None
)
# Get the current time
current_time = time.time()
# Calculate the time difference
time_diff = current_time - os.stat(recent_item).st_mtime if recent_item else float('inf')
log_message(f"[auto-stop-idle] - Logging time difference between current time and time files were last changed {time_diff}.")
# Check if the user is idle based on the idle time threshold
if time_diff > idle_threshold:
return "idle"
else:
return "active"
Cronで2分ごとに以下の処理が呼び出され、監視対象ディレクトリ配下のすべてのディレクトリの利用を監視し、すべてのディレクトリがidleと判定された場合に、Code Editorを停止させています。(Code Editor自身がCode Editorを終了させています)
# Monitor workspace_dirs for changes to implement auto-shutdown, as these paths track updates to both unsaved and saved editor content, covering all user activity scenarios.
workspace_dirs = ["/opt/amazon/sagemaker/sagemaker-code-editor-server-data/data/User/History", "/opt/amazon/sagemaker/sagemaker-code-editor-server-data/data/User/Backups/empty-window/untitled"]
idle_threshold = args.time # this is in seconds. for ex: 1800 seconds for 30 minutes
aws_region = args.region # get the region.
# Track the activity status for each directory
activity_status = [check_user_activity(directory, idle_threshold) for directory in workspace_dirs]
# Terminate the SageMaker Studio app if all directories are idle and no activity is observed.
if all(status == "idle" for status in activity_status):
# Load the resource metadata from the file
with open('/opt/ml/metadata/resource-metadata.json') as f:
resource_metadata = json.load(f)
# Extract the required details for deleting the app
domain_id = resource_metadata['DomainId']
space_name = resource_metadata['SpaceName']
app_name = resource_metadata['ResourceName']
app_type = resource_metadata['AppType']
resource_arn = resource_metadata["ResourceArn"]
# Use boto3 api call to delete the app.
sm_client = boto3.client('sagemaker',region_name=aws_region)
response = sm_client.delete_app(
DomainId=domain_id,
AppType=app_type,
AppName=app_name,
SpaceName=space_name
)
log_message(f"[auto-stop-idle] - Deleting app {app_type}-{app_name}. Domain ID: {domain_id}. Space name: {space_name}. Resource ARN: {resource_arn}.")
log_message("[auto-stop-idle] - SageMaker Code Editor app terminated due to being idle for given duration.")
else:
log_message("[auto-stop-idle] - SageMaker Code Editor app is not idle. Passing check.")