SageMakerとMLflowの連携

# はじめに

こちらは、 [Managing your machine learning lifecycle with MLflow and Amazon SageMaker](https://aws.amazon.com/blogs/machine-learning/managing-your-machine-learning-lifecycle-with-mlflow-and-amazon-sagemaker/)を参考にして実際に作成したものです。

**ただし、このブログの紹介で作成しているのは、MLflowをECS上にDeployし、S3とRDSをそれぞれArtifact store、backendストアにするところまでなので、 SageMakerもまとめて作りたい場合は[こちら](https://qiita.com/nakamasato/items/feb91c806225df98180a)を!**

MLflow初であれば→[MLflow 基礎](https://qiita.com/nakamasato/items/6337e7f543535ecb9062)


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/7059/b5ca4a16-e066-f18f-8dc8-84a453433410.png)

# 準備

1. AWSアカウント → まだ無い場合は[Sign Up](https://portal.aws.amazon.com/billing/signup#/start)
1. `aws-cdk`を[インストール＆設定](https://docs.aws.amazon.com/cdk/latest/guide/getting_started.html#getting_started_install)
    1. 詳細は[こちら](https://qiita.com/nakamasato/items/178984a622809261df20)を参照

1. [Docker](https://www.docker.com/)
1. https://github.com/aws-samples/amazon-sagemaker-mlflow-fargate をClone

# 1. MLflowをFarget上にCloudFormationStackを用いてDeploy

1. 上記のレポCloneしたディレクトリへ移動

    ```
    cd amazon-sagemaker-mlflow-fargate
    ```

1. 必要なものをインストール

    ```
    python3 -m venv .venv
    source .venv/bin/activate
    pip3 install -r requirements.txt
    ```
    
1. デプロイ (25分くらいかかる)

    AWSの特定のprofileを使用している場合は、 `--profile <profile名>`をつける

    ```
    cdk deploy --parameters ProjectName=mlflow --require-approval never
    ```

    <details><summary>結果詳細</summary><div>

    ```
    cdk deploy --parameters ProjectName=mlflow --require-approval never --profile naka-personal
    ...

    ✅  DeploymentStack

    Outputs:
    DeploymentStack.LoadBalancerDNS = Deplo-MLFLO-xxx-xxxx.elb.ap-northeast-1.amazonaws.com
    DeploymentStack.MLFLOWLoadBalancerDNSAEFB7E43 = Deplo-MLFLO-xxxx-xxxxx.elb.ap-northeast-1.amazonaws.com

    Stack ARN:
    arn:aws:cloudformation:ap-northeast-1:xxxxx:stack/DeploymentStack/798f4a90-313e-11ec-a179-0aa3345c497f
    ```

    </div></details>

    <details><summary>Docker起動していないとエラーになる</summary><div>

    Dockerを起動していないと以下のようなエラーになるので注意

    ```
    cdk deploy --parameters ProjectName=mlflow --require-approval never --profile naka-personal
    [Warning at /DeploymentStack/MLflow/Container/AssetImage] DockerImageAsset.repositoryName is deprecated. Override "core.Stack.addDockerImageAsset" to control asset locations
    DeploymentStack: deploying...
    [0%] start: Publishing 8f0fed36a7179b1d96d969db07932d3497d1d1a297b54c7b1eb5dd77dc952f06:current
    Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?
    [100%] fail: docker build --tag cdkasset-8f0fed36a7179b1d96d969db07932d3497d1d1a297b54c7b1eb5dd77dc952f06 . exited with error code 1: Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?

     ❌  DeploymentStack failed: Error: Failed to publish one or more assets. See the error messages above for more information.
        at Object.publishAssets (/usr/local/lib/node_modules/aws-cdk/lib/util/asset-publishing.ts:25:11)
        at Object.deployStack (/usr/local/lib/node_modules/aws-cdk/lib/api/deploy-stack.ts:252:3)
        at CdkToolkit.deploy (/usr/local/lib/node_modules/aws-cdk/lib/cdk-toolkit.ts:189:24)
        at initCommandLine (/usr/local/lib/node_modules/aws-cdk/bin/cdk.ts:225:9)
    Failed to publish one or more assets. See the error messages above for more information.
    ```

    </div></details>


    このコマンドでデプロイされたもの ([app.py](https://github.com/aws-samples/amazon-sagemaker-mlflow-fargate/blob/main/app.py)にかかれている) (CloudFormation Stack `DeploymentStack` でも詳細確認可):
    - IAM ROLE
        - `DeploymentStack-MLflowExecutionRoleXXXXXXXXXXX`
    - SECRET
        - `dbPassword`がSecretManagersに作成される
    - VPC
        - Vpc: `DeploymentStack/VPC`: [10.0.0.0/24](https://github.com/aws-samples/amazon-sagemaker-mlflow-fargate/blob/bd561f02607ea3df8495f01ab87991601feaf923/app.py#L58) <- このCidrがすでに使われている場合はエラるかも
        - Subnets:
            - `DeploymentStack/VPC/PublicSubnet1`
            - `DeploymentStack/VPC/PrivateSubnet1`
            - `DeploymentStack/VPC/DBSubnet2`
            - `DeploymentStack/VPC/PrivateSubnet2`
            - `DeploymentStack/VPC/PublicSubnet2`
            - `DeploymentStack/VPC/DBSubnet1`
        - Others: RouteTable, InterneteGateway, ElasticIP
    - S3 BUCKET
        - `mlflow-artifacts-<account id>`
    - DATABASE
        - 名前: ランダム文字列, size: `db.t2.small`, Engine: `MySQL Community`
    - FARGATE SERVICE
        - ECS cluster using Fargate: `mlflow` 
            - Service: `mlflow`
            - ECR: `<account id>.dkr.ecr.ap-northeast-1.amazonaws.com/aws-cdk/assets`



1. MLflow UIの確認

アウトプットの`DeploymentStack.LoadBalancerDNS`に書いてあるリンクを開く。

※ただし、LBがPublicで、MLflowはuser access controlの機能を提供してないので、実際に使う場合には、PrivateLinkなどを使ってPrivateにする必要がある

![スクリーンショット 2021-10-20 10.30.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/7059/aec2d883-055a-7262-f5f8-fc74188c9076.png)


# 2. SageMakerからの連携

ブログ内ではSageMakerの作成部分は書かれていないため省略… (予想外。) 　[最後に](#最後に)に比較を書いたので、SageMakerも含めて作成したい場合は、そちらも参考に。

SageMakerの中でのプロジェクト管理を[MLflowのRemoteURI](https://mlflow.org/docs/latest/quickstart.html#launch-a-tracking-server-on-a-remote-machine)を用いて行えるようになる

```python
import mlflow
mlflow.set_tracking_uri('<YOUR LOAD BALANCER URI>')
```

# 3. Farget上に作成したMLｆlowの削除 (20分ほどかかる)

作成したものの削除

```
cdk destroy --parameters ProjectName=mlflow --require-approval never --profile naka-personal
Are you sure you want to delete: DeploymentStack (y/n)? y
DeploymentStack: destroying...

...

 ✅  DeploymentStack: destroyed
```

# 比較 & まとめ

関連したCDKがいくつかあり試したので、一応所感を書いておく。

- [aws-mlflow-sagemaker-cdk](https://github.com/aws-samples/aws-mlflow-sagemaker-cdk): 
    - 2021-10-14 に作られた最新のもので、SageMakerとMLflowをまとめて構築できる最強のパック。
    - TypescriptっぽいのでPythonに慣れてる人にとってはちょっとマイナス。
    - MLｆlowのEndpointがinternalロードバランサーで作成されるので、デフォルトではMLflow UIへのアクセス方法がない‥ → [Client VPNを使って試した記事はこちら]()
- [amazon-sagemaker-mlflow-fargate](https://github.com/aws-samples/amazon-sagemaker-mlflow-fargate): 
    - こちらは今回紹介したもの
    - コードはPython
    - MLflowのEndpointがInternet facingとなるので、セキュリティ上そのままは使えない
    - 名前からはSageMakerとMLflow両方デプロイするように見えて実は、MLflowをFargate上にデプロイしているだけなので、SageMakerは別途自分で作成する必要がある
- [amazon-sagemaker-cdk-examples](https://github.com/aws-samples/amazon-sagemaker-cdk-examples):
    - SageMakerのCDKサンプルが沢山入っているもの
    - MLflowは関係ない
    - 一番使いたかったのは、 [notebook-teams](https://github.com/aws-samples/amazon-sagemaker-cdk-examples/tree/master/notebook-teams)だが、こちらはVPCやSubnetまで作成するので、今回紹介した MLflowをFargate上に構築するのとあまり相性が良くない。別々でVPCが作成されたあとのPrivateLinkなどの設定を別途作成する必要がある。→ それなら一番上の[aws-mlflow-sagemaker-cdk](https://github.com/aws-samples/aws-mlflow-sagemaker-cdk)が一番楽そう。

これらは、どれもVPCの構築からしてくれるので、全く何もないところにPOCで構築して試すにはもってこいである。ただし、既存のVPCの上に構築したい場合には、他のものを探したり自分で書き直す必要がありそう。

# Reference
- [aws-samples/aws-mlflow-sagemaker-cdk](https://github.com/aws-samples/aws-mlflow-sagemaker-cdk)
- [aws-samples/amazon-sagemaker-mlflow-fargate](https://github.com/aws-samples/amazon-sagemaker-mlflow-fargate)
- [aws-samples/amazon-sagemaker-cdk-examples](https://github.com/aws-samples/amazon-sagemaker-cdk-examples)
- [Managing your machine learning lifecycle with MLflow and Amazon SageMaker](https://aws.amazon.com/blogs/machine-learning/managing-your-machine-learning-lifecycle-with-mlflow-and-amazon-sagemaker/)
- [MLflow](https://mlflow.org/docs/latest/quickstart.html)
- [cdk コマンドの機能を 実際に叩いて理解する 【 AWS CDK Command Line Interface 】](https://dev.classmethod.jp/articles/aws-cdk-command-line-interface/)
- [AWS Cloud Development Kit(CDK)(Python)を使って「VPC+Sagemaker+Lambda」環境構築してみた(Sagemaker編)](https://dev.classmethod.jp/articles/aws-cdk-sage-nw2/)