常規的日誌收集方案中Client端都需要額外安裝一個Agent來收集日誌,例如logstash、filebeat等,額外的程式也就意味著環境的複雜,資源的佔用,有沒有一種方式是不需要額外安裝程式就能實現日誌收集呢?Rsyslog就是你要找的答案!
Rsyslog
Rsyslog是高速的日誌收集處理服務,它具有高效能、安全可靠和模組化設計的特點,能夠接收來自各種來源的日誌輸入(例如:file,tcp,udp,uxsock等),並通過處理後將結果輸出的不同的目的地(例如:mysql,mongodb,elasticsearch,kafka等),每秒處理日誌量能夠超過百萬條。
Rsyslog作為syslog的增強升級版本已經在各linux發行版預設安裝了,無需額外安裝。
收集Nginx日誌
ELK通過Rsyslog收集日誌流程圖如下:
- 處理流程為:Nginx --syslog--> Rsyslog --omkafka--> Kafka --> Logstash --> Elasticsearch --> Kibana
- Nginx產生日誌通過syslog系統服務傳給Rsyslog服務端,Rsyslog接收到日誌後通過omkafka模組將日誌寫入Kafka,Logstash讀取Kafka佇列然後寫入Elasticsearch,使用者通過Kibana檢索Elasticsearch裡儲存的日誌
- Rsyslog服務系統自帶無需安裝,所以整個流程中客戶端不需要額外安裝應用
- 服務端雖然Rsyslog也已安裝,但預設沒有omkafka模組,如果需要Rsyslog寫入Kafka需要先安裝這個模組
- omkafka模組在rsyslog v8.7.0之後的版本才支援,所以需要先通過
rsyslogd -v
命令檢視rsyslog版本,如果版本較低則需要升級
Rsyslog升級
1.新增rsyslog源的key
# apt-key adv --recv-keys --keyserver keys.gnupg.net AEF0CF8E
複製程式碼
2.新增rsyslog源地址
echo "deb http://debian.adiscon.com/v8-stable wheezy/" >> /etc/apt/sources.list
echo "deb-src http://debian.adiscon.com/v8-stable wheezy/" >> /etc/apt/sources.list
複製程式碼
3.升級rsyslog服務
# apt-get update && apt-get -y install rsyslog
複製程式碼
新增omkafka模組
1.安裝編譯工具,下邊autoreconf需要用到,不然無法生成configure檔案
# apt-get -y install pkg-config autoconf automake libtool unzip
複製程式碼
2.omkafka需要安裝一堆的依賴包
# apt-get -y install libdbi-dev libmysqlclient-dev postgresql-client libpq-dev libnet-dev librdkafka-dev libgrok-dev libgrok1 libgrok-dev libpcre3-dev libtokyocabinet-dev libglib2.0-dev libmongo-client-dev libhiredis-dev
# apt-get -y install libestr-dev libfastjson-dev uuid-dev liblogging-stdlog-dev libgcrypt-dev
# apt-get -y install flex bison librdkafka1 librdkafka-dev librdkafka1-dbg
複製程式碼
3.編譯安裝omkafka模組
# mkdir tmp && cd tmp
# git init
# git pull git@github.com:VertiPub/omkafka.git
# autoreconf -fvi
# ./configure --sbindir=/usr/sbin --libdir=/usr/lib --enable-omkafka && make && make install && cd ..
複製程式碼
Rsyslog收集nginx日誌
Client端Nginx配置
log_format jsonlog '{'
'"host": "$host",'
'"server_addr": "$server_addr",'
'"http_x_forwarded_for":"$http_x_forwarded_for",'
'"remote_addr":"$remote_addr",'
'"time_local":"$time_local",'
'"request_method":"$request_method",'
'"request_uri":"$request_uri",'
'"status":$status,'
'"body_bytes_sent":$body_bytes_sent,'
'"http_referer":"$http_referer",'
'"http_user_agent":"$http_user_agent",'
'"upstream_addr":"$upstream_addr",'
'"upstream_status":"$upstream_status",'
'"upstream_response_time":"$upstream_response_time",'
'"request_time":$request_time'
'}';
access_log syslog:server=rsyslog.domain.com,facility=local7,tag=nginx_access_log,severity=info jsonlog;
複製程式碼
1.Nginx在v1.10之後的版本才支援syslog的方式處理日誌,請確保你的Nginx版本高於1.10
2.為了降低logstash的處理壓力,同時也為了降低整個配置的複雜度,我們nginx的日誌直接採用json格式
3.拋棄文字檔案記錄nginx日誌,改用syslog直接將日誌傳輸到遠端的rsyslog伺服器,以便我們後續的處理;這樣做的另一個非常重要的好處是我們再也無需考慮nginx日誌的分割和定期刪除問題(一般我們為了方便管理通常會採用logrotate服務來對日誌進行按天拆分和定期刪除,以免磁碟被佔滿)
4.access_log直接輸出到syslog服務,各引數解釋如下:
- syslog:指明日誌用syslog服務接收
- server:接收syslog傳送日誌的Rsyslog服務端地址,預設使用udp協議,埠是514
- facility:指定記錄日誌訊息的型別,例如認證型別auth、計劃任務cron、程式自定義的local0-7等,沒有什麼特別的含義,不必深究,預設的值是local7
- tag:給日誌新增一個tag,主要是為了方便我們在服務端區分是哪個服務或者client傳來的日誌,例如我們這裡給了tag:
nginx_access_log
,如果有多個服務同時都寫日誌給rsyslog,且配置了不通的tag,在rsyslog服務端就可以根據這個tag找出哪些是nginx的日誌 - severity:定義日誌的級別,例如debug,info,notice等,預設是error
Server端Rsyslog配置
# cat /etc/rsyslog.d/rsyslog_nginx_kafka_cluster.conf
module(load="imudp")
input(type="imudp" port="514")
# nginx access log ==> rsyslog server(local) ==> kafka
module(load="omkafka")
template(name="nginxLog" type="string" string="%msg%")
if $inputname == "imudp" then {
if ($programname == "nginx_access_log") then
action(type="omkafka"
template="nginxLog"
broker=["10.82.9.202:9092","10.82.9.203:9092","10.82.9.204:9092"]
topic="rsyslog_nginx"
partitions.auto="on"
confParam=[
"socket.keepalive.enable=true"
]
)
}
:rawmsg, contains, "nginx_access_log" ~
複製程式碼
1.在rsyslog.d目錄下新增一個專門處理nginx日誌的配置檔案
2.rsyslog配置檔案重要配置解釋如下:
- module:載入模組,這裡我們需要載入imudp模組來接收nginx伺服器syslog發過來的日誌資料,也需要載入omkafka模組來將日誌寫入到kafka
- input:開啟udp協議,埠514,也可以同時開啟tcp協議,兩者可以共存
- template:定義一個模板,名字叫nginxLog,模板裡可以定義日誌的格式,因為我們傳的已經是json了,不需要再匹配格式,所以這裡不額外定義,注意模板名字要唯一
- action:在匹配到inputname為
imudp
且programname為nginx_access_log
(就是我們上邊nginx配置裡邊的tag)之後的處理方式,這裡的配置為匹配到的日誌通過omkafka模組寫入kafka叢集,還有一些關於omkafka更詳細的配置參考上邊給出的omkafka模組官方文件 - :rawmsg, contains:最後這一行的意思是忽略包含
nginx_access_log
的日誌,沒有這一行的話rsyslog服務預設會把所有日誌都記錄到message裡邊一份,我們已經把日誌輸出到kafka了,本地就沒必要再記錄了
3.omkafka模組檢查kafka裡邊topic是否存在,如果不存在則建立,無需手動建立kafka的topic
Server端logstash配置
input {
kafka {
bootstrap_servers => "10.82.9.202:9092,10.82.9.203:9092,10.82.9.204:9092"
topics => ["rsyslog_nginx"]
}
}
filter {
mutate {
gsub => ["message", "\\x", "\\\x"]
}
json {
source => "message"
}
date {
match => ["time_local","dd/MMM/yyyy:HH:mm:ss Z"]
target => "@timestamp"
}
}
output {
elasticsearch {
hosts => ["10.82.9.205", "10.82.9.206", "10.82.9.207"]
index => "rsyslog-nginx-%{+YYYY.MM.dd}"
}
}
複製程式碼
重要配置引數解釋如下:
- input:配置kafka的叢集地址和topic名字
- filter:一些過濾策略,因為傳入kafka的時候是json格式,所以不需要額外處理,唯一需要注意的是如果日誌中有中文,例如url中有中文內容時需要替換
\\x
,不然json格式會報錯 - output:配置ES伺服器叢集的地址和index,index自動按天分割
聯調測試
配置完成後分別重啟rsyslog服務和nginx服務,訪問nginx產生日誌
1.檢視kafka是否有正常生成topic
# bin/kafka-topics.sh --list --zookeeper 127.0.0.1:2181
__consumer_offsets
rsyslog_nginx
複製程式碼
2.檢視topic是否能正常接收日誌
# bin/kafka-console-consumer.sh --zookeeper localhost:2181 --topic rsyslog_nginx
{"host": "domain.com","server_addr": "172.17.0.2","http_x_forwarded_for":"58.52.198.68","remote_addr":"10.120.89.84","time_local":"28/Aug/2018:14:26:00 +0800","request_method":"GET","request_uri":"/","status":200,"body_bytes_sent":1461,"http_referer":"-","http_user_agent":"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36","upstream_addr":"-","upstream_status":"-","upstream_response_time":"-","request_time":0.000}
複製程式碼
3.kibana新增index,檢視Elasticsearch中是否有資料,如果前兩步都正常,kibana搜不到index或index沒有資料,多半是index名字寫錯了之類的基礎問題,仔細檢查
kibana查詢展示
-
開啟Kibana新增
rsyslog-nginx-*
的Index,並選擇timestamp,建立Index Pattern -
進入Discover頁面,可以很直觀的看到各個時間點請求量的變化,根據左側Field實現簡單過濾,例如我們想檢視所有訪問狀態為404的uri,可以點選request_uri和status後邊的add,這兩項的內容將出現在右側,然後點選status下邊404狀態碼後邊的加號,則只檢視狀態為404的請求,點選上方auto-refresh可以設定頁面自動重新整理時間
-
通過各種條件的組合查詢可以實現各種各樣的需求,例如每秒請求、頻寬佔用、異常比例、慢響應、TOP IP、TOP URL等等各種情況,並且可以通過Visualize很方便的將這些資訊繪製圖示,生成Dashboard儲存
寫在最後
- Nginx的access log絕對是網站的一個寶藏,通過日誌量的變化可以知道網站的流量情況,通過對status狀態的分析可以知道我們提供服務的可靠性,通過對特定活動url的追蹤可以實時瞭解活動的火爆程度,通過對某些條件的組合查詢也能為網站運營提供建議和幫助,從而使我們的網站更友好更易用
- Rsyslog服務的單點問題可以通過部署多個Rsyslog服務過三層負載來保證高可用,不過以我們的經驗來說rsyslog服務還是很穩定的,跑了一年多,每分鐘日誌處理量在20w左右,沒有出現過當機情況,不想這麼複雜的話可以寫個check rsyslog服務狀態的指令碼跑後臺,掛了自動拉起來
- 整個過程中我們使用了UDP協議,第一是因為Nginx日誌的syslog模式預設支援的就是UDP協議,翻了官網沒找到支援TCP的方式,我想這也是考慮到UDP協議的效能要比TCP好的多,第二也考慮到如果使用TCP遇到網路不穩定的情況下可能會不停的重試或等待,影響到Nginx的穩定。對於因為內容過長超過乙太網資料幀長度的問題暫時沒有遇到
如果你覺得文章對你有幫助,請轉發分享給更多的人。如果你覺得讀的不盡興,推薦閱讀以下文章: