适用场景
用于查询 kibana.kzmall.cc 的 DGJ、Sale、Basedata、ItemCenter、OpsManager、MQ、支付和订单日志,尤其适用于以下现象:
- 浏览器可以打开 Kibana,但终端报
Cannot reach Kibana; - Python 报
nodename nor servname provided,而浏览器和curl看起来正常; - 查询宽时间范围超时,或者 Discover 页面与脚本结果不一致;
- 需要把 HTTP、RPC、MQ、数据库和下游服务串成一条时间线。
本次确认的根因
本次不是 VPN 路由断开:
kibana.kzmall.cc解析到公司内网 IP;route -n get显示目标通过utun4和 VPN 网关转发;- 固定 IP 请求返回
401 Unauthorized,说明已到达 Kibana,只是尚未完成认证; - Python
urllib使用系统 resolver 时出现nodename nor servname provided。
因此,浏览器能访问、Python 失败并不矛盾,问题发生在终端解析器而不是业务网络。
标准排查顺序
1. 确认 Tunnelblick 实际路由
dig +short kibana.kzmall.cc
route -n get <解析出的IP>
osascript -e 'tell application "Tunnelblick" to get state of configurations'
ps aux | rg -i 'openvpn.*(kz|RDC)|Tunnelblick' | rg -v rg
正确路由应使用 utun*,不能只依据 Tunnelblick 菜单中的配置名称判断。当前环境的实际活动配置是 kz-office-oa-staging 和 kz-prod-oa-staging,不是菜单名称为 kz-prod 的配置。
2. 用固定 IP 验证 HTTP 层
curl --noproxy '*' -v -m 5 \
--resolve kibana.kzmall.cc:80:<IP> \
'http://kibana.kzmall.cc/api/status' \
-H 'kbn-version: 6.8.23' \
--insecure
状态含义:
| 结果 | 判断 |
|---|---|
401 Unauthorized | 网络、路由、HTTP 和 Host 已打通,检查认证 |
nodename nor servname provided | Python/DNS 解析失败 |
Connection timed out | VPN、路由、代理或服务不可达 |
403 | 已进入 HTTP 层,检查权限、Host 或会话 |
3. 使用查询脚本
脚本路径:
/Users/zhoujiangbin/.codex/skills/kibana-log-query-runner/scripts/query_kibana_logs.py
脚本会从共享凭据存储读取认证信息,并自动:
- 使用
dig +short获取当前 VPN IP; - 连接 IP 而不是直接依赖 Python DNS;
- 设置
Host: kibana.kzmall.cc; - 禁用通用 HTTP 代理;
- 给 Elasticsearch 查询增加
ignore_throttled=false。
正常查询示例:
python3 /Users/zhoujiangbin/.codex/skills/kibana-log-query-runner/scripts/query_kibana_logs.py \
--date 2026-08-05 \
--from '2026-08-05T17:46:20+08:00' \
--to '2026-08-05T17:46:30+08:00' \
--keyword 'JGTZ20260805000001' \
--size 100 \
--messages
必要时固定 IP:
python3 /Users/zhoujiangbin/.codex/skills/kibana-log-query-runner/scripts/query_kibana_logs.py \
--connect-ip <当前 dig 结果> \
--date 2026-08-05 \
--from '2026-08-05T17:46:20+08:00' \
--to '2026-08-05T17:46:30+08:00' \
--keyword 'RequestId或EventId' \
--messages
不要把临时 IP 永久写入 Skill 或代码;VPN/DNS 发生变化时重新执行 dig。
Discover 链接中的 index 不是实际索引
Discover URL 中类似下面的值:
_a.index=d6517990-ee0e-11ed-9db6-9b90c505ec7a
通常是 Kibana data view 的 ID,不是 Elasticsearch 的真实索引名。终端查询应改用具体日索引:
logstash-2026-08-10
这样可以明确知道查询覆盖了哪一天,也便于判断某一天索引是否存在、是否进入 Frozen。
Kibana 查询正确性规则
精确索引和时间窗口
优先查询单天索引 logstash-YYYY-MM-DD,从 1~5 分钟窗口开始;宽时间查询超时后按小时、分钟拆分。必须确认返回的 _shards.total > 0。
Elasticsearch 6.8 查询 Frozen/search-throttled 索引时,Console Proxy 路径必须带:
_search?ignore_throttled=false
查询脚本已经自动添加。缺少该参数时,最近热索引可能仍能查到,但历史 Frozen 索引可能被跳过;因此 hits.total=0 不能直接写成“没有日志”。还要区分:
hits.total=0:索引可查,但当前条件没有命中;index_not_found_exception:该日索引不存在;_shards.total=0:索引不可见、关闭或查询范围不成立。
eventDest 和 eventType 必须分别核对
查询 opscenter_notify 只能说明日志里出现过目标模块,不等于命中了货主区域变更事件。以一次已复核的最近日志为例:
索引:logstash-2026-08-10
正文时间:2026-08-10 17:16:01.387(Asia/Shanghai)
@timestamp:2026-08-10T09:16:01.945Z(UTC)
host:prod-glbomscenter-12
eventDest:OPSCENTER_NOTIFY
eventType:OPSCENTER_CUSTOMER_BASE_INFO_CHANGE_SELF
_shards:total=8, skipped=0, failed=0
这条日志证明 Kibana 查询和 OPSCENTER_NOTIFY 目标日志可达,但它是客户基础信息变化,不是货主区域变化。要确认 MQ-02,必须继续用区域事件的准确 eventType、routing key 或 eventId 复查。
Join Key 梯子
跨服务追踪不要只依赖业务单号,按以下顺序收集并继续查询:
- 业务单号、外部单号;
- 内部订单 ID、商品 ID、SID;
RequestId;- MQ
eventId、MessageId、routing key; - 支付单号、出库单号、退货单号;
source.keyword、host.name.keyword。
零命中判定
只有同时满足以下条件,才能把结果写成“索引内没有匹配日志”:
- 精确日索引查询成功;
- 查询 URL 包含
ignore_throttled=false; - 时间窗口足够小;
- 至少尝试两个独立 Join Key;
_shards.total非零;- 已重新执行查询,而不是直接相信 Discover 缓存。
索引不存在、Frozen 索引超时、账号不可见和真实 0 hits 必须分开记录。
浏览器 Discover 页面显示的旧结果可能来自之前加载的结果;需要通过 Console Proxy 重新执行一次,记录 _shards 和实际命中文档。
跨服务时间线格式
| 时间 | 系统/主机 | source | 动作 | 输入 Join Key | 输出 Join Key | 结果 |
|---|
同时记录:
- Elasticsearch
@timestamp; - message 内业务时间;
- 时区;
- 日志中直接观察到的事实;
- 根据上下游 Join Key 得出的推断。
安全边界
- 认证信息只从
/Users/zhoujiangbin/.codex/private/credentials.json读取,不复制密码、Cookie 或 Token。 - 默认使用 Kibana Console Proxy,不直接登录生产主机。
- 生产查询保持只读;消息重放、数据库修复和补偿操作需要单独授权。
- 认证成功只证明访问层成功,不代表 MQ 消费、Mongo、ES、Redis 或业务事务成功。