諸事情ありDockerとAWS SageMakerを利用したMKOpsを構築しようとして、MLFlowやらDVCやらをあれこれ(他にも色々)追加しようとして、訳が分からなくなったので一旦シンプルにした際の備忘録。
多分もっと良い方法は色々あります。
(Qiitaの記事書いてみようと唐突に思ったため)
基本的にはローカルのコンテナでは特徴量の探索やモデルの開発、少量のデータでの学習を行い、SageMakerで本格学習及びエンドポイントへのデプロイになります。
できるだけシンプルと言いつつコストの暴発が怖いため、予算ガードレール(AWS Budgets + 自動停止 Lambda)も最初から入れてコスト事故を防ぎたいな、といった感じです。
一旦自分で試行錯誤しながら色々やってるのでミスがあったらご指摘いただければと思います
qiita初投稿なので、不具合あったらすいません
TL;DR(最短手順)
- インフラを作成(S3, SageMaker ロール, Budgets, 自動停止 Lambda)
cd infra
cp terraform.tfvars.example terraform.tfvars
# 必要箇所(aws_profile, s3_bucket_name, budget_alert_emails など)を編集
terraform init
terraform apply -var="aws_profile=xxxx"
- データを S3 にアップロード
aws s3 cp ./app/data/processed/processed_data.csv s3://<YOUR_BUCKET>/data/train/ --profile xxxx
- Docker 開発コンテナで学習を実行(SageMaker)
docker-compose up -d
docker-compose exec jupyter-lab bash
export AWS_PROFILE=xxxx
export AWS_REGION=ap-northeast-1
cd /app/app/src
python deploy_example.py
- 学習完了確認
aws sagemaker list-training-jobs --profile xxxx
aws sagemaker describe-training-job --training-job-name <JOB_NAME> --profile xxxx
リポジトリ構成(抜粋)
.
├─ app/
│ └─ src/
│ ├─ train.py # SageMaker 学習スクリプト
│ ├─ inference.py # SageMaker 推論スクリプト
│ ├─ sagemaker_config.py # SageMaker 設定/デプロイ管理
│ └─ deploy_example.py # 学習・デプロイ実行例
└─ infra/
├─ main.tf # Provider / Data sources / Budgets / Lambda
├─ iam.tf # SageMaker 実行ロール、Lambda ロール
├─ s3.tf # データ保存用 S3 バケット
├─ variables.tf # 変数定義
├─ outputs.tf # 出力
├─ lambda/sagemaker_autostop.py # アイドル自動削除 Lambda
└─ terraform.tfvars.example # 変数の例
インフラの用意(今回はTerraformで)
シンプルにするため以下の想定で作成:
- S3 バケット(バージョニング/暗号化/ライフサイクル/公開ブロック)
- SageMaker 実行ロール(S3/Logs/ECR/SageMaker 権限)
- 予算ガードレール(AWS Budgets + SNS メール通知)
- アイドル自動停止(SageMaker エンドポイントを定期チェックして削除する Lambda)
変数例(infra/terraform.tfvars.example
)
aws_region = "ap-northeast-1"
aws_profile = "xxxx"
project_name = "zzzzzz"
environment = "dev"
s3_bucket_name = "your-unique-bucket-name"
# 予算ガードレール
enable_budgets = true
monthly_budget_limit = 20
budget_alert_emails = ["your-email@example.com"]
# 自動停止(任意)
enable_sagemaker_autostop = true
sagemaker_autostop_idle_hours = 1
実行:
cd infra
terraform init
terraform plan -var="aws_profile=xxxx"
terraform apply -var="aws_profile=xxxx"
完了後、Terraform の出力から以下を:取得
- S3 バケット名(例:
ml-base-sample-v1
) - SageMaker 実行ロール ARN
- 次のステップ案内(環境変数など)
Docker 開発コンテナでの実行
ローカル環境を汚さないため、Docker の開発コンテナから実行。AWS 認証情報はホストの ~/.aws
を読み取り専用でマウントし、コンテナ内で AWS_PROFILE
を指定します。
まだ学習段階なのでこんな感じですが、最終的にはIAM Role for Tasks やOIDC を使用想定
docker-compose.yml
(抜粋)
services:
jupyter-lab:
build:
context: .
dockerfile: Dockerfile
volumes:
- .:/app
- ~/.aws:/root/.aws:ro
ports:
- "8888:8888"
command: jupyter lab --ip=0.0.0.0 --allow-root --no-browser --NotebookApp.token=''
起動と実行(今回はdev containerを利用していますがコマンドも念の為):
docker-compose up -d
docker-compose exec jupyter-lab bash
export AWS_PROFILE=xxxx
export AWS_REGION=ap-northeast-1
cd /app/app/src
python deploy_example.py
データアップロードと学習開始
- 学習データをS3 へ
aws s3 cp ./app/data/processed/processed_data.csv s3://<YOUR_BUCKET>/data/train/ --profile xxxx
- 学習を実行(ここもgithub actionとかでどうにかする...予定)
# コンテナ内
cd /app/app/src
python deploy_example.py
- 学習の完了確認
aws sagemaker list-training-jobs --profile xxxx
aws sagemaker describe-training-job --training-job-name <JOB_NAME> --profile xxxx
# モデルアーティファクト例:
s3://sagemaker-<region>-<account>/.../output/model.tar.gz
コストガードレール(最初から入れる)
- 予算監視(AWS Budgets + SNS メール)
- 80% 予測/100% 実績でメール通知
-
budget_alert_emails
に通知先を設定(初回は SNS の Subscribe 確認が必要)
- 自動停止 Lambda(任意)
- 毎時実行でエンドポイントの CloudWatch
Invocations
を見て、指定時間アイドルなら削除 - 誤起動/止め忘れの長期コストを予防
- 毎時実行でエンドポイントの CloudWatch
片付け(コスト最小化)
- エンドポイントを作った場合:不要になれば削除(自動停止 Lambda も保険)
- 全リソース削除:
cd infra
terraform destroy -var="aws_profile=xxxx"
きっとそのうちまた書きます
参考(一応)
- SageMaker Developer Guide: https://docs.aws.amazon.com/sagemaker/
- SageMaker Python SDK: https://sagemaker.readthedocs.io/
- Terraform AWS Provider: https://registry.terraform.io/providers/hashicorp/aws/latest/docs
- AWS IAM Best Practices: https://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html