Docker:Fluentd收集容器日誌

 

快速啓動Fluentd

1、創建日誌文件和配置文件

mkdir /home/fluentd/container-logs  /home/fluentd/conf/

2、編寫配置文件

vi /home/fluentd/conf/fluent.conf

<source>
  @type   forward
</source>

<match *>
  @type              file
  path               /fluentd/log/${tag}/${tag}
  append             true
  <format>
    @type            single_value
    message_key      log
  </format>
  <buffer tag,time>
    @type             file
    timekey           1d
    timekey_wait      10m
    flush_mode        interval
    flush_interval    30s
  </buffer>
</match>

3、啓動Fluentd

# docker run -d -p 24224:24224  -v /home/fluentd/container-logs:/fluentd/log -v /home/fluentd/conf/fluent.conf:/fluentd/etc/fluent.conf    fluent/fluentd

此時會在宿主機的/home/fluentd/container-logs目錄下生成容器日誌,所有收集到的日誌文件將存儲至此。

啓動其他容器時指定容器的logging driver

在啓動容器的時候執行使用fluentd作爲logging driver,下面以啓動nginx容器舉例:

# docker run -d --log-driver fluentd --log-opt fluentd-address=localhost:24224 --log-opt tag="nginx-test" --log-opt fluentd-async-connect --name nginx-test -p 8080:80 nginx
--log-driver: 配置log驅動
--log-opt: 配置log相關的參數
tag:配置match tag fluentd-address: fluentd服務地址 fluentd-async-connect:fluentd-docker異步設置,避免fluentd掛掉之後導致Docker容器也掛了

Fluentd配置

配置文件用於讓用戶控制Fluentd輸入(input)和輸出(output)的行爲:(1) 選擇輸入和輸出插件,(2) 指定插件參數。配置文件要求必須存在以使Fluentd正常工作。

字符編碼

Fluentd假設配置文件編碼爲UTF-8或ASCII。

指令列表

配置文件由下列指令組成:

  1. source 指令確定輸入源。
  2. match 指令確定輸出目的地。
  3. filter 指令確定事件處理管道。
  4. system 指令設置系統級配置。
  5. label 指令將output和filter分組以進行內部路由。
  6. @include 指令用於包括其它文件。

配置示例 Step by Step

1. source: 所有數據的來源

選擇和配置Fluentd的輸入源,需要用source指令。Fluentd的標準輸入插件包括http和forward。http監聽HTTP端口,並接受從HTTP來的日誌消息。forward讓fluentd監聽TCP端口,並接受TCP包。當然,兩者可以同時開啓(可以添加任意多需要的源)。

# Receive events from 24224/tcp
# This is used by log forwarding and the fluent-cat command
<source>
  @type forward
  port 24224
</source>

# http://this.host:9880/myapp.access?json={"event":"data"}
<source>
  @type http
  port 9880
</source>

每個source指令必須包含 @type 參數。@type 參數指定了何種輸入插件將被使用。

插播一下:Routing

source 將事件提交到Fluentd的路由引擎。每個事件由3部分實體組成:tag, time 和 record。tag 是由’.'分隔的字符串(如:myapp.access),並且作爲Fluentd內部路由的指示。time字段由 input 插件指定,並且必須得是Unix時間格式。record 是一個JSON對象。

2. match: 告訴 fluentd 該幹什麼!

match 指令查找所有具有匹配tag的事件,並且進行處理。match 指令最常見的用法是將事件輸出到其它系統(因此,對應於match指令的插件被稱爲"output"插件)。Fluentd的標準輸出插件包括 file 和 forward。現在來加入到配置文件中。

# Receive events from 24224/tcp
# This is used by log forwarding and the fluent-cat command
<source>
  @type forward
  port 24224
</source>

# http://this.host:9880/myapp.access?json={"event":"data"}
<source>
  @type http
  port 9880
</source>

# 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 myapp.access>
  @type file
  path /var/log/fluent/access
</match>

每個 match 指令必須包括一個匹配模板和一個 @type 參數。只有tag 匹配到模板的事件會被送到輸出目的地(在上述示例中,只有tag爲"myapp.access"的事件會被匹配)。@type 參數指定了將要使用的 output 插件。

3. filter: 事件處理管道

filter 指令與 match 有相同的語法,但 filter 可以將處理串成管道。 使用 filter 時事件流看起來會像這樣:

Input -> filter 1 -> ... -> filter N -> Output

現在添加一個標準的 record_transformer filter 到剛剛寫的 match 示例中。

# http://this.host:9880/myapp.access?json={"event":"data"}
<source>
  @type http
  port 9880
</source>

<filter myapp.access>
  @type record_transformer
  <record>
    host_param "#{Socket.gethostname}"
  </record>
</filter>

<match myapp.access>
  @type file
  path /var/log/fluent/access
</match>

收到事件 {“event”: “data”} 後,先扔到filter: record_transformer中,record_transformer 在事件中添加了"host_param" 字段並且繼續向後傳,{“event”:“data”,“host_param”:“webserver1”},事件最終到達 file 輸出插件。

match 模板

通配符和展開

下列 match 模板可以用於<match> 和<filter>中的tag:

  • * 匹配單個tag部分。
    • 例如:模板 a.* 匹配 a.b,但不能匹配 a 與 a.b.c
  • ** 匹配0個或多個tag 部分
    • 例如:a.** 匹配a, a.b 和 a.b.c
  • {X,Y,Z} 匹配X, Y, 或 Z, 這裏 X, Y 和 Z都是匹配模板
    • 例如:模板 {a,b} 匹配 a 和 b,但不匹配 c
    • 這種方法可以用於組合 * 和 ** 模板。例如: a.{b,c}.* 和 a.{b,c.**}
  • 當多個模板同時在單個tag中列出時(由一個或多個空格分隔),將匹配所列出的任意一個模板。例如:
    • 模板 <match a b> 匹配 a 和 b
    • 模板 <match a.** b.*> 匹配 a, a.b, a.b.c (匹配到前一個模板)和 b.d (匹配到後一個模板)

匹配順序

Fluentd 嘗試以模板在配置文件中出現的順序進行匹配。所以看下面的例子:

# ** matches all tags. Bad :(
<match **>
  @type blackhole_plugin
</match>

<match myapp.access>
  @type file
  path /var/log/fluent/access
</match>

上面例子中,myapp.access 永遠都匹配不到。更寬鬆的匹配模板應定義在更嚴格的匹配模板之後。像這樣:

<match myapp.access>
  @type file
  path /var/log/fluent/access
</match>

# Capture all unmatched tags. Good :)
<match **>
  @type blackhole_plugin
</match>

當然,如果有兩個同樣的模板,後一個match將永遠無法匹配。如果你希望將事件發送到多個輸出,應考慮使用 out_copy 插件。

常見的陷阱是將<filter>放到<match>之後。由於前面說的原因,事件將無法到達filter,也就無法按預期的方式工作。

COPY 輸出插件

out_copy 是Fluentd的核心插件,無須另外安裝,out_copy 將事件複製多份,分別送到多個輸出插件中去。直接來個例子:

<match pattern>
  @type copy
  <store>
    @type file
    path /var/log/fluent/myapp1
    ...
  </store>
  <store>
    ...
  </store>
  <store>
    ...
  </store>
</match>

下面的例子將事件存到本地文件夾/var/log/fluent/myapp下,同時發送到Elasticsearch實例的fluentd.test 集合中。具體請參見out_fileout_elasticsearch插件的細節說明。

<match docker.*>
  @type copy
  <store>
    @type file
    path /var/log/fluent/myapp
    compress gzip
    <format>
      localtime false
    </format>
    <buffer time>
      timekey_wait 10m
      timekey 86400
      timekey_use_utc true
      path /var/log/fluent/myapp
    </buffer>
    <inject>
      time_format %Y%m%dT%H%M%S%z
      localtime false
    </inject>
  </store>
  <store>
    @type elasticsearch
    host 192.168.198.46
    port 9200
    index_name fluentd
    type_name test
  </store>
</match>

啓動一個docker,並將log-driver指向fluentd,即可將日誌輸出到fluentd,再轉發至elasticsearch,同時本地留有日誌備份。

docker run --rm --log-driver fluentd --log-opt fluentd-address=192.168.198.46:24224 --log-opt tag=docker.test alpine date

out_copy 參數

  • @type - 此值必須爲"copy"

  • deep_copy - 深度複製,默認爲false,out_copy在各store插件間共享事件記錄。當此值爲true時,out_copy爲每一store插件複製一份事件記錄。

  • <store> 字段 - 指定存儲目的地。格式與<match>指令一致。此字段必須至少出現一次。

  • ignore_error - 忽略錯誤。當某一store出現錯誤時,這個參數將作用於其餘store,例如:

    <match app.**>
      @type copy
      <store>
        @type plugin1
      </store>
      <store>
        @type plugin2
      </store>
    </match>
  • 若plugin1出現錯誤時,plugin2將不會被執行。若希望忽略不重要的store出現的錯誤時,可以指定該store的ignore_error參數。

    <match app.**>
      @type copy
      <store ignore_error>
        @type plugin1
      </store>
      <store>
        @type plugin2
      </store>
    </match>

     

 

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