---
title: Kubernetes ワークロード
description: アドミッション Webhook を使うか、ジョブからアドミッション API を呼び出して、OpenLM LicOps 経由で OpenLM Platform の Kubernetes の Pod にライセンスを割り当てます。
product: OpenLM Platform
---

Kubernetes のワークロードがライセンスのシートを待つようにするには、アノテーションを付けた Pod を LicOps のアドミッション Webhook に処理させるか、ジョブ自身からアドミッション API を呼び出します。どちらの方法でも、アプリケーションのイメージを変更する必要はありません。2 つの方法を次の表で比較します。

| 項目 | アドミッション Webhook | ジョブが API を呼び出す |
| --- | --- | --- |
| マニフェストに追加するもの | 4 つのアノテーション | init コンテナーと解放の処理 |
| クラスターの前提条件 | Webhook がインストールされ、Namespace にラベルが付いていること | LicOps 自体以外は不要 |
| リクエストが拒否された場合 | Pod の作成時に拒否される | 待機、失敗、再試行のどれにするかを自分で処理する |
| ステータス | プレリリース | 提供中 |
| 適したケース | ライセンスを使うワークロードが多く、cluster-admin 権限がある場合 | ワークロードが少ない場合、または Webhook をインストールする権限がない場合 |

## アドミッション Webhook で Pod にライセンスを割り当てる

まず、[Kubernetes にデプロイする](https://www.openlm.com/documentation/ja/cloud/deployment-operations/licops/deploy-kubernetes#アドミッション-webhook-をインストールする)の説明に従って Webhook をインストールします。そのうえで、両方のオプトインを追加します。

1. ワークロードを実行する Namespace にラベルを付けます。

   ```bash
   kubectl label namespace my-eda-workloads openlm.io/licensing=enabled
   ```

2. ライセンスを使う各ワークロードの Pod テンプレートにアノテーションを付けます。

   ```yaml
   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 は拒否されます。この動作は変更できません。

:::warning[オプトインが欠けていても何も通知されない]

Namespace のラベルまたは `needs-licensing` アノテーションが欠けている場合、Pod は何も変更されずに作成されます。エラーもイベントも警告も出ません。ライセンスの割り当てが「動作しない」ときは、まずこの 2 つを確認してください。

:::

Pod にライセンスが割り当てられたことを確認するには、そのコンテナーを一覧表示します。ライセンスが割り当てられた Pod には、自分で記述したよりも多くのコンテナーがあります。

```bash
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 つのステップが必要です。

1. **init コンテナーが許可とディスパッチを行う。** セッション ID を生成してシートを要求し（LicOps が `503` を返すか、容量不足で拒否している間は、待機してから再度要求します）、その後ディスパッチを呼び出します。セッション ID と、ディスパッチが返した `licenseFile` を、共有の `emptyDir` ボリュームに書き込みます。
2. **作業コンテナーがそのサーバーを使う。** アプリケーションを起動する前に、init コンテナーが書き込んだファイルから `LM_LICENSE_FILE` を設定します。
3. **作業コンテナーがシートを解放する。** 終了時の `trap` で、アプリケーションがどのように終了しても、セッション ID を指定して解放を呼び出します。

次のアウトラインは全体の構成を示したものです。init コンテナーのコマンドは省略しています。

```yaml
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 がシートを回収します。
