更新

Jun 7, 2024

  • 5.3 日志结构作者又做调整了,完整配置已更新,如果是 5.0 ~ 5.1.x 版本需要注意完整配置下面的代码对比部分。
  • 作者自己使用是把 modsns 从之前的后置改成了前置测试了好几个月,好处是某些服务挂了也不会影响 DNS 的解析,有想了解具体细节的吗?

更新维护不易,欢迎在文章尾部打赏作者,这个对于作者很重要,感谢你的支持!

我是从 4.0 版本开始使用 mosdns,经历了 4.1 和 4.2 不稳定的功能更新和今年 1 月份发布 5.x 大版本重构后貌似已经稳定下来。

托 @river_leaves 的福利用 mosdns 自带的 prometheus metrics 接口实时查看 DNS 解析情况。

配置中的规则是灵活且有时候很难调试,为了验证配置规则是否有效以及可视化看到域名访问频次,我从 mosdns 日志本身下手,需要的工具有 vector、prometheus、loki 和 grafana。

实时监控 mosdns 规则解析 Grafana 看板

当前教程仅适用于 mosdns 5.0 ~ 5.3.x 版本(后续版本没有发布可能存在配置变化,依据实际情况调整)。

mosdns

mosdns 5 版本采用了新数据源解包格式,配置我实在懒得调整了,直接在采用了 luci-app-mosdns 插件配置微调。配置中各个 plugins 名称请确保不要修改和变动,否则会导致 vector 转换规则无法正常工作。

看不到下面配置文件的,送上直达电梯

配置定义了 mosdns 日志的文件路径为 /var/log/mosdns.log,输出日志等级只需要是 INFO 即可。如果 mosdns 服务所在磁盘空间较小建议使用 logrotate 来切割日志并控制归档日志数量,以免出现空间不足的情况。

1/var/log/mosdns.log {
2  daily
3  rotate 2
4  compress
5  missingok
6  notifempty
7  copytruncate
8}

copytruncate 的意思是将旧日志文件的内容复制到新日志文件,默认是直接改名原文件会造成 mosdns 运行日志记录出现问题,设置好后确保 logrotate 定时运行:

1# crontab -e
20 1 * * * /bin/sh -c "/usr/sbin/logrotate -l=syslog -d /etc/logrotate.d"

vector

vector 是一个日志收集工具,能够从多个源(Source)收集、转换(Transform)并推送到下一个接收器(Sinks)。

vector 需要能够直接访问到 mosdns 的日志文件。这里有两种方式可以实现:一种是两个服务都在一台机器上运行,另外一种是通过容器化共享 volume 让 vector 可以读取 mosdns 日志。

工具本身是 Go 语言开发从 Github 直接下载好对应的包解压缩就能够使用或者使用一键安装脚本:

1curl --proto '=https' --tlsv1.2 -sSf https://sh.vector.dev | bash

Openwrt/Immortalwrt 用户可使用我个人维护的仓库 icyleaf/openwrt-dist 添加后即可安装(支持 amd64、armv8 平台的 snapshot 和 23.05.0 两个分支):

添加仓库密钥

1wget http://cdn.jsdelivr.net/gh/icyleaf/openwrt-dist@master/key-build.pub
2opkg-key add key-build.pub

根据 openwrt 平台不同修改源地址

1# 源规则
2# src/gz icyleaf https://icyleaf-openwrt-repo.vercel.app/{{{target}}/packages/{{arch}}
3
4# 添加 snapshot 分支 amd64 (x86/64) 平台的源
5echo "src/gz icyleaf https://icyleaf-openwrt-repo.vercel.app/snapshosts/packages/x86/64" >> /etc/opkg/customfeeds.conf

安装 vector

1opkg update
2opkg install vector

修改 /etc/vector/config.yml 的配置文件如下

 1data_dir: /tmp/vector
 2
 3sources:
 4  mosdns-log-file:
 5    type: file
 6    include:
 7      - /var/log/mosdns.log
 8    read_from: beginning
 9
10transforms:
11  mosdns-input:
12    type: filter
13    inputs:
14      - mosdns-log-file
15    condition: |
16      .file == "/var/log/mosdns.log"      
17
18  mosdns-data:
19    type: remap
20    inputs:
21      - mosdns-input
22    drop_on_error: true
23    source: |
24      .type = "mosdns"
25      .app = "mosdns"
26      del(.host)
27      del(.file)
28      del(.source_type)
29
30      message_parts = split!(.message, r'\t')
31
32      .timestamp = parse_timestamp!(message_parts[0], format: "%F %T")
33      .level = message_parts[1]
34
35      if (length(message_parts) == 6) {
36        .plugin = message_parts[2]
37        .processor = message_parts[3]
38        .message = message_parts[4]
39
40        if (exists(message_parts[5])) {
41          .metadata = parse_json!(message_parts[5])
42          . = merge!(., .metadata)
43          del(.metadata)
44        }
45      } else {
46        .processor = message_parts[2]
47        .message = message_parts[3]
48
49        if (exists(message_parts[4])) {
50          .metadata = parse_json!(message_parts[4])
51          . = merge!(., .metadata)
52          del(.metadata)
53        }
54      }
55
56      if (exists(.query)) {
57        . = merge!(., .query)
58        del(.query)
59      }      
60
61sinks:
62  # 同步到 loki,根据实际情况修改 endpoint 的值
63  loki:
64    type: loki
65    inputs:
66      - mosdns-data
67    endpoint: 'http://10.10.10.2:3100'
68    encoding:
69      codec: json
70    labels:
71      app: '{{ app }}'
72      type: '{{ type }}'
73    healthcheck:
74      enabled: true
75
76  # 临时输出转换数据到 vector 控制台(生产环境请禁用)
77  debug_mosdns:
78    type: console
79    inputs:
80      - mosdns-data
81    encoding:
82      codec: json

mosdns 5.3 对比 5.0 ~ 5.1.x 版本时间戳和 query 字段做了修改,需要调整配置文件:

 1...
 2-      .timestamp = parse_timestamp!(message_parts[0], format: "%F %T")
 3+      .timestamp = parse_timestamp!(message_parts[0], format: "%FT%T%.9fZ")
 4
 5...
 6      if (exists(.query)) {
 7-        . = merge!(., .query)
 8-        del(.query)
 9+        query_parts = split!(.query, r'\s')
10+        .domain = query_parts[0]
11+        .record = query_parts[2]
12+        .address = query_parts[5]
13      }

运行 vector 服务(部署好 loki 后再运行)

非 openwrt 用户使用

1vector --config /etc/vector/config.yml --watch-config --verbose

openwrt 用户使用

1$ /etc/init.d/vector start
2
3Loaded with warnings ["/etc/vector/config.yml"]
4-----------------------------------------------
5√ Component configuration
6√ Health check "loki"
7√ Health check "vector"
8-----------------------------------------------
9                                      Validated

使用 openwrt 插件的 vector 服务本身是会监控配置文件变化并重载,后面再调整的时候也不需要反复重启服务。

prometheus

prometheus 是一个监控数据服务,可以作为 Grafana 数据源使用。安装参考官方教程,配置文件需要把 mosdns metrics 地址(比如是 10.10.10.1:8338)加到 prometheus.yml 文件中:

 1global:
 2  scrape_interval:     1m
 3  evaluation_interval: 1m
 4
 5scrape_configs:
 6+  - job_name: mosdns
 7+    scrape_interval: 5s
 8+    # scrape_timeout: 10s
 9+
10+    # metrics_path: /metrics
11+    static_configs:
12+      - targets:
13+        - 10.10.10.1:8338

loki

loki 是一个日志聚合服务,本身也是 Grafana 研发的,可以作为 Grafana 数据源使用。参照官方文档就能部署好 loki 和 Grafana,唯一需要注意的是要提前下载好 loki 配置文件。部署好之后把 loki 地址更新到上面 vector 配置。

grafana

grafana 是一个数据可视化工具,安装见 loki 部分,已有服务直接跳过。

Dashboard 看板的配置就非常简单了,先添加好 prometheus 和 loki 的数据源后,导入 mosdns v5 看板,按照图示配置即可。

Grafana 导入 Dashboard 看板

Grafana 配置数据源

结语

感谢 mosdns 长达几个月的配置稳定之前挖的坑填上了,撒花!

如果你觉得我的文章对你有帮助,欢迎打赏,这对我非常重要,谢谢!

支付宝打赏 微信打赏