ELK+Kafka搭建日誌系統

1.什麼是ELK

通俗來講,ELK 是由 Elasticsearch、Logstash、Kibana 三個開源軟件的組成,這三個軟件當中,每個軟件用於完成不同的功能。

  • Elasticsearch: elasticsearch是一個高度可擴展的開源全文搜索和分析引擎,它可實現數據的實時全文搜索搜索、支持分佈式可實現高可用、提供 API 接口,可以處理大規模日誌數據,比如 Nginx、Tomcat、系統日誌等功能。
  • Logstash: logstash可以通過插件實現日誌收集和轉發,支持日誌過濾,支持普通 log、自定義 json格式的日誌解析。
  • kibana: kibana主要是通過接口調用 elasticsearch 的數據,並進行前端數據可視化的展現。

爲什麼使用 ELK?
ELK 組件在海量日誌系統的運維中,可用於解決以下主要問題:

  • 分佈式日誌數據統一收集,實現集中式查詢和管理
  • 故障排查
  • 安全信息和事件管理
  • 報表功能

ELK 組件在大數據運維繫統中,主要可解決的問題如下:

  • 日誌查詢,問題排查,故障恢復,故障自愈
  • 應用日誌分析,錯誤報警
  • 性能分析,用戶行爲分析

官方站點:https://www.elastic.co/cn/

2.搭建ELK日誌系統

架構圖:
在這裏插入圖片描述由於 Logstash 比較耗資源,一般我們不會在應用服務器上直接安裝 Logstash 來收集日誌,我們可能會採用更輕量級的 Filebeat 來採集日誌,但當多臺 Filebeat 向 Logstash 傳輸數據再交給ES入庫時,壓力會比較大,可以在 Filebeat 和 Logstash 之間加上一層消息隊列減輕壓力,比如Redis、Kafka。

實驗環境:

系統 節點 JDK Zookeeper Kafka Elasticsearch logstash kibana
CentOS7.6 elk-node1 (192.168.100.111) jdk-8u212 zookeeper-3.4.14 kafka_2.12-2.1.0 elasticsearch-6.8.7 logstash-6.8.7 kibana-6.8.7
CentOS7.6 elk-node2 (192.168.100.112) jdk-8u212 zookeeper-3.4.14 kafka_2.12-2.1.0 elasticsearch-6.8.7 logstash-6.8.7 kibana-6.8.7
CentOS7.6 elk-node3 (192.168.100.113) jdk-8u212 zookeeper-3.4.14 kafka_2.12-2.1.0 elasticsearch-6.8.7 logstash-6.8.7

實驗準備:

~]# systemctl stop firewalld
~]# systemctl disable firewalld
~]# setenforce 0
~]# sed -i '/SELINUX/s/enforcing/disabled/g' /etc/sysconfig/selinux

~]# cat /etc/hosts
	...
	192.168.100.111 elk-node1
	192.168.100.112 elk-node2
	192.168.100.113 elk-node3

2.1 安裝JDK

下載地址:https://www.oracle.com/technetwork/java/javase/downloads/java-archive-javase8-2177648.html

~]# tar xf jdk-8u212-linux-x64.tar.gz -C /usr/local/
~]# cd /usr/local/
~]# ln -sv jdk1.8.0_212/ jdk
~]# echo 'JAVA_HOME=/usr/local/jdk' > /etc/profile.d/jdk.sh
~]# echo 'PATH=$JAVA_HOME/bin:$PATH' >> /etc/profile.d/jdk.sh
~]# . /etc/profile.d/jdk.sh
~]# java -version
	java version "1.8.0_212"
	Java(TM) SE Runtime Environment (build 1.8.0_212-b10)
	Java HotSpot(TM) 64-Bit Server VM (build 25.212-b10, mixed mode)

2.2 安裝Zookeeper

下載地址: https://mirrors.tuna.tsinghua.edu.cn/apache/

zookeeper配置參數:http://zookeeper.apache.org/doc/current/zookeeperAdmin.html#sc_configuration

在Zookeeper的官網上有這麼一句話:ZooKeeper is a centralized service for maintaining configuration information, naming, providing distributed synchronization, and providing group services. 這大概描述了Zookeeper主要可以幹哪些事情:配置管理,名字服務,提供分佈式同步以及集羣管理。此處我們需要使用Zookeeper來管理Kafka集羣。

~]# tar xf zookeeper-3.4.14.tar.gz -C /opt/
~]# cd /opt/
~]# ln -sv zookeeper-3.4.14/ zookeeper
~]# cd zookeeper/conf/
~]# cp zoo_sample.cfg zoo.cfg
~]# cat zoo.cfg
	tickTime=2000
	initLimit=10
	syncLimit=5
	dataDir=/opt/zookeeper/data
	
	dataLogDir=/opt/zookeeper/log
	autopurge.snapRetainCount=3
	autopurge.purgeInterval=1
	
	clientPort=2181
	server.0=192.168.100.111:2888:3888
	server.1=192.168.100.112:2888:3888
	server.2=192.168.100.113:2888:3888
	
~]# mkdir ../{data,log}
~]# echo 0 > ../data/myid		#三臺zk編號不同,此處爲0,其餘兩臺爲12,與配置中的server.x有關
~]# echo 'ZK_HOME=/opt/zookeeper' > /etc/profile.d/zk.sh 
~]# echo 'PATH=$ZK_HOME/bin:$PATH' >> /etc/profile.d/zk.sh
~]# source /etc/profile.d/zk.sh
~]# zkServer.sh start
~]# zkServer.sh status
~]# zkCli.sh -server localhost:2181

配置解析:

  • tickTime:客戶端與服務器或者服務器與服務器之間每個tickTime時間就會發送一次心跳。通過心跳不僅能夠用來監聽機器的工作狀態,還可以通過心跳來控制Flower跟Leader的通信時間,默認2秒
  • initLimit:集羣中的follower服務器(F)與leader服務器(L)之間初始連接時能容忍的最多心跳數(tickTime的數量)。
  • syncLimit:集羣中flower服務器(F)跟leader(L)服務器之間的請求和答應最多能容忍的心跳數。
  • dataDir:該屬性對應的目錄是用來存放myid信息跟一些版本,日誌,跟服務器唯一的ID信息等。
  • clientPort:客戶端連接的接口,客戶端連接zookeeper服務器的端口,zookeeper會監聽這個端口,接收客戶端的請求訪問!這個端口默認是2181。
  • server.N=YYY:A:B
         N:代表服務器編號(也就是myid裏面的值)
         YYY:服務器地址
         A:表示 Flower 跟 Leader的通信端口,簡稱服務端內部通信的端口(默認2888)
         B:表示 是選舉端口(默認是3888)

2.3 安裝Kafka

下載地址:https://mirrors.tuna.tsinghua.edu.cn/apache/kafka/
kafka配置參數:http://kafka.apache.org/documentation/#brokerconfigs

~]# tar xf kafka_2.12-2.1.0.tgz -C /opt/
~]# cd /opt/
~]# ln -sv kafka_2.12-2.1.0/ kafka
~]# cd kafka/config/
~]# cp server.properties server.properties_bak
~]# cat server.properties | grep -v '#' | grep -v "^$"    
	broker.id=1			#每一個broker在集羣中的唯一表示,要求是正數
	listeners=PLAINTEXT://192.168.100.111:9092	#監控的kafka端口
	num.network.threads=3			#broker處理消息的最大線程數,一般情況下不需要去修改 
	num.io.threads=8				#broker處理磁盤IO的線程數,數值應該大於你的硬盤數 
	socket.send.buffer.bytes=102400		#socket的發送緩衝區
	socket.receive.buffer.bytes=102400	#socket的接受緩衝區
	socket.request.max.bytes=104857600	#socket請求的最大字節數
	log.dirs=/opt/kafka/kafka-logs		#kafka數據的存放地址,多個地址用逗號分割,多個目錄分佈在不同磁盤上可以提高讀寫性能
	num.partitions=3					#設置partitions 的個數
	num.recovery.threads.per.data.dir=1	
	offsets.topic.replication.factor=1
	transaction.state.log.replication.factor=1
	transaction.state.log.min.isr=1
	log.retention.hours=168				#數據文件保留多長時間,此處爲168h,粒度還可設置爲分鐘,或按照文件大小
	log.segment.bytes=1073741824		#topic的分區是以一堆segment文件存儲的,這個控制每個segment的大小,會被topic創建時的指定參數覆蓋
	log.retention.check.interval.ms=300000
	zookeeper.connect=192.168.100.111:2181,192.168.100.112:2181,192.168.100.113:2181	#zookeeper集羣地址
	zookeeper.connection.timeout.ms=6000	#kafka連接Zookeeper的超時時間
	group.initial.rebalance.delay.ms=0
	
~]# echo 'KFK_HOME=/opt/kafka' > /etc/profile.d/kfk.sh
~]# echo 'PATH=$KFK_HOME/bin:$PATH' >> /etc/profile.d/kfk.sh
~]# source /etc/profile.d/kfk.sh
~]# kafka-server-start.sh -daemon /usr/local/kafka/config/server.properties

驗證kafka是否可用:

~]# zkCli.sh -server localhost:2181
	[zk: localhost:2181(CONNECTED) 0] get /brokers/ids/1
	{"listener_security_protocol_map":{"PLAINTEXT":"PLAINTEXT"},"endpoints":["PLAINTEXT://192.168.100.111:9092"],"jmx_port":-1,"host":"192.168.100.111","timestamp":"1591675712330","port":9092,"version":4}
	cZxid = 0x10000001a
	ctime = Tue Jun 09 00:08:32 EDT 2020
	mZxid = 0x10000001a
	mtime = Tue Jun 09 00:08:32 EDT 2020
	pZxid = 0x10000001a
	cversion = 0
	dataVersion = 0
	aclVersion = 0
	ephemeralOwner = 0x20000a7ad170000
	dataLength = 200
	numChildren = 0

注: kafka節點默認需要的內存爲1G,在工作中可能會調大該參數,可修改kafka-server-start.sh的配置項。找到KAFKA_HEAP_OPTS配置項,例如修改爲:export KAFKA_HEAP_OPTS="-Xmx2G -Xms2G"。

2.4 安裝ELK

下載地址:https://www.elastic.co/cn/downloads/

2.4.1 安裝Elasticsearch

~]# tar xf elasticsearch-6.8.7.tar.gz -C /opt/
~]# cd /opt/
~]# ln -sv elasticsearch-6.8.7/ elasticsearch
~]# cd elasticsearch/config/
~]# cp elasticsearch.yml elasticsearch.yml_bak
~]# cat elasticsearch.yml
	cluster.name: myes			#集羣名稱,一定要一致,當集羣內節點啓動的時候,默認使用組播(多播),尋找集羣中的節點
	node.name: elk-node1		#節點名稱
	path.data: /opt/elasticsearch/data	#數據目錄
	path.logs: /opt/elasticsearch/log	#日誌目錄
	bootstrap.memory_lock: true			#啓動時鎖定內存
	network.host: 192.168.100.111		#監聽IP
	transport.tcp.port: 9300			#集羣內通信端口,默認9300
	http.port: 9200						#服務監聽端口,默認9200
	discovery.zen.ping.unicast.hosts: ["elk-node2", "elk-node3"]	#集羣中其他成員,需要能解析,請先做好host
	discovery.zen.minimum_master_nodes: 2	#成爲master需要的最小票數

~]# cat jvm.options | grep -v '#' | grep -v '^$' | head -n 2	#默認給elasticsearch分配的內存,生產環境需調大此數值 
	-Xms1g
	-Xmx1g

~]# useradd elastic		#elasticsearch 5.0後不能使用root啓動
~]# echo "123456" | passwd --stdin elastic
~]# chown -R elastic:elastic /opt/elasticsearch/

~]# vim /etc/sysctl.conf										#調整系統虛擬內存,否則會啓動不了
	vm.max_map_count=262144
~]# sysctl -p

~]# tail -n 4 /etc/security/limits.conf		#修改用戶可使用最大文件描述符 ,鎖定內存
	* soft nofile 65536
	* hard nofile 65536
	* soft memlock unlimited 
	* hard memlock unlimited
 
若不設置以上兩參數,啓動時會報錯:	
[1]: max file descriptors [4096] for elasticsearch process is too low, increase to at least [65535]
[2]: memory locking requested for elasticsearch process but memory is not locked
[3]: max virtual memory areas vm.max_map_count [65530] is too low, increase to at least [262144]

~]# su - elastic 											#es默認不能使用root啓動
~]# cd /opt/elasticsearch/bin
~]# ./opt/elasticsearch/bin/elasticsearch -d				#elastic用戶

~]# curl http://192.168.100.111:9200/_cat/nodes				#查看集羣節點信息,*號爲集羣master
	192.168.100.113 18 97 0 0.16 0.10 0.07 mdi - elk-node3
	192.168.100.112 13 97 0 0.07 0.14 0.10 mdi * elk-node2
	192.168.100.111 26 94 0 0.23 0.68 0.40 mdi - elk-node1

# Master 的職責:統計各 node 節點狀態信息、集羣狀態信息統計、索引的創建和刪除、索引分配的管理、關閉 node 節點等
# Slave 的職責:從 master 同步數據、等待機會成爲 Master

2.4.2 安裝Elasticsearch-head(可選)

Elasticsearch-head簡介:

  • ElasticSearch-head是一個H5編寫的ElasticSearch集羣操作和管理工具,可以對集羣進行傻瓜式操作。
  • 顯示集羣的拓撲,並且能夠執行索引和節點級別操作
  • 搜索接口能夠查詢集羣中原始json或表格格式的檢索數據
  • 能夠快速訪問並顯示集羣的狀態
  • 有一個輸入窗口,允許任意調用RESTful API。這個接口包含幾個選項,可以組合在一起以產生有趣的結果
  • es的圖形界面插件,託管於GitHub,使用9100端口

在 elasticsearch 5.x 版本以後不再支持直接安裝 head 插件,而是需要通過啓動一個服務。以下提供兩種安裝方式:
NPM安裝:

~]# yum install -y git npm   #NPM 的全稱是 Node Package Manager,是隨同 NodeJS 一起安裝的包管理和分發工具,它很方便讓 JavaScript 開發者下載、安裝、上傳以及管理已經安裝的包。
~]# cd /opt/
~]#git clone http://github.com/mobz/elasticsearch-head.git 
~]# cd elasticsearch-head/
~]# npm install grunt -save
~]# ll node_modules/grunt #確認生成文件
~]# npm install #執行安裝
~]# npm run start & #後臺啓動服務

~]# cat /opt/elasticsearch/config/elasticsearch.yml | tail -n 2		#開啓跨域訪問支持,然後重啓 elasticsearch 服務
	http.cors.enabled: true
	http.cors.allow-origin: "*"

Docker安裝:

~]# yum install docker -y
~]# systemctl start docker && systemctl enable docker

~]# mkdir -p /etc/docker
~]# tee /etc/docker/daemon.json <<-'EOF'		#配置鏡像加速,此處配置阿里雲鏡像加速
	{
	  "registry-mirrors": ["https://nqq67ahg.mirror.aliyuncs.com"]
	}
	EOF
~]# systemctl daemon-reload
~]# systemctl restart docker

~]# docker run -d -p 9100:9100 mobz/elasticsearch-head:5

~]# cat /opt/elasticsearch/config/elasticsearch.yml | tail -n 2		#開啓跨域訪問支持,然後重啓 elasticsearch 服務
	http.cors.enabled: true
	http.cors.allow-origin: "*"

默認監聽在9100端口,可直接訪問。

在這裏插入圖片描述

2.4.3 安裝Logstash

logstash配置我們後面進行說明

~]# tar xf logstash-6.8.3.tar.gz -C /opt/	
~]# cd /opt
~]# ln -sv logstash-6.8.3/ logstash

2.4.4 安裝Kibana

~]# tar xf kibana-6.8.7-linux-x86_64.tar.gz  -C /opt/
~]# cd /opt/
~]# ln -sv kibana-6.8.7-linux-x86_64/ kibana
~]# cd kibana/config/
~]# cp kibana.yml kibana.yml_bak
~]# cat kibana.yml
	server.port: 5601
	server.host: "192.168.100.111"
	server.name: "node1.kibana"
	elasticsearch.url: "http://192.168.100.111:9200"

~]# nohup ../bin/kibana &			#監聽5601端口 

寫環境變量:

~]# echo 'ES_HOME=/opt/elasticsearch' > /etc/profile.d/elk.sh
~]# echo 'LS_HOME=/opt/logstash' >> /etc/profile.d/elk.sh
~]# echo 'KB_HOME=/opt/kibana' >> /etc/profile.d/elk.sh
~]# echo 'PATH=$ES_HOME/bin:$LS_HOME/bin:$KB_HOME/bin:$PATH' >> /etc/profile.d/elk.sh 
~]# source /etc/profile.d/elk.sh

2.5 Nginx代理Kibana

~]# cat /etc/yum.repos.d/nginx.repo		#直接使用yum安裝
	[nginx-stable]
	name=nginx stable repo
	baseurl=http://nginx.org/packages/centos/$releasever/$basearch/
	gpgcheck=1
	enabled=1
	gpgkey=https://nginx.org/keys/nginx_signing.key
	module_hotfixes=true

~]# yum install -y nginx
~]# cat /etc/nginx/nginx.conf		#添加如下配置
	http{
		...
	    upstream kibana_server {
	        server 192.168.100.111:5601;
	        server 192.168.100.112:5601;
	        ip_hash;
	    }
	
	    server {
	        listen       80;
	        server_name  www.kibana.com;
	
	        access_log  /var/log/nginx/access.log  main;
	
	        location / {
	            proxy_pass http://kibana_server;
	        }
	    }   
		...
	}

還可以通過Nginx做一些訪問控制啥的,這裏就不描述了。

3.日誌採集

此處我們使用 filebeat 收集本地系統日誌,寫入 kafka,logstash 從 kafka 中讀取數據並傳給 elasticsearch,從而 kibana 進行展示。
給需要收集日誌主機安裝filebeat:

~]# tar xf filebeat-6.8.3-linux-x86_64.tar.gz -C /opt/
~]# cd /opt/
~]# ln -sv filebeat-6.8.3-linux-x86_64/ filebeat

3.1 收集系統日誌

此處我們使用 filebeat 收集本地系統日誌,寫入 kafka,logstash 從 kafka 中讀取數據並傳給 elasticsearch,從而 kibana 進行展示。
配置啓用filebeat:

~]# cat /opt/filebeat/filebeat.yml	修改如下兩個配置項
	filebeat.inputs:				#從哪裏收集
	- type: log
	  enabled: true
	  paths:
	    - /var/log/messages
	output.kafka:					#收集的數據寫到哪裏去
	  hosts: ["192.168.100.111:9092","192.168.100.112:9092","192.168.100.113:9092"]
	  topic: messages-topics		#寫到哪個topics
	  keep_alive: 10s

nohup ./filebeat -e -c filebeat.yml &

當我們filebeat啓用沒問題,此時數據就能寫到kafka中了。

查看kafka中是否創建了topics:

~]# kafka-topics.sh --list --zookeeper 192.168.100.111:2181,192.168.100.112:2181,192.168.100.113:2181
	__consumer_offsets
	messages-topics

kafka已有數據,我們還需使用logstash從kafka中讀取數據,交給elasticsearch。

logstash-input-kafka配置可參考:https://segmentfault.com/a/1190000016595992

配置啓用logstash:

~]# cat /opt/logstash/messages-logstash.conf 
	input {
	     kafka {
	         bootstrap_servers => "192.168.100.111:9092,192.168.100.112:9092,192.168.100.113:9092"	#kafka集羣地址
	         group_id => "logstash"				#此消費者所屬的組的標識符,消費者組是由多個處理器組成的單個邏輯訂閱服務器,主題中的消息將分發給具有相同group_id的所有Logstash實例。
	         auto_offset_reset => "earliest"	#如果Kafka中沒有初始偏移量,或者偏移量超出範圍,自動重置偏移量到最早的偏移量
	         decorate_events => true			#在輸出消息的時候會輸出自身的信息包括:消費消息的大小,topic 來源以及 consumer 的 group 信息。
	         topics => ["messages-topics"]		#哪個topics取數據
	         type => "messages"					#用於其他插件進行判斷
	     }
	}
	
	output {
	     if [type] == "messages" {				
	         elasticsearch {
	             hosts => ["192.168.100.111:9200"]
	             index => "messages-%{+YYYY-MM}"	#索引名稱
	         }
	     }
	}

~]# cd /opt/logstash
~]# nohup ./bin/logstash -f messages-logstash.conf &

在kibana添加索引:
在這裏插入圖片描述
在這裏插入圖片描述在這裏插入圖片描述
在這裏插入圖片描述至此,我們的日誌系統流程就走通了。

3.2 收集Nginx日誌

上面我們收集了系統日誌,現在再加上nginx訪問日誌。
filebeat配置修改:

~]# cat /opt/filebeat/filebeat.yml	#修改如下兩個配置項,修改後重啓服務
	- type: log
	  enabled: true
	
	  paths:
	    - /var/log/messages
	
	  fields:
	    topics: messages-topics
	
	- type: log
	  enabled: true
	
	  paths:
	   - /var/log/nginx/access.log
	
	  fields:
	    topics: nginx-access-topics

	output.kafka:
	  hosts: ["192.168.100.111:9092","192.168.100.112:9092","192.168.100.113:9092"]
	  topic: '%{[fields][topics]}'
	  keep_alive: 10s

logstash修改配置:

~]# cat messages-logstash.conf 	#修改如下配置項,修改後重啓服務
	input {
	     kafka {
	         bootstrap_servers => "192.168.100.111:9092,192.168.100.112:9092,192.168.100.113:9092"
	         group_id => "logstash"
	         auto_offset_reset => "earliest"
	         decorate_events => true
	         topics => ["messages-topics"]
	         type => "messages"
	     }
	
	     kafka {
	         bootstrap_servers => "192.168.100.111:9092,192.168.100.112:9092,192.168.100.113:9092"
	         group_id => "logstash"
	         auto_offset_reset => "earliest"
	         decorate_events => true
	         topics => ["nginx-access-topics"]
	         type => "nginx-access"
	     }
	}
	
	output {
	     if [type] == "messages" {
	         elasticsearch {
	             hosts => ["192.168.100.111:9200"]
	             index => "messages-%{+YYYY-MM}"
	         }
	     }
	
	     if [type] == "nginx-access" {
	         elasticsearch {
	             hosts => ["192.168.100.111:9200"]
	             index => "nginx-access-%{+YYYY-MM}"
	         }
	     }
	}

至此,我們就能簡單實現日誌採集、分類、索引、展示等功能了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章