《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