閱讀476 返回首頁    go 阿裏雲 go 技術社區[雲棲]


《ELK Stack權威指南 》第1章 入門示例

本節書摘來自華章出版社《ELK Stack權威指南 》一書中的第1章,第1節,作者饒琛琳,更多章節內容可以訪問雲棲社區“華章計算機”公眾號查看。



入 門 示 例

什麼是Logstash?為什麼要用Logstash?怎麼用Logstash?這是本章將要介紹的內容。本章從最基礎的知識著手,從以下幾步介紹Logstash的必備知識。1)下載安裝。介紹Logstash軟件的多種安裝部署方式,並給出推薦的方式。2)初次運行。通過Hello World示例,演示Logstash最簡單的運用,解釋其邏輯上的基礎原理。3)配置語法。介紹Logstash的DSL設計,Logstash命令的運行參數。4)插件安裝。靈活和豐富的插件是Logstash最重要的優勢。本節會介紹Logstash插件的安裝方式。5)長期運行方式。從初次終端測試到長期後台穩定運行,本節會介紹幾種不同方案,供讀者根據實際場景選擇。

1.1 下載安裝

1.下載

Logstash從1.5版本開始,將核心代碼和插件代碼完全剝離,並重構了插件架構邏輯,所有插件都以標準的Ruby Gem包形式發布。

下載官方軟件包的方式有以下幾種:

壓縮包方式

https://artifacts.elastic.co/downloads/logstash/logstash-5.1.1.tar.gz

Debian平台

https://artifacts.elastic.co/downloads/logstash/logstash-5.1.1.deb

Redhat平台

https://artifacts.elastic.co/downloads/logstash/logstash-5.1.1.rpm

2.安裝

在上麵這些包中,你可能更偏向使用rpm、dpkg等軟件包管理工具來安裝Logstash,開發者在軟件包裏預定義了一些依賴。比如,logstash-5.0.2就依賴於jre包。

另外,軟件包裏還包含有一些很有用的腳本程序,比如/etc/init.d/logstash。

如果你必須在一些很老的操作係統上運行Logstash,那你隻能用源代碼包部署了,記住要自己提前安裝好Java:

yum install openjdk-jre

export JAVA_HOME=/usr/java

tar zxvf logstash-5.0.2.tar.gz

3.最佳實踐

但是真正的建議是:如果可以,請用Elasticsearch官方倉庫來直接安裝Logstash!

Debian平台

wget -qO - https://artifacts.elastic.co/GPG-KEY-elasticsearch | sudo apt-key add -

sudo apt-get install apt-transport-https

echo "deb https://artifacts.elastic.co/packages/5.x/apt stable main" | sudo tee -a /etc/apt/sources.list.d/elastic-5.x.list

sudo apt-get update && sudo apt-get install logstash

Redhat平台

sudo rpm --import

https://artifacts.elastic.co/GPG-KEY-elasticsearch

sudo cat > /etc/yum.repos.d/elk.repo <<EOF

[logstash-5.x]

name=Elastic repository for 5.x packages

baseurl=https://artifacts.elastic.co/packages/5.x/yum

gpgcheck=1

gpgkey=https://artifacts.elastic.co/GPG-KEY-elasticsearch

enabled=1

autorefresh=1

type=rpm-md

EOF

sudo yum install -y logstash

enabled=1

EOF

yum clean all

yum install logstash

1.2 Hello World

與絕大多數IT技術介紹一樣,我們也以一個輸出“Hello World”的形式開始學習Logstash。

1.命令行運行

在終端中,像下麵這樣運行命令來啟動 Logstash 進程:

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

首先看到終端輸出一段進程啟動過程的提示輸出。提示以"Successfully started Logstash API endpoint {:port=>9600}"結束。

然後你會發現終端在等待你的輸入。沒問題,敲入Hello World,回車,看看會返回什麼結果!

{

"message" =>"Hello World",

"@version" =>"1",

"@timestamp" =>"2014-08-07T10:30:59.937Z",

"host" =>"raochenlindeMacBook-Air.local",

}

沒錯!就是這麼簡單。

2.完整示例

命令行運行當然不是什麼特別方便的用法,所以絕大多數情況下,我們都是采用額外定義一個logstash.conf配置文件的方式來啟動Logstash。下麵是我們的第一個完整版logstash.conf的示例:

input {

    stdin { }

}

output {

    stdout {

        codec => rubydebug {}

    }

    elasticsearch {

        Rost=>["127.0.0.1"]

    }

}

因為在5.0版本中,Elasticsearch和Kibana都是獨立服務。如果你按照上一節的最佳實踐配置好了yum的話,通過如下命令啟動服務即可:

# service elasticsearch start && service kibana start

然後在終端上這樣運行:

# bin/logstash -f logstash.conf

同樣,還是輸入一次Hello World。你會看到和上一次一樣的一段Ruby對象輸出。但事實上,這個完整示例可不止如此。打開另一個終端,輸入下麵一行命令:

# curl https://127.0.0.1:9200/_search?q=hello

你會看到終端上輸出下麵這麼一段內容:

{"took":15,"timed_out":false,"_shards":{"total":27,"successful":27,"failed":0},"hits":{"total":1,"max_score":0.095891505,"hits":[{"_index":"logstash-2015.08.22","_type":"logs","_id":"AU90s1eNgg_P5-w7SB32","_score":0.095891505,"_source":{"message":"Hello World","@version":"1","@timestamp":"2014-08-07T10:30:59.937Z","host":"raochenlindeMacBook-Air.local"}}]}}

這時候你打開瀏覽器,訪問https://127.0.0.1:5601地址,按照提示完成index pattern配置(正常的話隻需要點擊一下Create按鈕),即可點擊Discover頁麵看到如圖1-1所示的效果。你在終端上輸入的數據,可以從這個頁麵上任意搜索了。

 

圖1-1 Kibana上搜索的hello world

對index pattern配置有疑惑的讀者,可以閱讀本書第三部分關於Kibana的章節。

3.解釋

每位係統管理員都肯定寫過很多類似這樣的命令:cat randdata | awk '{print $2}' | sort | uniq -c | tee sortdata。這個管道符|可以算是Linux世界最偉大的發明之一(另一個是“一切皆文件”)。

Logstash就像管道符一樣!

輸入(就像命令行的cat)數據,然後處理過濾(就像awk或者uniq之類)數據,最後輸出(就像tee)到其他地方。

當然實際上,Logstash是用不同的線程來實現這些的。如果你運行top命令然後按下H鍵,你就可以看到下麵這樣的輸出:

    PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND

21401 root      16   0 1249m 303m  10m S 18.6  0.2 866:25.46 |worker

21467 root      15   0 1249m 303m  10m S  3.7  0.2 129:25.59 >elasticsearch.

21468 root      15   0 1249m 303m  10m S  3.7  0.2 128:53.39 >elasticsearch.

21400 root      15   0 1249m 303m  10m S  2.7  0.2 108:35.80 <file

21403 root      15   0 1249m 303m  10m S  1.3  0.2  49:31.89 >output

21470 root      15   0 1249m 303m  10m S  1.0  0.2  56:24.24 >elasticsearch.

如上例所示,Logstash很溫馨地給每類線程都取了名字,輸入的叫<xx,過濾的叫|xx,輸出的叫>xx。

數據在線程之間以事件的形式流傳。不要叫行,因為Logstash可以處理多行事件。

Logstash會給事件添加一些額外信息。最重要的就是@timestamp,用來標記事件的發生時間。因為這個字段涉及Logstash的內部流轉,所以必須是一個joda對象,如果你嚐試自己給一個字符串字段重命名為@timestamp的話,Logstash會直接報錯。所以,請使用logstash-filter-date插件來管理這個特殊字段。

此外,大多數時候,還可以見到另外幾個:

host標記事件發生在哪裏。

type標記事件的唯一類型。

tags標記事件的某方麵屬性。這是一個數組,一個事件可以有多個標簽。

你可以隨意給事件添加字段或者從事件裏刪除字段。事實上事件就是一個Ruby對象,或者更簡單地理解為就是一個哈希也行。

每個Logstash過濾插件,都會有四個方法叫add_tag、remove_tag、add_field和remove_field,它們在插件過濾匹配成功時生效。

推薦閱讀

官網上“the life of an event”文檔:https://logstash.net/docs/1.4.2/life-of-an-event

Elastic{ON}上《life of a logstash event》演講:https://speakerdeck.com/elastic/life-of-a-logstash-event

1.3 配置語法

Logstash社區通常習慣用Shipper、Broker和Indexer來描述數據流中不同進程各自的角色,如圖1-2所示。

 

圖1-2 Logstash角色說明

不過我見過很多運用場景裏都沒有用Logstash作為Shipper,或者說沒有用Elasticsearch作為數據存儲,也就是說也沒有Indexer。所以,我們其實不需要這些概念。隻需要學好怎麼使用和配置Logstash進程,然後把它運用到你的日誌管理架構中最合適它的位置就夠了。

1.3.1 語法

Logstash設計了自己的DSL,有點像Puppet的DSL,或許因為都是用Ruby語言寫的吧,區域、注釋、數據類型(布爾值、字符串數值、數組、哈希)都類似,條件判斷、字段引用等也一樣。

1.區段(section)

Logstash用{}來定義區域。區域內可以包括插件區域定義,你可以在一個區域內定義多個插件。插件區域內則可以定義鍵值對設置。示例如下:

input {

    stdin {}

    syslog {}

}

2.數據類型

Logstash支持少量的數據值類型:

希爾值(bool)

debug => true

字符串(string)

host =>"hostname"

數值(number)

port => 514

數組(array)

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

哈希(hash)

options => {

    key1 =>"value1",

    key2 =>"value2"

}

如果你用的版本低於1.2.0,哈希的語法跟數組是一樣的,像下麵這樣寫:

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

3.字段引用(field reference)

字段是 Logstash::Event對象的屬性。我們之前提過事件就像一個哈希一樣,所以你可以想象字段就像一個鍵值對。

如果你想在Logstash配置中使用字段的值,隻需把字段的名字寫在中括號[ ]裏就行了,這就叫“字段引用”。

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

[geoip][location][0]

Logstash的數組也支持倒序下標,即[geoip][location][-1]可以獲取數組最後一個元素的值。

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

"the longitude is %{[geoip][location][0]}"

4.條件判斷(condition)

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

表達式支持下麵這些操作符:

 "equality, etc: ==, !=, <, >, <=, >=

 "regexp: =~, !~

 "inclusion: in, not in

 "boolean: and, or, nand, xor

 "unary: !()

通常來說,你都會在表達式裏用到字段引用。比如:

if "_grokparsefailure" not in [tags] {

} else if [status] !~ /^2\d\d/ and [url] == "/noc.gif" {

} else {

}

1.3.2 命令行參數

Logstash提供了一個shell腳本叫logstash方便快速運行,下麵介紹它支持的參數:

1. -e

意即“執行”。我們在“Hello World”的時候已經用過這個參數了。事實上你可以不寫任何具體配置,直接運行bin/logstash -e ''可達到相同效果。這個參數的默認值是下麵這樣:

input {

    stdin { }

}

output {

    stdout { }

}

2. --config或-f

意即“文件”。真實運用中,我們會寫很長的配置,甚至可能超過shell所能支持的1024個字符長度。所以我們必把配置固化到文件裏,然後通過bin/logstash -f agent.conf這樣的形式來運行。

此外,Logstash還提供一個方便我們規劃和書寫配置的小功能。你可以直接用bin/logstash -f /etc/logstash.d/來運行。Logstash會自動讀取/etc/logstash.d/目錄下所有的文本文件,然後在自己內存裏拚接成一個完整的大配置文件,再去執行。

Logstash列出目錄下所有文件時是字母排序的。而Logstash配置段的filter和 output都是順序執行的,所以順序非常重要。采用多文件管理的用戶,推薦采用數字編號方式命名配置文件,同時在配置中嚴謹采用if判斷限定不同日誌的動作。

3. --configtest或-t

意即“測試”。用來測試Logstash讀取到的配置文件語法是否能正常解析。Logstash配置語法是用grammar.treetop定義的。尤其是使用了上一條提到的讀取目錄方式的讀者,尤其要提前測試。

4. --log或-l

意即“日誌”。Logstash默認輸出日誌到標準錯誤。生產環境下你可以通過bin/logstash -l logs/logstash.log命令來統一存儲日誌。

5. --pipeline-workers 或 -w

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

6. --pipeline-batch-size 或 -b

每個Logstash pipeline線程,在執行具體的filter和output函數之前,最多能累積的日誌條數,默認是125條。越大性能越好,同樣也會消耗越多的JVM內存。

7. --pipeline-batch-delay 或 -u

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

8. --pluginpath或-P

可以寫自己的插件,然後用bin/logstash --pluginpath /path/to/own/plugins加載它們。

如果你使用的Logstash版本在1.5.0-rc3到1.5.3之間,該參數一度被取消,請改用本地gem插件安裝形式。

9. --verbose

輸出一定的調試日誌。如果你使用的Logstash版本低於1.3.0,則用bin/logstash -v來代替。

10. --debug

輸出更多的調試日誌。如果你使用的Logstash版本低於1.3.0,則用bin/logstash -vv來代替。

1.3.3 設置文件示例

從Logstash 5.0開始,新增了$LS_HOME/config/logstash.yml文件,可以將所有的命令行參數都通過YAML文件方式設置。同時為了反映命令行配置參數的層級關係,參數也都改成用.而不用-了。

上小節的pipeline相關命令行參數,改用 YAML 文件的寫法如下:

pipeline:

    workers: 24

    batch:

        size: 125

        delay: 5

1.4 插件安裝

從Logstash 1.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查看本機現在有多少插件可用。(其實就在vendor/bundle/jruby/1.9/gems/目錄下。)

然後,假如你看到https://github.com/logstash-plugins/下新發布了一個logstash-output-webhdfs模塊(當然目前還沒有)。打算試試,就隻需運行如下命令:

bin/logstash-plugin install logstash-output-webhdfs

同樣,假如是升級,隻需運行如下命令即可:

bin/logstash-plugin update logstash-input-tcp

bin/logstash-plugin不但可以通過 rubygems平台安裝插件,還可以讀取本地路徑的gem文件,這對自定義插件或者無外接網絡的環境都非常有效:

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

執行成功以後。你會發現,logstash-5.0.2目錄下的 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)

1.5 長期運行方式

完成上一節的初次運行後,你可能會發現一點:一旦你按下Ctrl+C,停下標準輸入輸出,Logstash進程也就隨之停止了。作為一個肯定要長期運行的程序,應該怎麼處理呢?

本章節問題對於一個運維來說應該屬於基礎知識,鑒於ELK用戶很多其實不是運維,添加這段內容。

辦法有很多種,下麵介紹四種最常用的辦法。

1.標準的service方式

采用RPM、DEB發行包安裝的讀者,推薦采用這種方式。發行包內,都自帶有sysV或者systemd風格的啟動程序/配置,你隻需要直接使用即可。以RPM為例,/etc/init.d/logstash腳本中,會加載/etc/init.d/functions庫文件,利用其中的daemon函數,將Logstash 進程作為後台程序運行。

所以,你隻需把自己寫好的配置文件統一放在/etc/logstash/目錄下(注意目錄下所有配置文件都應該是.conf結尾,且不能有其他文本文件存在,因為logstash agent啟動的時候是讀取全文件夾的),然後運行service logstash start命令即可。

2.最基礎的nohup方式

這是最簡單的方式,也是Linux新手們很容易搞混淆的一個經典問題:

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,後麵加&。

3.更優雅的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

4. 最推薦的daemontools方式

不管是nohup還是screen,都不是可以很方便管理的方式,在運維管理一個ELK集群的時候,必須尋找一種盡可能簡潔的辦法。所以,對於需要長期後台運行的大量程序(注意大量,如果就一個進程,還是學習一下怎麼寫init腳本吧),推薦大家使用一款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子進程的身份運行,你還可以使用supervisorctl命令,單獨控製一係列 Logstash 子進程中某一個進程的啟停操作:

supervisorctl stop elkpro_2

最後更新:2017-05-19 14:33:36

  上一篇:go  《JAVA8開發指南》為什麼你需要關注 JAVA8
  下一篇:go  《Spark官方文檔》在YARN上運行Spark