Azure Machine Learning でオンラインエンドポイントの Mirror Traffic 機能を使ってみる

# はじめに
Azure Machine Learning のマネージドオンラインエンドポイントには、メインのデプロイに流れるライブトラフィックの一部を別のデプロイにコピー (ミラーリング)する機能があります。ただあまり情報がなかったため一通り試した流れをご紹介します。

:::note
マネージドオンラインエンドポイントはオンライン (リアルタイム推論)に使用されるエンドポイントです。一つのエンドポイントに複数のデプロイを構成でき、それぞれのモデル・デプロイに流れるトラフィックを一定比率で分割したり、また今回ご紹介するようにトラフィックをミラーリングして別のデプロイに受け渡したりすることが可能です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/57724/bc6ca82d-7c46-be0e-8dc6-dca22b556c1a.png)
[オンライン エンドポイントとは - Azure Machine Learning | Microsoft Docs](https://docs.microsoft.com/ja-jp/azure/machine-learning/concept-endpoints#what-are-online-endpoints)
:::

# 前提条件
- Azure のアカウントがあり、Azure ML ワークスペースが作成済みなこと
- Azure ML CLI v2 がインストール済みなこと ([CLI (v2) のインストールと設定](https://docs.microsoft.com/ja-jp/azure/machine-learning/how-to-configure-cli?tabs=public))

# 手順
## 準備

※もし、Azure CLIのデフォルトサブスクリプション、MLワークスペース・リソースグループが設定されていない場合は、下記コマンドをベースに実行しておきます。値はご自身の環境に合わせて修正をお願いします。
```sh
az account set --subscription <subscription id>
az configure --defaults workspace=<azureml workspace name> group=<resource group>
```

Azure ML のサンプルリポジトリをクローンします。
```sh
git clone https://github.com/Azure/azureml-examples
cd azureml-examples/cli
```

ここのリポジトリにAzure MLの使い方に関して幅広いコンテンツが用意されています。
今回はCLI v2ベースで進めていくため、`cli`ディレクトリを主に使っていきます。

エンドポイント名は何度も使っていくため、環境変数に入れておきます。
```sh
export ENDPOINT_NAME="<YOUR_ENDPOINT_NAME>"
```
※値に迷ったら、適当に
```sh
export ENDPOINT_NAME=endpt-sr-`echo $RANDOM`
```
として乱数を末尾に入れておきます。

## エンドポイントの作成
マネージドオンラインエンドポイントを作成していきます。構成ファイルはYAML形式で記述されています。
```yaml:azureml-examples/cli/endpoints/online/managed/sample/endpoint.yml
$schema: https://azuremlschemas.azureedge.net/latest/managedOnlineEndpoint.schema.json
name: my-endpoint
auth_mode: key
```
エンドポイントは推論結果をクライアントが呼び出すために使用するHTTPSエンドポイントであり、記載内容は名前と認証方法のみとシンプルです。

名前 (`name`)はAzureリージョンで一意である必要があります。今回はオンラインエンドポイント作成時に上記で作成した環境変数 `$ENDPOINT_NAME`)の値を使用するため、このYAMLに記載した`name`は使いません。

認証方法 (`auth_mode`)はキー認証か、Azure MLトークン認証 (Azure AD トークンではありません)を指定できます。キーに期限切れはありませんが、トークンは期限切れになります。
[オンライン エンドポイントで認証を行う - Azure Machine Learning | Microsoft Docs](https://docs.microsoft.com/ja-jp/azure/machine-learning/how-to-authenticate-online-endpoint)

エンドポイントを作成します。
```sh
az ml online-endpoint create --name $ENDPOINT_NAME -f endpoints/online/managed/sample/endpoint.yml
```
私の環境では40秒過ぎと、一分以内に作成が完了しました。

## デプロイの作成
作成したエンドポイントに対して、学習済みモデルを指定してデプロイを作成します。
今回は`blue`と`green`の２つのデプロイを作成し、`blue`デプロイへ流れるトラフィックの一部を`green`デプロイにミラーリングしていきます。

### ① `blue`デプロイの作成
まず一つ目のデプロイ (`blue`)を作成していきます。
デプロイの構成ファイルです。モデルのパス、推論スクリプトのパス、推論環境のcondaファイルとDockerイメージ、VMインスタンスのスペック・台数が指定されています。
```yaml:azureml-examples/cli/endpoints/online/managed/sample/blue-deployment.yml
$schema: https://azuremlschemas.azureedge.net/latest/managedOnlineDeployment.schema.json
name: blue
endpoint_name: my-endpoint
model:
  path: ../../model-1/model/
code_configuration:
  code: ../../model-1/onlinescoring/
  scoring_script: score.py
environment: 
  conda_file: ../../model-1/environment/conda.yml
  image: mcr.microsoft.com/azureml/openmpi3.1.2-ubuntu18.04:20210727.v1
instance_type: Standard_DS2_v2
instance_count: 1
```
なお、こちらの`endpoint_name`も今回は作成コマンド実行時に環境変数側のエンドポイント名を使う形になります。

モデルはscikit-learnを使って学習された回帰モデルになっていて、推論スクリプトは下記形になっています。
```python:azureml-examples/cli/endpoints/online/model-1/onlinescoring/score.py
import os
import logging
import json
import numpy
import joblib


def init():
    """
    This function is called when the container is initialized/started, typically after create/update of the deployment.
    You can write the logic here to perform init operations like caching the model in memory
    """
    global model
    # AZUREML_MODEL_DIR is an environment variable created during deployment.
    # It is the path to the model folder (./azureml-models/$MODEL_NAME/$VERSION)
    # Please provide your model's folder name if there is one
    model_path = os.path.join(
        os.getenv("AZUREML_MODEL_DIR"), "model/sklearn_regression_model.pkl"
    )
    # deserialize the model file back into a sklearn model
    model = joblib.load(model_path)
    logging.info("Init complete")


def run(raw_data):
    """
    This function is called for every invocation of the endpoint to perform the actual scoring/prediction.
    In the example we extract the data from the json input and call the scikit-learn model's predict()
    method and return the result back
    """
    logging.info("model 1: request received")
    data = json.loads(raw_data)["data"]
    data = numpy.array(data)
    result = model.predict(data)
    logging.info("Request processed")
    return result.tolist()
```
`init()`内でモデルを読み込み、`run()`で入力されたデータに対して推論を行う構成になっています。

`blue`デプロイを作成します。
```sh
az ml online-deployment create --name blue --endpoint $ENDPOINT_NAME -f endpoints/online/managed/sample/blue-deployment.yml --all-traffic
```
私の環境だと6分程度で作成されました。  

::: note 
`--all-traffic` フラグを付けることで、新しく作成されたデプロイにエンドポイントに対するトラフィックの100%を割り当てる形になります。付けない場合は割り当て0%で作成されます。
:::

サンプルデータを投げて推論を行ってみます。
```sh
az ml online-endpoint invoke --name $ENDPOINT_NAME --request-file endpoints/online/model-1/sample-request.json
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/57724/75144419-10ca-3bcc-658b-c221f86e8722.png)
無事に推論結果が返ってきました。

### ② `green`デプロイの作成
同様にして、`green`デプロイを作成します。
なお、モデル、推論スクリプトは`blue`デプロイの際と若干違った形になっており、デバッグ用に推論スクリプトはハードコーディングされた結果 (`result = [0.5, 0.5]`)を返すようになっています。
```yaml:azureml-examples/cli/endpoints/online/managed/sample/blue-deployment.yml
$schema: https://azuremlschemas.azureedge.net/latest/managedOnlineDeployment.schema.json
name: green
endpoint_name: my-endpoint
model:
  path: ../../model-2/model/
code_configuration:
  code: ../../model-2/onlinescoring/
  scoring_script: score.py
environment:
  conda_file: ../../model-2/environment/conda.yml
  image: mcr.microsoft.com/azureml/openmpi3.1.2-ubuntu18.04:20210727.v1
instance_type: Standard_DS2_v2
instance_count: 1
```

```sh
az ml online-deployment create --name green --endpoint $ENDPOINT_NAME -f endpoints/online/managed/sample/green-deployment.yml
```


トラフィックの状況を確認します。
```sh
az ml online-endpoint show -n $ENDPOINT_NAME --query traffic
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/57724/0bd4d626-c9eb-70f7-66d4-64e5f1951646.png)



こちらもサンプルデータでの推論を実行します。
```sh
az ml online-endpoint invoke --name $ENDPOINT_NAME --deployment green --request-file endpoints/online/model-2/sample-request.json
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/57724/51ed0079-0f95-e1b8-3696-25bdc9596087.png)
無事に結果が返ってきました。`green`にデプロイした方は結果が`[0.5, 0.5]`がハードコーディングされた形になっているので、正しく返ってきていることが確認できます。


## ミラーリング設定
エンドポイントに流れるトラフィックの10%を`green`デプロイにミラーリングします。設定の最大値は50%のようです。
```sh
az ml online-endpoint update --name $ENDPOINT_NAME --mirror-traffic "green=10"
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/57724/9bda8c13-64d8-9d06-db9e-aa8f38778c9a.png)


## メトリックの確認
何回か推論を実施し、それぞれのデプロイのメトリックを確認してみます。
```sh
az ml online-endpoint invoke --name $ENDPOINT_NAME --request-file endpoints/online/model-1/sample-request.json
```

Azure ML Studio上から簡単にデプロイログを確認できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/57724/89f09517-f5f2-2b18-6cd9-e2c3aa2ecfca.png)

エンドポイントの画面から「デプロイログ」画面へ行きます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/57724/109bdf13-cffc-c7dc-c7f3-2e816a416cad.png)

エンドポイントに投げた推論トラフィックの一部が、`blue`だけではなく`green`デプロイにも流れていることが確認できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/57724/18037f7a-0f0a-be7c-ca7d-e4df73018c10.png)

# おわりに
いかがでしたでしょうか？マネージドオンラインエンドポイントのMirror Traffic機能を使うことで、待機時間が許容範囲か、エラーが発生していないか等、メインとなるデプロイに影響を与えずに新しいデプロイを検証できます。

# 参考
[オンライン エンドポイントを使って ML モデルをデプロイする - Azure Machine Learning | Microsoft Docs](https://docs.microsoft.com/ja-jp/azure/machine-learning/how-to-deploy-managed-online-endpoints)
[オンライン エンドポイントの安全なロールアウト - Azure Machine Learning | Microsoft Docs](https://docs.microsoft.com/ja-jp/azure/machine-learning/how-to-safely-rollout-managed-endpoints#test-the-deployment-with-mirrored-traffic-preview)
[オンライン エンドポイント YAML リファレンス - Azure Machine Learning | Microsoft Docs](https://docs.microsoft.com/ja-jp/azure/machine-learning/reference-yaml-endpoint-online)