ライセンス持込みコンテナ
モデル・デプロイメントの作成時に、カスタム・コンテナ(Bring Your Own ContainerまたはBYOC)を実行時の依存性として構築および使用します。
カスタム・コンテナを使用すると、システムと言語の依存関係をパッケージ化し、推論サーバーをインストールおよび構成し、異なる言語ランタイムを設定できます。コンテナを実行するためのモデル・デプロイメント・リソースがあるインタフェースの定義済境界内。
BYOCを使用すると、異なる環境間でのコンテナの転送が可能になるため、アプリケーションをOCIクラウドに移行およびデプロイできます。
ジョブを実行するには、Dockerfile
を作成してからイメージを構築する必要があります。Pythonイメージを使用するDockerfile
から開始します。Dockerfile
は、ローカルおよびリモートのビルドを作成できるように設計されています。コードに対してローカルでテストする場合は、ローカル・ビルドを使用します。ローカル開発中、コードの変更ごとに新しいイメージを作成する必要はありません。
BYOC必須インタフェース
モデル・デプロイメントを使用するには、これらの必須インタフェースを作成または指定します。
モデル・アーティファクト
インタフェース | 説明 |
---|---|
データ・サイエンス・モデル・カタログにモデル・アーティファクトをアップロードします。 | モデル・デプロイメント・リソースで使用する前に、スコアリング・ロジック、MLモデル、依存ファイルなどのモデル・アーティファクトをデータ・サイエンス・モデル・カタログにアップロードする必要があります。 |
必須ファイルなし |
BYOCモデル・デプロイメントの作成に必須のファイルはありません。 ノート:モデル・デプロイメントにBYOCが使用されていない場合、 |
マウントされたモデル・アーティファクトの場所。 |
ブートストラップ・モデルのデプロイメント中に、モデル・アーティファクトを解凍し、実行中のコンテナ内の 一連のファイル(MLモデルおよびスコアリング・ロジックを含む)または一連のファイルを含むフォルダを圧縮すると、コンテナ内のMLモデルへの場所パスが異なります。スコアリング・ロジックでモデルをロードするときに正しいパスが使用されていることを確認します。 |
コンテナ・イメージ
インタフェース | 説明 |
---|---|
パッケージ実行時の依存関係。 | MLモデル・バイナリをロードおよび実行するために必要なランタイム依存関係を使用してコンテナ・イメージをパッケージ化します。 |
Webサーバーをパッケージ化してエンドポイントを公開します。 |
HTTPベースのステートレスWebサーバー(FastAPI、Flask、Triton、TensorFlowサービス、PyTorchサービスなど)を使用してコンテナ・イメージをパッケージ化します。
ノート: 推論サーバーのエンドポイントをデータ・サイエンス・エンドポイント・インタフェースを満たすようにカスタマイズできない場合は、プロキシ(NGINXなど)を使用して、サービス指定エンドポイントをフレームワークによって提供されるエンドポイントにマップします。 |
公開されたポート。 |
ポートは1024から65535までに制限されています。ポート24224、8446、および8447は除外されます。提供されているポートはサービスによってコンテナで公開されるため、Dockerファイルに再度公開する必要はありません。 |
イメージのサイズ。 | コンテナ・イメージのサイズは、非圧縮形式では16 GBに制限されています。 |
イメージにアクセスします。 | モデル・デプロイメントを作成するオペレータは、使用するコンテナ・イメージにアクセスできる必要があります。 |
Curlパッケージ。 | Docker HEALTHCHECK ポリシーが成功するには、curlパッケージがコンテナ・イメージにインストールされている必要があります。脆弱性がない最新の安定 curlコマンドをインストールします。 |
CMD , Entrypoint |
docker CMD またはEntrypoint は、WebサーバーをブートストラップするAPIまたはDockerファイルを介して提供する必要があります。 |
CMD 、Entrypoint サイズ。 |
CMD とEntrypoint の結合サイズは、2048バイトを超えることはできません。サイズが2048バイトを超える場合は、モデル・アーティファクトを使用してアプリケーション引数を指定するか、オブジェクト・ストレージを使用してデータを取得します。 |
一般的な推奨事項
推奨 | 説明 |
---|---|
モデル・アーティファクトでMLモデルをパッケージ化します。 |
MLモデルをアーティファクトとしてパッケージ化し、データ・サイエンス・モデル・カタログにアップロードして、コンテナ・イメージにMLモデルをパッケージ化するオプションがありますが、モデル・ガバナンスおよびモデル・バージョニング機能を使用します。モデル・カタログにモデルを保存します。 モデルがモデル・カタログにアップロードされ、モデル・デプロイメントの作成時に参照されると、データ・サイエンスはアーティファクトのコピーをダウンロードし、使用するスコアリング・ロジックのために |
すべての操作のイメージおよびイメージ・ダイジェストを指定します | イメージの使用の一貫性を維持するために、イメージおよびイメージ・ダイジェストを指定して、モデル・デプロイメント操作を作成、更新およびアクティブ化することをお薦めします。別のイメージへの更新操作中に、予想されるイメージに更新するには、イメージ・ダイジェストとイメージ・ダイジェストの両方が不可欠です。 |
脆弱性スキャン | OCI脆弱性スキャン・サービスを使用して、イメージ内の脆弱性をスキャンすることをお薦めします。 |
APIフィールドがnullです | APIフィールドが空の場合、空の文字列、空のオブジェクトまたは空のリストを渡さないでください。空のオブジェクトとして明示的に渡さないかぎり、フィールドをnullとして渡すか、まったく渡さないでください。 |
BYOCベスト・プラクティス
- モデル・デプロイメントでは、OCIレジストリに存在するコンテナ・イメージのみがサポートされます。
- モデル・デプロイメントのライフサイクル全体を通して、コンテナ・イメージがOCIレジストリに存在することを確認します。インスタンスが自動的に再起動した場合、またはサービス・チームがパッチ適用を実行した場合の可用性を確保するには、イメージが存在する必要があります。
- BYOCではdockerコンテナのみがサポートされています。
- データ・サイエンスは、圧縮されたモデル・アーティファクトを使用してMLモデルのスコアリング・ロジックを持ち、データ・サイエンス・モデル・カタログで使用可能であると想定します。
- コンテナ・イメージのサイズは、非圧縮形式では16 GBに制限されています。
- データ・サイエンスは、コンテナを開始する前に
HEALTHCHECK
タスクを追加するため、HEALTHCHECK
ポリシーはオーバーライドされるため、Dockerファイルに明示的に追加する必要はありません。ヘルス・チェックは、コンテナの起動後10分後に実行が開始され、30秒ごとに/health
がチェックされます。タイムアウトは3秒で、チェックごとに3回再試行されます。 - Docker
HEALTHCHECK
ポリシーが成功するには、curlパッケージがコンテナ・イメージにインストールされている必要があります。 - モデル・デプロイメント・リソースを作成するユーザーは、それを使用するには、OCIレジストリのコンテナ・イメージにアクセスできる必要があります。そうでない場合は、モデル・デプロイメントを作成する前にユーザー・アクセスのIAMポリシーを作成します。
- docker
CMD
またはEntrypoint
は、WebサーバーをブートストラップするAPIまたはDockerfileを介して提供する必要があります。 - 実行するコンテナに対して定義されたサービス・タイムアウトは10分であるため、この時間枠内で推測サービス・コンテナが開始される(正常である)ことを確認してください。
- モデル・デプロイメントを使用してクラウドにデプロイする前に、常にコンテナをローカルでテストしてください。
Dockerイメージ・ダイジェスト
Dockerレジストリ内のイメージは、リポジトリ、名前およびタグによって識別されます。さらに、Dockerでは、イメージの各バージョンに一意の英数字のダイジェストが付与されます。更新されたDockerイメージをプッシュする場合は、既存のタグを再利用するのではなく、更新されたイメージに識別するための新しいタグを指定することをお薦めします。ただし、更新されたイメージをプッシュし、それに以前のバージョンと同じ名前とタグを指定した場合でも、新しくプッシュされたバージョンは以前のバージョンとは異なるダイジェストを持ちます。
モデル・デプロイメント・リソースを作成する場合は、モデル・デプロイメントのベースとなるイメージの特定のバージョンの名前とタグを指定します。不整合を回避するために、モデル・デプロイメントでは、そのバージョンのイメージの一意のダイジェストが記録されます。モデル・デプロイメントの作成時にイメージのダイジェストを指定することもできます。
デフォルトでは、モデル・デプロイメントの基になるイメージの元のバージョンと同じ名前およびタグで、更新されたバージョンのイメージをDockerレジストリにプッシュすると、元のダイジェストを使用してイメージの元のバージョンを引き続き取得します。モデル・デプロイメントでイメージの新しいバージョンをプルする場合は、モデル・デプロイメントがプルするイメージのバージョンを識別するために使用するタグおよびダイジェストを使用してイメージ名を明示的に変更できます。
モデル・アーティファクトの準備
アーティファクトzipファイルを作成し、モデルとともにモデル・カタログに保存します。アーティファクトには、コンテナを操作して推論リクエストを実行するコードが含まれます。
コンテナは、推論サーバーのヘルスを返すために/health
エンドポイントを公開し、推論のために/predict
エンドポイントを公開する必要があります。
モデル・アーティファクトの次のPythonファイルは、ポート5000のFlaskサーバーを使用してこれらのエンドポイントを定義します:
# We now need the json library so we can load and export json data
import json
import os
import numpy as np
from sklearn.discriminant_analysis import LinearDiscriminantAnalysis
from sklearn.neural_network import MLPClassifier
import pandas as pd
from joblib import load
from sklearn import preprocessing
import logging
from flask import Flask, request
# Set environnment variables
WORK_DIRECTORY = os.environ["WORK_DIRECTORY"]
TEST_DATA = os.path.join(WORK_DIRECTORY, "test.json")
MODEL_DIR = os.environ["MODEL_DIR"]
MODEL_FILE_LDA = os.environ["MODEL_FILE_LDA"]
MODEL_PATH_LDA = os.path.join(MODEL_DIR, MODEL_FILE_LDA)
# Loading LDA model
print("Loading model from: {}".format(MODEL_PATH_LDA))
inference_lda = load(MODEL_PATH_LDA)
# Creation of the Flask app
app = Flask(__name__)
# API 1
# Flask route so that we can serve HTTP traffic on that route
@app.route('/health')
# Get data from json and return the requested row defined by the variable Line
def health():
# We can then find the data for the requested row and send it back as json
return {"status": "success"}
# API 2
# Flask route so that we can serve HTTP traffic on that route
@app.route('/predict',methods=['POST'])
# Return prediction for both Neural Network and LDA inference model with the requested row as input
def prediction():
data = pd.read_json(TEST_DATA)
request_data = request.get_data()
print(request_data)
print(type(request_data))
if isinstance(request_data, bytes):
print("Data is of type bytes")
request_data = request_data.decode("utf-8")
print(request_data)
line = json.loads(request_data)['line']
data_test = data.transpose()
X = data_test.drop(data_test.loc[:, 'Line':'# Letter'].columns, axis = 1)
X_test = X.iloc[int(line),:].values.reshape(1, -1)
clf_lda = load(MODEL_PATH_LDA)
prediction_lda = clf_lda.predict(X_test)
return {'prediction LDA': int(prediction_lda)}
if __name__ == "__main__":
app.run(debug=True, host='0.0.0.0', port = 5000)
コンテナの構築
OCIコンテナ・レジストリの任意のイメージを使用できます。次に、Flaskサーバーを使用するサンプルのDockerfileを示します。
FROM jupyter/scipy-notebook
USER root
RUN \
apt-get update && \
apt-get -y install curl
ENV WORK_DIRECTORY=/opt/ds/model/deployed_model
ENV MODEL_DIR=$WORK_DIRECTORY/models
RUN mkdir -p $MODEL_DIR
ENV MODEL_FILE_LDA=clf_lda.joblib
COPY requirements.txt /opt/requirements.txt
RUN pip install -r /opt/requirements.txt
docker HEALTHCHECK
ポリシーが機能するには、Curlパッケージをコンテナ・イメージにインストールする必要があります。
Dockerfileと同じディレクトリに、次のパッケージを含むrequirements.txt
ファイルを作成します。
flask
flask-restful
joblib
docker build
コマンドを実行します:
docker build -t ml_flask_app_demo:1.0.0 -f Dockerfile .
モデル・デプロイメントで使用できる圧縮解除されたコンテナ・イメージの最大サイズは、16 GBです。コンテナ・イメージのサイズはコンテナ・レジストリから取得されるため、モデル・デプロイメントのプロビジョニング時間が遅くなることに注意してください。可能なかぎり小さいコンテナ・イメージを使用することをお薦めします。
コンテナのテスト
モデル・アーティファクトおよび推論コードがDockerfileと同じディレクトリにあることを確認してください。ローカル・マシンでコンテナを実行します。ローカル・モデル・ディレクトリを/opt/ds/model/deployed_model
にマウントして、ローカル・マシンに格納されているファイルを参照する必要があります。
docker run -p 5000:5000 \
--health-cmd='curl -f http://localhost:5000/health || exit 1' \
--health-interval=30s \
--health-retries=3 \
--health-timeout=3s \
--health-start-period=1m \
--mount type=bind,src=$(pwd),dst=/opt/ds/model/deployed_model \
ml_flask_app_demo:1.0.0 python /opt/ds/model/deployed_model/api.py
10分で定義されたサービス内でコンテナが実行されていることを確認するヘルス・リクエストを送信します:
curl -vf http://localhost:5000/health
予測リクエストを送信してテストします:
curl -H "Content-type: application/json" -X POST http://localhost:5000/predict --data '{"line" : "12"}'
コンテナのOCIコンテナ・レジストリへのプッシュ
Oracle Cloud Infrastructure Registry (コンテナ・レジストリとも呼ばれる)との間でイメージをプッシュおよびプルする前に、Oracle Cloud Infrastructure認可トークンが必要です。認証トークン文字列は作成時にのみ表示されるため、認証トークンをただちに安全な場所にコピーするようにしてください。
- コンソールの右上隅で「プロファイル」メニューを開き、「ユーザー設定」をクリックして詳細を表示します。
- 「認証トークン」ページで、「トークンの生成」をクリックします。
- 認証トークンのわかりやすい説明を入力します。機密情報を入力しないでください。
- 「トークンの生成」をクリックします。新しい認証トークンが表示されます。
- 認証トークンをすぐに安全な場所にコピーし、後で取り出せるようにします。認証トークンはコンソールに再度表示されません。
- 「トークンの生成」ダイアログを閉じます。
- ローカル・マシンでターミナル・ウィンドウを開きます。
- コンテナ・イメージを構築、実行、テスト、タグ付けおよびプッシュできるように、コンテナ・レジストリにサインインします。
docker login -u '<tenant-namespace>/<username>' <region>.ocir.io
- ローカル・コンテナ・イメージをタグ付けします:
docker tag <local_image_name>:<local_version> <region>.ocir.io/<tenancy_ocir_namespace>/<repository>:<version>
- コンテナ・イメージをプッシュします:
docker push <region>.ocir.io/<tenancy>/byoc:1.0
ノート
イメージを格納したコンパートメントからOCIレジストリからイメージを読み取ることができるように、モデル・デプロイメント・リソースにリソース・プリンシパルのポリシーがあることを確認します。リソース・プリンシパルを使用したカスタム・コンテナへのモデル・デプロイメント・アクセスの付与
モデル・デプロイメントの作成時に、このコンテナ・イメージをBYOCオプションとともに使用する準備ができました。
BYOCモデルのデプロイメントでは、リージョン間コンテナ・イメージのプルはサポートされていません。たとえば、IAD (アッシュバーン)リージョンでBYOCモデル・デプロイメントを実行する場合、PHX (フェニックス)リージョンのOCIR (Oracle Cloud Container Registry)からコンテナ・イメージをプルすることはできません。
BYOC更新操作の動作
BYOC更新操作は、禁止マージ・タイプの部分更新です。
書込み可能な最上位レベル・フィールドは、リクエスト・コンテンツに定義されている場合には完全に置換する必要があり、それ以外の場合は変更されません。たとえば、次のようなリソースの場合:
{
"environmentConfigurationDetails": {
"environmentConfigurationType": "OCIR_CONTAINER",
"serverPort": 5454,
"image": "iad.ocir.io/testtenancy/md_byoc_ref_iris_data:1.0.1",
"imageDigest": "sha256:a9c8468cb671929aec7ad947b9dccd6fe8e6d77f7bcecfe2e10e1c935a88c2a5",
"environmentVariables": {
"a": "b",
"c": "d",
"e": "f"
},
"entrypoint": [ "python", "-m", "uvicorn", "a/model/server:app", "--port", "5000","--host","0.0.0.0"]
"cmd": ["param1"]
}
次のような更新に成功しました。
{
"environmentConfigurationDetails": {
"serverPort": 2000,
"environmentVariables": {"x":"y"},
"entrypoint": []
}
}
serverPort
およびenvironmentVariables
が更新コンテンツによって上書きされる状態になります(更新コンテンツにないディープ・フィールドの以前に存在したデータの破棄を含む)。image
は更新コンテンツに表示されず、明示的な空のリストによってentrypoint
がクリアされるため、変更されません:
{
"environmentConfigurationDetails": {
"environmentConfigurationType": "OCIR_CONTAINER",
"serverPort": 2000,
"image": "iad.ocir.io/testtenancy/md_byoc_ref_iris_data:1.0.1",
"imageDigest": "sha256:a9c8468cb671929aec7ad947b9dccd6fe8e6d77f7bcecfe2e10e1c935a88c2a5",
"environmentVariables": {"x": "y"},
"entrypoint": []
"cmd": ["param1"]
}
{ "environmentConfigurationDetails": null or {} }
を使用した更新が成功すると、何も上書きされません。最上位レベルの完全な置換では、リクエスト・コンテンツに存在しないすべての値が消去されるため、これを回避します。更新オブジェクトのすべてのフィールドはオプションであるため、イメージを指定しない場合は、デプロイメントでイメージを設定解除しないでください。データ・サイエンスは、nullでない場合にのみ、第2レベルのフィールドで置換を実行します。
リクエスト・オブジェクトにフィールドを設定しない(nullを渡す)場合、データ・サイエンスでは、差異の検索および既存のフィールド値への置換のためにそのフィールドは考慮されません。
フィールドの値をリセットするには、空のオブジェクトを渡します。リストおよびマップ・タイプのフィールドの場合、データ・サイエンスでは、値を消去するインジケータとして空のリスト([])またはマップ({})を受け入れることができます。いずれの場合も、nullは値を消去することを意味しません。ただし、値はいつでも別の値に変更できます。デフォルトポートを使用し、そのフィールド値を設定解除するには、デフォルトポートを明示的に設定します。
リストおよびマップ・フィールドへの更新は完全な置換です。データ・サイエンスは、個々の値のオブジェクト内では見えません。
イメージおよびダイジェストの場合、データ・サイエンスでは値を消去できません。
トリトン推論サーバー・コンテナを使用したデプロイ
NVIDIAのTriton Inference Serverは、チームがGPUまたはCPUベースのインフラストラクチャ上の任意のフレームワークからトレーニング済AIモデルをデプロイ、実行およびスケーリングできるようにすることで、AI推論を合理化および標準化します。
Tritonの主な機能は次のとおりです。
- コンカレント・モデル実行:複数のMLモデルを同時に処理する機能。この機能は、単一のシステムで一緒にデプロイおよび管理する必要がある複数のモデルで役立ちます。
- 動的バッチ処理:サーバーがワークロードに基づいて動的にリクエストをバッチ処理できるようにして、パフォーマンスを向上させます。
モデル・デプロイメントには、NVIDIATriton Inference Serverに対する特別なサポートがあります。NVIDIAのコンテナ・カタログから既存のTritonイメージをデプロイすると、モデル・デプロイメントの作成時に次の環境変数を使用して、コンテナ内の何も変更せずにTritonインタフェースが一致することがモデル・デプロイメントで保証されます:
CONTAINER_TYPE = TRITON
ONNXモデルのTritonへのデプロイ方法に関する完全な文書化されたサンプルは、データ・サイエンス・モデルのデプロイメントGitHubリポジトリにあります。