
2026/02/23 17:53
Show HN: 音声・映像テスト用の「Chaos Monkey」(WebRTC と UDP)
RSS: https://news.ycombinator.com/rss
要約▶
Japanese Translation:
改訂概要:
AV Chaos Monkey は、1,500 人以上の WebRTC 参加者が H.264 ビデオと Opus オーディオをストリーミングしながら、パケットロス、ジッタ、ビットレート低下、フレームドロップなどのリアルなネットワーク障害を注入するスケーラブルなカオスエンジニアリングプラットフォームです。 Spike Scheduler と Network Degrader を構成可能にし、FFmpeg でメディア変換、NAL/Opus リーダー、およびメモリキャッシュされたフレームを利用して CPU 使用率を約90 %削減します。
Kubernetes 上では、各 Pod が自動的にパーティション ID(
participant_id % total_partitions)を検出し、base_port + (partition_id × 10000) + participant_index を使用してポートを割り当てます。 StatefulSet として最大10 レプリカで実行され、各レプリカが約150 人の参加者を処理します。 UDP リレー チェーンは数千の RTP ストリームを長さプレフィックス付き TCP(:5001)に集約し、効率的な転送を実現した後、Go ツールでそれらを UDP(:5002)に戻します。
Coturn TURN サーバー(初期は3 レプリカ、HPA で1〜10へスケーリング)は STUN/TURN をサポートし、オプションの webrtc‑connector が SDP シグナリングを処理します。 観測性は Prometheus による
/metrics の5 秒ごとのスクレイピングと Grafana ダッシュボードで有効化され、参加者数、送信パケット/バイト数、アクティブスパイク、パケットロス %、ジッタ、および MOS スコアを表示します。
REST API はテストライフサイクル(
/api/v1/test/{id}/start、/stop など)、SDP 交換、スパイク注入のエンドポイントを公開します。設定は config/config.json により行われ、ユーザーはメディアパス、参加者数、期間、スパイク種別/件数、分布戦略(even/random/front/back/legacy)、ジッタパラメータを指定できます。リソース要件は参加者に応じてスケールし、約100 人で 2 GB RAM と 2 CPU コア、1,500 人では最大約18 GB RAM と 24 CPU コアが必要です。
この現実的なテストベッドにより、メディアストリーミングプラットフォームは本番展開前に CPU、メモリ、またはネットワークのボトルネックを特定できるため、ライブストリーミングおよび通信サービスの信頼性が向上します。
本文
AV Chaos Monkey – 分散型カオスエンジニアリングプラットフォーム
概要
1500 以上の WebRTC パーティシパント(H.264 ビデオ + Opus オーディオ)をシミュレートし、ネットワーク上にカオスを注入してビデオ会議システムの耐久性を検証するロードテストフレームワークです。
アーキテクチャ
メディア処理パイプライン
| コンポーネント | 機能 |
|---|---|
| FFmpeg | 入力ビデオを H.264 Annex‑B へ変換、起動時に Ogg/Opus オーディオへ |
| NAL Reader | H.264 ストリーム(SPS/PPS/IDR/Slices)を解析 |
| Opus Reader | Ogg コンテナから 20 ms のオーディオフレームを抽出 |
| Cache | フレームはメモリにキャッシュされ、全パーティシパントで共有(ゼロコピー)→ CPU 負荷約 90 % 削減 |
コントロールプレーン
- HTTP サーバー (
) – テストライフサイクル用 REST API:8080 - Spike Scheduler – カオスイベントを配布(均等、ランダム、前方集中・後方集中、レガシー)
- Network Degrader – パケットロス (1–25 %)、ジッタ (10–50 ms)、ビットレート低減 (30–80 %)、フレームドロップ (10–60 %) を適用
パーティシパントプール
- ポッドごとに自動分割:
participant_id % total_partitions = partition_id - 各パーティシパントは RTP (
ビデオ、PT=96
オーディオ) をストリームし、RTP 拡張ヘッダーに ID を埋め込み (PT=111
)ID=1 - プールサイズ – 1–100(ローカル)、100–500(Docker)、500–1500(Kubernetes)
Kubernetes 自動構成
| 機能 | 詳細 |
|---|---|
| Partition ID の検出 | ポッド名から () |
| ポート割り当て | |
| 例 | パーティション 0: ポート 5000‑14999、パーティション 1: 15000‑24999 |
| StatefulSet | 10 レプリカ;各レプリカ ≈150 パーティシパント |
| リソース | 1–4 CPU、2–4 GiB メモリ/ポッド(ホストスペックに応じて自動スケール) |
UDP Relay チェーン (Kubernetes 専用)
Orchestrator Pods (10×) → UDP :5000 → Length‑Prefixed TCP :5001 → kubectl port‑forward 15001:5001 → tools/udp-relay (Go) → UDP :5002
理由:
kubectl port-forward は TCP のみをサポート。クラスタ内リレーは UDP を単一の TCP ストリームにまとめ、先頭 2 バイトで長さを付与。
ローカルリレーはその TCP を再び UDP パケットへ変換。
WebRTC インフラストラクチャ
| コンポーネント | 詳細 |
|---|---|
| Coturn | StatefulSet(3 レプリカ、HPA 1–10) – TURN サーバ () |
| coturn‑lb | Service – TURN トラフィックをロードバランス |
| webrtc‑connector | オプションのプロキシ層 (Deployment + HPA 2–10) – SDP シグナリング |
| Docker Mode | ローカルテスト用に単一 Coturn コンテナ |
| Ports | 49152–65535 リレーレンジ |
| 認証情報 | |
クライアント統合
- UDP Receiver – Relay チェーン経由で全パーティシパントの RTP ストリームを集約。
- WebRTC Receiver – TURN を通じて 1:1 WebRTC 接続を確立し、最大150 パーティシパントに対応。
両者とも受信メディアをテスト対象(SFU/MCU/Mesh)へ転送します。
観測スタック (オプション)
| ツール | エンドポイント |
|---|---|
| Prometheus | を全オーケストレータポッドから 5 秒ごとにスクレイプ |
| Grafana | 事前構成済みダッシュボード () – NodePorts (Prometheus)、(Grafana) |
メトリクスにはパーティシパント数、送信パケット数、バイト数、アクティブな spike 数、パケットロス率、ジッタ、MOS スコア等が含まれます。
コアコンセプト
パーティシパントシミュレーション
- ビデオ: 実際のビデオファイルから H.264 NAL ユニットを生成し、RFC 6184 に従ってパケット化
- オーディオ: Ogg コンテナから Opus フレームを抽出し、RFC 7587 に従ってパケット化
- RTP ヘッダーにパーティシパント ID 拡張を付与
- フレーム単位の正確なタイミング(30 fps ビデオ、20 ms オーディオ)
カオス注入
| Spike タイプ | パラメータ | 効果 |
|---|---|---|
| (0–100) | アプリケーション層で RTP パケットをドロップ |
| , | レイテンシの変動を追加 |
| | ビデオエンコーディングをスロットル |
| (0–100) | ビデオフレームをスキップ |
| | 合計帯域幅を制限 |
配布戦略
- Even – 一様に間隔を空け、ジッタ付き
- Random – 予測不可能なタイミング
- Front‑loaded – 初期段階で密集した spike
- Back‑loaded – ベースライン後にカオス
- Legacy – 固定間隔のティック
システム実行方法
1. ローカル開発 (ネイティブ Go)
デバッグや小規模テスト(1–100 パーティシパント)に最適。
# オーケストレータ起動 go run cmd/main.go # 別ターミナルで UDP 受信機 go run examples/go/udp_receiver.go 5002 # config/config.json を編集 (num_participants: 10) # カオステスト実行 go run tools/chaos-test/main.go -config config/config.json
config/config.json
の例
config/config.json{ "base_url": "http://localhost:8080", "media_path": "public/rick-roll.mp4", "num_participants": 10, "duration_seconds": 300, "spikes": { "count": 20, "interval_seconds": 5, "types": { "rtp_packet_loss": { /* params */ }, "network_jitter": { /* params */ } } }, "spike_distribution": { "strategy": "random", "min_spacing_seconds": 5, "jitter_percent": 15 } }
2. Docker Compose (コンテナ化)
単体でのテスト、CI/CD、ミドルスケール(100–500 パーティシパント)に最適。
# オーケストレータコンテナをビルド&起動 ./scripts/start_everything.sh build # 別ターミナルで UDP 受信機 go run examples/go/udp_receiver.go 5002 # config/config.json を編集 (num_participants: 100) # コンテナ対象にカオステスト実行 go run tools/chaos-test/main.go -config config/config.json
docker-compose.yaml
のリソース制限例
docker-compose.yamlservices: orchestrator: deploy: resources: limits: cpus: "14.0" memory: 6G # より多くのパーティシパントが必要な場合は増量
| Docker メモリ | 最大パーティシパント数 | CPU コア |
|---|---|---|
| 8 GB | ~100 | 4 |
| 16 GB | ~250 | 8 |
| 24 GB | ~400 | 12 |
| 32 GB | ~500 | 14 |
3. Kubernetes + Nix (本番規模)
大規模テスト(500–1500 パーティシパント)に最適。
# Nix 環境へ入る nix develop # Kubernetes にデプロイ(システムリソースを自動検知) ./scripts/start_everything.sh run -config config/config.json
Go ツールチェーンで Docker イメージをビルド → kind クラスター → 10 オーケストレータポッド + UDP リレー → port‑forward → ローカル TCP→UDP リレー。
集約ストリームの受信
# UDP 受信機(Kubernetes 推奨) go run ./examples/go/udp_receiver.go 5002 # WebRTC 受信機(最大150 パーティシパント) go run ./examples/go/webrtc_receiver.go http://localhost:8080 <test_id> 150
API リファレンス
テストライフサイクル
| エンドポイント | メソッド | 説明 |
|---|---|---|
| POST | テスト作成(任意で ) |
| POST | テスト開始 |
| GET | メトリクス取得 |
| POST | テスト停止 |
WebRTC シグナリング
| エンドポイント | メソッド | 説明 |
|---|---|---|
| GET | SDP オファー取得 |
| POST | SDP アンサー設定 ( |
カオス注入
POST /api/v1/test/{test_id}/spike { "spike_id": "unique_id", "type": "rtp_packet_loss", "duration_seconds": 30, "participant_ids": [1001, 1002], "params": { "loss_percentage": "15" } }
クライアント統合
UDP Receiver (Go)
go run examples/go/udp_receiver.go 5002
RTP パケットを解析し、統計情報を表示。
WebRTC Receiver (Go)
# 単一パーティシパント go run ./examples/go/webrtc_receiver.go http://localhost:8080 <test_id> # 複数パーティシパント(最大150) go run ./examples/go/webrtc_receiver.go http://localhost:8080 <test_id> 150
パフォーマンス & スケーリング
| パーティシパント | メモリ | CPU | 帯域幅 |
|---|---|---|---|
| 100 | 2 GB | 2 コア | 250 Mbps |
| 500 | 6 GB | 8 コア | 1.2 Gbps |
| 1000 | 12 GB | 16 コア | 2.5 Gbps |
| 1500 | 18 GB | 24 コア | 3.7 Gbps |
1 パーティシパントあたり (1280×720 @30fps + Opus): 約 2.6 Mbps、約 140 パケット/秒。
トラブルシューティング
| 問題 | チェック / 対処 |
|---|---|
| UDP パケットが届かない | リレーが稼働しているか確認 ()、port‑forward をチェック、 で接続確認。 |
| WebRTC 接続失敗 | TURN サービス () が到達可能か、ICE 候補を確認。 |
| メモリ使用量が高い | からパーティシパント数を確認し、ポッド数を増減。 |
ライセンス
BSD 3‑Clause