Filebeat+Kafka+Logstash+Elasticsearch+Kibana 構建日誌分析系統

語言: CN / TW / HK

小知識,大挑戰!本文正在參與“程式設計師必備小知識”創作活動。

本文已參與 「掘力星計劃」 ,贏取創作大禮包,挑戰創作激勵金。

一、前言

隨著時間的積累,日誌資料會越來越多,當你需要檢視並分析龐雜的日誌資料時,可通過 Filebeat+Kafka+Logstash+Elasticsearch 採集日誌資料到 Elasticsearch(簡稱ES)中,並通過 Kibana 進行視覺化展示與分析。

本文介紹具體的實現方法。

二、背景資訊

Kafka 是一種分散式、高吞吐、可擴充套件的訊息佇列服務,廣泛用於日誌收集、監控資料聚合、流式資料處理、線上和離線分析等大資料領域,已成為大資料生態中不可或缺的部分。在實際應用場景中,為了滿足大資料實時檢索的需求,一般可以使用 Filebeat 採集日誌資料,將 Kafka 作為 Filebeat 的輸出端。Kafka 實時接收到 Filebeat 採集的資料後,以 Logstash 作為輸出端輸出。輸出到 Logstash 中的資料在格式或內容上可能不能滿足你的需求,此時可以通過 Logstash 的 filter 外掛過濾資料。最後將滿足需求的資料輸出到 ES 中進行分散式檢索,並通過 Kibana 進行資料分析與展示。 ​

簡單處理流程如下: 在這裡插入圖片描述

三、操作流程

  1. 準備工作
    • 完成環境準備
    • 包括建立對應服務
    • 安裝 Filebeat 。
  2. 配置 Filebeat:配置 Filebeat 的 input 為系統日誌,outpu 為 Kafka,將日誌資料採集到 Kafka 的指定 Topic 中。
  3. 配置 Logstash 管道:配置 Logstash 管道的 input 為 Kafka,output 為ES,使用 Logstash 消費 Topic 中的資料並傳輸到ES 中。
  4. 檢視日誌消費狀態:在訊息佇列 Kafka 中檢視日誌資料的消費的狀態,驗證日誌資料是否採集成功。
  5. 通過 Kibana 過濾日誌資料:在 Kibana 控制檯的 Discover 頁面,通過 Filter 過濾出 Kafka 相關的日誌。

四、準備工作

CenterOS 7.6 版本,推薦 8G 以上記憶體。 ​

1、Docker 環境

執行命令如下: ```bash

在 docker 節點執行

騰訊雲 docker hub 映象

export REGISTRY_MIRROR="https://mirror.ccs.tencentyun.com"

DaoCloud 映象

export REGISTRY_MIRROR="http://f1361db2.m.daocloud.io"

阿里雲 docker hub 映象

export REGISTRY_MIRROR=https://registry.cn-hangzhou.aliyuncs.com

安裝 docker

參考文件如下

https://docs.docker.com/install/linux/docker-ce/centos/

https://docs.docker.com/install/linux/linux-postinstall/

解除安裝舊版本

yum remove -y docker \ docker-client \ docker-client-latest \ docker-ce-cli \ docker-common \ docker-latest \ docker-latest-logrotate \ docker-logrotate \ docker-selinux \ docker-engine-selinux \ docker-engine

設定 yum repository

yum install -y yum-utils \ device-mapper-persistent-data \ lvm2 yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo

安裝並啟動 docker

yum install -y docker-ce-19.03.11 docker-ce-cli-19.03.11 containerd.io-1.2.13

mkdir /etc/docker || true

cat > /etc/docker/daemon.json <<EOF { "registry-mirrors": ["${REGISTRY_MIRROR}"], "exec-opts": ["native.cgroupdriver=systemd"], "log-driver": "json-file", "log-opts": { "max-size": "100m" }, "storage-driver": "overlay2", "storage-opts": [ "overlay2.override_kernel_check=true" ] } EOF

mkdir -p /etc/systemd/system/docker.service.d

Restart Docker

systemctl daemon-reload systemctl enable docker systemctl restart docker

關閉 防火牆

systemctl stop firewalld systemctl disable firewalld

關閉 SeLinux

setenforce 0 sed -i "s/SELINUX=enforcing/SELINUX=disabled/g" /etc/selinux/config

關閉 swap

swapoff -a yes | cp /etc/fstab /etc/fstab_bak cat /etc/fstab_bak |grep -v swap > /etc/fstab ```

驗證下 docker info: ```bash [[email protected]]# docker info Client: Debug Mode: false

Server: Containers: 16 Running: 11 Paused: 0 Stopped: 5 Images: 22 Server Version: 19.03.11 Storage Driver: overlay2 Backing Filesystem: xfs Supports d_type: true Native Overlay Diff: true Logging Driver: json-file Cgroup Driver: systemd Plugins: Volume: local Network: bridge host ipvlan macvlan null overlay Log: awslogs fluentd gcplogs gelf journald json-file local logentries splunk syslog Swarm: inactive Runtimes: runc Default Runtime: runc Init Binary: docker-init containerd version: 7ad184331fa3e55e52b890ea95e65ba581ae3429 runc version: dc9208a3303feef5b3839f4323d9beb36df0a9dd init version: fec3683 Security Options: seccomp Profile: default Kernel Version: 3.10.0-1127.el7.x86_64 Operating System: CentOS Linux 7 (Core) OSType: linux Architecture: x86_64 CPUs: 4 Total Memory: 11.58GiB Name: vm-autotest-server ID: KQ5B:KAG5:LLB5:CUD4:NQZX:4GHL:5XLY:FM7X:KRJ5:X3WK:42GV:QLON Docker Root Dir: /var/lib/docker Debug Mode: false Registry: https://index.docker.io/v1/ Labels: Experimental: false Insecure Registries: 172.16.62.179:5000 127.0.0.0/8 Registry Mirrors: https://registry.cn-hangzhou.aliyuncs.com/ Live Restore Enabled: false ```

### 2、Docker Compose 環境

Docker Compose是一個用於定義和執行多個 docker 容器應用的工具。使用 Compose 你可以用 YAML 檔案來配置你的應用服務,然後使用一個命令,你就可以部署你配置的所有服務了。

```bash # 下載 Docker Compose sudo curl -L "https://github.com/docker/compose/releases/download/1.29.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose

# 修改該檔案的許可權為可執行 chmod +x /usr/local/bin/docker-compose

# 驗證資訊 docker-compose --version ```

3、版本準備

| 元件 | 版本 | 部署方式 | | --- | --- | --- | | elasticsearch | 7.6.2 | Docker Compose | | logstash | 7.6.2 | Docker Compose | | kibana | 7.6.2 | Docker Compose | | zookeeper | latest | Docker Compose | | kafka | latest | Docker Compose | | filebeat | 7.4.2 | 二進位制 |

4、環境初始化

執行命令如下: ```bash

需要設定系統核心引數,否則 ES 會因為記憶體不足無法啟動

改變設定

sysctl -w vm.max_map_count=262144

使之立即生效

sysctl -p

建立 logstash 目錄,並將 Logstash 的配置檔案 logstash.conf 拷貝到該目錄

mkdir -p /mydata/logstash

需要建立 elasticsearch/data 目錄並設定許可權,否則 ES 會因為無許可權訪問而啟動失敗

mkdir -p /mydata/elasticsearch/data/ chmod 777 /mydata/elasticsearch/data/

``` ​

5、服務安裝

docker-compose.yml 檔案內容為: ```yaml version: '3' services: elasticsearch: image: elasticsearch:7.6.2 container_name: elasticsearch user: root environment: - "cluster.name=elasticsearch" #設定叢集名稱為elasticsearch - "discovery.type=single-node" #以單一節點模式啟動 volumes: - /mydata/elasticsearch/plugins:/usr/share/elasticsearch/plugins #外掛檔案掛載 - /mydata/elasticsearch/data:/usr/share/elasticsearch/data #資料檔案掛載 - /etc/localtime:/etc/localtime:ro - /usr/share/zoneinfo:/usr/share/zoneinfo ports: - 9200:9200 - 9300:9300 networks: - elastic

logstash: image: logstash:7.6.2 container_name: logstash environment: - TZ=Asia/Shanghai volumes: - /mydata/logstash/logstash.conf:/usr/share/logstash/pipeline/logstash.conf #掛載logstash的配置檔案 depends_on: - elasticsearch #kibana在elasticsearch啟動之後再啟動 links: - elasticsearch:es #可以用es這個域名訪問elasticsearch服務 ports: - 5044:5044 networks: - elastic

kibana: image: kibana:7.6.2 container_name: kibana links: - elasticsearch:es #可以用es這個域名訪問elasticsearch服務 depends_on: - elasticsearch #kibana在elasticsearch啟動之後再啟動 environment: - "elasticsearch.hosts=http://es:9200" #設定訪問elasticsearch的地址 - /etc/localtime:/etc/localtime:ro - /usr/share/zoneinfo:/usr/share/zoneinfo ports: - 5601:5601 networks: - elastic

zookeeper: image: wurstmeister/zookeeper container_name: zookeeper volumes: - /mydata/zookeeper/data:/data - /mydata/zookeeper/log:/datalog - /etc/localtime:/etc/localtime:ro - /usr/share/zoneinfo:/usr/share/zoneinfo networks: - elastic ports: - "2181:2181"

kafka: container_name: kafka image: wurstmeister/kafka depends_on: - zookeeper volumes: - /var/run/docker.sock:/var/run/docker.sock - /mydata/kafka:/kafka - /etc/localtime:/etc/localtime:ro - /etc/localtime:/etc/localtime:ro links: - zookeeper ports: - "9092:9092" networks: - elastic environment: - KAFKA_LISTENERS=INTERNAL://kafka:9092, OUT://kafka:29092 - KAFKA_ADVERTISED_LISTENERS=INTERNAL://kafka:9092, OUT://kafka:29092 - KAFKA_LISTENER_SECURITY_PROTOCOL_MAP=INTERNAL:PLAINTEXT,OUT:PLAINTEXT - KAFKA_INTER_BROKER_LISTENER_NAME=OUT - KAFKA_ZOOKEEPER_CONNECT=zookeeper:2181 - KAFKA_MESSAGE_MAX_BYTES=2000000 - KAFKA_CREATE_TOPICS=logs:1:1

networks: elastic: ```

將該檔案上傳的 linux 伺服器上,執行 docker-compose up 命令即可啟動所有服務。 ```bash [[email protected]]# docker-compose -f docker-compose.yml up -d [[email protected]]# docker-compose ps Name Command State Ports


elasticsearch /usr/local/bin/docker-entr ... Up 0.0.0.0:9200->9200/tcp, 0.0.0.0:9300->9300/tcp
kafka start-kafka.sh Up 0.0.0.0:9092->9092/tcp
kibana /usr/local/bin/dumb-init - ... Up 0.0.0.0:5601->5601/tcp
logstash /usr/local/bin/docker-entr ... Up 0.0.0.0:5044->5044/tcp, 9600/tcp
zookeeper /bin/sh -c /usr/sbin/sshd ... Up 0.0.0.0:2181->2181/tcp, 22/tcp, 2888/tcp, 3888/tcp [[email protected] elk]# ```

filebeat 客戶端安裝方式: ```bash curl -L -O https://artifacts.elastic.co/downloads/beats/filebeat/filebeat-7.4.2-linux-x86_64.tar.gz

tar xzvf filebeat-7.4.2-linux-x86_64.tar.gz cd filebeat-7.4.2-linux-x86_64 ```

6、服務設定

當所有依賴服務啟動完成後,需要對以下服務進行一些設定。 ```bash

elasticsearch 需要安裝中文分詞器 IKAnalyzer,並重新啟動。

docker exec -it elasticsearch /bin/bash

此命令需要在容器中執行

elasticsearch-plugin install https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v7.6.2/elasticsearch-analysis-ik-7.6.2.zip docker restart elasticsearch

logstas h需要安裝 json_lines 外掛,並重新啟動。

docker exec -it logstash /bin/bash logstash-plugin install logstash-codec-json_lines docker restart logstash ``` ​

五、配置 Filebeat

修改 filebeat.yml 檔案內容 ```yaml ilebeat.inputs: - type: log enabled: true paths: - /var/log/nginx/*.log

filebeat.config.modules: path: ${path.config}/modules.d/*.yml reload.enabled: false

setup.template.settings: index.number_of_shards: 1

setup.dashboards.enabled: false

setup.kibana: host: "http://kafka:5601" output.kafka: hosts: ["kafka:9092"] topic: 'logs' codec.json: pretty: false ``` 引數說明:

| 引數 | 說明 | | --- | --- | | type | 輸入型別。設定為log,表示輸入源為日誌。 | | enabled | 設定配置是否生效。true表示生效,false表示不生效。 | | paths | 需要監控的日誌檔案的路徑。多個日誌可在當前路徑下另起一行寫入日誌檔案路徑。 | | hosts | 訊息佇列Kafka例項的接入點。 | | topic | 日誌輸出到訊息佇列Kafka的Topic,請指定為已建立的Topic。 |

注意: 客戶端 hosts 新增 kafka 對應 server 的 ip 地址 以及 filebeat 配置建議使用 ansible。 ```bash [[email protected]# cat /etc/hosts 172.16.62.179 kafka

客戶端啟動服務

[[email protected]#./filebeat & ```

更多配置請參見:

六、配置 Logstash 管道

修改 logstash.conf 內容: ```bash input {

# 來源beats

beats {

    # 埠

port => "5044"

}

kafka { bootstrap_servers => "kafka:29092" topics => ["logs"] group_id => "logstash" codec => json }

}

分析、過濾外掛,可以多個

filter {

grok {

match => { "message" => "%{COMBINEDAPACHELOG}"}

}

geoip {

source => "clientip"

}

}

output { # 選擇elasticsearch elasticsearch { hosts => ["http://es:9200"] #index => "%{[@metadata][beat]}-%{[@metadata][version]}-%{+YYYY.MM.dd}" index => "logs-%{+YYYY.MM.dd}" } } ```

input 引數說明:

| 引數 | 說明 | | --- | --- | | bootstrap_servers | 訊息佇列 Kafka 例項的接入點 | | group_id | 指定已建立的 Consumer Group 的名稱。 | | topics | 指定為已建立的 Topic 的名稱,需要與 Filebeat 中配置的 Topic 名稱保持一致。 | | codec | 設定為 json,表示解析 JSON 格式的欄位,便於在 Kibana 中分析。 |

output 引數說明:

| 引數 | 說明 | | --- | --- | | hosts | ES的訪問地址,取值為http://:9200。 | | user | 訪問 ES 的使用者名稱,預設為 elastic。 | | password | 訪問 ES 的密碼。 | | index | 索引名稱。設定為 logs‐%{+YYYY.MM.dd} 表示索引名稱以 logs 為字首,以日期為字尾,例如 logs-2021.09.28。 |

注意: logstash 中最為關鍵的地方在於 filter,為了除錯 filter 的配置。

更多配置請參見:

七、檢視 kafka 日誌消費狀態

操作命令如下: ```bash

進入容器

docker exec -it kafka bash

kafka 預設安裝在 /opt/kafka

cd opt/kafka

要想查詢消費資料,必須要指定組

bash-5.1# bin/kafka-consumer-groups.sh --bootstrap-server 172.16.62.179:9092 --list logstash

檢視 topic

bash-5.1# bin/kafka-topics.sh --list --zookeeper 172.16.62.179:2181 __consumer_offsets logs

檢視消費情況

bash-5.1# bin/kafka-consumer-groupsdescribe --bootstrap-server 172.16.62.179:9092 --group logstash

GROUP TOPIC PARTITION CURRENT-OFFSET LOG-END-OFFSET LAG CONSUMER-ID HOST CLIENT-ID logstash logs 0 107335 107335 0 logstash-0-c6d82a1c-0f14-4372-b49f-8cd476f54d90 /172.19.0.2 logstash-0

引數解釋:

--describe 顯示詳細資訊

--bootstrap-server 指定kafka連線地址

--group 指定組。

```

欄位解釋:

| TOPIC | PARTITION | CURRENT-OFFSET | LOG-END-OFFSET | LAG | CONSUMER-ID | HOST | CLIENT-ID | | --- | --- | --- | --- | --- | --- | --- | --- | | topic名字 | 分割槽id | 當前已消費的條數 | 總條數 | 未消費的條數 | 消費id | 主機ip | 客戶端id |

從上面的資訊可以看出,topic 為 logs 總共消費了 107335 條資訊, 未消費的條數為 0。也就是說,消費資料沒有積壓的情況.

八、檢視 ES 內容

通過 elasticsearch-head 外掛檢視 ES 中是否收到了由 logstash 傳送過來的日誌

在這裡插入圖片描述

九、通過 Kibana 過濾日誌資料

1、建立 index-pattern

開啟 es,進入首頁後,點選“connect to your Elasticsearch index” 在這裡插入圖片描述

填入 es 中的索引名,支援正則匹配,輸入 Index pattern(本文使用 logs-*),單擊 Next step。 在這裡插入圖片描述

選擇“@timestamp”作為時間過濾欄位,然後點選“create index pattern”: 在這裡插入圖片描述

建立完成後: 在這裡插入圖片描述

2、檢視日誌

在左側導航欄,單擊 Discover。 在這裡插入圖片描述

從頁面左側的下拉列表中,選擇已建立的索引模式(logs-*)。 在頁面右上角,選擇一段時間,檢視對應時間段內的 Filebeat 採集的日誌資料。

十、小結

在企業實際專案中,elk 是比較成熟且廣泛使用的技術方案。logstash 效能稍弱於 filebeat,一般不直接運行於採集點,推薦使用filebeat。在日誌進入elk前,從經驗性角度,前置 kafka,一方面作為佇列和緩衝,另一方面提供了統一的入口渠道。 ​

原始碼地址: