ELK之logstash

下載安裝(Redhat/Centos7)

  • rpm --import http://packages.elasticsearch.org/GPG-KEY-elasticsearch cat > /etc/yum.repos.d/logstash.repo <<EOF [logstash-5.0] name=logstash repository for 5.0.x packages baseurl=http://packages.elasticsearch.org/logstash/5.0/centos gpgcheck=1 gpgkey=http://packages.elasticsearch.org/GPG-KEY-elasticsearch enabled=1 EOF yum clean all yum install logstash

hello world

  • # bin/logstash -e 'input{stdin{}}output{stdout{codec=>rubydebug}}'

logstash用不一樣的線程來實現對輸入信息處理以後顯示成咱們但願的樣子,logstash給每一個線程都取了名字,輸入的叫xx,過濾的叫\xxnode

數據在線程之間以事件的形式流傳,不要叫行,由於logstash能夠處理多行事件。python

logstash會給事件添加一些額外的信息,最重要的就是@timestamp,用來標記事件的發生時間。由於這個字段涉及到logstash的內部流轉,因此必須是一個joda對象,若是嘗試本身給一個字符串字段重命名爲@timestamp的話,logstash會直接報錯。因此請使用filters/data插件來管理這個特殊字段。linux

另外的幾個字段:ios

  • host標記發生位置
  • type標記事件的惟一類型
  • tags標記事件的某方面屬性。這是一個數組,一個事件能夠有多個標籤

你能夠隨意給事件添加字段或者從事件裏刪除字段。事實上事件就是一個Ruby對象,或者更簡單的理解爲就是一個哈希。git

注:每一個logstash過濾插件都有四個方法:github

add_tag、remove_tag、add_field、remove_fieldweb

配置語法

logstash習慣用shipper、broker、indexer來描述數據流中不一樣進程的角色。正則表達式

語法

在不少的運維場景中並無用logstash做爲shipper,或者說 沒有用elasticsearch做爲是數據存儲,也就是沒有indexer。redis

logstash設計了本身的DSL--有點像Puppet的DSL,二者均是經過Ruby語言寫的--包括區域、註釋、數據類型(布爾值、字符串、數值、數組、哈希)。條件判斷,字段引用等。shell

區段

logstash用{}來定義區域。區域內能夠包括插件區域定義,能夠在一個區域中定義多個插件。插件區域內則能夠定義鍵值對設置。示例:

input{

stdin{}

syslog{}

}

數據類型

logstash支持少許的數據值類型

  • bool

debug => true

  • string

host => "hostname"

  • number

port => 514

  • array

match => ["datetime","UNIX","ISO8601"]

  • hash

option => {

key1 => "value1",

key2 => "value2"

}

注:若是版本低於1.2.0,哈希的語法跟數組是同樣的,示例:

match => ["field1","pattern1","field2","pattern2"]

字段引用

字段是logstash::Event對象的屬性。能夠想象字段就像一個鍵值對。若是你想在Logstash中使用字段的值,只須要把字段的名字寫在中括號中就好了,這就叫字段引用。

對於嵌套字段(也就是多維哈希表,或者叫哈希的哈希),每層字段名都寫在[]中。好比你能夠從geoip獲取到longitude值(這是個笨辦法,實際上有單獨的字段專門存這個數據的):

[geoip][location][0]

注:logstash的數組也支持倒序下標,及[geoip][location][-1]能夠獲取數組最後一個元素的值。

Logstash還支持變量內插,在字符串裏使用字段引用的方法是這樣:

「the longitude is %{[geoip][location][0]}」

條件判斷(condition)

Logstash從1.3.0版本開始支持條件判斷和表達式。

表達式支持下面這些操做符:

  • ==,!=,<,>,<=,>=
  • =~(匹配正則),!~(不匹配正則)
  • in(包含),not in(不包含)
  • and,or,nand(非與),xor(非或)
  • ()(複合表達式),!()(對複合表達式取反)

 

示例:

if "_grokparsefailure" not in [tags] {
} else if [status] !~ /^2\d\d/ or ( [url] == "/noc.gif" nand [geoip][city] != "beijing" ) {
} else {
}

命令行參數 

logstash提供了一個shell腳本叫logstash,方便快速運行。

  • -e

即執行。事實上你能夠不寫任何具體配置,直接運行bin/logstash -e ‘ ’達到相同的效果,這個參數的默認值是下面這樣的:

input{

       stdin{  }    

}

output{

        stdout{  }

}

  • --config或-f

即文件。bin/logstash -f agent.conf,或者bin/logstash -f /etc/logstash.d/

注:logstash列出目錄下全部文件時是字母排序的。而logstash配置段的filter和output都是順序執行的,因此順序很是重要。採用多文件管理的用戶,推薦採用數字編號方式命名配置文件,同時在配置中,嚴謹採用if判斷限定不一樣日誌的動做。

  • --configtest或-t

即測試。用來測試logstash讀取的配置文件是否存在語法錯誤。logstash配置語法是用grammar.treetop定義的,尤爲是使用了上一條提到的讀取目錄方式的讀者,尤爲要提早測試。

  • --log或-l

即日誌。logstash默認輸出日誌到標準錯誤。生產環境下你能夠經過bin/logstash -l log/logstash.log命令來統一存儲日誌。

  • --pipelinne-workers或-w

運行filter和output的pipeline線程的數量。默認是CPU核數。

  • --pipeline-batch-delay或-u

每一個logstash pipeline線程,在打包批量日誌的時候,最多等待毫秒數。默認是5ms。

  • --pluginpath或-P

能夠寫本身的插件,而後用bin/logstash --pluginpath /path/to/own/plugins進行加載。

  • -verbose

輸出必定的調試日誌。

設置文件

從logstash 5.0開始,新增了$LS_HOME/config/logstash.yml文件,能夠將全部的命令行參數都經過YAML文件方式設置。同時爲了反映命令行配置參數的層級關係,參數也都改爲用.而不是-了。

pipeline:

        workers:24

   bath:

    size:125

    delay:5

plugin的安裝

從logstash1.5.0版本開始,logstash將全部插件都獨立拆分紅gem包。這樣每一個插件均可以獨立更新,不用等待logstash自身作總體更新的時候才能使用。

爲了達到這個目標,logstash配置了專門的plugin管理命令

plugin用法說明

Usage:
    bin/logstash-plugin [OPTIONS] SUBCOMMAND [ARG] ...

Parameters:
    SUBCOMMAND                    subcommand
    [ARG] ...                     subcommand arguments

Subcommands:
    install                       Install a plugin
    uninstall                     Uninstall a plugin
    update                        Install a plugin
    list                          List all installed plugins

Options:
    -h, --help                    print help

 示例

bin/logstash-plugin list查看本機如今有多少插件可用(起始就是在vender/bundle/jruby/1.9/gems的目錄下)

若發佈新模塊logstash-output-webhdfs。只須要運行:bin/logstash-plugin install logstash-output-webhdfs

假如只是升級的話:bin/logstash-plugin update logstash-input-tcp

本地插件安裝

bin/logstash-plugin install /path/to/logstash-filter-crash.gem

執行成功後在logstash-5.0.0目錄下的Gemfile文件最後一行多出一段內容:

gem "logstash-filter-crash", "1.1.0", :path => "vendor/local_gems/d354312c/logstash-filter-mweibocrash-1.1.0"

同時Gemfile.jruby-1.9.lock文件開頭也會多出一段內容:

PATH
  remote: vendor/local_gems/d354312c/logstash-filter-crash-1.1.0
  specs:
    logstash-filter-crash (1.1.0)
      logstash-core (>= 1.4.0, < 2.0.0)

 長期運行

標準service方式

rpm發行包安裝的用戶:/etc/init.d/logstash腳本中,會加載/etc/init.d/functions庫文件,利用其中的daemon函數,將logstash進程做爲後臺程序運行。

因此只要確保配置文件存在於/etc/logstash/conf.d/目錄下全部的conf結尾的文件且無其餘文件,便可經過service logstash start啓動

最基礎的nohup方式

command
command > /dev/null
command > /dev/null 2>&1
command &
command > /dev/null &
command > /dev/null 2>&1 &
command &> /dev/null
nohup command &> /dev/null

想要維持一個長期後臺運行的logstash,你須要同時在命令前面加nohup,後面加&。

更優雅的SCREEN方式

screen算是linux運維一箇中高級技巧。經過screen命令建立的環境下運行的終端命令,其父進程不是sshd的登陸會話,而是screen。這樣就能夠避免用戶退出進程消失的問題,又隨時能從新接管回終端繼續操做。

建立獨立的screen命令:

screen -dmS elkscreen_1

接管連入建立的elkscreen_1

screen -r elkscreen_1

運行logstash以後,不要按Ctrl+C,而是按Ctrl+A+D,斷開環境。想要從新接管,依然screen -r elkscreen_1便可。

若建立了多個screen,可經過:

screen -list

最推薦的daemontools方式

daemontools工具:daemontools、python實現的supervisord、perl實現的ubic、ruby實現的god等。

以supervisord爲例,由於出現比較早,可經過epel倉庫直接安裝:

yum -y install supervisord --enablerepo=epel

 在/etc/supervisord.conf配置文件中添加內容,定義你要啓動的程序:

[program:elkpro_1]
environment=LS_HEAP_SIZE=5000m
directory=/opt/logstash
command=/opt/logstash/bin/logstash -f /etc/logstash/pro1.conf -w 10 -l /var/log/logstash/pro1.log
[program:elkpro_2]
environment=LS_HEAP_SIZE=5000m
directory=/opt/logstash
command=/opt/logstash/bin/logstash -f /etc/logstash/pro2.conf -w 10 -l /var/log/logstash/pro2.log

而後service supervisord start 便可。

logstash會以supervisord子進程的身份運行,你還可使用supervisordctl命令單獨控制一系列logstash子進程中某一個進程的啓停操做:

supervisorctl stop elkpro_2

  • 輸入插件

  • 讀取文件(File)

logstash使用一個名叫FileWatch的Ruby Gem庫來監聽文件變化。這個庫支持glob展開文件路徑,並且會記錄一個叫.sincedb的數據庫文件來跟蹤被監聽的日誌文件的當前讀取位置。因此,不要擔憂logstash會漏過你的數據。

sincedb文件中記錄了每一個被監聽文件的inide、major number、minor number和pos。

inode:在其餘博文中已經闡述;

major device number:能夠看作是設備驅動程序,被同一設備驅動程序管理的設備有相同的major device number。這個數字實際是Kernel中device driver table的索引。這個表保存着不一樣的設備驅動程序;

minor number:表明被訪問的具體設備,也就是說Kernel根據major device number找到的設備驅動程序,而後再從minor device number得到設備位置屬性。

 pos:包含發生錯誤的位置的絕對文件位置;

  • 配置示例

input {
    file {
        path => ["/var/log/*.log", "/var/log/message"]
        type => "system"
        start_position => "beginning"
    }
}
  • 解釋

有一些比較有用的配置項,能夠用來指定File Watch庫的行爲:

    •   discover_interval

logstash每隔多久去檢查一次被監聽的path下是否有新文件,默認15s。

    •   exclude

不想被監聽的文件能夠排除出去,這裏跟path同樣支持glob展開。

glob:所謂的 glob 模式是指 shell 所使用的簡化了的正則表達式。星號(*)匹配零個或多個任意字符;[abc]匹配任何一個列在方括號中的字符(這個例子要麼匹配一個 a,要麼匹配一個 b,要麼匹配一個 c);問號(?)只匹配一個任意字符;若是在方括號中使用短劃線分隔兩個字符,表示全部在這兩個字符範圍內的均可以匹配(好比 [0-9] 表示匹配全部 0 到 9 的數字)。

    •   close_older

一個已經監聽中的文件,若是超過這個值的時間內沒有更新內容,就關閉監聽它的文件句柄。默認是3600s。

    •   ignore_older

在每次檢查文件列表的時候,若是一個文件的最後修改時間超過這個值,就忽略這個文件。默認是86400s。

    •   sincedb_path

若是你不想用默認的$HOME/.sincedb(windows平臺上在C:\windows\System32\config\systemprofile\.sincedb),能夠經過這個配置定義sincedb文件到其餘位置。

    •   sincedb_write_interval

logstash每隔多久寫一次sincedb文件,默認是15s。

    •   stat_interval

logstash每隔多久檢查一次被監聽文件狀態(是否有更新,默認是1s)

    •   start_position

logstash從什麼位置開始讀取文件數據,默認是結束位置,也就是說logstash進程會以相似tail -f的形式運行。若是你是要導入原有數據,把這個設定成「beginning」,logstash進程就從頭開始讀取,相似less +F的形式運行。

  • 注意

一、一般你要導入原有數據進Elasticsearch的話,你還須要filter/date插件來修改默認的@timestamp字段值。

二、FileWatch只支持絕對路徑,並且會不自動遞歸目錄。因此有須要的話,請用數組方式都寫明具體哪些文件。

三、LogStash::Input::File只是在進程運行的註冊階段初始化一個FileWatch對象,因此它不能支持相似fluentd那樣的path=> 「/path/to/%{+yyyy/mm/dd/hh}.log」寫法。達到相同目的,你只能寫成path=>"/path/to/*/*/*/*.log"。FileWatch模塊提供了一個稍微簡單一點的寫法:/path/to/**/*.log,用**來縮寫表示遞歸所有子目錄。

四、在單個input/file中監聽的文件數量太多的話,每次啓動掃描構建監聽隊列會消耗較多的時間。給使用者的感受好像讀取不到同樣,這是正常現象。

五、start_position僅在該文件從未被監聽過的時候起做用,若是sincedb文件中已經有這個文件的inode記錄了,那麼logstash依然會從記錄的pos開始讀取數據。

六、由於windows平臺上沒有inode概念,logstash某些版本在windows平臺上監聽文件不是很靠譜,windows平臺上,推薦考慮使用nxlog做爲收集端。

  • 標準輸入(Stdin)

input {
    stdin {
        add_field => {"key" => "value"}
        codec => "plain"
        tags => ["add"]
        type => "std"
    }
}
  • 運行結果

用上面的新stdin設置從新運行一次最開始的hello world示例。建議你們把整段配置都寫入一個文本文件,而後運行命令:bin/logstash -f stdin.conf。輸入「hello world」並回車,你會在終端看到以下的輸出:

{
       "message" => "hello world", "@version" => "1", "@timestamp" => "2014-08-08T06:48:47.789Z", "type" => "std", "tags" => [ [0] "add" ], "key" => "value", "host" => "raochenlindeMacBook-Air.local" }
  • 解釋

type和tags是logstash事件中兩個特殊的字段。一般說咱們會在輸入區段中經過type來標記事件類型----咱們確定是提早能知道這個事件屬於什麼類型的。而tags這是在數據處理過程當中,由具體的插件來添加或者刪除的。

最多見的用法像下面這樣:

input {
    stdin {
        type => "web"
    }
}
filter {
    if [type] == "web" {
        grok {
            match => ["message", %{COMBINEDAPACHELOG}]
        }
    }
}
output {
    if "_grokparsefailure" in [tags] {
        nagios_nsca {
            nagios_status => "1"
        }
    } else {
        elasticsearch {
        }
    }
}
  • 讀取Syslog數據

syslog多是運維領域最流行的數據傳輸協議了。當你想從設備上收集系統日誌的時候,syslog應該會是你的第一選擇。尤爲是網絡設備,好比思科----syslog幾乎是惟一可行的辦法。

這裏只講如何把logstash配置成一個syslog服務器來接收數據。有關rsyslog的用法,稍後的類型項目中,會有更詳細的介紹。

  • 配置示例

input {
  syslog {
    port => "514"
  }
}
  • 運行結果

做爲簡單的測試,先暫停本機的syslog或rsyslog進程,而後啓動logstash進程(這樣就不會有端口衝突的問題)。如今,本機的syslog就會默認發送到logstash裏了。咱們能夠用自帶的logger命令行工具發送一條「hello world」信息到syslog裏,即logstash裏面。看到logstash輸出像下面這樣。

{
           "message" => "Hello World", "@version" => "1", "@timestamp" => "2014-08-08T09:01:15.911Z", "host" => "127.0.0.1", "priority" => 31, "timestamp" => "Aug 8 17:01:15", "logsource" => "raochenlindeMacBook-Air.local", "program" => "com.apple.metadata.mdflagwriter", "pid" => "381", "severity" => 7, "facility" => 3, "facility_label" => "system", "severity_label" => "Debug" }
  • 解釋

Logstash是用UDPSocket,TCPServer和Logstash::Filter::Grok來實現Logstash::Inputs::Syslog的。因此你起始能夠直接用logstash配置實現同樣的效果:

input {
  tcp {
    port => "8514"
  }
}
filter {
  grok {
    match => ["message", "%{SYSLOGLINE}" ]
  }
  syslog_pri { }
}
  • 最佳實踐

建議在使用Logstash::Inputs::Syslog的時候走TCP協議來傳輸數據;

由於具體實現中,UDP監聽器只用了一個線程,而TCP監聽器會在接收每一個鏈接的時候都啓動新的線程來處理後續步驟。

若是你已經使用UDP監聽收集日誌,用下行命令檢查你的UDP接收隊列的大小:



netstat -plnu | awk 'NR==1 || $4~/:514$/{print $2}' Recv-Q 228096

228096是UDP接收隊列的默認最大大小,這時候linux內核開始丟棄數據包了。

強 烈建議使用Logstash::Input::Tcp和Logstash::filters::Grok配合實現一樣的syslog功能。

雖然Logstash::Input::Syslog在使用TCPServer的時候能夠採用多線程處理的接收,可是在同一個客戶端數據處理中,其grok和date是一直在該線程中完成的,這會致使整體上的處理性能幾何級的降低,通過測試,TCPServer每秒能夠接收50000條數據,而在同一線程中啓用grok後每秒只能處理5000條,再加上date只能到500條。

纔將這兩步拆分到filters階段後,logstash支持對該階段插件單獨設置多線程運行,大大提升了整體處理性能。在相同環境下,logstash -f tcp.conf -w 20的測試中,整體處理性能能夠達到30000條數據。

注:測試採用 logstash 做者提供的 yes "<44>May 19 18:30:17 snack jls: foo bar 32" | nc localhost 3000 命令。出處見:https://github.com/jordansissel/experiments/blob/master/ruby/jruby-netty/syslog-server/Makefile

  •  貼士

 若是實在沒辦法切換到TCP協議,你能夠本身寫程序或者使用其餘基於異步IO框架(好比libev)的項目。下面是一個簡單的異步IO實現UDP監聽數據輸入Eleasticsearch的示例:

https://gist.github.com/chenryn/7c922ac424324ee0d695

  • 讀取網絡數據(TCP)

將來你可能會用到redis服務器或者其餘消息隊列系統做爲logstash broker的角色。不過logstash其實也有本身的TCP/UDP插件,在臨時任務的時候,也算能用,尤爲是測試環境。

小貼士:

雖然Logstash::Input::TCP用Ruby的Socket和Openssl庫實現了高級的SSL功能,但Logstash自己只能在SizedQueue中緩存20個事件。這就是建議在生產環境中換用其餘消息隊列的緣由。

  • 配置示例

input {
    tcp {
        port => 8888
        mode => "server"
        ssl_enable => false
    }
}
  • 常見場景

目前看來,Logstash::Input::TCP最多見的用法就是配合nc命令導入舊數據。在啓動logstash進程後,在另外一個終端運行以下的命令便可導入數據:

# nc 127.0.0.1 8888 < olddata 

這種作法比用Logstash::Input::File好,由於當nc命令結束,咱們就知道數據導入完畢了。而用input/file方式,logstash進程還會一直等待新數據輸入被監聽的文件,不能直接看出是否任務完成了。

 

 

 

 

 

 

 

 

未完待續……

相關文章
相關標籤/搜索