几周前不知道为什么,yyets的内存使用率暴涨,直接给我机器弄没了。
内核的OOM机制都没起作用,猜测可能是dockerd
的默认的OOM score是-500,导致没人敢杀吧。最近这几天配置上了Graylog来收集日志,下次再出现问题可以看日志了,大概这样:
Graylog基础配置、收集docker日志
配置Graylog倒是很容易,docker-compose
一把梭,docker也恰巧支持GELF协议。Graylog装好之后,配置一个GELF的input,如下图所示
小提示,如果你的Graylog是用docker起的,那么在publish port时要额外注意,docker默认只publish TCP,所以要 -p 127.0.0.1:12201:12201/udp
确认运行起来之后,可以开一个容器试试看,注意这里要写127.0.0.1
,写localhost
的话,dockerd可能会给搞很多幺蛾子(解析到IPv6给你颜色看看)。
docker run --log-driver gelf --log-opt gelf-address=udp://127.0.0.1:12201 alpine echo hello world
也可以选择用nc
发一条消息看看
echo -n '{ "version": "1.1", "host": "example.org", "short_message": "A short message again", "level": 5, "_some_info": "foo" }' | nc -w1 -u localhost 12201
配置无误的话就应该已经能在搜索页面看到日志了
配置GeoIP
Graylog带有GeoIP的支持,可以自动通过MaxMind的数据库显示访客的IP地址。配置起来比较麻烦,并且文档非常模糊不清🤣
启用Geo-Location Processor
首先要启用这个模块,在System - Configurations最下面可以看到。需要自己去下载数据库
懒得注册账号的可以去这里下载
https://github.com/P3TERX/GeoLite.mmdb
这里的City库比较新
https://github.com/wp-statistics/GeoLite2-City
下载好之后放到某个目录,确保Graylog有权限访问,确认就行了,我就直接丢到了宿主机的volume的目录
调整处理顺序
System- Configurations,最上面看 Message Processors Configuration 确保GeoIP Resolve而已经启用,并且顺序正确,至少要放到pipeline后,我给放到最后了
Lookup Table – Adapters
要创建Adapters,路径是 System- Lookup Tables- Data Adapters,Data Adapter Type选择 GeoIP的那个
Lookup Table – Cache
中间的那个标签页,创建一个cache
Lookup Tables
终于可以创建Lookup Tables了,最左侧的标签页,选择刚刚创建好的adapter和cache。这个Name是唯一的,下一步要用,记下来哦。
创建Pipelines
😓还没完,还要创建pipeline
去调用Lookup Table
创建pipeline rules
System - Pipelines - Manage rules - Create rule
rule source是核心,定义了怎么取IP、解析后怎样呈现数据。拿我的一行log为例:
如果你的IP地址是单独的一个字段中,比如上面的source
、container_name
这种单独的一行,那么就很容易了,比如说你的字段叫 src_ip
rule "GeoIP lookup" when has_field("src_ip") then let geo = lookup("geoip", $message.src_ip); set_field("src_ip_geo_location", geo["coordinates"]); set_field("src_ip_geo_country", geo["country"].iso_code); set_field("src_ip_geo_city", geo["city"].names.en); end
很好理解,如果src_ip
字段存在,就用geoip
这个Lookup Table查询,还记得吧,这个geoip
是上一步Lookup Table的Name。
如果你的日志是像我这种,IP记录在message中,那就这样,先用grok
去提取IP地址,然后再进行查询
rule "GeoIP lookup" when has_field("message") then let ipObj = grok(pattern: "(%{IP})", value: to_string($message.message)); // ipObj.IP 就是真正的IP地址,可能是IPv4 也可能是IPv6 let geo = lookup("geoip", ipObj.IP); set_field("src_ip_geo_location", geo["coordinates"]); set_field("src_ip_geo_country", geo["country"].iso_code); set_field("src_ip_geo_city", geo["city"].names.en); end
但是这样还不是很完美,仔细观察,我的log的IP是在()
包围中的,有些时候我也会用logging.info
去记录IP,那么这样子就会重复了。想当然的,这东西看起来是正则表达式的样子,那么(\(%{IP}\))
😎辣鸡Graylog会直接给你报错,无法保存
这个时候要做的事情是创建一个新的 Grok规则,然后去应用,如图所示,Pattern为 \(%{IP}\)
名字随便起一个
然后规则里用(%{Tornado})
就可以了
遇到问题可以用debug(ip)
这种去排错,Graylog的log🤪会显示这个变量的内容
创建pipeline
还没完,在Manage rules旁边有一个Manage pipelines,创建一个pipeline
名字随便起,创建好之后 Edit Connections – Default Stream
然后创建stage,rules选择刚刚弄好的rule
Stage 0没用可以删掉
保存好,回到主界面应该能看到IP和地理位置了
添加Geo Location Map
Graylog有一个有点有趣的功能,可以根据log来做聚合查询,包括GeoIP的信息。在主界面的侧边可以看到aggregation
点进去这样配置
Update widget 就有了,大概这样
总结
- log服务器和应用服务器不要在同一台机器上,否则到时候一起挂了,都没得看
- 😏 自从被打之后,我再也不监听
0.0.0.0
了,一切全靠 Cloudflare Argo Tunnel 解决,连nginx都不需要 - 新版本的docker(20.10起)也可以看GELF的log,但是
docker-compose
不可以 - 这Graylog的文档是真的绝,说得不明不白的,甚至还有全角引号
- 没太多有用的资料,搜到的就是他们官方的论坛
- 🤡还有undefined的bug,后来到MongoDB里手动删除的