LOG SEARCH & ANALYTICS · 从入门到专家
Splunk 是一个机器数据平台。它的核心使命是:采集任意来源的机器数据(日志、指标、配置文件、API 返回……),实时索引,然后让你用一套强大的搜索语言(SPL)去查询、分析和可视化这些数据。
和其他监控工具的关键区别:Splunk 是通用索引引擎——你不必预定义 Schema,数据是什么样 Splunk 就存什么样,搜索时才动态提取字段。这意味着你可以把 Webserver 日志、数据库审计日志、Kubernetes events、应用追踪数据全部扔进去,然后用同一种语言搜索。
| 组件 | 角色 | 说明 |
|---|---|---|
| Universal Forwarder | 数据采集 | 轻量级 agent,部署在数据源机器上,把日志/指标转发给 Indexer。极低资源开销 |
| Indexer | 索引与存储 | 接收数据、建索引、写入磁盘。数据被组织为 buckets(hot/warm/cold/frozen) |
| Search Head | 搜索入口 | 用户交互层,处理 SPL 搜索请求,把查询分发到 Indexer 并聚合结果 |
| Deployment Server | 配置管理 | 集中管理 Forwarder 的配置和 App 部署 |
| Cluster Master | 集群管理 | 管理 Indexer Cluster 的数据复制和高可用 |
| License Master | 许可管理 | 管理 Splunk 许可容量(按日摄入量计费) |
单实例(Splunk Free):所有功能跑在一个进程里,适合本地开发、POC。免费版限制 500MB/天摄入。
分布式:Search Head + Indexer 分离。适用于生产环境,水平扩展。Indexer 可以组成集群(Indexer Cluster)实现数据副本和故障转移。
Splunk Cloud:托管版,省去运维 Indexer/Cluster 的工作,适合不想自己管基础设施的团队。
# 下载 Splunk (去 splunk.com 注册免费账号) # macOS 用 .dmg, Linux 用 .tgz # 解压后启动 cd /Applications/Splunk/bin # macOS 默认路径 ./splunk start --accept-license # 首次启动会提示设置 admin 密码 # 访问 http://localhost:8000 ,用 admin + 你的密码登录 # 配置开机自启 ./splunk enable boot-start # 状态检查 / 停止 ./splunk status ./splunk stop
本地学习建议直接装 Splunk Enterprise(60天试用期后可转 Free 许可,摄入量有限但学习够用)。Unified Forwarder 是单独的包,在数据源机器上部署,体积小得多。
Input → Parsing → Indexing → Search。每条进入 Splunk 的数据都要经过这 4 个阶段。
Input:数据从来源被读入(文件、TCP/UDP 端口、脚本输出、HTTP Event Collector 等)。
Parsing:事件拆分、时间戳提取、字符集转换、字段提取(如 host、source、sourcetype)。
Indexing:写入索引文件,生成倒排索引和 lexicon。
Search:搜索请求分发到索引分片,并行扫描后聚合返回。
sourcetype 是 Splunk 里最重要的元数据之一。它告诉 Splunk 数据的格式,决定解析方式。预设的 sourcetype(如 access_combined、linux_secure、syslog)自带字段提取规则。
当你看到搜索结果里字段自动出现 status、src_ip、uri_path 时,那就是 sourcetype 在背后工作。
# 方法1:通过 Web UI Settings → Add Data → Upload Files → 选择文件 → 设置 sourcetype → Review → Submit # 方法2:编辑 inputs.conf 监控目录 $SPLUNK_HOME/etc/system/local/inputs.conf [monitor:///var/log/myapp/] index = main sourcetype = myapp_log disabled = false # 方法3:通过 REST API 用 HEC 发送 curl -k https://localhost:8088/services/collector/event \ -H "Authorization: Splunk <token>" \ -d '{"event": "login failed user=alice", "sourcetype": "myapp"}'
配置 inputs.conf 后需要重启 Splunk 或通过 splunk _internal call /services/admin/inputstatus/_reload 热加载。
生产环境别在每台服务器装完整 Splunk,用 UF (Universal Forwarder)。UF 体积小(~50MB),CPU 占用极低,负责把数据无脑转发到 Indexer。
# inputs.conf — 定义采集什么 [monitor:///var/log/nginx/access.log] index = web sourcetype = nginx_access # outputs.conf — 定义发给谁 [tcpout] defaultGroup = primary [tcpout:primary] server = 10.0.1.20:9997,10.0.1.21:9997 sslVerifyServerCert = false
SPL (Search Processing Language) 是 Splunk 的魔法。它借鉴了 Unix 管道的思想:一条命令的输出,通过管道 | 传给下一条命令。你从很宽的结果集开始,逐步过滤 → 转换 → 聚合 → 可视化。
# 关键词搜索(最宽的结果) error # 字段过滤(key=value 是自动字段匹配) sourcetype=nginx_access status=500 # 布尔逻辑(AND/OR/NOT 大写) error AND server NOT localhost # 比较运算符 bytes>10000 status>=400 # 通配符 host=web-* uri_path="/api/*"
# top — 统计最常见的值 sourcetype=nginx_access | top uri_path limit=10 # stats — 聚合统计(最有用的命令之一) sourcetype=nginx_access | stats count avg(bytes) max(bytes) min(bytes) # stats + by — 分组统计 sourcetype=nginx_access | stats count avg(bytes) max(bytes) by status # timechart — 时间序列聚合 sourcetype=nginx_access | timechart span=1h count by status # sort — 排序 sourcetype=nginx_access | stats count by uri_path | sort -count | head 20 # dedup — 去重 sourcetype=nginx_access | dedup client_ip
eval 是最强大的命令之一,它让你创建新的计算字段。
# 把 bytes 转为 KB ... | eval size_kb = round(bytes / 1024, 2) # 条件判断 — 给请求分类 ... | eval latency_level = case( response_time < 200, "fast", response_time < 1000, "normal", response_time >= 1000, "slow" ) # 时间运算 — 计算耗时 ... | eval duration_ms = (end_time - start_time) * 1000 # 字符串操作 ... | eval domain = replace(client_ip, "(\d+\.\d+)\.\d+\.\d+", "\1.0.0") ... | eval upper_path = upper(uri_path)
当自动字段不够用时,rex 用正则从 _raw 中提取字段。
# 从日志中提取自定义字段 ... | rex "User (?<username>\S+) logged in from (?<ip>\d+\.\d+\.\d+\.\d+)" # 从 URL 路径提取版本号 ... | rex field=uri_path "/api/v(?<api_version>\d+)/" # 从 URL query string 提取参数 ... | rex field=uri_query "page=(?<page>\d+)"
# 查找"访问了 /login 且报错"的 IP 们 sourcetype=nginx_access status=500 [ search sourcetype=nginx_access uri_path="/login" | fields client_ip ] # 查找最近 1 小时没有心跳的服务器 sourcetype=server_heartbeat NOT [ search sourcetype=server_heartbeat earliest=-1h | fields host ]
把多条离散事件拼接成完整的事务(session)。
# 按 session_id 和 client_ip 拼接用户的一次完整访问链路
sourcetype=nginx_access | transaction session_id client_ip maxspan=5m \
startswith="uri_path=/login" endswith="uri_path=/checkout"
① 先用关键词搜索熟悉数据 → ② 加字段过滤缩小范围 → ③ 用 stats 做聚合统计 → ④ 用 eval 做计算 → ⑤ 用 timechart 看趋势 → ⑥ rex 自定义提取 → ⑦ 子搜索和事务关联。不要一开始就追求复杂 SPL。
Splunk 的"知识对象"是对数据的元层描述。它们让搜索更快、更一致、更可复用。
| 对象 | 作用 | 示例 |
|---|---|---|
| Field Extraction | 从 _raw 中提取字段 | 自动或通过 props.conf 定义正则 |
| Field Alias | 给字段起别名,统一不同 source 的字段名 | client_ip = src_ip = remote_addr |
| Calculated Field | 基于已有字段动态计算新字段 | size_mb = bytes/1024/1024 |
| Event Type | 给匹配特定条件的事件打标签 | "login_failure" = status=401 |
| Tag | 给字段值打标签,支持一对多映射 | tag "critical" 可以匹配多个 error_code |
| Lookup | CSV/kvstore 查找表,关联外部数据 | IP → 地理位置、user_id → 部门 |
| Macro | 可复用的 SPL 片段 | `error_traffic` = sourcetype=* status>=500 |
# 1. 准备 CSV 文件 (ip_location.csv) # ip_start,ip_end,country,city # 1.0.0.0,1.0.0.255,US,Los Angeles # 2. Settings → Lookups → Add new → 上传 CSV # 3. 在搜索中使用 sourcetype=nginx_access | lookup ip_location ip_start AS client_ip OUTPUT country city | stats count by country city
# 定义 macro: "web_errors(1)" sourcetype=$arg1$ status>=500 # 使用(带参数) `web_errors(nginx_access)` | stats count by status, uri_path
Splunk 提供两代仪表板工具:Classic Dashboard(基于 Simple XML)和 Dashboard Studio(基于 JSON,现代化 UI)。推荐新项目直接用 Dashboard Studio,更灵活、可视化更丰富。
# 面板1:请求量趋势(时间序列图) sourcetype=nginx_access | timechart span=1m count # 面板2:HTTP 状态码分布(饼图) sourcetype=nginx_access | stats count by status # 面板3:Top 10 慢请求(表格) sourcetype=nginx_access response_time>1000 | stats count avg(response_time) as avg_ms by uri_path | sort -avg_ms | head 10 # 面板4:错误率趋势(面积图) sourcetype=nginx_access | eval is_error = if(status>=500, 1, 0) | timechart span=1h eval(round(sum(is_error)/count*100,2)) as error_rate_pct # 面板5:单值指标(Single Value) sourcetype=nginx_access | stats avg(response_time) as avg_latency_ms | eval avg_latency_ms = round(avg_latency_ms, 1)
Base Search vs Inline Search:多个面板共用同一个数据源时,设置一个 Base Search,各面板只写 post-processing SPL,显著减少重复查询。
Drilldown:点击图表中的某个 segment,触发另一个搜索或跳转到另一个面板。比如点击「500 错误」segment,drilldown 到具体的错误日志列表。
Token 传递:用 $token_name$ 在面板间共享参数。比如时间选择器 token → 传给所有查询;点击某个 host → 带 token 过滤到其他面板。
① 顶部放 KPI 单值(总请求数、错误率、平均延迟)→ ② 中间放趋势图(请求量、延迟变化)→ ③ 底部放明细表格。阅读顺序从上到下、从全局到细节。
Splunk Alert = 定时搜索 + 触发条件 + 动作。可以每 5 分钟跑一次搜索,"如果结果数 > 0 就发 Webhook 给 PagerDuty"。
# Step 1:写好搜索查询(验证结果符合预期) sourcetype=nginx_access status>=500 earliest=-5m | stats count by status, uri_path # Step 2:Save As → Alert # - Alert type: Scheduled # - Schedule: every 5 minutes # - Trigger: Number of Results > 0 # Step 3:配置 Trigger Actions # - Send Email (含结果表格) # - Webhook → Slack / PagerDuty / 企业微信 # - Run a script (自定义脚本) # Step 4:设置 Throttling(防止告警风暴) # - Suppress for 30 minutes after first alert
基于基线而非阈值:固定阈值(如 "CPU > 80%")容易误报。用 Splunk ML Toolkit 的 anomaly detection 学习正常模式,告警只在偏离时触发。
Throttling:永远设置抑制时间,否则半夜故障会被同一告警刷屏。
Rich Notification:告警附带前 10 条明细、相关仪表板链接,让 on-call 工程师拿到告警就能定位。
报表本质上是把搜索的结果定时快照并发送。可以配置为 PDF 邮件、CSV 导出、或存到 Summary Index 供长期趋势分析。
# 每日错误汇总,早上 9:00 发送 PDF 到老板 sourcetype=nginx_access status>=500 earliest=-1d@d latest=@d | stats count by status, uri_path | sort -count # Save As → Report → Schedule: daily at 9:00 → Email PDF
数据模型(Data Model)是对原始数据的结构化视图。你把复杂的 SPL 查询封装成层次化的数据集(Events、Searches、Transactions),让不懂 SPL 的业务用户也能通过 Pivot 拖拽式分析数据。
一个 Data Model 包含多个 Object Type:
| Type | 说明 |
|---|---|
| Root Event | 事件数据集,基于约束条件(如 sourcetype=access_combined) |
| Root Search | 基于 SPL 搜索的数据集 |
| Root Transaction | 基于关联规则的数据集 |
| Child Object | 继承父 Object 的约束,附加自己的过滤 |
# 名称:Web Analytics # 添加 Root Event: # - Constraint: sourcetype=nginx_access # - Auto-extracted fields → 勾选 status, uri_path, bytes, client_ip # 添加 Child Object "Errors": # - Additional Constraint: status >= 400 # 添加 Calculated Field "Size MB": # - Formula: bytes / 1048576 # 然后用户就能去 Pivot 里拖拽 status, uri_path 做交叉分析了
Pivot 让业务用户不用写 SPL 也能分析数据。选择一个 Data Model → 选择可视化类型 → 拖拽字段到行/列/过滤条件 → 实时预览。适合给产品经理、运营同学做自助分析。
Splunk Cloud 免去维护 Indexer 集群的负担,但需要注意:
① 数据摄入延迟:UF → Cloud 通过公网或专线,需考虑带宽和延迟。建议用专用 Input Data Manager (IDM) 做缓冲。
② App 部署受限:Cloud 环境由 Splunk 管理,安装 App 需要通过 Support Ticket,部分 App 受限。
③ 数据驻留:选择对应 Region(US, EU, APAC 等)。
Search Head Cluster (SHC) 实现搜索端的高可用。最少 3 台 Search Head 组成集群,通过 Captain 协调。一台挂了自动 failover,用户的 scheduled search 和知识对象自动迁移。
❶ 时间范围 — 永远指定最早和最晚时间,不要在 All Time 搜索
❷ 前置过滤 — 把最严格的条件放在管道最前面
❸ fields 而非 table — | fields a,b,c 比 | table a,b,c 快
❹ 避免 join — join 非常昂贵,尽量用 lookup 替代
❺ Summary Index — 高频统计先存到 Summary Index,搜索时可以读取预计算好的结果
❻ Accelerate — 对数据模型启用加速,Pivot 查询速度提升 10-100x
❼ tstats — 用 tstats 替代 stats 直接读索引元数据,速度极快
❽ Inspect Job — 慢查询先点 Job → Inspect Job 看 distribution 和 scan count
# 传统 stats(慢,需要扫描全部 event) index=web | stats count by host # tstats(快,直接读 tsidx metadata) | tstats count WHERE index=web BY host # tstats + prestats 用于 Dashboard | tstats prestats=t count avg(bytes) WHERE index=web BY sourcetype | timechart span=1h count avg(bytes) by sourcetype
# 查看 Splunk 自身日志 index=_internal | stats count by component, log_level # 查看索引和 bucket 状态 | dbinspect index=* | stats sum(sizeOnDiskMB) as total_mb by index # 查看慢搜索 index=_audit action=search search=* total_run_time>10 | table user search total_run_time # License 用量 index=_internal source=*license_usage.log type=Usage | timechart span=1d sum(b) as daily_bytes
如果你想系统性地学习:
Power User → 基础搜索、知识对象、仪表板。建议第一个考。
Admin → 部署、集群管理、性能调优。适合运维。
Architect → 大规模部署方案设计。适合高级工程师。
Consultant → 综合实战能力。适合解决方案工程师。
Core Certified → 最高级别认证。