高セキュリティなコードエージェントのための VM 分離
gVisor、Firecracker microVM、ハードウェアレベルの分離をエージェントに適用します。
「高セキュリティなコードエージェントのための VM 分離」はCoddyKit上の無料AI Agentsレッスンです。 これはレッスン2/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはAI Agents学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 AI Agentsコースには全4レッスンが含まれています。
Dockerを超えて強固な分離へ
標準のDockerコンテナはホストのカーネルを共有します。コンテナ内でカーネルの脆弱性が悪用されると、ホストへ脱出される可能性があります。高セキュリティのコード実行には、より強固な分離レイヤーが必要です。
主なアプローチは2つあります。gVisor(ユーザー空間のカーネルプロキシ)とFirecracker(軽量なmicroVM)です。
gVisorの仕組み
gVisorは、Sentryというユーザー空間コンポーネントをコンテナとホストカーネルの間に挿入します。コンテナのシステムコールはSentryに送られ、実際のカーネルではなくGoで安全なサブセットが再実装されます。
ランタイムはrunsc(run sandboxed container)と呼ばれます。
# Configure Docker to use gVisor runtime (runsc)
# /etc/docker/daemon.json:
# {
# "runtimes": {
# "runsc": { "path": "/usr/local/bin/runsc" }
# }
# }
import docker
client = docker.from_env()
output = client.containers.run(
'python:3.12-slim',
'python -c "print(\"hello from gVisor\")"',
runtime='runsc', # use gVisor
network_disabled=True,
auto_remove=True
)
print(output.decode())gVisorによるシステムコールのインターセプト
コンテナ内のコードがopen()、read()、socket()を呼び出すと、gVisorがシステムコールをインターセプトし、許可、エミュレート、拒否のいずれかを判断します。
ptraceやRawソケットの作成など、機密性の高いシステムコールはデフォルトでブロックされ、一般的な攻撃経路が塞がれます。
# gVisor blocks dangerous syscalls like ptrace.
# This code would fail inside a gVisor container:
#
# import ctypes
# libc = ctypes.CDLL(None)
# libc.ptrace(...) # EPERM: Operation not permitted
#
# Normal Python I/O and computation works fine:
# open(), read(), write(), socket() (if network enabled)
# are all emulated safely by Sentry.
print('gVisor intercepts syscalls before they reach the host kernel')gVisorのパフォーマンス上のトレードオフ
すべてのシステムコールは、カーネルに直接送られるのではなくSentryを経由します。そのため、I/O負荷の高いワークロードでは約10~30%のオーバーヘッドが発生します。CPUバウンドの計算では、オーバーヘッドははるかに小さくなります。
起動時間は通常のDockerと同程度で、数ミリ秒です。
import time
import docker
client = docker.from_env()
start = time.time()
client.containers.run('python:3.12-slim', 'python -c "pass"',
runtime='runsc', auto_remove=True)
print(f'gVisor startup: {time.time()-start:.2f}s') # ~0.3-0.8s
start = time.time()
client.containers.run('python:3.12-slim', 'python -c "pass"',
auto_remove=True)
print(f'Docker startup: {time.time()-start:.2f}s') # ~0.1-0.3sFirecracker microVM
Firecrackerはまったく異なるアプローチを採用しています。各ワークロードを独自のカーネルを持つ完全な仮想マシンで実行します。VMは約50msで起動し、オーバーヘッドメモリはわずか約5MBです。
VMは完全に分離されたカーネルを持つため、共有カーネルに対する攻撃対象領域がありません。
# Firecracker is controlled via a REST API on a Unix socket.
# Python SDK example (firecracker-python-sdk or direct HTTP):
import requests_unixsocket
session = requests_unixsocket.Session()
base = 'http+unix://%2Ftmp%2Ffirecracker.socket'
# Boot the microVM
session.put(f'{base}/boot-source', json={
'kernel_image_path': '/opt/kernel/vmlinux',
'boot_args': 'console=ttyS0 reboot=k panic=1 pci=off'
})
session.put(f'{base}/actions', json={'action_type': 'InstanceStart'})
print('MicroVM booted in ~50ms')Firecrackerのセキュリティモデル
FirecrackerのVMは、設計上、攻撃対象領域を最小限に抑えています。VMMが公開するデバイスタイプは5種類(virtio-net、virtio-block、serial、RTC、keyboard)だけです。USB、PCIバス、BIOSはありません。
各VMはハイパーバイザーレベルで分離されているため、VM内でカーネルが悪用されてもホストには到達できません。
# Firecracker security properties:
# 1. Each microVM has its own Linux kernel instance
# 2. Guest-to-host attack surface is tiny (5 device types)
# 3. The VMM (Virtual Machine Monitor) runs unprivileged
# 4. No shared memory between VMs
# 5. Snapshot/restore: freeze a running VM, clone it for next request
# Used in production by:
# - AWS Lambda (each function invocation = Firecracker microVM)
# - Fly.io (each app container)
# - Replit (code execution)
print('Firecracker: full VM isolation at container startup speed')Kata Containers:両方のアプローチの融合
Kata Containersは軽量なVM(FirecrackerまたはQEMUを使用可能)を利用しながら、標準のOCIコンテナインターフェースを公開します。通常のDockerコマンドを実行すれば、KataがVMレイヤーを透過的に処理します。
import docker
client = docker.from_env()
# Kata Containers registered as 'kata-runtime' in daemon.json
output = client.containers.run(
'python:3.12-slim',
'python -c "import platform; print(platform.node())"',
runtime='kata-runtime', # each container = a VM
mem_limit='256m',
network_disabled=True,
auto_remove=True
)
print(output.decode()) # unique VM hostname適切な分離レベルの選択
適切なサンドボックスは、脅威モデルと許容できるレイテンシによって決まります。
- Docker (runc):高速でオーバーヘッドが小さい一方、カーネルを共有します。信頼できるコードや、軽くフィルタリングしたコードに適しています
- gVisor (runsc):システムコールのフィルタリング、同じイメージ形式、軽微なオーバーヘッドを提供します。バランスのよい選択肢です
- Firecracker/Kata:完全なVM分離と50msの起動時間を提供します。大規模な信頼できないユーザーコードの実行に適しています
セキュリティと起動レイテンシの比較表
分離の深さと起動速度には反比例の関係があります。エージェントのユースケースで許容できるレイテンシに基づいて選択してください。
# Isolation vs Latency summary:
#
# Runtime | Isolation | Startup | Overhead
# -----------------|---------------|----------|----------
# runc (Docker) | Namespace | ~100ms | ~0%
# gVisor (runsc) | Syscall filter | ~300ms | ~15-30%
# Kata Containers | Full VM | ~500ms | ~10%
# Firecracker | Full VM | ~50ms | ~5%
# QEMU KVM | Full VM | ~1-2s | ~5%
#
# For interactive agent tools: gVisor is usually the sweet spot.
# For high-throughput batch jobs: Firecracker snapshots.
ISOLATION_OPTIONS = {
'runc (Docker)': {'isolation': 'Namespace', 'startup': '~100ms', 'overhead': '~0%'},
'gVisor (runsc)': {'isolation': 'Syscall filter', 'startup': '~300ms', 'overhead': '~15-30%'},
'Kata Containers': {'isolation': 'Full VM', 'startup': '~500ms', 'overhead': '~10%'},
'Firecracker': {'isolation': 'Full VM', 'startup': '~50ms', 'overhead': '~5%'},
'QEMU KVM': {'isolation': 'Full VM', 'startup': '~1-2s', 'overhead': '~5%'},
}
for runtime, info in ISOLATION_OPTIONS.items():
print(f"{runtime:<17} | {info['isolation']:<14} | startup {info['startup']:<7} | overhead {info['overhead']}")
サンドボックスの事前起動
エージェントのリクエストごとにVMをコールドスタートすると、レイテンシが増加します。本番システムでは、アイドル状態のサンドボックスのプールを事前に起動しておきます。リクエストが到着すると、起動済みのサンドボックスを割り当てて使用し、その後破棄します(再利用は決してしません)。
import queue, threading
SANDBOX_POOL_SIZE = 5
pool = queue.Queue()
def pre_warm():
'Start a sandbox and put it in the pool.'
container = client.containers.create(
'python:3.12-slim',
'tail -f /dev/null',
runtime='runsc',
mem_limit='256m',
network_disabled=True
)
container.start()
pool.put(container)
# Pre-warm the pool at startup
for _ in range(SANDBOX_POOL_SIZE):
threading.Thread(target=pre_warm, daemon=True).start()
def claim_sandbox():
return pool.get(timeout=5) # blocks until one is readyスケールのためのスナップショットと復元
Firecrackerは、実行中のVMをディスクにスナップショット保存できます。スナップショットには、メモリ状態、デバイス状態、CPUレジスタが記録されます。スナップショットからの復元は約10msで完了し、コールドブートよりはるかに高速です。
この方法を使えば、Pythonインタープリタを一度初期化してスナップショットを保存し、リクエストごとに復元できます。
# Firecracker snapshot workflow:
# 1. Boot microVM, run Python interpreter, wait for REPL ready
# 2. Pause VM
# 3. Create snapshot
# PUT /snapshot/create { snapshot_path, mem_file_path }
# 4. For each request:
# PUT /snapshot/load { snapshot_path, mem_file_path }
# # VM resumes from paused state with Python already loaded
# # Send code via stdin/virtio-serial, read output
# 5. Discard VM after request (never reuse)
print('Snapshot restore: ~10ms vs 50ms cold boot for Firecracker')gVisorがコンテナとホストカーネルの間に挿入するコンポーネントはどれですか
gVisorの分離モデルは、システムコールをインターセプトする特定のコンポーネントに依存しています。このアーキテクチャを理解することは、セキュリティ上の保証を評価するうえで重要です。
VM分離のまとめ
高セキュリティのエージェントコード実行では、標準のDockerからgVisor(システムコールのインターセプト、低オーバーヘッド)またはFirecracker(完全なVM、50msの起動時間、約5MBのオーバーヘッド)へ移行します。
トレードオフは常に分離の深さと起動レイテンシの間にあります。本番環境では、事前起動プールとVMスナップショットによって、レイテンシのコストの大部分を取り戻せます。
よくある質問
「高セキュリティなコードエージェントのための VM 分離」レッスンは無料ですか?
はい。「高セキュリティなコードエージェントのための VM 分離」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、AI Agentsコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 AI Agentsコースには全4レッスンが含まれています。
「高セキュリティなコードエージェントのための VM 分離」で何を学びますか?
gVisor、Firecracker microVM、ハードウェアレベルの分離をエージェントに適用します。 ブラウザで直接実行するハンズオンコードでAI Agentsを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。
AI Agentsを始めるのに経験は必要ですか?
事前経験は必要ありません。CoddyKitのAI Agentsは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン2/4です。
「高セキュリティなコードエージェントのための VM 分離」レッスンにはどのくらい時間がかかりますか?
ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。
このAI Agentsレッスンでコードを書いて実行できますか?
はい。すべてのAI Agentsレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。
このコースのすべてのレッスン
- Docker ベースのエージェントサンドボックス
- 高セキュリティなコードエージェントのための VM 分離
- E2B とクラウドサンドボックスサービス
- コード実行のセキュリティポリシー