0x01 前言

最近通过zabbix发现服务器的负载特别高,经常超过阈值,发现这种现象已经持续了一段时间:

复查操作记录发现早在12月11日我就将ELK套件升级到了最新版本,而我这个服务器因为是对外的,所以nginx的日志非常庞大,所以导致filebeat读取的时候性能顺好非常大。

0x02 filebeat

在我登入服务器查看相关参数时发现filebeat的CPU占用率居高不下:

而filebeat只巡检三个日志:

- input_type: log
  paths:
    - /usr/local/html/*/logs/ngx_access.log
    - /var/log/nginx/access.log
  tags: server_ngx_access_log

- input_type: log
  paths:
    - /var/log/modsecurity/*/*/*
  tags: modsec_audit_log
  close_eof: true
  clean_*: true

其中modsecurity的审计日志记录形式为:

SecAuditLogType Concurrent

也就是每条日志保存为一个单一的文件,这个比较特殊,目录的层级结构如下:

[root@hk1 log]# tree modsecurity/
modsecurity/
├── 20171210
│   ├── 20171210-0000
│   │   └── 20171210-000023-151283522357.275185
│   ├── 20171210-0014
│   │   ├── 20171210-001449-151283608954.936162
│   │   └── 20171210-001450-151283609056.525275
│   ├── 20171210-0019
│   │   ├── 20171210-001928-151283636851.191223
│   │   ├── 20171210-001933-151283637325.387680
│   │   └── 20171210-001943-151283638395.748607

因为这些文件最会写入一次,所以filebeat读取一次就可以将harvester(收集器)关闭,所以我在配置中将close_eof设为true。

因为我还有另一台服务器使用filebeat手机nginx日志,但没有使用modsecurity,所以我一度认为是因为是因为modsecurity日志的目录增多而导致filebeat负载过高。

当我去除modsecurity日志的读取配置并重启filebeat后发现高负载的情况依旧存在。不过为了降低filebeat状态注册表,我在配置文件中增加了clean_*这个配置,这样可以大大降低状态注册表的大小:

[root@hk1 ~]# ll -h /var/lib/filebeat/registry 
-rw------- 1 root root 636K 12月 18 21:39 /var/lib/filebeat/registry

这个文件记录着各个文件的读取情况以及偏移量,如果文件非常多,就会导致这个注册表文件逐渐变大,使用clean_*这个参数可以有效减少这个注册文件的大小。

最后我停止读取nginx日志并开始读取modsecurity的日志,发现CPU占用率得到了极大的改善,已经恢复到以前的水平。

在重新读取nginx日之后再次出现CPU负载变高的情况。

0x03 nginx

在比较两个服务器的日志发现香港服务器的nginx日志超过了2G:

[root@hk1 ~]# ll -h /usr/local/html/ngx.hk/logs/ngx_access.log 
-rw-r--r-- 1 nginx nginx 2.1G Dec 17 01:07 /usr/local/html/ngx.hk/logs/ngx_access.log

我的服务器会定期备份,所以这个庞大的日志也是一个大问题,将nginx日志截断就显得尤为重要。

因为我网站问的人很少,所以日志增长速度比较缓慢,阶段周期设置为每月进行较为合理。计划任务使用crontab即可,而脚本如下:

[root@hk1 ~]# cat /usr/local/shell/ngx_log_rotation_enginx.sh 
#!/bin/bash
logs_path="/usr/local/html/ngx.hk/logs/"
pid_path="/var/run/nginx.pid"
 
mv ${logs_path}ngx_access.log ${logs_path}ngx_access_$(date +"%Y-%m").log
 
kill -USR1 `cat ${pid_path}`
  • logs_path:定义日志文件的路径
  • pid_path:定义pid的路径
  • mv:将文件重命名

注意mv命令中的日志文件名:ngx_access.log。请将这个文件名根据实际情况进行修改。

然后使用kill命令向nginx发送USR1信号,停止接收新的连接、等待当前连接断开后立即重载配置文件并重启服务。

因为我是每月分割一次,所以我的文件名为:

ngx_access_$(date +"%Y-%m").log

例如:

ngx_access_2017-12.log

如果需要按天备份,那么文件名建议为:

ngx_access_$(date +"%Y-%m").log

如:

ngx_access_20171218.log

接下来是定时任务,如果是每月1号执行,那么crontab为:

0 0 1 * * root sh /usr/local/shell/ngx_log_rotation_enginx.sh

上面语句的意思是每月1号的0点0分使用root用户执行shell命令。如果需要每天执行,则:

0 0 */1 * * root sh /usr/local/shell/ngx_log_rotation_enginx.sh

以上语句的意义为每天的0点0分使用root用户执行命令,注意一定要指定时与分!

0x04 结语

经过观察,最近服务器的负载已经恢复正常。不过我比较疑惑的是为什么filebeat 6.0.1会有这种问题,在5.6的时候并没有这个问题。

以下是最近三天的负载情况:

从图中可以很明显地看到负载分界线。