<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Fluentd 簡明教程

          共 6234字,需瀏覽 13分鐘

           ·

          2020-10-18 05:08

          如果你的應(yīng)用運(yùn)行在分布式架構(gòu)上,你很可能會(huì)使用集中式日志系統(tǒng)來收集它們的日志,其中我們使用比較廣泛的一個(gè)工具就是 fluentd,包括在容器化時(shí)代用來收集 Kubernetes 集群應(yīng)用日志 fluentd 也是使用非常多的。本我們將解釋它是如何工作的,以及如何根據(jù)需求來調(diào)整配置 fluentd。

          基本概念

          我們可能有在 bash 中執(zhí)行過 tail -f myapp.log | grep "what I want" > example.log 這樣的命令,這其實(shí)就是 fluentd 比較擅長做的事情,tail 日志或者接收某種形式的數(shù)據(jù),然后過濾轉(zhuǎn)換,最后發(fā)送到后端存儲(chǔ)中,我們可以將上面的命令分成多段來分析。

          輸入

          tail?-f?myapp.log

          我們要對(duì)一個(gè)文件進(jìn)行長期的 tail,每當(dāng)有什么日志信息被添加到文件中,它就會(huì)顯示在屏幕上。這在 fluentd 中叫做**輸入插件**,tail 只是其中之一,但還有很多其他可用的插件。

          過濾

          |?grep?"what?I?want"

          在這里,我們從尾部 -f 的輸出中,只過濾包含我們想要的字符串的日志行,在 fluentd 中這叫做**過濾插件**。

          輸出

          >?example.log

          在這里,我們將 grep 命令過濾后的輸出保存到一個(gè)名為 example.log 的文件中。在 fluentd 中,這就是**輸出插件,**除了寫到文件之外,fluentd 還有很多插件可以把你的日志輸出到其他地方。

          這就是 fluentd 的最基本的運(yùn)行流程,你可以讀取日志,然后處理,然后把它發(fā)送到另一個(gè)地方做進(jìn)一步的分析。接下來讓我們用一個(gè)小 demo 來實(shí)踐這些概念,看看這3個(gè)插件是如何在一起工作的。

          Demo

          在這個(gè)demo 中,我們將使用 fluentd 來讀取 docker 應(yīng)用日志。

          設(shè)置

          這里我們將 demo 相關(guān)的配置放置到了 Github 倉庫:https://github.com/r1ckr/fluentd-simplified,克隆后最終會(huì)得到以下目錄結(jié)構(gòu)。

          fluentd/
          ????├──?etc/
          ????│???└──?fluentd.conf
          ????├──?log/
          ????│???└──?kong.log
          ????└──?output/

          其中的 output/ 是 fluentd 寫入日志文件的目錄,在 log/kong.log 中,有一些來自本地運(yùn)行的 kong 容器的日志,它們都是 docker 格式的日志。

          {
          ????"log":"2019/07/31?22:19:52?[notice]?1#0:?start?worker?process?32\n",
          ????"stream":"stderr",
          ????"time":"2019-07-31T22:19:52.3754634Z"
          }

          這個(gè)文件的每一行都是一個(gè) json 文件,這就是 docker 默認(rèn)驅(qū)動(dòng)的日志格式。我們將對(duì)這個(gè)文件進(jìn)行 tail 和解析操作,它有應(yīng)用日志和訪問日志混合在一起。我們的目標(biāo)是只獲取訪問日志。etc/fluentd.conf 是我們的 fluentd 配置,其中有一個(gè)輸入和一個(gè)輸出部分,我們稍后會(huì)仔細(xì)來分析,首先運(yùn)行 fluentd 容器。

          運(yùn)行 fluentd

          $?chmod?777?output/
          $?docker?run?-ti?--rm?\
          -v?$(pwd)/etc:/fluentd/etc?\
          -v?$(pwd)/log:/var/log/?\
          -v?$(pwd)/output:/output?\
          fluent/fluentd:v1.11-debian-1?-c?/fluentd/etc/fluentd-simplified-finished.conf?-v

          注意上面的運(yùn)行命令和我們要掛載的卷

          • etc/ 是掛載在容器內(nèi)部的 /fluentd/etc/ 目錄下的,以覆蓋 fluentd 的默認(rèn)配置。
          • log/ 掛載到 /var/log/,最后在容器里面掛載到 /var/log/kong.log
          • output/ 掛載到 /output,以便能夠看到 fluentd 寫入磁盤的內(nèi)容。

          運(yùn)行容器后,會(huì)出現(xiàn)如下所示的錯(cuò)誤信息:

          2020-10-16?03:35:28?+0000?[info]:?#0?fluent/log.rb:327:info:?fluentd?worker?is?now?running?worker=0

          這意味著 fluentd 已經(jīng)啟動(dòng)并運(yùn)行了。現(xiàn)在我們知道了 fluentd 是如何運(yùn)行的了,接下來我們來看看配置文件的一些細(xì)節(jié)。

          Fluentd 配置

          輸入輸出

          首先查看 input 部分

          <source>
          ??@type?tail
          ??path?"/var/log/*.log"
          ??tag?"ninja.*"
          ??read_from_head?true
          ??
          ????@type?"json"
          ????time_format?"%Y-%m-%dT%H:%M:%S.%NZ"
          ????time_type?string
          ??

          source>

          我們來仔細(xì)查看下這幾個(gè)配置:

          • @type tail:是我們想要的輸入類型, 這和 tail -f 非常相似。
          • path "/var/log/*.log":表示它將跟蹤任何以 .log 結(jié)尾的文件,每個(gè)文件都會(huì)產(chǎn)生自己的標(biāo)簽,比如:var.log.kong.log
          • tag "ninja.*":這將在這個(gè)源創(chuàng)建的每個(gè)標(biāo)簽前加上 ninja. ,本例中,我們只有一個(gè)以 ninja.var.log.kong.log 結(jié)束的文件。
          • read_from_head true:表示讀取整個(gè)文件,而不只是新的日志行。
          • 部分:由于 docker 日志的每一行都是一個(gè) json 對(duì)象,所以我們將以 json 的方式進(jìn)行解析。

          然后是輸出 output 部分的配置。

          #?Output

          ??@type?file
          ??path?/output/example.log
          ??
          ????timekey?1d
          ????timekey_use_utc?true
          ????timekey_wait?1m
          ??


          在這個(gè)配置中,有兩個(gè)重要的部分。

          • **>:這表示我們要匹配 fluentd 中的所有標(biāo)簽,我們這里只有一個(gè),就是上面輸入插件創(chuàng)建的那個(gè)。
          • path /output/example:這是保存緩沖區(qū)的目錄名,也是每個(gè)日志文件的開頭名稱。
          output
          ├──?example
          │???├──?buffer.b5b1c174b5e82c806c7027bbe4c3e20fd.log
          │???└──?buffer.b5b1c174b5e82c806c7027bbe4c3e20fd.log.meta
          ├──?example.20190731.log
          └──?example.20200510.log

          有了這個(gè)配置,我們就有了一個(gè)非常簡單的輸入/輸出管道了。

          現(xiàn)在我們可以來看看 fluentd 創(chuàng)建的一個(gè)文件中的一些日志 example.20200510.log

          2020-05-10T17:04:17+00:00?ninja.var.log.kong.log?{"log":"2020/05/10?17:04:16?[warn]?35#0:?*4?[lua]?globalpatches.lua:47:?sleep():?executing?a?blocking?'sleep'?(0.004?seconds),?context:?init_worker_by_lua*\n","stream":"stderr"}
          2020-05-10T17:04:17+00:00?ninja.var.log.kong.log?{"log":"2020/05/10?17:04:16?[warn]?33#0:?*2?[lua]?globalpatches.lua:47:?sleep():?executing?a?blocking?'sleep'?(0.008?seconds),?context:?init_worker_by_lua*\n","stream":"stderr"}
          2020-05-10T17:04:17+00:00?ninja.var.log.kong.log?{"log":"2020/05/10?17:04:17?[warn]?32#0:?*1?[lua]?mesh.lua:86:?init():?no?cluster_ca?in?declarative?configuration:?cannot?use?node?in?mesh?mode,?context:?init_worker_by_lua*\n","stream":"stderr"}
          2020-05-10T17:04:30+00:00?ninja.var.log.kong.log?{"log":"172.17.0.1?-?-?[10/May/2020:17:04:30?+0000]?\"GET?/?HTTP/1.1\"?404?48?\"-\"?\"curl/7.59.0\"\n","stream":"stdout"}
          2020-05-10T17:05:38+00:00?ninja.var.log.kong.log?{"log":"172.17.0.1?-?-?[10/May/2020:17:05:38?+0000]?\"GET?/users?HTTP/1.1\"?401?26?\"-\"?\"curl/7.59.0\"\n","stream":"stdout"}
          2020-05-10T17:06:24+00:00?ninja.var.log.kong.log?{"log":"172.17.0.1?-?-?[10/May/2020:17:06:24?+0000]?\"GET?/users?HTTP/1.1\"?499?0?\"-\"?\"curl/7.59.0\"\n","stream":"stdout"}

          注意上面的日志,每行都有3列,格式為:

          log>????log>????log>

          注意:標(biāo)簽都是 "ninja" 字符串加上目錄路徑和文件名,之間使用". "分隔。

          過濾

          現(xiàn)在我們已經(jīng)在 fluentd 中實(shí)現(xiàn)了日志的收集,接下來讓我們對(duì)它進(jìn)行一些過濾操作。

          到目前為止,我們已經(jīng)實(shí)現(xiàn)了前面那條命令的2個(gè)部分,tail -f /var/log/*.log> example.log 工作正常,但是如果你看一下輸出,我們有訪問日志和應(yīng)用日志混合在一起,現(xiàn)在我們需要實(shí)現(xiàn) grep 'what I want' 過濾。

          在這個(gè)例子中,我們只想要訪問日志,丟棄其他的日志行。比如說,通過 HTTP 進(jìn)行 grepping 會(huì)給我們提供所有的訪問日志,并將應(yīng)用日志排除在外,下面的配置就可以做到這一點(diǎn)。


          ??@type?grep
          ??
          ????key?log
          ????pattern?/HTTP/
          ??


          我們來分析下這個(gè)過濾配置:

          • >**:表示我們將只過濾以 ninja.var.log.kong 開頭的標(biāo)簽日志。
          • @type grep:使用 grep 這個(gè)插件進(jìn)行過濾。
          • 部分:這里我們要在日志內(nèi)容的記錄鍵中提取 "HTTP", 通過這個(gè)配置,我們的 fluentd 管道中添加了一個(gè)新的塊。

          現(xiàn)在我們停止并再次運(yùn)行容器。我們應(yīng)該在輸出日志中看到一些不同的日志了,沒有應(yīng)用日志,只有訪問日志數(shù)據(jù)。

          2020-05-10T17:04:30+00:00?ninja.var.log.kong.log?{"log":"172.17.0.1?-?-?[10/May/2020:17:04:30?+0000]?\"GET?/?HTTP/1.1\"?404?48?\"-\"?\"curl/7.59.0\"\n","stream":"stdout"}
          2020-05-10T17:05:38+00:00?ninja.var.log.kong.log?{"log":"172.17.0.1?-?-?[10/May/2020:17:05:38?+0000]?\"GET?/users?HTTP/1.1\"?401?26?\"-\"?\"curl/7.59.0\"\n","stream":"stdout"}
          2020-05-10T17:06:24+00:00?ninja.var.log.kong.log?{"log":"172.17.0.1?-?-?[10/May/2020:17:06:24?+0000]?\"GET?/users?HTTP/1.1\"?499?0?\"-\"?\"curl/7.59.0\"\n","strea

          解析訪問日志

          為了熟悉我們的配置,下面讓我們添加一個(gè)解析器插件來從訪問日志中提取一些其他有用的信息。在 grep 過濾器后使用下面配置。


          ??@type?parser
          ??key_name?log
          ??
          ????@type?nginx
          ??


          同樣我們來仔細(xì)查看下這個(gè)配置:

          • >**:我們將解析所有以 ninja.var.log.kong 開頭的標(biāo)簽,就像上面的一樣。
          • @type parser:過濾器的類型是 parser 解析器。
          • 我們將對(duì)日志內(nèi)容的 log key 進(jìn)行解析。
          • 由于這些都是 nginx 的訪問日志,我們將使用 @type nginx 的解析器。

          現(xiàn)在我們的管道是下面這個(gè)樣子了。


          我們?cè)俅沃匦逻\(yùn)行容器,現(xiàn)在的訪問日志應(yīng)該是這樣的了。

          2020-05-10T17:04:30+00:00?ninja.var.log.kong.log?{"remote":"172.17.0.1","host":"-","user":"-","method":"GET","path":"/","code":"404","size":"48","referer":"-","agent":"curl/7.59.0","http_x_forwarded_for":""}

          這是之前日志中的第一個(gè)訪問日志,現(xiàn)在日志內(nèi)容完全不同了,我們的鍵從日志流,變成了 remote、host、user、method、path、code、size、referer、agent 以及 http_x_forwarded_for。如果我們要把這個(gè)保存到 Elasticsearch 中,我們將能夠通過 method=GET 或其他組合進(jìn)行過濾了。

          當(dāng)然我們還可以更進(jìn)一步,在 remote 字段中使用 geoip 插件來提取我們我們 API 的客戶端的地理位置信息,大家可以自行測試,不過需要注意的時(shí)候需要我們的鏡像中包含這些插件。

          總結(jié)

          現(xiàn)在我們知道了如何用 docker 來讓 fluentd 讀取配置文件,我們了解了一些常用的 fluentd 配置,我們能夠從一些日志數(shù)據(jù)中來過濾、解析提取有用的信息。

          原文鏈接:https://scaleout.ninja/post/fluentd-simplified/


          推薦閱讀






          ?點(diǎn)擊屏末?|??|?即刻學(xué)習(xí)

          瀏覽 59
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                    <th id="afajh"><progress id="afajh"></progress></th>
                    欧美日本一区 | 日本乱伦精品 | 99香蕉精品99久久久久久 | 韩国久久 | 天天综合~91入口 |