debug-buttercup

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。

6336星標
545分支
更新於 2026/7/30
SKILL.md
唯讀
名稱
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。

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 和部署指南)
  • 除錯 crs Kubernetes 命名空間之外的問題
  • 不涉及故障症狀的效能調優

命名空間與服務

所有 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

快速參考:

  • DinDkubectl 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 健康狀況以及佇列深度。