- はじめに
- Kubeflow Pipelines のアーキテクチャ
- KFP v2 SDK の基本的な使い方
- 高度なパイプラインパターン
- パイプラインのキャッシュとアーティファクト管理
- ワークフローオーケストレーションツールの比較
- Multi-Step ML パイプラインの実践例
- Kubernetes のリソース管理
- 運用上の注意事項
- 障害事例と復旧手順
- プロダクションチェックリスト
- 参考資料

はじめに
ML プロジェクトがプロダクション規模へ成長すると、データ前処理からモデル学習、評価、デプロイまでのワークフロー全体を安定して管理することが中心的な課題になる。Jupyter Notebook での実験は再現性が低く、手動でのスクリプト実行はミスが起きやすい。こうした問題を解決するために ML パイプラインオーケストレーション ツールが必要になる。
Kubeflow Pipelines(KFP) は Google が主導するオープンソースプロジェクトで、Kubernetes 上で ML ワークフローを定義し実行するプラットフォームである。各ステップを独立したコンテナとして実行することで再現性を保証し、パイプラインのバージョン管理と実験の追跡に対応する。本記事では KFP v2 SDK のアーキテクチャから実践的なパイプライン構築、プロダクション運用戦略までを詳しく扱う。
Kubeflow Pipelines のアーキテクチャ
中心的なコンポーネント構造
Kubeflow Pipelines は複数のマイクロサービスで構成される。
| コンポーネント | 役割 | 技術スタック |
|---|---|---|
| Pipeline Service | パイプラインの CRUD、実行管理 | gRPC/REST API |
| Metadata Service | アーティファクトと実行メタデータの保存 | ML Metadata (MLMD) |
| Persistence Agent | ワークフロー状態を DB へ同期 | Kubernetes Controller |
| Scheduler | 繰り返し実行(Recurring Run)の管理 | CronJob ベース |
| UI Server | Web ダッシュボード | React ベース SPA |
| Artifact Store | パイプライン成果物の保存 | MinIO / S3 / GCS |
KFP v2 でのアーキテクチャ変更点
KFP v2 では v1 に比べて根本的なアーキテクチャ変更が行われた。従来の Argo Workflows への依存を取り除き、独自のワークフローエンジンを導入している。
# KFP v2 vs v1 の主な違いの比較
"""
KFP v1:
- Argo Workflows ベースの実行
- kfp.dsl.ContainerOp を使用
- YAML ベースのパイプライン定義が可能
KFP v2:
- 独自のワークフローエンジン (または Argo を選択可能)
- kfp.dsl.component デコレータを使用
- IR (Intermediate Representation) YAML の導入
- ML Metadata のネイティブ統合
- 型安全なコンポーネントインターフェース
"""
# v2 のアーキテクチャレイヤー
ARCHITECTURE_LAYERS = {
"SDK Layer": "Python DSL でパイプラインを定義 (kfp.dsl)",
"IR Layer": "プラットフォーム非依存の中間表現 (PipelineSpec YAML)",
"Backend Layer": "パイプラインの実行と管理 (API Server)",
"Runtime Layer": "コンテナオーケストレーション (K8s Pod)",
"Metadata Layer": "実行履歴とアーティファクトの追跡 (MLMD)",
}
KFP v2 SDK の基本的な使い方
コンポーネントの作成
KFP v2 では、コンポーネントを @component デコレータで定義する。各コンポーネントは独立したコンテナで実行される。
from kfp import dsl
from kfp.dsl import Input, Output, Dataset, Model, Metrics
# 軽量な Python コンポーネント (依存が少ない場合)
@dsl.component(
base_image="python:3.11-slim",
packages_to_install=["pandas==2.1.4", "scikit-learn==1.4.0"],
)
def preprocess_data(
raw_data_path: str,
test_size: float,
train_dataset: Output[Dataset],
test_dataset: Output[Dataset],
metrics: Output[Metrics],
):
"""データ前処理コンポーネント"""
import pandas as pd
from sklearn.model_selection import train_test_split
df = pd.read_csv(raw_data_path)
# 欠損値の処理
df = df.dropna(subset=["target"])
df = df.fillna(df.median(numeric_only=True))
# 学習/テストの分割
train_df, test_df = train_test_split(
df, test_size=test_size, random_state=42, stratify=df["target"]
)
# アーティファクトとして保存
train_df.to_csv(train_dataset.path, index=False)
test_df.to_csv(test_dataset.path, index=False)
# メトリクスのロギング
metrics.log_metric("total_samples", len(df))
metrics.log_metric("train_samples", len(train_df))
metrics.log_metric("test_samples", len(test_df))
metrics.log_metric("feature_count", len(df.columns) - 1)
カスタムコンテナコンポーネント
重い依存が必要な場合はカスタムコンテナイメージを使う。
# カスタムイメージベースのコンポーネント
@dsl.component(
base_image="gcr.io/my-project/ml-training:v2.1",
)
def train_model(
train_dataset: Input[Dataset],
model_type: str,
hyperparameters: dict,
trained_model: Output[Model],
metrics: Output[Metrics],
):
"""モデル学習コンポーネント"""
import pandas as pd
import joblib
from sklearn.ensemble import RandomForestClassifier, GradientBoostingClassifier
from sklearn.metrics import accuracy_score, f1_score
train_df = pd.read_csv(train_dataset.path)
X_train = train_df.drop("target", axis=1)
y_train = train_df["target"]
# モデルの選択
model_map = {
"random_forest": RandomForestClassifier,
"gradient_boosting": GradientBoostingClassifier,
}
model_cls = model_map[model_type]
model = model_cls(**hyperparameters)
model.fit(X_train, y_train)
# モデルの保存
joblib.dump(model, trained_model.path)
# 学習メトリクス
y_pred = model.predict(X_train)
metrics.log_metric("train_accuracy", accuracy_score(y_train, y_pred))
metrics.log_metric("train_f1", f1_score(y_train, y_pred, average="weighted"))
metrics.log_metric("model_type", model_type)
# モデルのメタデータ
trained_model.metadata["framework"] = "scikit-learn"
trained_model.metadata["model_type"] = model_type
パイプラインの定義
コンポーネントを組み合わせてパイプライン全体を定義する。
from kfp import dsl, compiler
@dsl.pipeline(
name="ml-training-pipeline",
description="End-to-end ML training pipeline with evaluation and deployment",
)
def ml_training_pipeline(
raw_data_path: str = "gs://my-bucket/data/raw.csv",
test_size: float = 0.2,
model_type: str = "random_forest",
accuracy_threshold: float = 0.85,
):
# Step 1: データ前処理
preprocess_task = preprocess_data(
raw_data_path=raw_data_path,
test_size=test_size,
)
preprocess_task.set_cpu_limit("2")
preprocess_task.set_memory_limit("4Gi")
# Step 2: モデル学習
train_task = train_model(
train_dataset=preprocess_task.outputs["train_dataset"],
model_type=model_type,
hyperparameters={
"n_estimators": 200,
"max_depth": 10,
"min_samples_split": 5,
},
)
train_task.set_cpu_limit("4")
train_task.set_memory_limit("8Gi")
train_task.set_accelerator_type("nvidia.com/gpu")
train_task.set_accelerator_limit(1)
# Step 3: モデル評価
eval_task = evaluate_model(
test_dataset=preprocess_task.outputs["test_dataset"],
trained_model=train_task.outputs["trained_model"],
accuracy_threshold=accuracy_threshold,
)
# Step 4: 条件付きデプロイ (精度が閾値を超えた場合)
with dsl.Condition(
eval_task.outputs["deploy_decision"] == "approved",
name="check-accuracy",
):
deploy_task = deploy_model(
model=train_task.outputs["trained_model"],
serving_endpoint="ml-model-serving",
)
# パイプラインのコンパイル
compiler.Compiler().compile(
pipeline_func=ml_training_pipeline,
package_path="ml_pipeline.yaml",
)
高度なパイプラインパターン
並列実行と条件分岐
@dsl.pipeline(name="parallel-training-pipeline")
def parallel_training_pipeline(
raw_data_path: str,
accuracy_threshold: float = 0.85,
):
# データ前処理 (共通)
preprocess_task = preprocess_data(
raw_data_path=raw_data_path,
test_size=0.2,
)
# 複数モデルの並列学習
models = ["random_forest", "gradient_boosting", "xgboost"]
train_tasks = []
for model_type in models:
train_task = train_model(
train_dataset=preprocess_task.outputs["train_dataset"],
model_type=model_type,
hyperparameters={"n_estimators": 200, "max_depth": 10},
)
train_task.set_display_name(f"Train {model_type}")
train_tasks.append(train_task)
# 最適モデルの選択
select_task = select_best_model(
models=[t.outputs["trained_model"] for t in train_tasks],
metrics=[t.outputs["metrics"] for t in train_tasks],
)
# チャンピオンモデルのデプロイ
with dsl.Condition(
select_task.outputs["best_accuracy"] >= accuracy_threshold,
name="accuracy-gate",
):
deploy_model(
model=select_task.outputs["best_model"],
serving_endpoint="champion-model",
)
繰り返し実行と Exit Handler
@dsl.pipeline(name="robust-ml-pipeline")
def robust_ml_pipeline(raw_data_path: str):
# Exit Handler: パイプラインの完了/失敗時に通知を送る
notify_task = send_notification(
pipeline_name="robust-ml-pipeline",
notification_channel="slack",
)
with dsl.ExitHandler(exit_task=notify_task):
# メインのパイプラインロジック
preprocess_task = preprocess_data(
raw_data_path=raw_data_path,
test_size=0.2,
)
train_task = train_model(
train_dataset=preprocess_task.outputs["train_dataset"],
model_type="gradient_boosting",
hyperparameters={"n_estimators": 300, "max_depth": 12},
)
eval_task = evaluate_model(
test_dataset=preprocess_task.outputs["test_dataset"],
trained_model=train_task.outputs["trained_model"],
accuracy_threshold=0.85,
)
# Recurring Run の設定 (KFP クライアント)
from kfp.client import Client
client = Client(host="https://kubeflow.example.com/pipeline")
# 毎日午前 2 時にパイプラインを実行
client.create_recurring_run(
experiment_id="daily-training-exp",
job_name="daily-model-retraining",
pipeline_id="robust-ml-pipeline-v2",
cron_expression="0 2 * * *",
max_concurrency=1,
params={
"raw_data_path": "gs://my-bucket/data/daily/latest.csv",
},
)
パイプラインのキャッシュとアーティファクト管理
キャッシュ戦略
KFP は、コンポーネントの入力が同一であれば以前の実行結果を再利用するキャッシュ機能に対応している。
# キャッシュの設定
@dsl.pipeline(name="cached-pipeline")
def cached_pipeline(raw_data_path: str):
# キャッシュの有効化 (既定値: True)
preprocess_task = preprocess_data(
raw_data_path=raw_data_path,
test_size=0.2,
)
preprocess_task.set_caching_options(enable_caching=True)
# 学習ステップはキャッシュを無効化 (最新データで常に再学習)
train_task = train_model(
train_dataset=preprocess_task.outputs["train_dataset"],
model_type="random_forest",
hyperparameters={"n_estimators": 200},
)
train_task.set_caching_options(enable_caching=False)
アーティファクトの型と管理
from kfp.dsl import (
Input, Output,
Dataset, Model, Metrics,
ClassificationMetrics, SlicedClassifications,
Artifact, HTML, Markdown,
)
@dsl.component(base_image="python:3.11-slim")
def generate_evaluation_report(
test_dataset: Input[Dataset],
trained_model: Input[Model],
classification_metrics: Output[ClassificationMetrics],
html_report: Output[HTML],
eval_metrics: Output[Metrics],
):
"""評価レポート生成コンポーネント"""
import json
# ClassificationMetrics: 混同行列の可視化
classification_metrics.log_confusion_matrix(
categories=["negative", "positive"],
matrix=[[850, 50], [30, 270]],
)
# ROC カーブのロギング
classification_metrics.log_roc_curve(
fpr=[0.0, 0.1, 0.2, 0.5, 1.0],
tpr=[0.0, 0.6, 0.8, 0.95, 1.0],
threshold=[1.0, 0.8, 0.5, 0.2, 0.0],
)
# HTML レポートの生成
report_content = "<h1>Model Evaluation Report</h1>"
report_content += "<p>Accuracy: 0.933</p>"
report_content += "<p>F1 Score: 0.891</p>"
with open(html_report.path, "w") as f:
f.write(report_content)
# 数値メトリクス
eval_metrics.log_metric("accuracy", 0.933)
eval_metrics.log_metric("f1_score", 0.891)
eval_metrics.log_metric("precision", 0.844)
eval_metrics.log_metric("recall", 0.900)
ワークフローオーケストレーションツールの比較
ML ワークフローのオーケストレーションに使えるツールは複数ある。プロジェクトの要件に応じて適切なツールを選ぶ必要がある。
| 特性 | Kubeflow Pipelines | Apache Airflow | Argo Workflows | Prefect |
|---|---|---|---|---|
| 主な用途 | ML パイプライン専用 | 汎用データパイプライン | 汎用ワークフロー | 汎用データパイプライン |
| 実行環境 | Kubernetes 必須 | 多様な Executor | Kubernetes 必須 | ハイブリッド (サーバ/クラウド) |
| ML ネイティブ | 高い (MLMD, アーティファクト) | 低い (プラグインが必要) | 中程度 | 中程度 |
| UI/可視化 | ML 実験ダッシュボード | DAG モニタリング | ワークフロー可視化 | フローダッシュボード |
| キャッシュ | コンポーネント単位 | タスク単位 | Memoization | タスク単位 |
| スケーリング | Kubernetes ネイティブ | Celery/K8s Executor | Kubernetes ネイティブ | Dask/Ray 統合 |
| 学習コスト | 高い | 中程度 | 高い | 低い |
| コミュニティ | 活発 (CNCF) | 非常に活発 (Apache) | 活発 (CNCF) | 成長中 |
| GPU 対応 | ネイティブ | 限定的 | ネイティブ | 外部統合が必要 |
選択の基準
- Kubeflow Pipelines: Kubernetes 基盤があり、ML 専用のパイプラインが必要な場合
- Airflow: データエンジニアリングと ML をまとめて管理し、成熟したエコシステムが必要な場合
- Argo Workflows: Kubernetes ネイティブな汎用ワークフローが必要で、ML 特化機能は自前で実装できる場合
- Prefect: すぐ始められることと、柔軟なデプロイ環境が必要な場合
Multi-Step ML パイプラインの実践例
パイプライン全体: データ準備からデプロイまで
from kfp import dsl, compiler
from kfp.dsl import Input, Output, Dataset, Model, Metrics
@dsl.component(
base_image="python:3.11-slim",
packages_to_install=["pandas==2.1.4", "great-expectations==0.18.8"],
)
def validate_data(
raw_data_path: str,
validated_data: Output[Dataset],
validation_metrics: Output[Metrics],
) -> str:
"""データ品質の検証"""
import pandas as pd
df = pd.read_csv(raw_data_path)
# 基本的なデータ品質チェック
checks = {
"row_count_check": len(df) > 100,
"null_ratio_check": df.isnull().mean().max() < 0.3,
"duplicate_check": df.duplicated().mean() < 0.05,
"target_balance_check": df["target"].value_counts(normalize=True).min() > 0.1,
}
all_passed = all(checks.values())
for check_name, passed in checks.items():
validation_metrics.log_metric(check_name, int(passed))
validation_metrics.log_metric("total_rows", len(df))
validation_metrics.log_metric("all_checks_passed", int(all_passed))
if all_passed:
df.to_csv(validated_data.path, index=False)
return "passed"
else:
failed = [k for k, v in checks.items() if not v]
raise ValueError(f"Data validation failed: {failed}")
@dsl.component(
base_image="python:3.11-slim",
packages_to_install=["pandas==2.1.4", "scikit-learn==1.4.0"],
)
def feature_engineering(
validated_data: Input[Dataset],
feature_config: dict,
features_dataset: Output[Dataset],
feature_metrics: Output[Metrics],
):
"""フィーチャーエンジニアリング"""
import pandas as pd
import numpy as np
from sklearn.preprocessing import StandardScaler, LabelEncoder
df = pd.read_csv(validated_data.path)
# 数値フィーチャーのスケーリング
numeric_cols = df.select_dtypes(include=[np.number]).columns.tolist()
numeric_cols = [c for c in numeric_cols if c != "target"]
scaler = StandardScaler()
df[numeric_cols] = scaler.fit_transform(df[numeric_cols])
# カテゴリフィーチャーのエンコーディング
cat_cols = df.select_dtypes(include=["object"]).columns.tolist()
for col in cat_cols:
le = LabelEncoder()
df[col] = le.fit_transform(df[col].astype(str))
df.to_csv(features_dataset.path, index=False)
feature_metrics.log_metric("numeric_features", len(numeric_cols))
feature_metrics.log_metric("categorical_features", len(cat_cols))
feature_metrics.log_metric("total_features", len(df.columns) - 1)
@dsl.component(
base_image="gcr.io/my-project/ml-serving:v1.0",
)
def deploy_to_kserve(
model: Input[Model],
serving_endpoint: str,
namespace: str,
) -> str:
"""KServe へモデルをデプロイ"""
import subprocess
import json
import yaml
inference_service = {
"apiVersion": "serving.kserve.io/v1beta1",
"kind": "InferenceService",
"metadata": {
"name": serving_endpoint,
"namespace": namespace,
},
"spec": {
"predictor": {
"model": {
"modelFormat": {"name": "sklearn"},
"storageUri": model.uri,
"resources": {
"requests": {"cpu": "1", "memory": "2Gi"},
"limits": {"cpu": "2", "memory": "4Gi"},
},
}
}
},
}
manifest_path = "/tmp/isvc.yaml"
with open(manifest_path, "w") as f:
yaml.dump(inference_service, f)
result = subprocess.run(
["kubectl", "apply", "-f", manifest_path],
capture_output=True, text=True,
)
if result.returncode != 0:
raise RuntimeError(f"Deploy failed: {result.stderr}")
return f"Deployed to {namespace}/{serving_endpoint}"
@dsl.pipeline(
name="e2e-ml-pipeline",
description="データ検証からモデルデプロイまでの ML パイプライン全体",
)
def e2e_ml_pipeline(
raw_data_path: str = "gs://ml-data/raw/dataset.csv",
model_type: str = "gradient_boosting",
accuracy_threshold: float = 0.85,
serving_endpoint: str = "fraud-detector",
namespace: str = "ml-serving",
):
# 通知のための Exit Handler
notify = send_notification(
pipeline_name="e2e-ml-pipeline",
notification_channel="slack",
)
with dsl.ExitHandler(exit_task=notify):
# 1. データ検証
validate_task = validate_data(raw_data_path=raw_data_path)
# 2. フィーチャーエンジニアリング
feature_task = feature_engineering(
validated_data=validate_task.outputs["validated_data"],
feature_config={"scaling": "standard", "encoding": "label"},
)
# 3. データ分割
split_task = preprocess_data(
raw_data_path=feature_task.outputs["features_dataset"].uri,
test_size=0.2,
)
# 4. モデル学習
train_task = train_model(
train_dataset=split_task.outputs["train_dataset"],
model_type=model_type,
hyperparameters={"n_estimators": 300, "max_depth": 12},
)
train_task.set_cpu_limit("4")
train_task.set_memory_limit("16Gi")
# 5. モデル評価
eval_task = evaluate_model(
test_dataset=split_task.outputs["test_dataset"],
trained_model=train_task.outputs["trained_model"],
accuracy_threshold=accuracy_threshold,
)
# 6. 条件付きデプロイ
with dsl.Condition(
eval_task.outputs["deploy_decision"] == "approved",
name="deploy-gate",
):
deploy_to_kserve(
model=train_task.outputs["trained_model"],
serving_endpoint=serving_endpoint,
namespace=namespace,
)
# コンパイルと投入
compiler.Compiler().compile(
pipeline_func=e2e_ml_pipeline,
package_path="e2e_ml_pipeline.yaml",
)
Kubernetes のリソース管理
Pod リソースとノードアフィニティの設定
@dsl.pipeline(name="resource-managed-pipeline")
def resource_managed_pipeline():
train_task = train_model(
train_dataset=preprocess_task.outputs["train_dataset"],
model_type="xgboost",
hyperparameters={"n_estimators": 500},
)
# リソース制限
train_task.set_cpu_limit("8")
train_task.set_memory_limit("32Gi")
train_task.set_accelerator_type("nvidia.com/gpu")
train_task.set_accelerator_limit(2)
# ノードセレクタ (GPU ノードで実行)
train_task.add_node_selector_constraint(
label_name="cloud.google.com/gke-accelerator",
value="nvidia-tesla-v100",
)
# Toleration の設定
train_task.set_gpu_limit(2).add_toleration(
key="nvidia.com/gpu",
operator="Exists",
effect="NoSchedule",
)
# PVC のマウント (大容量データ)
train_task.add_pvolumes({
"/mnt/data": dsl.PipelineVolume(
pvc="ml-data-pvc",
volume_name="data-volume",
),
})
# タイムアウトの設定 (秒単位)
train_task.set_timeout(3600) # 1 時間
# リトライの設定
train_task.set_retry(
num_retries=3,
policy="Always",
backoff_duration="30s",
backoff_factor=2.0,
backoff_max_duration="600s",
)
運用上の注意事項
リソース関連の注意点
- メモリ OOM: 大容量データセットを扱うコンポーネントには十分なメモリを割り当てる必要がある。Pandas の
read_csvはデータサイズの 3-5 倍のメモリを消費する。 - GPU リソースの競合: 複数のパイプラインが同時に GPU を要求すると Pending 状態が長引く。ResourceQuota と PriorityClass を設定すること。
- PVC への同時アクセス: ReadWriteOnce の PVC は一つの Pod しかマウントできない。並列コンポーネントが同じ PVC にアクセスすると失敗する。
セキュリティ関連の注意点
- シークレット管理: パイプラインのパラメータに API キーやパスワードを直接渡してはいけない。Kubernetes Secret を環境変数としてマウントすること。
- イメージの脆弱性: ベースイメージのセキュリティ脆弱性を定期的にスキャンすること。
python:3.11-slimの代わりにdistrolessイメージの利用を検討する。 - RBAC の設定: パイプラインのサービスアカウントに最小権限の原則を適用すること。
障害事例と復旧手順
事例 1: Pod OOMKilled
症状: コンポーネントの Pod が OOMKilled 状態で失敗する
# Pod の状態確認
kubectl get pods -n kubeflow -l pipeline/runid=run-abc123
kubectl describe pod train-model-xxxxx -n kubeflow
# イベントで OOMKilled を確認
# Last State: Terminated
# Reason: OOMKilled
# Exit Code: 137
復旧手順:
# 1. メモリ制限の引き上げ
train_task.set_memory_limit("64Gi")
# 2. データをチャンク単位で処理するようコンポーネントを修正
@dsl.component(base_image="python:3.11-slim")
def train_with_chunks(
train_dataset: Input[Dataset],
chunk_size: int,
trained_model: Output[Model],
):
import pandas as pd
from sklearn.linear_model import SGDClassifier
model = SGDClassifier(loss="log_loss")
chunks = pd.read_csv(train_dataset.path, chunksize=chunk_size)
for chunk in chunks:
X = chunk.drop("target", axis=1)
y = chunk["target"]
model.partial_fit(X, y, classes=[0, 1])
import joblib
joblib.dump(model, trained_model.path)
事例 2: パイプラインのバージョン衝突
症状: パイプライン更新後に既存の Recurring Run が失敗する
復旧手順:
from kfp.client import Client
client = Client(host="https://kubeflow.example.com/pipeline")
# 1. 既存の Recurring Run を無効化
client.disable_recurring_run(recurring_run_id="run-xxx")
# 2. 新しいパイプラインバージョンをアップロード
pipeline_version = client.upload_pipeline_version(
pipeline_package_path="ml_pipeline_v3.yaml",
pipeline_version_name="v3.0",
pipeline_id="ml-training-pipeline",
)
# 3. 新しい Recurring Run を作成
client.create_recurring_run(
experiment_id="daily-training-exp",
job_name="daily-model-retraining-v3",
version_id=pipeline_version.pipeline_version_id,
cron_expression="0 2 * * *",
max_concurrency=1,
)
事例 3: メタデータ DB への接続失敗
症状: ML Metadata Service への接続エラーでアーティファクト追跡に失敗する
# MLMD サービスの状態確認
kubectl get pods -n kubeflow -l app=metadata-grpc-server
kubectl logs metadata-grpc-server-xxxxx -n kubeflow
# MySQL/PostgreSQL の接続確認
kubectl exec -it metadata-grpc-server-xxxxx -n kubeflow -- \
mysql -h metadata-db -u root -p -e "SHOW DATABASES;"
# MLMD サービスの再起動
kubectl rollout restart deployment metadata-grpc-server -n kubeflow
プロダクションチェックリスト
インフラ設定
- Kubernetes クラスタへの Kubeflow Pipelines のインストールとバージョン確認 (KFP v2 推奨)
- Artifact Store (MinIO/S3/GCS) の設定とアクセス権限の確認
- Metadata DB (MySQL/PostgreSQL) の高可用性構成
- RBAC と名前空間分離の設定
- GPU ノードプールとオートスケーリングの構成
パイプライン開発
- すべてのコンポーネントにリソース制限(CPU/Memory/GPU)を設定
- リトライポリシーとタイムアウトの設定
- キャッシュ戦略の策定 (どのステップをキャッシュするか決める)
- パイプラインパラメータの既定値の設定
- データ検証コンポーネントの組み込み
運用とモニタリング
- Recurring Run の設定と同時実行数の制限
- パイプライン失敗の通知 (Slack/PagerDuty) の設定
- アーティファクトストレージの容量モニタリング
- MLMD のバックアップスケジュールの設定
- パイプライン実行履歴の整理ポリシー (retention policy)
セキュリティ
- コンテナイメージの脆弱性スキャンの自動化
- Kubernetes Secret による機密情報の管理
- ネットワークポリシーによる Pod 間通信の制限
- サービスアカウントへの最小権限の原則の適用