
debug-buttercup
熱門除錯在 Kubernetes 上運行的 Buttercup CRS(Cyber Reasoning System,網路推理系統)。適用於診斷 crs 命名空間中的 Pod 當機、無限重啟(restart loop)、Redis 故障、資源壓力、磁碟滿載、DinD(Docker-in-Docker)問題或任何服務異常行為。涵蓋初篩排查(triage)、日誌分析、佇列檢查,以及以下服務的常見故障模式:redis、fuzzer-bot、coverage-bot、seed-gen、patcher、build-bot、scheduler、task-server、task-downloader、program-model、litellm、dind、tracer-bot、merger-bot、competition-api、pov-reproducer、scratch-cleaner、registry-cache、image-preloader、ui。
除錯在 Kubernetes 上運行的 Buttercup CRS(Cyber Reasoning System,網路推理系統)。適用於診斷 crs 命名空間中的 Pod 當機、無限重啟(restart loop)、Redis 故障、資源壓力、磁碟滿載、DinD(Docker-in-Docker)問題或任何服務異常行為。涵蓋初篩排查(triage)、日誌分析、佇列檢查,以及以下服務的常見故障模式:redis、fuzzer-bot、coverage-bot、seed-gen、patcher、build-bot、scheduler、task-server、task-downloader、program-model、litellm、dind、tracer-bot、merger-bot、competition-api、pov-reproducer、scratch-cleaner、registry-cache、image-preloader、ui。
Debug Buttercup
何時使用
crs命名空間中的 Pod 處於 CrashLoopBackOff、OOMKilled 或不斷重啟- 多個服務同時重啟(連鎖故障 / 串聯失效 cascade failure)
- Redis 無回應或顯示 AOF 警告
- 佇列(Queue)持續堆積但任務完全沒有推進
- 節點顯示 DiskPressure、MemoryPressure 或 PID pressure
- Build-bot 無法連線至 Docker 守護程式(DinD 故障)
- Scheduler 卡住且未推進任務狀態
- 健康檢查探針(Health check probes)意外失敗
- 已部署的 Helm values 與實際的 Pod 設定不符
何時「不」使用
- 部署或升級 Buttercup(請使用 Helm 和部署指南)
- 除錯
crsKubernetes 命名空間之外的問題 - 不涉及故障症狀的效能調優
命名空間與服務
所有 Pod 均運行於命名空間 crs。核心服務:
| 層級 | 服務 |
|---|---|
| Infra | redis, dind, litellm, registry-cache |
| Orchestration | scheduler, task-server, task-downloader, scratch-cleaner |
| Fuzzing | build-bot, fuzzer-bot, coverage-bot, tracer-bot, merger-bot |
| Analysis | patcher, seed-gen, program-model, pov-reproducer |
| Interface | competition-api, ui |
初篩排查流程(Triage Workflow)
務必從初篩排查(Triage)開始。首先執行以下三條指令:
# 1. Pod 狀態 - 檢查重啟次數、CrashLoopBackOff、OOMKilled
kubectl get pods -n crs -o wide
# 2. 事件 - 故障發生的時間軸
kubectl get events -n crs --sort-by='.lastTimestamp'
# 3. 僅限警告 - 過濾掉干擾訊息
kubectl get events -n crs --field-selector type=Warning --sort-by='.lastTimestamp'
接著進一步縮小範圍:
# 為何特定 Pod 會重啟?檢查 Last State Reason(OOMKilled、Error、Completed)
kubectl describe pod -n crs <pod-name> | grep -A8 'Last State:'
# 檢查實際資源限制 vs 預期設定
kubectl get pod -n crs <pod-name> -o jsonpath='{.spec.containers[0].resources}'
# 崩潰容器的日誌(--previous = 已死亡的容器)
kubectl logs -n crs <pod-name> --previous --tail=200
# 當前日誌
kubectl logs -n crs <pod-name> --tail=200
歷史問題 vs 當前進行中的問題
高重啟次數並不一定代表問題仍在持續進行——重啟次數會在 Pod 的生命週期內累計。請務必區分:
--tail會顯示日誌緩衝區的末尾,可能包含舊訊息。請使用--since=300s來確認問題是否在當前持續發生。- 在日誌輸出加上
--timestamps有助於比對不同服務之間的事件時間關聯。 - 檢查
describe pod中的Last State時間戳記,以查看最近一次崩潰發生的確切時間。
連鎖故障檢測(Cascade Detection)
當許多 Pod 在大約同一時間重啟時,在調查單一 Pod 之前,請先檢查是否有共享相依性故障(shared-dependency failure)。最常見的連鎖故障為:Redis 倒下 -> 每個服務都收到 ConnectionError/ConnectionRefusedError -> 引發大規模重啟。請在多個 --previous 日誌中尋找相同的錯誤訊息——如果全部都顯示 redis.exceptions.ConnectionError,請除錯 Redis 本身,而不是各個單獨的服務。
日誌分析
# 一次查看某個服務的所有副本 (Replicas)
kubectl logs -n crs -l app=fuzzer-bot --tail=100 --prefix
# 即時串流查看 (Stream live)
kubectl logs -n crs -l app.kubernetes.io/name=redis -f
# 收集所有日誌至磁碟(使用既有指令稿)
bash deployment/collect-logs.sh
資源壓力
# 個別 Pod 的 CPU / 記憶體使用量
kubectl top pods -n crs
# 節點層級 (Node-level)
kubectl top nodes
# 節點狀態(磁碟壓力 DiskPressure、記憶體壓力 MemoryPressure、PID 壓力)
kubectl describe node <node> | grep -A5 Conditions
# Pod 內部的磁碟使用量
kubectl exec -n crs <pod> -- df -h
# 什麼東西佔用了磁碟空間
kubectl exec -n crs <pod> -- sh -c 'du -sh /corpus/* 2>/dev/null'
kubectl exec -n crs <pod> -- sh -c 'du -sh /scratch/* 2>/dev/null'
Redis 除錯
Redis 是核心骨幹。當它倒下時,所有服務都會產生連鎖反應。
# Redis Pod 狀態
kubectl get pods -n crs -l app.kubernetes.io/name=redis
# Redis 日誌(AOF 警告、OOM、連線問題)
kubectl logs -n crs -l app.kubernetes.io/name=redis --tail=200
# 連線至 Redis CLI
kubectl exec -n crs <redis-pod> -- redis-cli
# 在 redis-cli 內部:關鍵診斷指令
INFO memory # used_memory_human, maxmemory
INFO persistence # aof_enabled, aof_last_bgrewrite_status, aof_delayed_fsync
INFO clients # connected_clients, blocked_clients
INFO stats # total_connections_received, rejected_connections
CLIENT LIST # 查看有哪些連線
DBSIZE # Key 總數
# AOF 設定
CONFIG GET appendonly # 是否啟用 AOF?
CONFIG GET appendfsync # fsync 策略:everysec, always, 或 no
# /data 掛載在哪裡?(磁碟 vs tmpfs 對 AOF 效能有重大影響)
kubectl exec -n crs <redis-pod> -- mount | grep /data
kubectl exec -n crs <redis-pod> -- du -sh /data/
佇列檢查(Queue Inspection)
Buttercup 使用帶有 Consumer Group 的 Redis Streams。佇列名稱:
| 佇列 | Stream Key |
|---|---|
| Build | fuzzer_build_queue |
| Build Output | fuzzer_build_output_queue |
| Crash | fuzzer_crash_queue |
| Confirmed Vulns | confirmed_vulnerabilities_queue |
| Download Tasks | orchestrator_download_tasks_queue |
| Ready Tasks | tasks_ready_queue |
| Patches | patches_queue |
| Index | index_queue |
| Index Output | index_output_queue |
| Traced Vulns | traced_vulnerabilities_queue |
| POV Requests | pov_reproducer_requests_queue |
| POV Responses | pov_reproducer_responses_queue |
| Delete Task | orchestrator_delete_task_queue |
# 檢查 Stream 長度(待處理訊息數量)
kubectl exec -n crs <redis-pod> -- redis-cli XLEN fuzzer_build_queue
# 檢查 Consumer Group 的延遲(Lag)
kubectl exec -n crs <redis-pod> -- redis-cli XINFO GROUPS fuzzer_build_queue
# 檢查每個 Consumer 的待處理訊息(Pending Messages)
kubectl exec -n crs <redis-pod> -- redis-cli XPENDING fuzzer_build_queue build_bot_consumers - + 10
# 任務登錄表 (Task Registry) 大小
kubectl exec -n crs <redis-pod> -- redis-cli HLEN tasks_registry
# 各任務狀態的計數
kubectl exec -n crs <redis-pod> -- redis-cli SCARD cancelled_tasks
kubectl exec -n crs <redis-pod> -- redis-cli SCARD succeeded_tasks
kubectl exec -n crs <redis-pod> -- redis-cli SCARD errored_tasks
Consumer groups: build_bot_consumers, orchestrator_group, patcher_group, index_group, tracer_bot_group。
健康檢查(Health Checks)
Pod 會將時間戳記寫入 /tmp/health_check_alive。Liveness probe 會檢查該檔案的新鮮度。
# 檢查健康檔案的新鮮度
kubectl exec -n crs <pod> -- stat /tmp/health_check_alive
kubectl exec -n crs <pod> -- cat /tmp/health_check_alive
如果 Pod 陷入不斷重啟的迴圈(restart-looping),通常是因為主程序被阻塞(例如在等待 Redis 或卡在 I/O),導致健康檢查檔案無法更新而逾期。
遙測(Telemetry - OpenTelemetry / Signoz)
所有服務皆透過 OpenTelemetry 匯出追蹤(Traces)與指標(Metrics)。若已部署 Signoz(global.signoz.deployed: true),可使用其 UI 進行跨服務的分散式追蹤(distributed tracing)。
# 檢查是否已設定 OTEL
kubectl exec -n crs <pod> -- env | grep OTEL
# 確認 Signoz Pod 是否正在運行(若已部署)
kubectl get pods -n platform -l app.kubernetes.io/name=signoz
追蹤功能對於診斷慢速任務處理、找出流水線中哪個服務是瓶頸,以及比對 scheduler -> build-bot -> fuzzer-bot 鏈結中的跨服務事件特別有用。
磁碟區與儲存(Volume and Storage)
# PVC 狀態
kubectl get pvc -n crs
# 檢查 corpus tmpfs 是否已掛載、其容量大小以及備援類型
kubectl exec -n crs <pod> -- mount | grep corpus_tmpfs
kubectl exec -n crs <pod> -- df -h /corpus_tmpfs 2>/dev/null
# 檢查是否已設定 CORPUS_TMPFS_PATH
kubectl exec -n crs <pod> -- env | grep CORPUS
# 完整磁碟配置 - 實體磁碟 vs tmpfs
kubectl exec -n crs <pod> -- df -h
當 global.volumes.corpusTmpfs.enabled: true 時會設定 CORPUS_TMPFS_PATH。這會影響 fuzzer-bot、coverage-bot、seed-gen 和 merger-bot。
部署設定驗證(Deployment Config Verification)
當行為與預期不符時,請驗證 Helm values 是否確實生效:
# 檢查 Pod 的實際資源限制
kubectl get pod -n crs <pod-name> -o jsonpath='{.spec.containers[0].resources}'
# 檢查 Pod 的實際 Volume 定義
kubectl get pod -n crs <pod-name> -o jsonpath='{.spec.volumes}'
Helm values 樣板打字錯誤(例如 Key 名稱錯誤)會默默退回(fallback)至 Chart 的預設值。如果部署的資源與 values 樣板不符合,請檢查 Key 名稱是否對不上。
特定服務的除錯
關於個別服務的詳細症狀、根本原因與修復方法,請參閱 references/failure-patterns.md。
快速參考:
- DinD:
kubectl logs -n crs -l app=dind --tail=100-- 尋找 docker daemon 當機、儲存驅動程式錯誤 - Build-bot:檢查 build 佇列深度、DinD 連線能力、編譯期間的 OOM
- Fuzzer-bot:corpus 磁碟使用量、CPU 節流限制(throttling)、crash 佇列積壓
- Patcher:LiteLLM 連線能力、LLM 逾時、patch 佇列深度
- Scheduler:中央大腦 --
kubectl logs -n crs -l app=scheduler --tail=-1 --prefix | grep "WAIT_PATCH_PASS\|ERROR\|SUBMIT"
診斷腳本(Diagnostic Script)
執行自動化初篩快照:
bash {baseDir}/scripts/diagnose.sh
傳入 --full 可一併傾印(dump)所有 Pod 最近的日誌:
bash {baseDir}/scripts/diagnose.sh --full
這會在單一流程中收集 Pod 狀態、事件、資源使用量、Redis 健康狀況以及佇列深度。





