Kubernetes ワークロード
Kubernetes のワークロードがライセンスのシートを待つようにするには、アノテーションを付けた Pod を LicOps のアドミッション Webhook に処理させるか、ジョブ自身からアドミッション API を呼び出します。どちらの方法でも、アプリケーションのイメージを変更する必要はありません。2 つの方法を次の表で比較します。
| 項目 | アドミッション Webhook | ジョブが API を呼び出す |
|---|---|---|
| マニフェストに追加するもの | 4 つのアノテーション | init コンテナーと解放の処理 |
| クラスターの前提条件 | Webhook がインストールされ、Namespace にラベルが付いていること | LicOps 自体以外は不要 |
| リクエストが拒否された場合 | Pod の作成時に拒否される | 待機、失敗、再試行のどれにするかを自分で処理する |
| ステータス | プレリリース | 提供中 |
| 適したケース | ライセンスを使うワークロードが多く、cluster-admin 権限がある場合 | ワークロードが少ない場合、または Webhook をインストールする権限がない場合 |
アドミッション Webhook で Pod にライセンスを割り当てる
まず、Kubernetes にデプロイするの説明に従って Webhook をインストールします。そのうえで、両方のオプトインを追加します。
-
ワークロードを実行する Namespace にラベルを付けます。
kubectl label namespace my-eda-workloads openlm.io/licensing=enabled -
ライセンスを使う各ワークロードの Pod テンプレートにアノテーションを付けます。
spec:template:metadata:annotations:openlm.io/needs-licensing: "true"openlm.io/vendor: "MLM"openlm.io/features: "MATLAB:1"openlm.io/job-id: "nightly-regression-0042"
| アノテーション | 必須 | 値 |
|---|---|---|
openlm.io/needs-licensing | はい | 必ず "true" を指定します。それ以外の値の場合、Pod には何も変更が加えられません。 |
openlm.io/vendor | はい | プールのベンダー。GET /api/v1/stats に表示されるとおりに指定します。 |
openlm.io/features | はい | フィーチャーとシート数を "Innovus:1" のように name:count の形式で指定します。Pod ごとにフィーチャーは 1 つにしてください。複数指定した場合、ライセンスが付与されるのは最初のフィーチャーだけです。 |
openlm.io/job-id | いいえ | Pod のライセンス使用とともに記録するジョブ名。 |
このような Pod が作成されると、Webhook が LicOps にシートを要求します。LicOps が拒否した場合、Pod は拒否され、その Pod のコントローラー(たとえば Job)が後で Pod の作成を再試行します。LicOps が許可した場合、Webhook は、シートをディスパッチして Pod のライセンス通信をリダイレクトする init コンテナーと、チェックアウトを LicOps に渡すサイドカーを追加します。サイドカーは、Pod が終了して Kubernetes が SIGTERM でサイドカーを停止したときにシートを解放します。ノードの障害やメモリー不足などで、このシグナルなしにサイドカーが強制終了された場合、シートはセッションがタイムアウトするまで保持されます。
Webhook は、Pod の最初のコンテナーに対してだけ、LM_LICENSE_FILE とベンダー固有の変数(MLM_LICENSE_FILE など)をサイドカーを指すように設定し、FEATURES 変数を追加します。マニフェストで設定した LM_LICENSE_FILE は、サイドカーのフォールバックとして保持されます。ライセンスが必要なアプリケーションは最初のコンテナーに配置してください。
LicOps に 1.5 秒以内に到達できない場合、Webhook は Pod をそのまま通します。Pod は自身のライセンス設定でチェックアウトし、LicOps を経由しません。LicOps がエラーを返した場合や要求を拒否した場合、Pod は拒否されます。この動作は変更できません。
Namespace のラベルまたは needs-licensing アノテーションが欠けている場合、Pod は何も変更されずに作成されます。エラーもイベントも警告も出ません。ライセンスの割り当てが「動作しない」ときは、まずこの 2 つを確認してください。
Pod にライセンスが割り当てられたことを確認するには、そのコンテナーを一覧表示します。ライセンスが割り当てられた Pod には、自分で記述したよりも多くのコンテナーがあります。
kubectl get pod <pod> -o jsonpath='{.spec.initContainers[*].name}{"\n"}{.spec.containers[*].name}{"\n"}'
kubectl get namespace my-eda-workloads --show-labels
ジョブから API を呼び出す
ジョブ自身が API を呼び出す場合、Pod には次の 3 つのステップが必要です。
- init コンテナーが許可とディスパッチを行う。 セッション ID を生成してシートを要求し(LicOps が
503を返すか、容量不足で拒否している間は、待機してから再度要求します)、その後ディスパッチを呼び出します。セッション ID と、ディスパッチが返したlicenseFileを、共有のemptyDirボリュームに書き込みます。 - 作業コンテナーがそのサーバーを使う。 アプリケーションを起動する前に、init コンテナーが書き込んだファイルから
LM_LICENSE_FILEを設定します。 - 作業コンテナーがシートを解放する。 終了時の
trapで、アプリケーションがどのように終了しても、セッション ID を指定して解放を呼び出します。
次のアウトラインは全体の構成を示したものです。init コンテナーのコマンドは省略しています。
initContainers:
- name: openlm-admit
image: curlimages/curl:8.10.1
# Admit (retrying), then dispatch; write /openlm/session-id and /openlm/env.sh.
containers:
- name: work
image: your-registry/your-licensed-app:1.0
env:
- name: OL_URL
value: "http://openlm-router-api.<namespace>.svc.cluster.local:8100"
command: ["/bin/sh", "-c"]
args:
- |
release() {
curl -s --max-time 5 -X POST "$OL_URL/api/v1/admission-controller/release" \
-H 'Content-Type: application/json' \
-d "{\"sessionId\":\"$(cat /openlm/session-id)\"}" || true
}
trap release EXIT TERM INT
. /openlm/env.sh
your-application --your --flags
インテグレーションキットには、この方法で構成した、コメント付きの完全な Job kubernetes/job-direct-api.yaml が含まれています。そのアドレスを LicOps の Service http://openlm-router-api.<namespace>.svc.cluster.local:8100 に向けてください。Pod の IP アドレスや kubectl port-forward ではなく、必ず Service のアドレスを使います。
解放は、作業の完了を待つ別のサイドカーからではなく、作業コンテナー自身の trap から行ってください。Job の Pod はすべてのコンテナーが終了した時点で初めて完了となるため、待機し続けるサイドカーがあると Job がいつまでも終了しません。Kubernetes 1.29 以降では、ネイティブサイドカー(restartPolicy: Always を指定した init コンテナー)を使うとこの問題を回避できます。サンプルの Job には、この方式がコメントアウトされたブロックとして含まれています。
ノードの障害などで解放が届かなかった場合でも、シートが失われたままになることはありません。セッションのタイムアウト時に、LicOps がシートを回収します。
ドキュメントチームは、大規模言語モデルを使ってこのページを下書きすることがあります。公開前に、テクニカルライターがすべてのページをレビューし、製品と照らし合わせて検証します。最終的な判断は人間が行います。