使用ElasticSearch+LogStash+Kibana+Redis搭建日志管理服务

1. 日志平台的结构示意图

使用ElasticSearch+LogStash+Kibana+Redis搭建日志管理服务

说明:

  • 多个独立的agent(Shipper)负责收集不同来源的数据,一个中心agent(Indexer)负责汇总和分析数据,在中心agent前的Broker(使用redis实现)作为缓冲区,中心agent后的ElasticSearch用于存储和搜索数据,前端的Kibana提供丰富的图表展示。
  • Shipper表示日志收集,使用LogStash收集各种来源的日志数据,可以是系统日志、文件、redis、mq等等;
  • Broker作为远程agent与中心agent之间的缓冲区,使用redis实现,一是可以提高系统的性能,二是可以提高系统的可靠性,当中心agent提取数据失败时,数据保存在redis中,而不至于丢失;
  • 中心agent也是LogStash,从Broker中提取数据,可以执行相关的分析和处理(Filter);
  • ElasticSearch用于存储最终的数据,并提供搜索功能;
  • Kibana提供一个简单、丰富的web界面,数据来自于ElasticSearch,支持各种查询、统计和展示;

2. 搭建部署

环境:

  • 本机(20.8.40.49)上部署:redis, 中心agent(LogStash), ElasticSearch以及Kibana
  • 远程测试机(20.20.79.75)上部署:独立agent(LogStash)
  • Redis版本:3.0.0-rc1
  • LogStash版本;logstash-1.4.2
  • ElasticSearch版本:elasticsearch-1.3.4
  • Kibana版本:kibana-3.1.1

2.1 部署redis

部署一个redis单机实例:

$ wget https://github.com/antirez/redis/archive/3.0.0-rc1.tar.gz
$ tar zxvf 3.0.0-rc1.tar.gz -C /usr/local

 

redis.conf配置文件为:

include ../redis.conf
daemonize yes
pidfile /var/run/redis_6379.pid
port 6379
logfile /opt/logs/redis/6379.log
appendonly yes

 

启动:

$ redis.server redis.conf

ip为10.7.40.40, 端口为6379

2.2 部署中心LogStash

下载并解压:

$ wget https://download.elasticsearch.org/logstash/logstash/logstash-1.4.2.tar.gz
$ tar zxvf logstash-1.4.2.tar.gz -C /usr/local/
$ cd /usr/local/logstash-1.4.2
$ mkdir conf logs

配置文件conf/central.conf:

input {
    redis {
        host => "127.0.0.1"
        port => 6379
        type => "redis-input"
        data_type => "list"
        key => "key_count"
    }   
}

output {
    stdout {}
    elasticsearch {
        cluster => "elasticsearch"
        codec => "json"
        protocol => "http"
    }   
}

 

启动:

$ bin/logstash agent --verbose --config conf/central.conf --log logs/stdout.log

配置文件表示输入来自于redis,使用redis的list类型存储数据,key为”key_count”;输出到elasticsearch,cluster的名称为”elasticsearch”;

2.3 部署ElasticSearch

下载并解压:

$ wget https://download.elasticsearch.org/elasticsearch/elasticsearch/elasticsearch-1.3.4.tar.gz
$ tar zxvf elasticsearch-1.3.4.tar.gz -C /usr/local

elasticsearch使用默认配置即可,默认的cluster name为:elasticsearch;

启动:

$ bin/elasticsearch -d

2.4 部署远程LogStash

与部署中心LogStash的步骤是类似的,只是配置文件不一样,使用新的配置文件启动即可;

配置文件conf/shipper.conf的内容为:

input {
    file {
        type => "type_count"
        path => ["/data/logs/count/stdout.log", "/data/logs/count/stderr.log"]
        exclude => ["*.gz", "access.log"]
    }   
}

output {
    stdout {}
    redis {
        host => "20.8.40.49"
        port => 6379
        data_type => "list"
        key => "key_count"
    }   
}

配置文件表示输入来自于目录/data/logs/count/下的stdout.log和stderr.log两个文件,且排除该目录下所有.gz文件和access.log;(这里因为path没有使用通配符,所以exclude是没有效果的);输出表示将监听到的event发送到redis服务器,使用redis的list保存,key为”key_count”,这里的data_type属性和key属性应该与中心agent的配置一致;

2.5 部署Kibana

下载并安装:

$ wget https://download.elasticsearch.org/kibana/kibana/kibana-3.1.1.tar.gz
$ tar zxvf kibana-3.1.1.tar.gz

 

修改配置文件config.js,仅需要配置elasticsearch的地址即可:

elasticsearch: "http://20.8.40.49:9200"

 

将目录kibana-3.1.1拷贝到jetty的webapp目录下,并启动jetty:

$ mv kibana-3.1.1 /usr/local/jetty-distribution-9.2.1.v20140609/webapps/
$ bin/jetty start

 

浏览器访问:

http://20.8.40.49:8080/kibana-3.1.1/

 

3. 简单测试

打开LogStash的远程agent和中心agent的日志:

$ tail -f logs/stdout.log

 

远程agent的数据是以rpush操作将event推送到redis的list中,中心agent通过blpop命令从redis的list中提取数据,因此,测试时由于数据量小,通过命令llen key_count的返回结果很可能为空,因此为了观察redis中数据流的变化,可以使用monitor命令:

$ redis-cli -p 6379 monitor

 

现在,我们向/data/logs/count目录下的stdout.log和stderr.log各发送一条数据:

$ echo "stdout: just a test message" >> stdout.log
$ echo "stderr: just a test message" >> stderr.log

 

远程agent和中心agent都会收到event消息,如远程agent的日志为:

{:timestamp=>"2014-10-31T09:30:40.323000 0800", :message=>"Received line", :path=>"/data/logs/count/stdout.log", :text=>"stdout: just a test message", :level=>:debug, :file=>"logstash/inputs/file.rb", :line=>"134"}
{:timestamp=>"2014-10-31T09:30:40.325000 0800", :message=>"writing sincedb (delta since last write = 52)", :level=>:debug, :file=>"filewatch/tail.rb", :line=>"177"}
......
{:timestamp=>"2014-10-31T09:30:49.350000 0800", :message=>"Received line", :path=>"/data/logs/count/stderr.log", :text=>"stderr: just a test message", :level=>:debug, :file=>"logstash/inputs/file.rb", :line=>"134"}
{:timestamp=>"2014-10-31T09:30:49.352000 0800", :message=>"output received", :event=>{"message"=>"stderr: just a test message", "@version"=>"1", "@timestamp"=>"2014-10-31T01:30:49.350Z", "type"=>"type_count", "host"=>"dn1", "path"=>"/data/logs/count/stderr.log"}, :level=>:debug, :file=>"(eval)", :line=>"19"}

 

我们可以观察到redis的输出:

1414714174.936642 [0 20.20.79.75:54010] "rpush" "key_count" "{\"message\":\"stdout: just a test message\",\"@version\":\"1\",\"@timestamp\":\"2014-10-31T00:10:04.530Z\",\"type\":\"type_count\",\"host\":\"dn1\",\"path\":\"/data/logs/count/stdout.log\"}"
1414714174.939517 [0 127.0.0.1:56094] "blpop" "key_count" "0"
1414714198.991452 [0 20.20.79.75:54010] "rpush" "key_count" "{\"message\":\"stderr: just a test message\",\"@version\":\"1\",\"@timestamp\":\"2014-10-31T00:10:28.586Z\",\"type\":\"type_count\",\"host\":\"dn1\",\"path\":\"/data/logs/count/stderr.log\"}"
1414714198.993590 [0 127.0.0.1:56094] "blpop" "key_count" "0"

 

从elasticsearch中执行如下的简单查询:

$ curl \'localhost:9200/_search?q=type:type_count&pretty\'
{
  "took" : 3,
  "timed_out" : false,
  "_shards" : {
    "total" : 6,
    "successful" : 6,
    "failed" : 0
  },
  "hits" : {
    "total" : 2,
    "max_score" : 0.5945348,
    "hits" : [ {
      "_index" : "logstash-2014.10.31",
      "_type" : "type_count",
      "_id" : "w87bRn8MToaYm_kfnygGGw",
      "_score" : 0.5945348,
      "_source":{"message":"stdout: just a test message","@version":"1","@timestamp":"2014-10-31T08:10:04.530 08:00","type":"type_count","host":"dn1","path":"/data/logs/count/stdout.log"}
    }, {
      "_index" : "logstash-2014.10.31",
      "_type" : "type_count",
      "_id" : "wwmA2BD6SAGeNsuYz5ax-Q",
      "_score" : 0.5945348,
      "_source":{"message":"stderr: just a test message","@version":"1","@timestamp":"2014-10-31T08:10:28.586 08:00","type":"type_count","host":"dn1","path":"/data/logs/count/stderr.log"}
    } ]
  }
}

 

再切换到Kibana的web界面:http://20.8.40.49:8080/kibana-3.1.1

使用ElasticSearch+LogStash+Kibana+Redis搭建日志管理服务

4. 后续工作


  • 使用LogStash的Filter对日志数据进行过滤和分析;
  • 使用Redis的Cluster模式替换单机模式;
  • 在elasticsearch中对数据进行高级的分析和查询;
  • 熟悉Kibana的展示组件以及查询语法;

参考:

via: http://nkcoder.github.io

在WordPress中同时支持HTTP和HTTPS

  1. 2014.06.25更新: 目前本博客已同时支持HTTPHTTPS。其中HTTP版本针对中国大陆地区有所优化,比如避免了一些敏感链接;而HTTPS版本则显示正常页面,更适用于没有被墙的风险的用户们。

以下是原文:
之前有提到过给Wordpress启用HTTPS。后来碰到过一些问题,比如Amazon的S3不支持HTTPS的CName,以及不知道怎样让Wordpress同时支持HTTP和HTTPS,于是就暂时停掉了HTTPS。

前两天又心血来潮研究了一下,发现同时支持HTTP和HTTPS是可行的。在wp-config.php里改一点点就可以,如下:

$leonax_site_url = ($_SERVER["HTTPS"]?"https://":"http://")."leonax.net";
define('WP_SITE_URI', $leonax_site_url);
define('WP_SITEURI', $leonax_site_url);
define("WP_CONTENT_URL", $leonax_site_url . "/wp-content");

这样一来,当用户用HTTP访问的时候,Wordpress仍然会用http://leonax.net来响应;而当用户用HTTPS来访问的时候,Wordpress就会自动切换成https://leonax.net/. 站点的内部链接都会自动切换。

via:leonax.net

Mac OS 刷新DNS

OS X Yosemite

在 OS X Yosemite v10.10.4 中,请使用以下“终端”命令来还原 DNS 缓存设置:

sudo killall -HUP mDNSResponder

在 OS X Yosemite v10.10 至 v10.10.3 中,请使用以下“终端”命令来还原 DNS 缓存设置:

sudo discoveryutil mdnsflushcache

OS X Mavericks、Mountain Lion 和 Lion

请使用以下“终端”命令来还原 DNS 缓存设置:

sudo killall -HUP mDNSResponder

Mac OS X v10.6

请使用以下“终端”命令来还原 DNS 缓存设置:

sudo dscacheutil -flushcache

进程的守护神 – Supervisor

Supervisor是一个Python开发的client/server系统,可以管理和监控*nix上面的进程。不过同daemontools一样,它也不能监控daemon进程

部件

Supervisor有不同的部件组成,部件分别负责不同的功能,对进程进行监控和管理。

  • supervisord
    Supervisor的server部分称为supervisord。主要负责管理子进程,响应客户端的命令,log子进程的输出,创建和处理不同的事件

  • supervisorctl
    Supervisor的命令行客户端。它可以与不同的supervisord进程进行通信,获取子进程信息,管理子进程

  • Web Server
    Supervisor的web server,用户可以通过web对子进程进行监控,管理等等,作用与supervisorctl一致。

  • XML-RPC interface
    XML-RPC接口,提供XML-RPC服务来对子进程进行管理,监控

安装

安装supervisor很简单,通过pip就可以安装

sudo pip install supervisor

安装完成之后,就可以用"echo_supervisord_conf"命令来生成配置文件,例如

echo_supervisord_conf > /etc/supervisord.conf
echo_supervisord_conf > /path/to/supervisord.conf

配置

配置文件supervisord.conf是一个ini文件,可以对http_server、supervisord、supervisorctl和program进行配置。不过默认生成的文件已经对大部分进行配置,如果简单使用,只需要配置program的部分就可以了。

配置文件必须要有一个program配置项,这样supervisord才知道哪个program需要被管理和监控。例如下面tornado和nodejs应用的配置
“`
[program:tornado_app]
command=python /home/vagrant/tornado/app.py
startsecs=0
stopwaitsecs=0
autostart=true
autorestart=true
stdout_logfile=/home/vagrant/tornado/log/app.log
stderr_logfile=/home/vagrant/tornado/log/app.err

[program:node_app]
command=node /home/vagrant/node/app.js
startsecs=0
stopwaitsecs=0
autostart=true
autorestart=true
stdout_logfile=/home/vagrant/node/log/app.log
stderr_logfile=/home/vagrant/node/log/app.err
“`

启动

配置文件生成之后,就可以启动supervisord了

supervisord #默认使用/etc/supervisord.conf的配置文件
supervisord -c /path/to/supervisord.conf

当配置文件变化后,可以通过下面的命令reload conf,然后重启supervisord进程

kill -HUP cat /tmp/supervisord.pid #不过试了一下没有成功

通过supervisordctl管理进程

然后通过supervisorctl就可以监控管理program了
“`
$ supervisorctl -c conf/app.conf status
node_app RUNNING pid 6916, uptime 0:00:00
tornado_app RUNNING pid 6917, uptime 0:00:00

$ supervisorctl -c conf/app.conf stop node_app
node_app: stopped

$ supervisorctl -c conf/app.conf stop tornado_app
tornado_app: stopped

$ supervisorctl -c conf/app.conf status
node_app STOPPED Apr 04 02:34 AM
tornado_app STOPPED Apr 04 02:35 AM

$ supervisorctl -c conf/app.conf start all
node_app: started
tornado_app: started

$ supervisorctl -c conf/app.conf status
node_app RUNNING pid 8080, uptime 0:00:00
tornado_app RUNNING pid 8079, uptime 0:00:00
“`

通过web管理进程

如果配置文件开启http server,那么就可以通过web界面来管理program了。

$ grep -A 3 "inet_http_server" conf/app.conf
[inet_http_server] ; inet (TCP) server disabled by default
port=0.0.0.0:8383 ; (ip_address:port specifier, *:port for all iface)
#username=user ; (default is no username (open server))
#password=123 ; (default is no password (open server))

然后打开 http://domain.com:8383 就可以访问了

问题

通过supervisord可以很方便的管理program,可以同时管理多个program,也可以管理一个program的多个进程。而且提供了命令行、web、xml-rpc的接口来管理和监控进程,通过配置文件,可以指定进程挂掉后如何处理(可以重启或者其它方式处理挂掉的进程)

但是,supervisord本身也是一个program,如果它自己挂掉了怎么办?

via http://linbo.github.io/2013/04/04/supervisor/