面對海量日誌,爲什麼選用fluentd作爲核心組件?

"本文主要講解了fluentd的爲什麼選用fluentd作爲核心組件,它的優勢是什麼"

1、前言

我是標題黨,所謂佛無南北,架構沒有好壞之分,只有是否合適的區別,比如常常被人詬病的單體架構,耦合性高,可擴展性低。事實上,特別對於有成本考慮的初創企業,單體架構常常是最佳選擇,因爲簡單,它能快速幫助企業完成產品和市場的高度契合,但是當企業的用戶規模擴大後,這樣的架構往往又成爲隱患。話又說回來了,沒有一個可以適用於所有的產品和規模的完美架構,任何架構只能完成特定的一組目標,或者一系列的需求和條件。隨着時間的推移,爲了與時俱進,任何產品或者服務功能需要完善,架構也一樣,那些在普通用戶規模下的架構很少能在100倍規模下有效。

fluentd也一樣,當存在多種多樣數據源和存儲目標時比較合適,因爲它支持500+插件進行日誌輸入輸出,特別是大多數數據源都是自定義的應用,你會發現fluentd和這些應用結合起來的能力比其它日誌收集框架要簡單有效。

2、性能

fluentd的性能已經在各個領域得到了證明,其最大的用戶可以從50000+服務器中收集日誌,每天處理5TB的數據,峯值時每秒可以處理5萬行數據,可以在客戶端和服務端分別部署,客戶端收集日誌發送到服務端(目前大多采用fluent-bit作爲客戶端)

3、架構

fluentd是一個開源的數據收集器,它統一了數據的收集和使用。它的架構有以下特點(看上圖說話):

  • 使用json統一日誌格式

  • 可插拔的架構(靈活的插件功能,允許擴展功能)

  • 最少資源佔用(C+Ruby編寫)

  • 可靠性高

4、社區支持

fluentd目前由CNCF社區維護,大名鼎鼎的雲原生計算基金會,雲時代的操作系統Kubenetes就是由它發起和維護的。社區活躍,詳情見下圖:

5、安裝使用

安裝使用簡單,支持多種安裝方式,具體可以參考官網安裝方式,最簡單的方式就是直接通過鏡像運行,使用方式,如下所示:

1. 拉取鏡像

docker pull fluent/fluentd:v1.6-debian-1

2. 創建收集配置

# /tmp/fluentd.conf
<source>
  @type http
  port 9880
  bind 0.0.0.0
</source>
<match **>
  @type stdout
</match>

3. docker運行,啓動fluentd

$ docker run -p 9880:9880 -v $(pwd)/tmp:/fluentd/etc -e FLUENTD_CONF=fluentd.conf fluent/fluentd:v1.6-debian-1
2019-08-21 00:30:37 +0000 [info]: parsing config file is succeeded path="/fluentd/etc/fluentd.conf"
2019-08-21 00:30:37 +0000 [info]: using configuration file: <ROOT>
  <source>
    @type http
    port 9880
    bind "0.0.0.0"
  </source>
  <match **>
    @type stdout
  </match>
</ROOT>
2019-08-21 00:30:37 +0000 [info]: starting fluentd-1.6.3 pid=6 ruby="2.6.3"
2019-08-21 00:30:37 +0000 [info]: spawn command to main:  cmdline=["/usr/local/bin/ruby", "-Eascii-8bit:ascii-8bit", "/usr/local/bundle/bin/fluentd", "-c", "/fluentd/etc/fluentd.conf", "-p", "/fluentd/plugins", "--under-supervisor"]
2019-08-21 00:30:38 +0000 [info]: gem 'fluentd' version '1.6.3'
2019-08-21 00:30:38 +0000 [info]: adding match pattern="**" type="stdout"
2019-08-21 00:30:38 +0000 [info]: adding source type="http"
2019-08-21 00:30:38 +0000 [info]: #0 starting fluentd worker pid=13 ppid=6 worker=0
2019-08-21 00:30:38 +0000 [info]: #0 fluentd worker is now running worker=0
2019-08-21 00:30:38.332472611 +0000 fluent.info: {"worker":0,"message":"fluentd worker is now running worker=0"}

4. 發送HTTP請求

$ curl -X POST -d 'json={"json":"message"}' http://localhost:9880/sample.test
$ docker ps -a
CONTAINER ID        IMAGE                          COMMAND                  CREATED              STATUS              PORTS                                         NAMES
775a8e192f2b        fluent/fluentd:v1.6-debian-1   "tini -- /bin/entryp…"   About a minute ago   Up About a minute   5140/tcp, 24224/tcp, 0.0.0.0:9880->9880/tcp   tender_leakey


$ docker logs 775a8e192f2b | tail -n 1
2019-08-21 00:33:00.570707843 +0000 sample.test: {"json":"message"}

其它安裝和使用方式可參照如下鏈接:

日誌收集工具fluentd安裝配置及使用介紹

Kubernetes集羣環境下fluentd日誌收集方案介紹

6、線上實踐

如上圖所示,在各個節點上以DaemonSet方式部署fluent-bit,fluent-bit在各個節點上收集事件、日誌等信息,收集完成後發送到fluentd進行統一彙總、過濾、存儲處理。

示例:

fluentd指令配置信息:

<source>
  @type forward
  port 24224
</source>


# http://this.host:9880/myapp.access?json={"event":"data"}
<source>
  @type http
  port 9880
</source>
<match nginx*>                        #匹配有tag爲mem的類型
  @type stdout                        #匹配成功直接標準輸出
</match>


# Match events tagged with "myapp.access" and
# store them to /var/log/fluent/access.%Y-%m-%d
# Of course, you can control how you partition your data
# with the time_slice_format option.
<match tbsm*>
  @type file
  path /home/logs/${tag}/${tag}
  append true
  <format>
      @type single_value
      message_key log
      add_newline true
  </format>
  <buffer tag,time>
    @type file
    # timekey 5m 每隔5分鐘形成一個日誌文件
    # timekey_wait 1m 生成等待時間1分鐘
    chunk_limit_size 50M
     # 每隔1分鐘寫一次日誌
    flush_interval 1m
    flush_at_shutdown true
    flush_mode interval
  </buffer>
</match>


以上能夠滿足把集羣節點,各個服務的日誌進行集中到fluentd節點上進行存儲。目前上述指令配置能夠把原來各個節點上的日誌原封不動的集中到fluend所在服務器,當然你也可以對日誌進行處理,比如json格式、添加時間戳、tag標籤等。那麼日誌又是如何傳遞到fluentd服務呢?

如下所示fluent-bit配置:

[SERVICE]
    Flush        1
    Daemon       ON  
    Log_Level    debug




[INPUT]
    Name        tail
    Path        /home/logs/tbsms1/tbsms1.log
    Db          /tmp/tbsms1.db
    Db.sync     Full
    Tag         tbsms1


[INPUT]
    Name        tail
    Path        /home/logs/tbsms2/tbsms2.log
    Db          /tmp/tbsms2.db
    Db.sync     Full
    Tag         tbsms2


[INPUT]
    Name        tail
    Path        /home/logs/tbsms3/tbsms3.log
    Db          /tmp/tbsms3.db
    Db.sync     Full
    Tag         tbsms3


[INPUT]
    Name        tail
    Path        /home/logs/tbsms4/tbsms4.log
    Db          /tmp/tbsms4.db
    Db.sync     Full
    Tag         tbsms4


[INPUT]
    Name        tail
    Path        /home/logs/tbsms5/tbsms5.log
    Db          /tmp/tbsms5.db
    Db.sync     Full
    Tag         tbsms5


[OUTPUT]
    Name        forward
    Match       *
    Host        12.18.1.6
    Port        24224

如上所示就可以把各個服務所在日誌路徑下的日誌信息發送到fluentd,當然,你可能會說,當我的服務出現問題的時候,我不僅會查看服務日誌的信息,還會查看當前機器所在節點的內存、cpu等監控信息。fluent-bit也是支持的,具體可以參考:

一文了解日誌收集工具fluent-bit

輕量級日誌收集轉發 | fluent-bit指令詳解(一)

輕量級日誌收集轉發 | fluent-bit配置詳解(二)

輕量級日誌收集轉發 | fluent-bit外部插件詳解(三)

7、問題總結

1. 如上示例所示,在使用的過程中,會發現緩存路徑${tag}沒有被替換掉,如下所示:

drwxr-xr-x 3 root root  4096 Feb 14 17:01 logs
drwxr-xr-x 4 root root  4096 Feb 14 17:41 ${tag}

但是當緩存中的數據刷新到file中之後,file中的數據以及tag是正常替換的。個人覺得這是fluentd的一個可以接受的bug。

2. fluent-bit日誌收集過程中出現如下文件被跳過問題如何處理?

2020/01/20 11:37:55] [debug] [in_tail] file=/home/logs/server/server.2019-12-17.log read=32767 lines=0
[2020/01/20 11:37:55] [debug] [in_tail] file=/home/logs/server/server.2019-12-18.log read=32767 lines=0
[2020/01/20 11:37:55] [error] [in_tail] file=/home/logs/server/server.2019-12-16.log requires a larger buffer size, lines are too long. Skipping file.
[2020/01/20 11:37:55] [error] [in_tail] file=/home/logs/server/server.2019-12-17.log requires a larger buffer size, lines are too long. Skipping file.

添加Buffer_Chunk_Size和Buffer_Chunk_Size,其中Buffer_Chunk_Size默認是32Kb,如果一行數據的長度大於這個值,可能會出現如上錯誤,其中Buffer_Max_Size默認情況下跟Buffer_Chunk_Size保持一致。當然你也可以配置自動跳過過長數據行。

[INPUT]
    Name        tail
    Path        /home/logs/server/*.log
    Db          /tmp/ng.db
    Db.sync     Full
    Tag         nginx-log
    Buffer_Chunk_Size 320KB
    Buffer_Max_Size   520KB

3. 生成如下所示大量日誌文件,而我只想每天生成一個文件。如何配置?

# append false
file.20140608.log_0
file.20140608.log_1
file.20140609.log_0
file.20140609.log_1

在fluentd配置文件中添加append true配置即可解決,按照指定時間生成,如下所示:

# append true
file.20140608.log
file.20140609.log

4. 如何把節點日誌從各個節點轉發到其中一臺機器?

在服務端fluentd配置source,其中source: 數據源配置,可接受log-tail、http、tcp、udp等方式數據如下所示:

 <source>
    @type forward
    bind "0.0.0.0"
    port 24222
  </source>

在fluent-bit客戶端配置forward,如下所示:

[OUTPUT]
    Name        forward
    Match       *
    Host        12.18.71.14
    Port        24222

8、本文總結

本文主要簡單介紹fluent-bit&fluentd優勢以及在日誌收集過程中的總結和心得。如果有用,可以關注、後臺回覆【pdf】獲得詳細文檔。

推薦


Kubernetes排障指南

從零搭建Kubernetes下的nignx和tomcat

Kubernetes中如何使用ClusterDNS進行服務發現?

Kubernetes入門培訓(內含PPT)

從Ice到Kubernetes容器技術,微服務架構經歷了什麼?


原創不易,隨手關注或者”在看“,誠摯感謝!

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