はじめに
re:Invent 2019の直前にAmazon SageMaker Operators for Kubernetesというものがひっそりと(?)リリースされています。
https://aws.amazon.com/jp/blogs/news/introducing-amazon-sagemaker-operators-for-kubernetes/
KubernetesからSageMakerをコントロールできるよーっていうものみたいです。
https://sagemaker.readthedocs.io/en/stable/amazon_sagemaker_operators_for_kubernetes.html
おっ!と思ったけど誰も試してないっぽいので誰にもささらなかったんでしょうか?
Sagemakerあんまり分かってないですが、ちょっと試しにやってみたところ、ブログに書いてあるとおりではなかなかうまくいかなかったので、手順まとめときます。
EKSセットアップ
EKSクラスタの作成
EKSクラスタを作ります。
apiVersion: eksctl.io/v1alpha5
kind: ClusterConfig
metadata:
name: sagemaker-cluster
region: ap-northeast-1
iam:
withOIDC: true
serviceAccounts:
- metadata:
name: sagemaker-k8s-operator-default
namespace: sagemaker-k8s-operator-system
attachPolicyARNs:
- "arn:aws:iam::aws:policy/AmazonSageMakerFullAccess"
nodeGroups:
- name: "ng-1"
desiredCapacity: 1
$ eksctl create cluster -f cluster.yaml
インスタンスはなんでもいいです。
MLで使うインスタンスはクラスタのWorkerNodeではなく、SageMakerで作成されるので、EKSで考慮する必要はないです。
SageMaker Operatorsのインストール
$ curl -O https://raw.githubusercontent.com/aws/amazon-sagemaker-operator-for-k8s/master/release/rolebased/installer.yaml
eks.amazonaws.com/role-arn
を作成したものに変えます。
$ eksctl get iamserviceaccount --cluster sagemaker-cluster
NAMESPACE NAME ROLE ARN
sagemaker-k8s-operator-system sagemaker-k8s-operator-default arn:aws:iam::123456789012:role/eksctl-sagemaker-cluster-addon-iamserviceacc-Role1-NH9RC551YX3B
apiVersion: v1
kind: ServiceAccount
metadata:
annotations:
eks.amazonaws.com/role-arn: arn:aws:iam::123456789012:role/eksctl-sagemaker-cluster-addon-iamserviceacc-Role1-NH9RC551YX3B
$ kubectl apply -f installer.yaml
SageMaker関連のCRDが作成されます。
$ kubectl get crd | grep sagemaker
batchtransformjobs.sagemaker.aws.amazon.com 2019-12-18T07:23:42Z
endpointconfigs.sagemaker.aws.amazon.com 2019-12-18T07:23:42Z
hostingdeployments.sagemaker.aws.amazon.com 2019-12-18T07:23:42Z
hyperparametertuningjobs.sagemaker.aws.amazon.com 2019-12-18T07:23:42Z
models.sagemaker.aws.amazon.com 2019-12-18T07:23:42Z
trainingjobs.sagemaker.aws.amazon.com 2019-12-18T07:23:42Z
EKS側の準備はここまでです。
TrainingJobを動かす
AWSブログ に書いているサンプルは説明もあんまりないし、ちょっとよくわからなかったので、こちらのドキュメントのTrainingJobを動かしてみます。
https://sagemaker.readthedocs.io/en/stable/amazon_sagemaker_operators_for_kubernetes_jobs.html#trainingjob-operator
https://github.com/aws/amazon-sagemaker-operator-for-k8s/blob/master/samples/xgboost-mnist-trainingjob.yaml
その前にデータの準備します。
このへん全然書いてないんですよね・・・
S3バケットの作成
データソースの保存と作成したモデルのアップロード用にS3バケットを作成します。
$ aws s3api create-bucket --bucket $BUCKET_NAME --create-bucket-configuration LocationConstraint=ap-northeast-1
データはこちらのMNISTのショートバージョンを使わせてもらいました。
https://github.com/ozt-ca/tjo.hatenablog.samples/tree/master/r_samples/public_lib/jp/mnist_reproduced
(他も試したんですけど、なかなかうまくいかず・・・)
$ curl -O https://raw.githubusercontent.com/ozt-ca/tjo.hatenablog.samples/master/r_samples/public_lib/jp/mnist_reproduced/short_prac_train.csv
$ curl -O https://raw.githubusercontent.com/ozt-ca/tjo.hatenablog.samples/master/r_samples/public_lib/jp/mnist_reproduced/short_prac_test.csv
そのまま使うと、こんなエラーが出て失敗します。
ClientError: Non-numeric value 'l' found in the header line 'label,pixel0,pixel1,pixel2,pixel3,pixel4,pixel5,pi...' of file 'short_prac_train.csv'. CSV format require no header line in it. If header line is already removed, XGBoost does not accept non-numeric value in the data.
ヘッダ行がいらないってことみたいなので、1行目は削除します。
で、S3にアップロードします。
$ aws s3 cp short_prac_train.csv s3://${BUCKET_NAME}/train/
$ aws s3 cp short_prac_test.csv s3://${BUCKET_NAME}/validation/
SageMaker用IAMRoleを作成
SageMakerで使用するIAMRoleを作成します。
S3からデータソースを持ってくるのと、作成したモデルをS3上にアップロードするので、S3のパーミッションをつけときます。
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "",
"Effect": "Allow",
"Principal": {
"Service": "sagemaker.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
$ aws iam create-role --role-name eks-sagemaker-role --assume-role-policy-document file://policy.json
$ aws iam attach-role-policy --role-name eks-sagemaker-role --policy-arn arn:aws:iam::aws:policy/AmazonS3FullAccess
$ aws iam attach-role-policy --role-name eks-sagemaker-role --policy-arn arn:aws:iam::aws:policy/AmazonSageMakerFullAccess
TrainingJobを作成
サンプルをダウンロードします。
curl -O https://raw.githubusercontent.com/aws/amazon-sagemaker-operator-for-k8s/m
aster/samples/xgboost-mnist-trainingjob.yaml
ダウンロードしたファイルを下記のように修正します。
apiVersion: sagemaker.aws.amazon.com/v1
kind: TrainingJob
metadata:
name: xgboost-mnist
spec:
hyperParameters:
- name: max_depth
value: "5"
- name: eta
value: "0.2"
- name: gamma
value: "4"
- name: min_child_weight
value: "6"
- name: silent
value: "0"
- name: objective
value: multi:softmax
- name: num_class
value: "10"
- name: num_round
value: "10"
algorithmSpecification:
trainingImage: 501404015308.dkr.ecr.ap-northeast-1.amazonaws.com/xgboost:1 # Regionに合わせて変更 アカウントIDはhttps://docs.aws.amazon.com/ja_jp/sagemaker/latest/dg/sagemaker-algo-docker-registry-paths.html を参照
trainingInputMode: File
roleArn: arn:aws:iam::123456789012:role/eks-sagemaker-role # 作成したSageMaker用Roleを指定
region: ap-northeast-1 # Region変更
outputDataConfig:
s3OutputPath: s3://<<Bucket Name>>/output/ # 作成したS3バケット、パスを指定
resourceConfig:
instanceCount: 1
instanceType: ml.m4.xlarge
volumeSizeInGB: 5
stoppingCondition:
maxRuntimeInSeconds: 86400
inputDataConfig:
- channelName: train
dataSource:
s3DataSource:
s3DataType: S3Prefix
s3Uri: s3://<<Bucket Name>>/xgboost/train/ # 作成したS3バケット、パスを指定
s3DataDistributionType: FullyReplicated
contentType: text/csv
compressionType: None
- channelName: validation
dataSource:
s3DataSource:
s3DataType: S3Prefix
s3Uri: s3://<<Bucket Name>>/xgboost/validation/ # 作成したS3バケット、パスを指定
s3DataDistributionType: FullyReplicated
contentType: text/csv
compressionType: None
tags:
- key: tagKey
value: tagValue
実行!
$ kubectl apply -f xgboost-mnist-trainingjob.yaml
始まりました。
$ kubectl describe trainingjob
Name: xgboost-mnist
Namespace: default
(略)
Sage Maker Training Job Name: xgboost-mnist-a850b392217011ea86c606020759f870
Secondary Status: Starting
Training Job Status: InProgress
Events: <none>
終わり!
$ kubectl describe trainingjob
Name: xgboost-mnist
Namespace: default
(略)
Sage Maker Training Job Name: xgboost-mnist-a850b392217011ea86c606020759f870
Secondary Status: Completed
Training Job Status: Completed
Events: <none>
モデルもできてました。
まとめ
MLで使うインスタンスはSageMaker側で管理になるので、EKSクラスタでは考慮しなくていいっていうのはなかなかいいんじゃないかなーと。
これスポット使えるのかな?
にしてもこのYAML書けるようになるまでは覚えること多すぎて先が遠いなーっていう印象です。