Kubernetes
Kubernetes(K8s)は、クラスター全体でコンテナを実行し、指定された数のレプリカを正常な状態に維持して、GPUでの学習ジョブや推論ジョブをスケジュールします。
Kubernetes(K8sとも略されます)は、複数のマシンから成るクラスター全体でコンテナ化されたアプリケーションを実行するオープンソースシステムです。ユーザーは、実行するコンテナイメージ、維持するレプリカ数、各レプリカに必要なCPU、メモリ、GPUの容量など、ワークロードの望ましい状態を宣言します。Kubernetesはその状態に合わせて、コンテナの起動、再起動、移動、スケーリングを継続的に行います。Googleは社内のBorgクラスター管理システムを基に開発したこのプロジェクトを2014年6月に発表し、2015年7月のバージョン1.0で、新たに設立されたCloud Native Computing Foundationのシードプロジェクトとして提供しました。名前はギリシャ語で「操舵手」を意味し、K8sはKとsの間にある8文字を置き換えた表記です。機械学習運用(MLOps)では、Kubernetesは共有ハードウェア上で分散学習ジョブ、バッチ推論、モデルサービングを実行する共通レイヤーです。
アーキテクチャと制御ループ#
クラスターはコントロールプレーンとワーカーノードで構成されます。コントロールプレーンには、すべてのクライアントが接続するAPIサーバー、クラスターの状態を保存するetcd、ノードに新しいPodを割り当てるスケジューラー、各種オブジェクトを監視するコントローラーがあります。オンプレミスサーバーでもクラウド仮想マシンでも、各ワーカーノードではkubeletエージェントとcontainerdやCRI-Oなどのコンテナランタイムが動作します。Kubernetesがスケジュールする最小単位はPodです。Podは、ネットワークアドレスとストレージボリュームを共有する1つ以上のコンテナで構成されます。
ワークロードは通常YAMLで記述されるオブジェクトとして宣言し、kubectlで適用します。Deploymentは指定された数の同一Podを稼働させ、イメージの変更時には段階的に置き換えます。ServiceはそれらのPodに安定したアドレスを1つ割り当て、リクエストを振り分けます。Jobはタスクが完了するまでPodを実行します。コントローラーは宣言された状態と実際の状態を比較し、差異があれば対応します。
この同じループによって、Kubernetesは自己修復します。ノードに障害が発生すると、そのPodは稼働状態から外れ、コントローラーが正常なノード上に代替Podを作成します。容量不足でPendingのままのPodも、クラスターオートスケーラーがノードを追加する判断材料になります。
機械学習におけるKubernetes#
GPUはデバイスプラグインを通じてPodに割り当てられます。デバイスプラグインはGPUをnvidia.com/gpuなどのカウント可能なリソースとして公開します。また、Kubernetes 1.34で安定版となったDynamic Resource Allocationを使うと、GPUモデルやメモリなどの属性を指定してPodからデバイスを要求できます。NVIDIAのGPU OperatorはGPUノードにドライバーとプラグインをインストールし、1つのGPUをMulti-Instance GPUスライスに分割したり、複数のPodで時間共有したりできます。OpenAIは2021年、GPT-3やCLIPなどのモデルを学習するため、単一のKubernetesクラスターを7,500ノードに拡張したと報告しました。
オープンソースプロジェクトは、Kubernetes上に機械学習専用のレイヤーを追加します。
- Kubeflow: クラスター上で分散PyTorch学習、機械学習パイプライン、ノートブックを実行します。
- Kueue: バッチジョブと学習ジョブをキューイングし、チームのクォータを適用するため、高価なGPUを常時稼働させながら、1つのチームによる独占を防げます。
- KServe: モデルをオートスケーリング対応のエンドポイントで提供します。アイドル状態のモデルをゼロまでスケールダウンすることもできます。
- Horizontal Pod Autoscaler: CPU使用率やキュー長などのカスタムメトリクスに基づいて推論レプリカを増減し、トラフィックの変化に応じてレイテンシーを一定に保ちます。
Jobは、バッチ推論などの単発GPUタスクを実行する最も簡単な方法です。Ultralytics公式DockerイメージにはyoloコマンドとYOLO26 nanoの重みが含まれているため、このJobではコマンドを設定し、GPUを1台要求するだけです。
apiVersion: batch/v1
kind: Job
metadata:
name: yolo26-predict
spec:
backoffLimit: 2 # retry a failed pod at most twice
template:
spec:
restartPolicy: Never
containers:
- name: yolo
image: ultralytics/ultralytics:latest
command: ["yolo", "predict", "model=yolo26n.pt", "source=https://ultralytics.com/images/bus.jpg"]
resources:
limits:
nvidia.com/gpu: 1 # schedule only onto a node with a free GPUkubectl apply -f job.yamlでJobを送信すると、スケジューラーが空きGPUのあるノードにPodを配置し、kubectl logs job/yolo26-predictがpredictモードでの物体検出結果を出力します。学習 Jobも同じパターンで、チェックポイント用の永続ボリュームに加え、PyTorchのデータローダーワーカー用として/dev/shmにメモリ内ボリュームを追加します。
Kubernetes、Docker、サーバーレスの比較#
- Docker: イメージをビルドし、1台のマシン上でコンテナを実行します。Kubernetesは複数のマシンにコンテナを配置します。バージョン1.24以降、DockerでビルドされたイメージはDocker Engineではなく、containerdまたはCRI-Oを通じて実行されます。
- サーバーレスコンピューティング: Google Cloud RunやAWS Lambdaなどのサービスはクラスターを完全に隠蔽し、リクエスト単位で課金します。Knativeを使うと、Kubernetesクラスターでも同様のゼロスケールモデルを利用できます。
- マネージドKubernetes: Google Kubernetes Engine(GKE)、Amazon Elastic Kubernetes Service(EKS)、Azure Kubernetes Service(AKS)は、顧客に代わってコントロールプレーンを実行します。GKE Autopilotはワーカーノードも管理します。










