ELK-LogStash案例

1、需求解析

1.1、需求解析

对数据进行分析的方式无非就是图和表,所谓表的分析,就是将数据统计后,按照顺序排列起来,比如我们平常所说的TOPn、排名前5客户端IP、排名前5用户访问页面等。如果我们想看看我们的网站在全国各地的
分布热度,表虽然能够在一定程度上分析,但是理解起来不太方面,不能做到一目了然,而图就可以达到对应的效果。
 
接下来我们就需要实现将我们项目的客户端IP在全国地图展示出来,这个功能我们就需要一个IP数据库来识别客户端IP所在的地理位置。

1.2、IP地址数据库

GeoLite2(https://dev.maxmind.com/geoip/geoip2/geolite2/)是一个解压直接使用的城市IP地理位置数据库,支持IPv4和IPv6两种地址,GeoLite2的免费和收费版本,仅仅是精确度的差别,我们
教学用的就是最新的免费版本。据说每周二都会更新IP地址数据。
 
GeoIP根据经度和纬度生成 [geoip][location] 格式数据。该字段以GeoJSON格式存储。借助于Elasticsearch模板输出该格式字段添加到Elasticsearch索引的geo_point(GeoJSON格式即geoip),从而为其他应用程序提供GeoJSON的地理区域服务。

1.3、GeoJSON

GeoJSON格式示例:http://geojson.org/geojson-spec.html
   { "type": "GeometryCollection",
   "geometries": [
     { "type": "Point",
       "coordinates": [100.0, 0.0]
       },
     { "type": "LineString",
       "coordinates": [ [101.0, 0.0], [102.0, 1.0] ]
       }
   ]
   }
也就是说: 我们es中存储的数据是是json格式,属性值是单字符串格式,而IP数据库中的解析出来的经纬度也是浮 点型数字,而地图的位置标识以数组格式存在的,所以我们将输入到es之前,还需要对logstash接收的数据 进行定制修改,这就涉及到logstash的filter组件定制数据格式[数据类型(浮点型)
+数据组合(数组)]。 es模板示例: https://www.elastic.co/guide/en/logstash/current/plugins-outputselasticsearch.html

1.4、安装插件

logstash-plugin install logstash-filter-geoip
logstash-plugin install logstash-filter-mutate 
logstash-plugin install logstash-filter-useragent

logstash对于IP数据库的识别主要靠如下几个插件的功能
   # logstash-plugin list --verbose | egrep 'geoip|mutate|useragent'
   logstash-filter-geoip (7.2.2)
   logstash-filter-mutate (3.5.2)
   logstash-filter-useragent (3.3.1)
插件解析: useragent 从数据中获取用户相关属性信息 geoip 根据用户IP信息,获取具体地理位置信息 mutate 对数据进行格式转换

1.5、数据格式

# 定制数据格式
filter {
  geoip {
    source => "客户端IP字段名"                # 根据用户行为数据获取客户端IP地址
    add_field => { "新字段名称" => "属性值" } # 增加扩展字段,主要是数组格式的经纬度数据
  }
  mutate {
    convert => [ "属性", "数据格式"]          # 将普通字符串数据,转换为特点浮点类型
  }
}

2、实践-IP地址解析所属地域名字

2.1、需求分析

默认情况下,logstash已经加载了三种插件,所以我们可以直接对定制的json格式nginx日志数据进行改造,根据我们对geoip的了解,需要从以下几个方面来考虑:
在geoip使用source来指定客户端IP的获取字段名称,http_x_real_ip|http_x_forwarded_for source => "http_x_real_ip"
geoip需要借助于IP数据库文件来进行IP地址与经纬度的对应关系database => "path/to/GeoLite2数据库文件"
geoip的经纬度默认保存在:geoip.longitude和geoip.latitude属性中,以字符串的形式单独存在,

我们需要将其改造为一条数组格式的扩展属性,便于在地图上定位IP地理位置。 样式1:   add_field
=> [ "[geoip][coordinates]", "%{[geoip][longitude]}" ]   add_field => [ "[geoip][coordinates]", "%{[geoip][latitude]}" ]
样式2:   add_field
=> [ "[coordinates]", "%{[geoip][latitude]},%{[geoip][longitude]}" ]
IP地理位置的经纬度数值以浮点形式存在,所以需要进行扩展字段数据类型转换 mutate {     convert
=> [ "[geoip][coordinates]", "float"] }

2.2、准备地址数据库

root@logstash:~# dpkg -L logstash | grep mmdb
/usr/share/logstash/vendor/bundle/jruby/2.5.0/gems/logstash-filter-geoip-7.2.11-java/vendor/GeoLite2-ASN.mmdb
/usr/share/logstash/vendor/bundle/jruby/2.5.0/gems/logstash-filter-geoip-7.2.11-java/vendor/GeoLite2-City.mmdb

# 当然,我们还可以自己去官方网站去下载最新的ip地址数据库,不过软件安装的基本上就是我们想要的了,复制到指定的目录下
cp /usr/share/logstash/vendor/bundle/jruby/2.5.0/gems/logstash-filter-geoip-7.2.11-java/vendor/GeoLite2-City.mmdb /etc/logstash/GeoLite2-City.mmdb

2.3、logstash+filebeat+nginx模拟信息调试

2.3.1、logstash的配置

cat << 'CAT_END' > /etc/logstash/conf.d/my_nginx_geoip.conf
input {
  beats {
    port => 5044
    codec => json
  }
}
filter {
  if [log_type] == "access" {
    geoip {
      source => "http_x_real_ip"
      target => "geoip"
      database => "/etc/logstash/GeoLite2-City.mmdb"
      add_field => [ "[geoip][coordinates]", "%{[geoip][longitude]}" ]
      add_field => [ "[geoip][coordinates]", "%{[geoip][latitude]}" ]
    }
    mutate {
      convert => [ "[geoip][coordinates]", "float"]
    }
  }
}
output {
  stdout { codec => rubydebug }
}
CAT_END

# 属性解析:因为只有access的日志才有http_x_real_ip,所以我们需要结合if语句来获取正常的访问日志

2.3.2、启动logstash

logstash -f my_nginx_geoip.conf

2.3.3、配置filebeat并且启动

cat << 'CAT_END' > /etc/filebeat/my_nginx_json.yml 
filebeat.inputs:
- type: log
  id: nginx_access_json
  enabled: true
  paths:
    - /var/log/nginx/access_json.log
  fields:
    log_type: "access"
  fields_under_root: true
  json.keys_under_root: true
  json.overwrite_keys: true
- type: log
  id: nginx_error
  enabled: true
  paths:
    - /var/log/nginx/error.log
  fields:
    log_type: "error"
  fields_under_root: true

setup.template.settings:
  index.number_of_shards: 5
  index.number_of_replicas: 1
output.logstash:
 hosts: ["192.168.10.28:5044"]
CAT_END

filebeat -f /etc/filebeat/my_nginx_json.yml 

2.3.4、访问nginx

# 中国广东深圳
curl http://192.168.10.30/ -H "X-Forwarded-For: 223.74.107.250" -H "X-Real-IP: 223.74.107.250"

2.3.5、查看logstash输出日志

{
                "log_type" => "access",
                "@version" => "1",
    "http_x_forwarded_for" => "223.74.107.250",
                    "host" => {
        "name" => "filebeat"
    },
...
                    "tags" => [
        [0] "beats_input_raw_event"
    ],
             "remote_user" => "-",
                   "geoip" => {
        "continent_code" => "AS",
         "country_code3" => "CN",
           "region_name" => "Guangdong",
              "latitude" => 22.5333,
              "location" => {
            "lon" => 114.1333,
            "lat" => 22.5333
        },
                    "ip" => "223.74.107.250",
          "country_name" => "China",
             "longitude" => 114.1333,
           "coordinates" => [
            [0] 114.1333,
            [1] 22.5333
        ],
         "country_code2" => "CN",
             "city_name" => "Shenzhen",
           "region_code" => "GD",
              "timezone" => "Asia/Shanghai"
    },
...
}

结果显示:我们根据IP地址,的确从IP数据库中获取到了地理位置的经纬度,而且在扩展字段coordinates中组合起来了
注意:如果是内网IP的话,会显示如下信息:[0] "_geoip_lookup_failure"、"geoip" => {}

2.4、改造logstash配置

2.4.1、配置logstash

cat << 'CAT_END' > /etc/logstash/conf.d/my_nginx_geoip.conf
input {
  beats {
    port => 5044
    codec => json
  }
}
filter {
  if [log_type] == "access" {
    geoip {
      source => "http_x_real_ip"
      target => "geoip"
      database => "/etc/logstash/GeoLite2-City.mmdb"
      add_field => [ "[geoip][coordinates]", "%{[geoip][longitude]}" ]
      add_field => [ "[geoip][coordinates]", "%{[geoip][latitude]}" ]
    }
    mutate {
      convert => [ "[geoip][coordinates]", "float"]
    }
  }
}
output {
 if [log_type] == "access"{
   elasticsearch {
   hosts => ["192.168.10.25:9200"]
   index => "logstash-nginx-geo-access-%{+yyyy.MM.dd}"
   }
 }
 if [log_type] == "error"{
   elasticsearch {
     hosts => ["192.168.10.25:9200"]
     index => "logstash-nginx-error-%{+yyyy.MM.dd}"
   }
 }
}
CAT_END

# 注意:
# 为了避免在后续kibana中绘图发生如下报错,我需要将索引名称设置为"logstash-*"开头样式
# The index pattern xx does not contain any of the following compatible field types: geo_point

2.4.2、启动服务

systemctl start logstash

2.4.3、检查端口是否开启

root@logstash:~# ss -tunlp | grep 5044
tcp   LISTEN 0      4096                    *:5044            *:*    users:(("java",pid=3293,fd=108))

2.4.4、编写shell脚本访问nginx

ip.txt文件下载:https://files.cnblogs.com/files/ygbh/ip.zip?t=1686206987&download=true
cat << 'CAT_END' > access_nginx_url.sh #!/bin/bash cat ip.txt | while read ip do num=$(echo $ip|cut -d"." -f 4) for i in $(seq ${num}) do curl http://192.168.10.30 -s -I -H "X-Forwarded-For: ${ip}" -H "X-Real-IP: ${ip}" >>/dev/null curl http://192.168.10.25/${num}/ -s >>/dev/null done sleep 1 done CAT_END

2.4.5、查询效果

 

posted @ 2023-06-08 09:46  小粉优化大师  阅读(35)  评论(0编辑  收藏  举报