name: debug-buttercup description: > 调试在Kubernetes上运行的Buttercup CRS(网络推理系统)。 当诊断crs命名空间中的pod崩溃、重启循环、Redis故障、资源压力、 磁盘饱和、DinD问题或任何服务行为异常时使用。 覆盖日志分析、队列检查、资源监控和常见故障模式的解决, 涉及服务: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。
调试Buttercup
使用时机
crs命名空间中的pod处于CrashLoopBackOff、OOMKilled或重启状态- 多个服务同时重启(级联故障)
- Redis无响应或显示AOF警告
- 队列增长但任务无进展
- 节点显示DiskPressure、MemoryPressure或PID压力
- Build-bot无法连接到Docker守护进程(DinD故障)
- Scheduler卡住且任务状态无进展
- 健康检查探针意外失败
- 部署的Helm值与实际pod配置不匹配
不使用时机
- 部署或升级Buttercup(使用Helm和部署指南)
- 调试
crsKubernetes命名空间外的问题 - 不涉及故障症状的性能调优
命名空间和服务
所有pod在crs命名空间中运行。关键服务:
| 层 | 服务 |
|---|---|
| 基础设施 | redis、dind、litellm、registry-cache |
| 编排 | scheduler、task-server、task-downloader、scratch-cleaner |
| 模糊测试 | build-bot、fuzzer-bot、coverage-bot、tracer-bot、merger-bot |
| 分析 | patcher、seed-gen、program-model、pov-reproducer |
| 界面 | competition-api、ui |
故障排除工作流
始终从故障排除开始。首先运行这三个命令:
# 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:'
# 检查实际资源限制与预期
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
历史问题与持续问题
高重启计数不一定意味着问题在持续——重启会在pod的整个生命周期累积。始终区分:
--tail显示日志缓冲区的末尾,可能包含旧消息。使用--since=300s确认问题当前正在发生。- 日志输出中的
--timestamps有助于跨服务关联事件。 - 检查
describe pod中的Last State时间戳,查看最近崩溃何时实际发生。
级联检测
当许多pod同时重启时,先检查共享依赖故障,再调查单个pod。最常见的级联:Redis宕机 -> 每个服务获得ConnectionError/ConnectionRefusedError -> 大规模重启。在多个--previous日志中寻找相同错误——如果它们都显示redis.exceptions.ConnectionError,调试Redis而非单个服务。
日志分析
# 同时查看服务的所有副本
kubectl logs -n crs -l app=fuzzer-bot --tail=100 --prefix
# 实时流式日志
kubectl logs -n crs -l app.kubernetes.io/name=redis -f
# 收集所有日志到磁盘(现有脚本)
bash deployment/collect-logs.sh
资源压力
# 每个pod的CPU/内存
kubectl top pods -n crs
# 节点级别
kubectl top nodes
# 节点条件(磁盘压力、内存压力、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 # 总键数
# 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/
队列检查
Buttercup使用带有消费者组的Redis流。队列名称:
| 队列 | 流键 |
|---|---|
| 构建 | fuzzer_build_queue |
| 构建输出 | fuzzer_build_output_queue |
| 崩溃 | fuzzer_crash_queue |
| 确认漏洞 | confirmed_vulnerabilities_queue |
| 下载任务 | orchestrator_download_tasks_queue |
| 就绪任务 | tasks_ready_queue |
| 补丁 | patches_queue |
| 索引 | index_queue |
| 索引输出 | index_output_queue |
| 追踪漏洞 | traced_vulnerabilities_queue |
| POV请求 | pov_reproducer_requests_queue |
| POV响应 | pov_reproducer_responses_queue |
| 删除任务 | orchestrator_delete_task_queue |
# 检查流长度(待处理消息)
kubectl exec -n crs <redis-pod> -- redis-cli XLEN fuzzer_build_queue
# 检查消费者组延迟
kubectl exec -n crs <redis-pod> -- redis-cli XINFO GROUPS fuzzer_build_queue
# 检查每个消费者的待处理消息
kubectl exec -n crs <redis-pod> -- redis-cli XPENDING fuzzer_build_queue build_bot_consumers - + 10
# 任务注册表大小
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
消费者组:build_bot_consumers、orchestrator_group、patcher_group、index_group、tracer_bot_group。
健康检查
Pod将时间戳写入/tmp/health_check_alive。活动探针检查文件新鲜度。
# 检查健康文件新鲜度
kubectl exec -n crs <pod> -- stat /tmp/health_check_alive
kubectl exec -n crs <pod> -- cat /tmp/health_check_alive
如果pod重启循环,健康检查文件可能因主进程阻塞(例如等待Redis、I/O卡住)而过期。
遥测(OpenTelemetry / Signoz)
所有服务通过OpenTelemetry导出跟踪和指标。如果Signoz已部署(global.signoz.deployed: true),使用其UI进行跨服务的分布式跟踪。
# 检查OTEL是否配置
kubectl exec -n crs <pod> -- env | grep OTEL
# 验证Signoz pod在运行(如果已部署)
kubectl get pods -n platform -l app.kubernetes.io/name=signoz
跟踪对于诊断慢任务处理、识别流水线中的瓶颈以及跨调度器 -> build-bot -> fuzzer-bot链关联事件特别有用。
卷和存储
# 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。
部署配置验证
当行为与预期不符时,验证Helm值是否实际生效:
# 检查pod的实际资源限制
kubectl get pod -n crs <pod-name> -o jsonpath='{.spec.containers[0].resources}'
# 检查pod的实际卷定义
kubectl get pod -n crs <pod-name> -o jsonpath='{.spec.volumes}'
Helm值模板错字(例如错误键名)会静默回退到图表默认值。如果部署资源与值模板不匹配,检查键名不匹配。
服务特定调试
详细的服务特定症状、根本原因和修复,请参阅references/failure-patterns.md。
快速参考:
- DinD:
kubectl logs -n crs -l app=dind --tail=100– 查找docker守护进程崩溃、存储驱动错误 - Build-bot:检查构建队列深度、DinD连接性、编译期间OOM
- Fuzzer-bot:corpus磁盘使用情况、CPU限制、崩溃队列积压
- Patcher:LiteLLM连接性、LLM超时、补丁队列深度
- Scheduler:中央大脑 –
kubectl logs -n crs -l app=scheduler --tail=-1 --prefix | grep "WAIT_PATCH_PASS\|ERROR\|SUBMIT"
诊断脚本
运行自动化故障排除快照:
bash {baseDir}/scripts/diagnose.sh
传递--full以同时转储所有pod的最近日志:
bash {baseDir}/scripts/diagnose.sh --full
此操作在一次运行中收集pod状态、事件、资源使用情况、Redis健康和队列深度。