mcpField
R
runpod-deployment

runpod-deployment

github.com/scientiacapitalクラウド・DevOps28109 回インストール3 週間前に更新
リポジトリ

runpod-deployment について

RunPod上のGPUワークロードのデプロイと運用を支援するClaudeスキルです。サーバーレスワーカー、vLLMエンドポイント、専用Podに加え、GPU選定やコスト管理、監視の手順を扱います。

主な機能

  1. 01サーバーレスハンドラーのパターン
  2. 02vLLMエンドポイントのデプロイ
  3. 03GPUとPodの選定
  4. 04コストとスケーリングの指針
  5. 05ヘルスチェックとメトリクス

活用シーン

  1. 01サーバーレス推論エンドポイントのデプロイ
  2. 02vLLM APIによるモデル提供
  3. 03予算に合わせたGPU選定
  4. 04エンドポイントの状態とスケーリングの監視

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/scientiacapital/skills --skill runpod-deployment

インストール後、Claude Code で/runpod-deploymentを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

config.json
reference/
cicd.md
cost-optimization.md
model-deployment.md
monitoring.md
pod-management.md
project-configs.md
serverless-workers.md
templates.md
troubleshooting.md
vllm-setup.md
templates/
runpod-worker.py

詳細

RunPod インフラストラクチャ上で GPU ワークロードをデプロイおよび管理します:
  1. サーバーレスワーカー - 秒単位の課金でゼロにスケールするハンドラー
  2. vLLM エンドポイント - 2〜3倍のスループットを実現する OpenAI 互換の LLM サービング
  3. Pod 管理 - 開発・トレーニング用の専用 GPU インスタンス
  4. コスト最適化 - GPU の選択、スポットインスタンス、予算管理

主な成果物:

  • ストリーミング対応の本番環境対応サーバーレスハンドラー
  • OpenAI API 互換の vLLM デプロイ
  • あらゆるモデルサイズに対応するコスト最適化された GPU の選択
  • ヘルスモニタリングと自動スケーリングの構成

<quick_start> 最小構成のサーバーレスハンドラー(v1.8.1):

import runpod

def handler(job):
    """Basic handler - receives job, returns result."""
    job_input = job["input"]
    prompt = job_input.get("prompt", "")

    # Your inference logic here
    result = process(prompt)

    return {"output": result}

runpod.serverless.start({"handler": handler})

ストリーミングハンドラー:

import runpod

def streaming_handler(job):
    """Generator for streaming responses."""
    for chunk in generate_chunks(job["input"]):
        yield {"token": chunk, "finished": False}
    yield {"token": "", "finished": True}

runpod.serverless.start({
    "handler": streaming_handler,
    "return_aggregate_stream": True
})

vLLM OpenAI 互換クライアント:

from openai import OpenAI

client = OpenAI(
    api_key="RUNPOD_API_KEY",
    base_url="https://api.runpod.ai/v2/ENDPOINT_ID/openai/v1",
)

response = client.chat.completions.create(
    model="meta-llama/Llama-3.1-8B-Instruct",
    messages=[{"role": "user", "content": "Hello!"}],
    max_tokens=100,
)

</quick_start>

<success_criteria> RunPod のデプロイは、次の条件を満たす場合に成功です:

  • ハンドラーがエラーなくリクエストを処理する
  • エンドポイントが適切にスケールする(0 → N ワーカー)
  • コールドスタート時間がユースケースに対して許容範囲である
  • コストが予算の見積もり内に収まる
  • ヘルスチェックが継続的に成功する </success_criteria>

<m1_mac_critical>

M1/M2 Mac:ローカルで Docker をビルドできない

ARM アーキテクチャは RunPod の x86 GPU と互換性がありません。

解決策:GitHub Actions が代わりにビルドします:

# Push code - Actions builds x86 image
git add . && git commit -m "Deploy" && git push

完全な GitHub Actions ワークフローについては reference/cicd.md を参照してください。

Apple Silicon で RunPod 用にローカルで docker build を実行しないでください。 </m1_mac_critical>

<gpu_selection>

GPU 選択マトリクス(2025年1月)

GPUVRAMSecure $/時Spot $/時最適な用途
RTX A400016GB$0.36$0.18埋め込み、小規模モデル
RTX 409024GB$0.44$0.227B〜8B 推論
A4048GB$0.65$0.3913B〜30B、ファインチューニング
A100 80GB80GB$1.89$0.8970B モデル、本番環境
H100 80GB80GB$4.69$1.8870B+ トレーニング

クイック選択:

def select_gpu(model_params_b: float, quantized: bool = False) -> str:
    effective = model_params_b * (0.5 if quantized else 1.0)
    if effective <= 3: return "RTX_A4000"      # $0.36/hr
    if effective <= 8: return "RTX_4090"       # $0.44/hr
    if effective <= 30: return "A40"           # $0.65/hr
    if effective <= 70: return "A100_80GB"     # $1.89/hr
    return "H100_80GB"                         # $4.69/hr

詳細な料金と予算管理については reference/cost-optimization.md を参照してください。 </gpu_selection>

<handler_patterns>

ハンドラーパターン

進捗の更新(長時間実行タスク)
import runpod

def long_task_handler(job):
    total_steps = job["input"].get("steps", 10)

    for step in range(total_steps):
        process_step(step)
        runpod.serverless.progress_update(
            job_id=job["id"],
            progress=int((step + 1) / total_steps * 100)
        )

    return {"status": "complete", "steps": total_steps}

runpod.serverless.start({"handler": long_task_handler})
エラーハンドリング
import runpod
import traceback

def safe_handler(job):
    try:
        # Validate input
        if "prompt" not in job["input"]:
            return {"error": "Missing required field: prompt"}

        result = process(job["input"])
        return {"output": result}

    except torch.cuda.OutOfMemoryError:
        return {"error": "GPU OOM - reduce input size", "retry": False}
    except Exception as e:
        return {"error": str(e), "traceback": traceback.format_exc()}

runpod.serverless.start({"handler": safe_handler})

非同期パターン、バッチ処理、高度なハンドラーについては reference/serverless-workers.md を参照してください。 </handler_patterns>

<vllm_deployment>

vLLM デプロイ

注記: vLLM は OpenAI 互換の API フォーマットを使用しますが、接続先はあなたの RunPod エンドポイントであり、 OpenAI のサーバーではありません。モデルはあなたの GPU 上で実行されます(Llama、Qwen、Mistral など)。

環境設定
vllm_env = {
    "MODEL_NAME": "meta-llama/Llama-3.1-70B-Instruct",
    "HF_TOKEN": "${HF_TOKEN}",
    "TENSOR_PARALLEL_SIZE": "2",        # Multi-GPU
    "MAX_MODEL_LEN": "16384",
    "GPU_MEMORY_UTILIZATION": "0.95",
    "QUANTIZATION": "awq",              # Optional: awq, gptq
}
OpenAI 互換ストリーミング
from openai import OpenAI

client = OpenAI(
    api_key="RUNPOD_API_KEY",
    base_url="https://api.runpod.ai/v2/ENDPOINT_ID/openai/v1",
)

stream = client.chat.completions.create(
    model="meta-llama/Llama-3.1-8B-Instruct",
    messages=[{"role": "user", "content": "Write a poem"}],
    stream=True,
)

for chunk in stream:
    if chunk.choices[0].delta.content:
        print(chunk.choices[0].delta.content, end="", flush=True)
RunPod 直接ストリーミング
import requests

url = "https://api.runpod.ai/v2/ENDPOINT_ID/run"
headers = {"Authorization": "Bearer RUNPOD_API_KEY"}

response = requests.post(url, headers=headers, json={
    "input": {"prompt": "Hello", "stream": True}
})
job_id = response.json()["id"]

# Stream results
stream_url = f"https://api.runpod.ai/v2/ENDPOINT_ID/stream/{job_id}"
with requests.get(stream_url, headers=headers, stream=True) as r:
    for line in r.iter_lines():
        if line: print(line.decode())

HuggingFace、TGI、カスタムモデルのパターンについては reference/model-deployment.md を参照してください。 </vllm_deployment>

<auto_scaling>

自動スケーリング構成

スケーラーの種類
種類最適な用途構成
QUEUE_DELAY変動するトラフィックscaler_value=2(2秒を目標)
REQUEST_COUNT予測可能な負荷scaler_value=5(ワーカーあたり5リクエスト)
構成パターン
configs = {
    "interactive_api": {
        "workers_min": 1,      # Always warm
        "workers_max": 5,
        "idle_timeout": 120,
        "scaler_type": "QUEUE_DELAY",
        "scaler_value": 1,     # 1s latency target
    },
    "batch_processing": {
        "workers_min": 0,
        "workers_max": 20,
        "idle_timeout": 30,
        "scaler_type": "REQUEST_COUNT",
        "scaler_value": 5,
    },
    "cost_optimized": {
        "workers_min": 0,
        "workers_max": 3,
        "idle_timeout": 15,    # Aggressive scale-down
        "scaler_type": "QUEUE_DELAY",
        "scaler_value": 5,
    },
}

Pod のライフサイクルとスケーリングの詳細については reference/pod-management.md を参照してください。 </auto_scaling>

<health_monitoring>

ヘルスとモニタリング

クイックヘルスチェック
import runpod

async def check_health(endpoint_id: str):
    endpoint = runpod.Endpoint(endpoint_id)
    health = await endpoint.health()

    return {
        "status": health.status,
        "workers_ready": health.workers.ready,
        "queue_depth": health.queue.in_queue,
        "avg_latency_ms": health.metrics.avg_execution_time,
    }
GraphQL メトリクスクエリ
query GetEndpoint($id: String!) {
    endpoint(id: $id) {
        status
        workers { ready running pending throttled }
        queue { inQueue inProgress completed failed }
        metrics {
            requestsPerMinute
            avgExecutionTimeMs
            p95ExecutionTimeMs
            successRate
        }
    }
}

構造化ログ、アラート、ダッシュボードについては reference/monitoring.md を参照してください。 </health_monitoring>

<dockerfile_pattern>

Dockerfile テンプレート

FROM runpod/pytorch:2.1.0-py3.10-cuda12.1.1-devel-ubuntu22.04

WORKDIR /app

# Install dependencies (cached layer)
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

# Copy application
COPY . .

# RunPod entrypoint
CMD ["python", "-u", "handler.py"]

runpod.toml、requirements.txt のパターンについては reference/templates.md を参照してください。 </dockerfile_pattern>

<file_locations>

参照ファイル

コアパターン:

  • reference/serverless-workers.md - ハンドラーパターン、ストリーミング、非同期処理
  • reference/model-deployment.md - vLLM、TGI、HuggingFace のデプロイ
  • reference/pod-management.md - GPU タイプ、スケーリング、ライフサイクル

運用:

  • reference/cost-optimization.md - 予算管理、適正なリソース選定
  • reference/monitoring.md - ヘルスチェック、ロギング、GraphQL
  • reference/troubleshooting.md - よくある問題と解決策

DevOps:

  • reference/cicd.md - M1 Mac ビルド向けの GitHub Actions
  • reference/templates.md - Dockerfile、runpod.toml の設定
  • templates/runpod-worker.py - 本番環境向けハンドラーテンプレート </file_locations>
## リクエストの振り分け

ユーザーがサーバーレスデプロイを希望している場合: → ハンドラーパターン、Dockerfile、デプロイ手順を提示します → 参照先:reference/serverless-workers.md

ユーザーが vLLM エンドポイントを希望している場合: → vLLM の環境設定、OpenAI クライアントのセットアップを提示します → 参照先:reference/model-deployment.md

ユーザーがコスト最適化を希望している場合: → GPU 選択マトリックス、スポット価格、予算管理を提示します → 参照先:reference/cost-optimization.md

ユーザーが M1/M2 Mac を使用している場合: → 重要:ビルドには GitHub Actions を必ず使用する必要があります → 参照先:reference/cicd.md

ユーザーにデプロイの問題がある場合: → ヘルスエンドポイントを確認し、ログを確認します → 参照先:reference/troubleshooting.md

<cost_quick_ref>

コスト早見表

ストレージコスト:

  • コンテナディスク:$0.10/GB/月(5 分単位で課金)
  • ネットワークボリューム:最初の 1TB は $0.07/GB/月、その後は $0.05/GB

コスト見積もり:

def estimate_monthly_cost(gpu_type, daily_requests, avg_time_s):
    rates = {"RTX_4090": 0.44, "A40": 0.65, "A100_80GB": 1.89}
    daily_hours = (daily_requests * avg_time_s) / 3600
    return daily_hours * 30 * rates.get(gpu_type, 1.0)

# Example: 1000 requests/day, 5s each, RTX 4090
# = (1000 * 5) / 3600 * 30 * 0.44 = $18.33/month

</cost_quick_ref>

<cli_commands>

CLI コマンド早見表

# Install
pip install runpod

# Deploy endpoint
runpodctl project deploy --name my-endpoint --gpu-type "NVIDIA RTX 4090"

# Health check
runpod endpoint health ENDPOINT_ID

# View logs
runpod endpoint logs ENDPOINT_ID

# Scale workers
runpod endpoint scale ENDPOINT_ID --min 1 --max 10

# Local testing
python handler.py --rp_serve_api

</cli_commands>

<example_session>

セッション例

ユーザー:「Llama 3.1 8B モデルを RunPod のサーバーレスにデプロイする」

Claude:

  1. まず GPU を選択します。8B モデルは RTX 4090($0.44/hr)に収まります:
gpu_type = "NVIDIA GeForce RTX 4090"
  1. スループットを 2~3 倍にするには vLLM を使用します。次の設定でエンドポイントを作成します:
env = {
    "MODEL_NAME": "meta-llama/Llama-3.1-8B-Instruct",
    "MAX_MODEL_LEN": "8192",
    "GPU_MEMORY_UTILIZATION": "0.95",
}
  1. OpenAI 互換 API 経由でアクセスします:
from openai import OpenAI
client = OpenAI(
    api_key="YOUR_KEY",
    base_url="https://api.runpod.ai/v2/ENDPOINT_ID/openai/v1",
)
  1. コスト見積もり:コンピューティングは約 $0.44/hr、アイドル時はゼロまでスケールします。 </example_session>

結果サイドカーの出力

最後の手順として、~/.claude/skill-analytics/last-outcome-runpod-deployment.json に書き込みます:

{"ts":"[UTC ISO8601]","skill":"runpod-deployment","version":"1.0.0","variant":"default",
 "status":"[success|partial|error]","runtime_ms":[estimated ms from start],
 "metrics":{"pods_configured":[n],"deployments_created":[n]},
 "error":null,"session_id":"[YYYY-MM-DD]"}

一部のステージが失敗しても結果が生成された場合は、ステータスに "partial" を使用します。出力がまったく生成されなかった場合に限り、"error" を使用します。

コメント