elasticsearch 2.x 부터 Root로 보안상문제로 아래와 같이 실행되지 않음


Exception in thread "main" java.lang.RuntimeException: don't run elasticsearch as root.


그리고 shutdown 관련되서 기존 curl로 shutdown가 되지 않음 


https://www.elastic.co/guide/en/elasticsearch/reference/2.1/cluster-nodes-shutdown.html

The _shutdown API has been removed. Instead, setup Elasticsearch to run as a service (see Running as a Service on Linux or Running as a Service on Windows) or use the -p command line option to write the PID to a file.


yum(rpm)으로 설치 할 경우  init.d 스크립트를 만들어줘서 상관 없지만 그냥 소스 파일 가져다가 내가 원하는 위치에 압축풀어서 사용하므로 간단하게 만들었음 현재로서는 내가 원하는 기능만 간략하게~
상황에 따라서 추후 업데이트 예정

#!/bin/sh

DIR=$(echo $(cd $(dirname $0); pwd))

ES_HOME=${DIR}
ES_USER=elasticsearch
ES_HEAP_SIZE=1g
MAX_LOCKED_MEMORY=unlimited
MAX_OPEN_FILES=65535
MAX_MAP_COUNT=200000
PID=${ES_HOME}/elasticsearch.pid

if ! id -u "$ES_USER" >/dev/null 2>&1; then
    groupadd $ES_USER
    useradd -s /sbin/nologin -g $ES_USER $ES_USER
fi

case "$1" in
  start)
    chown -R ${ES_USER}.${ES_USER} ${DIR}

    if [ -n "$MAX_OPEN_FILES" ]; then
        ulimit -n $MAX_OPEN_FILES
    fi

    if [ -n "$MAX_LOCKED_MEMORY" ]; then
        ulimit -l $MAX_LOCKED_MEMORY
    fi

    if [ -n "$MAX_MAP_COUNT" -a -f /proc/sys/vm/max_map_count ]; then
        sysctl -q -w vm.max_map_count=$MAX_MAP_COUNT
    fi

    if [ -e ${PID} ] && [ ps -p `cat ${PID}` > /dev/null 2>&1 ]; then
       echo "Error - elasticsearch Running"
    else
       sudo -u ${ES_USER} ES_HEAP_SIZE="${ES_HEAP_SIZE}" ${ES_HOME}/bin/elasticsearch -d -p ${PID}
    fi

    ;;
  stop)
    if [ -e ${PID} ] ; then
       kill `cat ${PID}`
    fi
    ;;
  *)
    echo $"Usage: $0 {start | stop}"
    exit 1
esac
exit 0


추가로 host 처리 디폴트 localhost(127.0.0.1) 또는 아이피 동시 안되는 문제는 network.host 아래와 같이 하면됨

Allow binding to multiple addresses

https://github.com/elastic/elasticsearch/issues/13592

network.host: 0.0.0.0


Posted by 시니^^

Kibana Plugin 모음


https://github.com/elastic/kibana/wiki/Known-Plugins



Visualizations


Posted by 시니^^

elasticsearch 데이터를 넣으면 데이터를 보고 알아서 필드 타입 대해서 정의 해주는데 

상황에 따라서 정수와 실수에 대한 정의 또는 int와 bigint에 대한 처리를 해줘야 될때가 있다 

그럴 경우 특정 필드에서 대해서 매핑 처리가 가능하다

아래 래퍼런스 사이트 참조

https://www.elastic.co/guide/en/elasticsearch/reference/current/dynamic-templates.html


샘플 데이터 : curl -XPUT localhost:9200/_template/stat --upload-file template.json

{ "order":0, "template":"stat-*", "settings":{ "index.refresh_interval":"5s" }, "mappings":{ "_default_":{ "dynamic_templates":[ { "long_fields":{ //long "match":"long_*", "mapping":{ "type":"long" } } }, { "double_fields":{ //double "match":"double_*", "unmatch":"*_text", //외 처리 가능 레퍼런스보면 정규식형태도 있음 "mapping":{ "type":"double" } } }, { "string_fields":{ //string 드에 대한 처리 "match_mapping_type":"string", "match":"*", "mapping":{ "index":"analyzed", "omit_norms":true, "type":"string", "fields":{ "raw":{ "index":"not_analyzed", "ignore_above":256, "type":"string" } } } } } ], "_all":{ "enabled":true } } }, "aliases":{} }


Posted by 시니^^



kibana 에서 Unique Count 하는데 일상적으로 RDBMS에서 

SELECT DISTINCT(color) FROM cars

할때와 다르다


구글링 결과 아래 링크 참조 하면 이해가 될듯하다


https://www.elastic.co/guide/en/elasticsearch/guide/current/cardinality.html


The first approximate aggregation provided by Elasticsearch is the cardinality metric. This provides the cardinality of a field, also called a distinct or unique count. You may be familiar with the SQL version:



그래서 elasticsearch Distinct count 할 때 정밀도를 설정하는 부분이 있다

precision_threshold accepts a number from 0–40,000. Larger values are treated as equivalent to 40,000.

최대 4000까지 설정 할 수 있으며 위에 설정을 kibana에서도 설정 할 수 있는데 아래와 같이 하면 된다.



Practically speaking, a threshold of 100 maintains an error under 5% even when counting millions of unique values.

수치가 100의 경우 100만건 기준으로 5%로의 오차가 존재 할 수 있다고 한다.

참고하면 될듯함


Posted by 시니^^

elasticsearch Bulk insert(put) 대량 데이터 입력하기

공식 가이드 API : http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/docs-bulk.html


1) 데이터 파일 생성

$ vi put_data
{ "index":{ "_index" : "logstash-2015.03.06", "_type" : "access_log", "_id" : "1" } }
{ "host":"web01","http_host": "192.168.1.123"}
{ "index":{ "_index" : "logstash-2015.03.06", "_type" : "access_log", "_id" : "2" } }
{ "host":"web01","http_host": "192.168.1.124"}


2) Curl Post 로 전송

$ curl -s -XPOST localhost:9200/_bulk --data-binary @put_data
{"took":317,"errors":false,"items":[{"index":{"_index":"logstash-2015.03.06","_type":"access_log","_id":"1","_version":1,"status":201}},{"index":{"_index":"logstash-2015.03.06","_type":"access_log","_id":"2","_version":1,"status":201}}]}


3) 데이터 확인

$ curl -XGET localhost:9200/logstash-2015.03.06/access_log/1
{"_index":"logstash-2015.03.06","_type":"access_log","_id":"1","_version":1,"found":true,"_source":{ "host":"web01","http_host": "192.168.1.123"}}

$ curl -XGET localhost:9200/logstash-2015.03.06/access_log/2
{"_index":"logstash-2015.03.06","_type":"access_log","_id":"2","_version":1,"found":true,"_source":{ "host":"web01","http_host": "192.168.1.124"}}


4) index와 type이 동일하다면 url쓰고 제외해도됨

$ vi put_data 
{ "index":{ "_id" : "1" } }
{ "host":"web01","http_host": "192.168.1.123"}
{ "index":{ "_id" : "2" } }
{ "host":"web01","http_host": "192.168.1.124"}

$ curl -s -XPOST localhost:9200/logstash-2015.03.06/access_log/_bulk --data-binary @put_data
{"took":321,"errors":false,"items":[{"index":{"_index":"logstash-2015.03.06","_type":"access_log","_id":"1","_version":1,"status":201}},{"index":{"_index":"logstash-2015.03.06","_type":"access_log","_id":"2","_version":1,"status":201}}]}


※ UDP 방식도 있는 듯한데 2.0에서 삭제될 예정이라고함

Bulk UDP has been deprecated and will be removed in Elasticsearch 2.0. You should use the standard bulk API instead.


Curl 참조해서 다른 스크립트 언어에서도 POST 로 방식으로 짜면될듯함

node.js의 경우 라이브러리 활용하면 될 듯 : https://github.com/phillro/node-elasticsearch-client

//Bulk index example
var commands = []
commands.push({ "index" : { "_index" :'my_index_name', "_type" : "my_type_name"} })
commands.push({field1:'value',field2:'value'})


    elasticSearchClient.bulk(commands, {})
            .on('data', function(data) {})
            .on('done', function(done){})
            .on('error', function(error){})
            .exec();


Posted by 시니^^

elasticsearch index templates 만들기

가이드 : http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/indices-templates.html


1. GET을 이용한 저장된 전체 인덱스 템플릿가져오기

$ curl -XGET localhost:9200/_template/
{"logstash":{"order":0,"template":"logstash-*","settings":{"index.refresh_interval":"5s"},"mappings":{"_default_":{"dynamic_templates":[{"string_fields":{"mapping":{"index":"analyzed","omit_norms":true,"type":"string","fields":{"raw":{"index":"not_analyzed","ignore_above":256,"type":"string"}}},"match_mapping_type":"string","match":"*"}}],"properties":{"geoip":{"dynamic":true,"path":"full","properties":{"location":{"type":"geo_point"}},"type":"object"},"@version":{"index":"not_analyzed","type":"string"}},"_all":{"enabled":true}}},"aliases":{}},"nginx_log":{"order":0,"template":"nginx_log-*","settings":{"index.refresh_interval":"5s"},"mappings":{"_default_":{"dynamic_templates":[{"string_fields":{"mapping":{"index":"analyzed","omit_norms":true,"type":"string","fields":{"raw":{"index":"not_analyzed","ignore_above":256,"type":"string"}}},"match":"*","match_mapping_type":"string"}}],"properties":{"geoip":{"dynamic":true,"path":"full","properties":{"location":{"type":"geo_point"}},"type":"object"},"@version":{"index":"not_analyzed","type":"string"}},"_all":{"enabled":true}}},"aliases":{}}}

※ 2개 logstash / nginx_log  두개 인덱스 템플릿 등록된게 보인다


2. GET을 이용해서 하나만 지정해서 보기

$ curl -XGET localhost:9200/_template/nginx_log
{"nginx_log":{"order":0,"template":"nginx_log-*","settings":{"index.refresh_interval":"5s"},"mappings":{"_default_":{"dynamic_templates":[{"string_fields":{"mapping":{"index":"analyzed","omit_norms":true,"type":"string","fields":{"raw":{"index":"not_analyzed","ignore_above":256,"type":"string"}}},"match":"*","match_mapping_type":"string"}}],"properties":{"geoip":{"dynamic":true,"path":"full","properties":{"location":{"type":"geo_point"}},"type":"object"},"@version":{"index":"not_analyzed","type":"string"}},"_all":{"enabled":true}}},"aliases":{}}}


3. PUT 신규 템플릿 신규 등록

$ curl -XPUT localhost:9200/_template/nginx_log2 -d ' > { > "order":0, > "template":"nginx_log2-*", > "settings":{ > "index.refresh_interval":"5s" > }, > "mappings":{ > "_default_":{ > "dynamic_templates":[{ > "string_fields":{ > "mapping":{ > "index":"analyzed", > "omit_norms":true, > "type":"string", > "fields":{ > "raw":{ > "index":"not_analyzed", > "ignore_above":256, > "type":"string" > } > } > }, > "match_mapping_type":"string", > "match":"*" > } > } > ], > "properties":{ > "geoip":{ > "dynamic":true, > "path":"full", > "properties":{ > "location":{ > "type":"geo_point" > } > }, > "type":"object" > }, > "@version":{ > "index":"not_analyzed", > "type":"string" > } > }, > "_all":{ > "enabled":true > } > } > }, > "aliases":{ > } > }' {"acknowledged":true}


4. DELETE 템플릿 삭제

$ curl -XDELETE localhost:9200/_template/nginx_log2
{"acknowledged":true}


이것 외에도 GET할때 여러개 템플릿 같이 보기등 가이드사이트 가면 몇가지 예시 더 있음 참고할것!~

Posted by 시니^^

Elasticsearch  node.js를 이용해서 데이터 입력(PUT) 하기


logstash이 잘되어있어서 패턴 잘구성해서 logstash을 이용해도 되지만 logstash패턴 사용하는 법을 좀 봐야되고...

잘 사용법도 모르는 환경에서 계속 서비스 RDBMS에 커넥션 유지하는 것도 부담스러워서 따로 node.js로 짜기로함 


기본적으로 콘솔에서 curl 날리는 예시는 아래와 같음

$ curl -XPUT 'http://localhost:9200/logstash-2015.03.06/access_log/1' -d '{ > "host": "web01", > "http_host": "192.168.1.123", > "clientip": "192.2.3.55", > "timestamp": "Fri Feb 06 2015 14:04:22 GMT+0900 (KST)", > "verb": "GET", > "request": "/css/comm.css", > "httpversion": "1.1", > "response": "304", > "bytes": "0", > "referrer": "http://192.168.1.124/", > "agent": "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.17 (KHTML, like Gecko) Chrome/24.0.1312.56 Safari/537.17", > "request_time": 0 > }'


등록 결과  아래와 같이 나온걸 볼 수 있다

{"_index":"logstash-2015.03.06","_type":"access_log","_id":"1","_version":1,"created":true}


브라우져에서 head 들어가보면 확인 가능하다.

http://localhost:9200/_plugin/head/


이걸 node.js http라이브러리이용하면 간단하다.

var http = require('http'); function elasticsearchPut(index,type,id,put_data){ var option = { hostname: 'localhost', port: 9200, path: '/'+index+'/'+type+'/'+id, method: 'PUT' }; var req = http.request(option, function(res) { console.log('STATUS: ' + res.statusCode); console.log('HEADERS: ' + JSON.stringify(res.headers)); res.setEncoding('utf8'); res.on('data', function (chunk) { console.log(chunk); }); }); req.on('error', function(e) { console.log('problem with request: ' + e.message); }); // DATA PUT req.write(JSON.stringify(put_data)); req.end(); } var index = 'logstash-2015.03.06'; var type = 'access_log'; var id = 2; var data = { "host": "web01", "http_host": "192.168.1.123", "clientip": "192.2.3.55", "timestamp": "Fri Feb 06 2015 14:04:22 GMT+0900 (KST)", "verb": "GET", "request": "/css/comm.css", "httpversion": "1.1", "response": "304", "bytes": "0", "referrer": "http://192.168.1.124/", "agent": "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.17 (KHTML, like Gecko) Chrome/24.0.1312.56 Safari/537.17", "request_time": 0 }; elasticsearchPut(index,type,id,data);


콘솔에서 실행하면 아래와 같이 결과 메세지를 동일하게 볼 수 있다.

$ node test.js 
STATUS: 201
HEADERS: {"content-type":"application/json; charset=UTF-8","content-length":"91"}
{"_index":"logstash-2015.03.06","_type":"access_log","_id":"2","_version":1,"created":true}


예시로 nginx access_log로 했는데 실제 사용하는데는 이벤트나 구매내역등 실제 서비스로그를 RDBMS에서 주기적으로 가져와서 분석하는 용도로 사용함


추가적 node.js 라이브러리 및 Bulk insert 참고

elasticsearch Bulk insert(put) 대량 데이터 입력하기


Posted by 시니^^

각 툴에 대한 설명

1) elasticsearch => JAVA Lucene기반의 검색엔진

   URL : http://www.elasticsearch.org/

   Github : https://github.com/elasticsearch/elasticsearch


2) logstash => 실시간으로 다양한 로그를 가져와서 elasticsearch 넣어주는 역할

   URL :  http://logstash.net/

   Github : https://github.com/elasticsearch/logstash

   ※ logstash 경우 꼭 elasticsearch와 연동하지 않더라도 다양한 어플리케이션 로그를 input으로 받아서 다른 저장소로 전달하는 ouput 작업을 하기 위해서 쓰기 좋은 듯하다.


3) Kibana => elasticsearch와 연동해서 시각적으로 볼 수 있게 해주는 툴 node.js기반임

   URL :  http://www.elasticsearch.org/overview/kibana/

   Github : https://github.com/elasticsearch/kibana


설치 및 실행가이드

1. JAVA설치 - elasticsearch 사용하기 위해서 필요

$ yum install java
==================================================
 Package                              Arch        
==================================================
Installing:
 java-1.7.0-openjdk                   x86_64      
Installing for dependencies:
 flac                                 x86_64      
 giflib                               x86_64      
 jpackage-utils                       noarch      
 libasyncns                           x86_64      
 libsndfile                           x86_64      
 pulseaudio-libs                      x86_64      
 ttmkfdir                             x86_64      
 tzdata-java                          noarch      
 xorg-x11-fonts-Type1                 noarch      
Transaction Summary
==================================================
Install      10 Package(s)


2. elasticsearch 설치 및 실행

$ wget https://download.elasticsearch.org/elasticsearch/elasticsearch/elasticsearch-1.4.4.tar.gz
$ tar xvfz elasticsearch-1.4.4.tar.gz
$ cd elasticsearch-1.4.4/bin
$ ./elasticsearch -d
$ ps aux | grep elasticsearch 

※ 옵션 -d 데몬으로 백그라운드실행


※ ElasticSearch 모니터링 추가 Plugin 설치 

$ ./plugin -install mobz/elasticsearch-head

=> URL : http://localhost:9200/_plugin/head/


$ ./plugin -install lukas-vlcek/bigdesk 

=> URL :  http://localhost:9200/_plugin/bigdesk/


$ ./plugin -install lmenezes/elasticsearch-kopf

=> URL :  http://localhost:9200/_plugin/kopf/


3. Logstash 설치

$ wget https://download.elasticsearch.org/logstash/logstash/logstash-1.4.2.tar.gz
$ tar xvfz logstash-1.4.2.tar.gz


※ 테스트 Nginx Access Log 추가

  참고사이트 : http://www.bravo-kernel.com/2014/12/setting-up-logstash-1-4-2-to-forward-nginx-logs-to-elasticsearch/


1) nginx.conf 로그구조 수정 후 Nginx 재시작

http {
    log_format main '$http_host '
                    '$remote_addr [$time_local] '
                    '"$request" $status $body_bytes_sent '
                    '"$http_referer" "$http_user_agent" '
                    '$request_time '
                    '$upstream_response_time';
    access_log  /var/log/nginx/access.log  main;
}


2) nginx 패턴 추가

$ vi ./logstash-1.4.2/patterns/nginx 
NGUSERNAME [a-zA-Z\.\@\-\+_%]+
NGUSER %{NGUSERNAME}
NGINXACCESS %{IPORHOST:http_host} %{IPORHOST:clientip} \[%{HTTPDATE:timestamp}\] \"(?:%{WORD:verb} %{NOTSPACE:request}(?: HTTP/%{NUMBER:httpversion})?|%{DATA:rawrequest})\" %{NUMBER:response} (?:%{NUMBER:bytes}|-) %{QS:referrer} %{QS:agent} %{NUMBER:request_time:float} %{NUMBER:upstream_time:float}
NGINXACCESS %{IPORHOST:http_host} %{IPORHOST:clientip} \[%{HTTPDATE:timestamp}\] \"(?:%{WORD:verb} %{NOTSPACE:request}(?: HTTP/%{NUMBER:httpversion})?|%{DATA:rawrequest})\" %{NUMBER:response} (?:%{NUMBER:bytes}|-) %{QS:referrer} %{QS:agent} %{NUMBER:request_time:float

3) Nginx logstash conf 생성

$ vi ./logstash-1.4.2/log_list/nginx.conf

====================================================== input { file { path => "/var/log/nginx/access.log" } } filter { mutate { replace => { "type" => "nginx_access" } } grok { match => { "message" => "%{NGINXACCESS}" } } date { match => [ "timestamp" , "dd/MMM/YYYY:HH:mm:ss Z" ] } geoip { source => "clientip" } } output { elasticsearch { host => localhost port => 9200 protocol => http } stdout { codec => rubydebug } }

※ 데이터 읽어와서 NGINXACCESS 매칭해서 elasticsearch로 보내는 설정정보이다

   elasticsearch 외에도 logstash의 경우 다양한 input output방식으로 데이터를 실시간 전달가능하다.

※ protocol 디폴트가 node이므로 버젼에 따라서 Kibana 사용할려면 http 설정해줘야될 경우도 있다

자세한 내용 참고 : http://logstash.net/docs/1.4.2/outputs/elasticsearch


4) conf TEST 옵션으로 확인
$ ../bin/logstash -f nginx.conf -t
Configuration OK


5) logstash 실행

$ ../bin/logstash -f nginx.conf
{
         "message" => "192.168.25.111 192.0.0.30 [02/Mar/2015:15:10:37 +0900] \"GET /favicon.ico HTTP/1.1\" 404 3652 \"-\" \"Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.17 (KHTML, like Gecko) Chrome/24.0.1312.56 Safari/537.17\" 0.000 -",
        "@version" => "1",
      "@timestamp" => "2015-03-02T06:10:37.000Z",
            "host" => "testServer01",
            "path" => "/var/log/nginx/access.log",
            "type" => "nginx_access",
       "http_host" => "192.168.25.111",
        "clientip" => "192.0.0.30",
       "timestamp" => "02/Mar/2015:15:10:37 +0900",
            "verb" => "GET",
         "request" => "/favicon.ico",
     "httpversion" => "1.1",
        "response" => "404",
           "bytes" => "3652",
        "referrer" => "\"-\"",
           "agent" => "\"Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.17 (KHTML, like Gecko) Chrome/24.0.1312.56 Safari/537.17\"",
    "request_time" => 0.0
}


※ elasticsearch-head 설치했다면 http://localhost:9200/_plugin/head/ 데이터 확인


4. Kibana 설치

$ wget https://download.elasticsearch.org/kibana/kibana/kibana-4.0.0-linux-x64.tar.gz
$ tar xvfz kibana-4.0.0-linux-x64.tar.gz 
$ cd kibana-4.0.0-linux-x64

1) config 수정 ( port 및 elasticsearch_url 등)

$ vi config/kibana.yml ====================================================== # Kibana is served by a back end server. This controls which port to use. port: 5601 # The Elasticsearch instance to use for all your queries. elasticsearch_url: "http://localhost:9200"

※ 설치법 찾아보면 kibana_index: "logstash-*" 인덱스 수정하라고 하는 듯한데 logstash-*로 인덱스 잡아주면 아래 에러 나면서 사이트 접속이 안됨.....

Fatal Error Courier Fetch Error: unhandled error Error: Request to Elasticsearch failed: {"_index":"logstash-*","_type":"config","_id":"4.0.0","error":"[logstash-*] missing"}

   그래서 kibana_index: ".kibana" 그대로 유지하였더니 잘됨... 보니까 kibana_index란 셋팅하는 대쉬보드 정보 저장하는 저장소의 정보인듯함... 검색 인덱스 셋팅은 kibana 접속후에 아래와같이 Configure an index pattern에서 index 추가하면됨

2) 최종적으로 웹브라우져 켜서 config 에 설정한 port 로 접속하면됨

 - http://server_ip:5601 


※ visualization 과 Dashboard 설정하는 부분은 나중에 시간있을때 추가하는걸로~!!




Posted by 시니^^