1. 养乐多|杨城的个人博客首页
  2. 技术杂谈
  3. Other

利用ELK+Redis搭建Nginx日志分析平台

ELK分别为 Elasticsearch、Logstash及Kibana,我们先来通过一张图来帮助了解其业务实现原理
利用ELK+Redis搭建Nginx日志分析平台
1. 安装前准备工作
虚拟机:192.168.63.129 安装Nginx(安装步骤省略,可yum安装,也可以编译安装),Logstash(机器内存建议512M及以上)
系统环境:centos-release-7-3.1611.el7.centos.x86_64
Linux version 3.10.0-514.26.2.el7.x86_64 (builder@kbuilder.dev.centos.org) (gcc version 4.8.5 20150623 (Red Hat 4.8.5-11) (GCC) )
虚拟机:192.168.63.131 安装Elasticsearch、Logstash、Kibana及Redis(机器内存建议4G及以上)
系统环境:centos-release-7-4.1708.el7.centos.x86_64
Linux version 3.10.0-693.2.2.el7.x86_64 (builder@kbuilder.dev.centos.org) (gcc version 4.8.5 20150623 (Red Hat 4.8.5-16) (GCC) )
建议关闭系统防火墙,否则后面需要写自定义路由规则来允许访问特定端口服务

# 查看默认防火墙状态
[root@localhost yangcheng]# firewall-cmd --state # 关闭后显示notrunning,开启后显示running
[root@localhost yangcheng]# systemctl stop firewalld.service  # 停止firewall
[root@localhost yangcheng]# systemctl disable firewalld.service  # 禁止firewall开机启动
# 有时很可能还需要关闭 SELinux,这个因环境而异

(1)先在131服务器上下载ELK+Redis安装包,为了便于管理,我这里统一下载到 /usr/local/src/ 的 elkr 目录下

[root@localhost src]# mkdir elkr # 创建目录
[root@localhost src]# cd elkr
[root@localhost elkr]# wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-5.6.0.tar.gz
[root@localhost elkr]# wget https://artifacts.elastic.co/downloads/logstash/logstash-5.6.0.tar.gz
[root@localhost elkr]# wget https://artifacts.elastic.co/downloads/kibana/kibana-5.6.0-linux-x86_64.tar.gz
[root@localhost elkr]# wget http://download.redis.io/releases/redis-4.0.1.tar.gz
[root@localhost elkr]# wget http://nodejs.org/dist/latest/node-v8.5.0.tar.gz   # 后面安装elasticsearch可视化管理插件会用到
# 将上述文件分别解压到 /usr/local/elkr 目录下,事先需要创建 elkr 目录
[root@localhost elkr]# tar -zxvf elasticsearch-5.6.0.tar.gz -C /usr/local/elkr/
[root@localhost elkr]# tar -zxvf logstash-5.6.0.tar.gz -C /usr/local/elkr/
[root@localhost elkr]# tar -zxvf kibana-5.6.0-linux-x86_64.tar.gz -C /usr/local/elkr/
[root@localhost elkr]# tar -zxvf redis-4.0.1.tar.gz -C /usr/local/elkr/
[root@localhost elkr]# tar -zxf node-v8.5.0.tar.gz -C /usr/local/elkr/
# 当前是在 /usr/local/src/elkr 目录,现在我们进入 /usr/local/elkr 目录可以看到解压后的文件
[root@localhost elkr]# cd /usr/local/elkr && ls
elasticsearch-5.6.0  kibana-5.6.0-linux-x86_64  logstash-5.6.0  node-v8.5.0  redis-4.0.1
# 我这里将各个文件重命名了(因人而异),操作省略。命令:mv 文件名A  文件名B
[root@localhost elkr]# ls
elasticsearch  elasticsearch-head  kibana  logstash  node  redis

(2)129服务器上下载Nginx或yum安装nginx和Logstash包(步骤略)
2. 开始安装
(1)安装Elasticsearch

# 由于elasticsearch不允许通过root账号直接启动,因此这里事先给它创建一个工作组及用户并设置密码(我这里密码也为elkr)
[root@localhost elkr]# groupadd elkr
[root@localhost elkr]# useradd elkr
[root@localhost elkr]# passwd elkr
# 将elkr目录及下面文件所属组及用户都设置成elkr
[root@localhost elkr]# chown -R elkr:elkr /usr/local/elkr
# 切换到elkr用户下,并进入 /usr/local/elkr/elasticsearch 目录,了解下有哪些文件
[root@localhost elkr]# su elkr # 这里是从root用户切换至其他账号,因此不需要再输入密码。有的是su,有的是sudo,因环境而异
[elkr@localhost elkr]# cd /usr/local/elkr/elasticsearch
[elkr@localhost elasticsearch]$ ls
bin  config  data  lib  LICENSE.txt  logs  modules  NOTICE.txt  plugins  README.textile
# 一会需要用到的有:bin目录下可执行文件,启动服务等等;config下面是配置文件;现在进入bin目录,启动elasticsearch服务
[elkr@localhost elasticsearch]$ cd bin
# 启动服务并放至后台运行
[elkr@localhost bin]$ nohup ./elasticsearch >/dev/null 2>&1 &
# 测试服务是否正常启动
[elkr@localhost bin]$ curl http://127.0.0.1:9200
{
  "name" : "xLkn8-N",
  "cluster_name" : "elasticsearch",
  "cluster_uuid" : "cPIQF1XDReevoo4_uhbWjQ",
  "version" : {
    "number" : "5.6.0",
    "build_hash" : "781a835",
    "build_date" : "2017-09-07T03:09:58.087Z",
    "build_snapshot" : false,
    "lucene_version" : "6.6.0"
  },
  "tagline" : "You Know, for Search"
}
# 上述信息表示,服务已正常启动。默认情况下,elasticsearch服务只能在虚拟机内部使用http://127.0.0.1:9200地址来访问【宿主机如何访问,稍后讲到】

注意:新环境第一次运行时可能由于各种配置原因或环境依赖导致启动失败,如果想更直观查看是否能启动成功,见如下操作

[elkr@localhost bin]$ ./elasticsearch
# 回车后,可以看到es服务启动过程,如果启动失败,会显示相关错误信息。也可以从logs目录下查看日志信息。

这里简单说下导致启动失败的常见问题:
[1]: max file descriptors [4096] for elasticsearch process is too low, increase to at least [65536]
[2]: max virtual memory areas vm.max_map_count [65530] is too low, increase to at least [262144]
解决方法:切换至root用户,修改 /etc/security/limits.conf 文件,新增如下两行:
elkr soft nofile 65536
elkr hard nofile 65536
保存后,切换到elkr用户,执行 ulimit -Hn 命令即可查看到是否生效。再用root用户修改 /etc/sysctl.conf 文件,新增 vm.max_map_count=262144,保存即可。
参数值具体要设置多大,这个根据实际错误信息而定。如遇到其他错误,可以上网查询解决方案,也可以参考 http://www.cnblogs.com/sonofelice/p/6937061.html

现在来实现在宿主机访问虚拟机中elasticsearch服务,可以修改 /usr/local/elkr/elasticsearch/config/ 目录下 elasticsearch.yml 配置文件

[elkr@localhost config]$ vim elasticsearch.yml
# 将55行network.host 和 59行http.port 前面的“#”号去掉,并将IP设置成虚拟机IP如192.168.63.131,端口号保持9200不变,保存后重启elasticsearch服务生效
# 查看es服务进程
[elkr@localhost config]$ ps -ef | grep elasticsearch
elkr      61719  61301  8 11:28 pts/0    00:00:45 /bin/java -Xms2g -Xmx2g -XX:+UseConcMarkSweepGC -XX:CMSInitiatingOccupancyFraction=75 -XX:+UseCMSInitiatingOccupancyOnly -XX:+AlwaysPreTouch -server -Xss1m -Djava.awt.headless=true -Dfile.encoding=UTF-8 -Djna.nosys=true -Djdk.io.permissionsUseCanonicalPath=true -Dio.netty.noUnsafe=true -Dio.netty.noKeySetOptimization=true -Dio.netty.recycler.maxCapacityPerThread=0 -Dlog4j.shutdownHookEnabled=false -Dlog4j2.disable.jmx=true -Dlog4j.skipJansi=true -XX:+HeapDumpOnOutOfMemoryError -Des.path.home=/usr/local/elkr/elasticsearch -cp /usr/local/elkr/elasticsearch/lib/* org.elasticsearch.bootstrap.Elasticsearch
elkr      61903  61301  0 11:37 pts/0    00:00:00 grep --color=auto elasticsearch
# 根据服务进程号61719,kill -9杀掉该进程,然后重启elasticsearch服务
[elkr@localhost config]$ kill -9 61719
[elkr@localhost elasticsearch]$ cd /usr/local/elkr/elasticsearch/bin
[elkr@localhost bin]$ nohup ./elasticsearch >/dev/null 2>&1 &
[elkr@localhost bin]$ curl http://192.168.63.131:9200
{
  "name" : "xLkn8-N",
  "cluster_name" : "elasticsearch",
  "cluster_uuid" : "cPIQF1XDReevoo4_uhbWjQ",
  "version" : {
    "number" : "5.6.0",
    "build_hash" : "781a835",
    "build_date" : "2017-09-07T03:09:58.087Z",
    "build_snapshot" : false,
    "lucene_version" : "6.6.0"
  },
  "tagline" : "You Know, for Search"
}

# 宿主机通过浏览器也可以访问,见下图
利用ELK+Redis搭建Nginx日志分析平台
(2)安装Elasticsearch-head可视化管理工具
注意:在elasticsearch 5.X版本中不支持直接安装head插件,网上有大量文章描述的是基于elasticsearch 2.X的版本可视化插件安装。
a. 下载插件工具,回到 /usr/local/elkr 目录下通过git下载插件,如果提示 git 命令不存在,执行 yum install git -y 安装

[elkr@localhost elkr]$ git clone git://github.com/mobz/elasticsearch-head.git       # 速度慢的话,可能需要科学上网,大家懂的
[elkr@localhost elkr]$ cd elasticsearch-head/
[elkr@localhost elasticsearch-head]$ npm install  # npm是随同NodeJS一起安装的包管理工具,若没有安装nodejs,这里需要装一下,否则提示命令不存在

b. 此前已经下载好了nodejs了,进入/usr/local/elkr/node 目录,现在安装。
注意:安装时若遇到g++命令不存在之类的错误,则需要解决下gcc环境,执行 yum -y install gcc automake autoconf libtool make 或 yum install gcc gcc-c++ 就可以了。

[elkr@localhost node]$ ./configure
[elkr@localhost node]$ make
[elkr@localhost node]$ make install
# 测试是否安装成功,显示版本号
[elkr@localhost node]$ node -v
v8.5.0
# 继续安装elasticsearch-head
[elkr@localhost elasticsearch-head]$ npm install   # 执行后等待安装完毕,速度慢的话,可能需要科学上网,大家懂的
# 执行完成后,进入 /node_modules/grunt 下
[elkr@localhost elasticsearch-head]$ cd node_modules/grunt
# 确认该目录下是否有grunt二进制程序,若没有,则需要执行下面操作
[elkr@localhost grunt]$ cd ../../
[elkr@localhost elasticsearch-head]$ npm install grunt --save
c. 编辑 elasticsearch-head 下 Gruntfile.js 配置文件,新增一项hostname,IP为当前虚拟机IP,保存
[elkr@localhost elasticsearch-head]$ vim Gruntfile.js
connect: {
                        server: {
                                options: {
                                        hostname:'192.168.63.131',
                                        port: 9100,
                                        base: '.',
                                        keepalive: true
                                }
                        }
                }

d. 编辑 elasticsearch-head/_site 下 app.js 配置文件,找到 “http://localhost:9200” 内容,修改成 elasticsearch 服务对应的地址,我这里应该修改成 http://192.168.63.131:9200
e. 编辑 /usr/local/elkr/elasticsearch/config/elasticsearch.yml 文件,新增如下内容
http.cors.enabled: true
http.cors.allow-origin: “*”
保存后,重启elasticsearch服务。目的是解决“集群健康值:未连接”的问题。
e. 启动 elasticsearch-head 服务并放至后台运行

[elkr@localhost elasticsearch-head]$ cd node_modules/grunt/bin/
[elkr@localhost bin]$ nohup ./grunt server >/dev/null 2>&1 &

好了,现在可以看到效果了,如下图:
利用ELK+Redis搭建Nginx日志分析平台
(3)因为后面Logstash需要用到redis服务,因此先安装Redis,切换到root用户,进入 /usr/local/elkr/redis 目录

[root@localhost redis]# make
[root@localhost redis]# make install
# 上述步骤执行成功后,切换至utils目录,使用脚本安装redis服务
# 在使用脚本安装服务的过程中,可以一路按回车完成安装。之后可以再次运行脚本文件,并通过输入不同的端口号建立多个Redis服务
[root@localhost redis]# cd utils/
[root@localhost utils]# ./install_server.sh
Welcome to the redis service installer
This script will help you easily set up a running redis server

Please select the redis port for this instance: [6379]
Selecting default: 6379
Please select the redis config file name [/etc/redis/6379.conf]
Selected default - /etc/redis/6379.conf
Please select the redis log file name [/var/log/redis_6379.log]
Selected default - /var/log/redis_6379.log
Please select the data directory for this instance [/var/lib/redis/6379]
Selected default - /var/lib/redis/6379
Please select the redis executable path [/usr/local/bin/redis-server]
Selected config:
Port           : 6379
Config file    : /etc/redis/6379.conf
Log file       : /var/log/redis_6379.log
Data dir       : /var/lib/redis/6379
Executable     : /usr/local/bin/redis-server
Cli Executable : /usr/local/bin/redis-cli
Is this ok? Then press ENTER to go on or Ctrl-C to abort.
Copied /tmp/6379.conf => /etc/init.d/redis_6379
Installing service...
Successfully added to chkconfig!
Successfully added to runlevels 345!
Starting Redis server...
Installation successful!
# 启动redis服务
[root@localhost utils]# systemctl start redis_6379
[root@localhost utils]# systemctl status redis_6379
● redis_6379.service - LSB: start and stop redis_6379
   Loaded: loaded (/etc/rc.d/init.d/redis_6379; bad; vendor preset: disabled)
   Active: active (exited) since Sun 2017-09-17 16:11:32 CST; 6s ago
     Docs: man:systemd-sysv-generator(8)
  Process: 10584 ExecStart=/etc/rc.d/init.d/redis_6379 start (code=exited, status=0/SUCCESS)

Sep 17 16:11:31 localhost.localdomain systemd[1]: Starting LSB: start and st...
Sep 17 16:11:31 localhost.localdomain redis_6379[10584]: /var/run/redis_6379...
Sep 17 16:11:32 localhost.localdomain systemd[1]: Started LSB: start and sto...
Hint: Some lines were ellipsized, use -l to show in full.
# 测试redis是否正常可用
[root@localhost utils]# cd /usr/local/bin/
[root@localhost bin]# redis-cli
127.0.0.1:6379> set name yangcheng
OK
127.0.0.1:6379> get name
"yangcheng"
127.0.0.1:6379> exit
[root@localhost bin]#
# 为了便于服务器IP远程访问redis,需要修改配置文件redis.conf
# 找到当前生效的 bind 127.0.0.1 这行,修改为 bind 127.0.0.1 192.168.63.131
# 启用redis密码,找到#requirepass foobared这行,去掉注释,并将foobared修改为123456
# 重启redis
[root@localhost conf]# systemctl restart redis_6379  # 或者 ps -ef | grep redis 找到相关进程,kill掉,再启动redis
[root@localhost redis]# redis-cli -h 192.168.63.131 -p 6379 -a 123456
192.168.63.131:6379> set a b
OK
192.168.63.131:6379> get a
"b"
192.168.63.131:6379> exit
[root@localhost redis]#

(4)Logstash(不需要编译安装,解压后配置好相关文件,启动即可使用)
此处需要区分客户端和服务端,我这里把192.168.63.129当做客户端,程序包和131服务器文件存放路径一致,129上也是在 /usr/local/elkr/logstash目录
【客户端】配置129上Logstash配置文件,进入 /usr/local/elkr/logstash/config/下面,新建配置文件存放目录myconf,新建 shipper.conf

[elkr@localhost myconf]$ vim shipper.conf
input {
    file {
        path => [
            "/usr/local/nginx/logs/access.log"
        ]
    }
}
output {
    # 输出到控制台
    # stdout { }
    redis{
        host => "192.168.63.131"
        port => 6379
        password => "123456" #如果有安全认证,此项为密码
        db => 8
        data_type => "channel"
        key => "logstash_list_0"
    }
}

【服务端】配置131上Logstash相关配置文件,进入 /usr/local/elkr/logstash/config/下面,新建配置文件存放目录myconf,新建 indexer.conf

[elkr@localhost myconf]$ vim indexer.conf
input {
        redis {
                host => "192.168.63.131"
                port => 6379
                password => "123456" #如果有安全认证,此项为密码
                db => 8
                data_type => "channel"
                key => "logstash_list_0" #与客户端保持一致
                batch_count => 1  # 队列中读取数据时,一次性取出多少条,1表示不使用该功能
        }
}

output{
        #这里,我把获取到的信息存到日志文件里,用于测试效果,后面可以将此处改成存放至es中
        file {
                path => "/usr/local/elkr/logstash/logs/all.log" # 可以查看此日志信息内容确认是否正常获取到消息
                flush_interval => 0
        }
}
# 启动131上logstash的indexer
[elkr@localhost bin]$ ./logstash -f /usr/local/elkr/logstash/config/myconf/indexer.conf # 读 redis日志输出到logstash指定日志文件
OpenJDK 64-Bit Server VM warning: If the number of processors is expected to increase from one, then you should configure the number of parallel GC threads appropriately using -XX:ParallelGCThreads=N
Sending Logstash's logs to /usr/local/elkr/logstash/logs which is now configured via log4j2.properties
[2017-10-16T00:21:58,704][INFO ][logstash.modules.scaffold] Initializing module {:module_name=>"fb_apache", :directory=>"/usr/local/elkr/logstash/modules/fb_apache/configuration"}
[2017-10-16T00:21:58,706][INFO ][logstash.modules.scaffold] Initializing module {:module_name=>"netflow", :directory=>"/usr/local/elkr/logstash/modules/netflow/configuration"}
[2017-10-16T00:21:59,211][INFO ][logstash.pipeline        ] Starting pipeline {"id"=>"main", "pipeline.workers"=>1, "pipeline.batch.size"=>125, "pipeline.batch.delay"=>5, "pipeline.max_inflight"=>125}
[2017-10-16T00:21:59,230][INFO ][logstash.inputs.redis    ] Registering Redis {:identity=>"redis://<password>@192.168.63.131:6379/8 channel:logstash_list_0"}
[2017-10-16T00:21:59,267][INFO ][logstash.pipeline        ] Pipeline main started
[2017-10-16T00:21:59,488][INFO ][logstash.inputs.redis    ] Subscribed {:channel=>"logstash_list_0", :count=>1}
[2017-10-16T00:21:59,548][INFO ][logstash.agent           ] Successfully started Logstash API endpoint {:port=>9600}
# 启动129上logstash的shipper
[elkr@localhost bin]$ ./logstash -f /usr/local/elkr/logstash/config/myconf/shipper.conf  # 收集 nginx 日志输出到 redis
OpenJDK 64-Bit Server VM warning: If the number of processors is expected to increase from one, then you should configure the number of parallel GC threads appropriately using -XX:ParallelGCThreads=N
Sending Logstash's logs to /usr/local/elkr/logstash/logs which is now configured via log4j2.properties
[2017-10-16T00:22:35,661][INFO ][logstash.modules.scaffold] Initializing module {:module_name=>"fb_apache", :directory=>"/usr/local/elkr/logstash/modules/fb_apache/configuration"}
[2017-10-16T00:22:36,020][INFO ][logstash.modules.scaffold] Initializing module {:module_name=>"netflow", :directory=>"/usr/local/elkr/logstash/modules/netflow/configuration"}
[2017-10-16T00:22:38,986][INFO ][logstash.pipeline        ] Starting pipeline {"id"=>"main", "pipeline.workers"=>1, "pipeline.batch.size"=>125, "pipeline.batch.delay"=>5, "pipeline.max_inflight"=>125}
[2017-10-16T00:22:39,622][INFO ][logstash.pipeline        ] Pipeline main started
[2017-10-16T00:22:40,095][INFO ][logstash.agent           ] Successfully started Logstash API endpoint {:port=>9600}
# 建议服务以后台进程运行模式启动,命令示例:
[elkr@localhost bin]$ nohup ./logstash -f /usr/local/elkr/logstash/config/myconf/XXX.conf >/dev/null 2>&1 &

我们可以测试一下,回到Logstash客户端即shipper所在主机,129服务器,模拟日志产生:

[root@localhost logs]# echo "Hello World" >> /usr/local/nginx/logs/access.log
# 再切换到indexer所在主机,即131服务器上查看是否收到该消息
[root@localhost logs]# tail -f /usr/local/elkr/logstash/logs/all.log
{"@version":"1","host":"localhost.localdomain","path":"/usr/local/nginx/logs/access.log","@timestamp":"2017-10-15T16:26:40.627Z","message":"Hello World"}
# 出现以上信息,表明nginx日志内容读取相关服务正常运行。
# 现在我们将服务端即131上Logstash的 配置文件 indexer.conf 输出更改成 存放至es中,修改内容如下:
output {
        elasticsearch{
                hosts => ["192.168.63.131:9200"]
        }
}
# 保存,重启 indexer.conf 服务(查找进程ps -ef | grep logstash 再 kill -9 进程号,然后启动服务)

回到Logstash客户端即shipper所在主机,129服务器,模拟日志产生:

[root@localhost logs]# echo "Yangcheng" >> /usr/local/nginx/logs/access.log

访问ES服务地址:http://192.168.63.131:9100/,查看数据是否正常写入进来了,下图可以看到数据已正常写入
利用ELK+Redis搭建Nginx日志分析平台
(4)Kibana已经解压过了,不需要安装,配置好相关文件即可,启动 Kibana 服务并放至后台运行,启动成功后,使用端口为5601

[elkr@localhost bin]$ cd /usr/local/elkr/kibana/bin
[elkr@localhost bin]$ nohup ./kibana >/dev/null 2>&1 &
[elkr@localhost bin]$ curl http://127.0.0.1:5601
<script>var hashRoute = '/app/kibana';
var defaultRoute = '/app/kibana';

var hash = window.location.hash;
if (hash.length) {
  window.location = hashRoute + hash;
} else {
  window.location = defaultRoute;
}</script>
[elkr@localhost bin]$

这里需要注意,Kibana默认是只能在虚拟机内部访问。接下来需要修改配置文件 /usr/local/elkr/kibana/config/kibana.yml
将 server.port 前面”#”去掉,端口号保持不变;
将 server.host 前面”#”去掉,并将”localhost”改成虚拟机IP “192.168.63.131”;
将 elasticsearch.url 前面”#”去掉,并将”http://localhost:9200″改成”http://192.168.63.131:9200″;
将 elasticsearch_preserve_host 前面”#”去掉;
将 kibana.index 前面”#”去掉。
保存,重启服务(可以通过 fuser -n tcp 5601 查看到进程号,然后 kill -9 进程号,再启动服务)
最后通过宿主机浏览器可以正常访问Kibana,如下图(点击Create按钮,可创建默认索引)
利用ELK+Redis搭建Nginx日志分析平台
点击左侧菜单列表中 Discover 查看es信息数据,如下图
利用ELK+Redis搭建Nginx日志分析平台
至此,已实现ELK+Redis日志分析平台完整搭建,上述各个服务除了由于远程访问或服务故障,有修改过配置文件外,服务其他配置项基本采用服务默认配置。如果要在生产环境使用则还需进行更多配置及优化处理。
描述不清楚的地方,还请多多指出,谢谢!

原创文章,作者:iConan,如若转载,请注明出处:https://www.aspyc.com/archives/499.html

发表评论

电子邮件地址不会被公开。 必填项已用*标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据

评论列表(4条)

  • iConan
    iConan 19/10/2017 下午12:44

    测试环境,可以删除副本分片,集群健康值会恢复绿色。 执行:curl -XPUT "http://192.168.63.131:9200/_settings&quot; -d' { "number_of_replicas" : 0 }'

  • iConan
    iConan 16/10/2017 上午3:16

    由于时间原因导致本该两个月前发布的文章,现在才发布。描述不对的地方,还请各位大神多多指点,谢谢!