1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        輕量級日志 Loki 全攻略

        共 1519字,需瀏覽 4分鐘

         ·

        2022-05-20 19:09


        文章來源:https://c1n.cn/0wHvF

        前言

        在對公司容器云的日志方案進(jìn)行設(shè)計的時候,發(fā)現(xiàn)主流的 ELK(Elasticsearch,Logstash,Kibana)或者 EFK(Elasticsearch,F(xiàn)ilebeat or Fluentd,Kibana)比較重,再加上現(xiàn)階段對于 ES 復(fù)雜的搜索功能很多都用不上,最終選擇了 Grafana 開源的 Loki 日志系統(tǒng)。

        下面我們來介紹下 Loki 的一些基本概念和架構(gòu),當(dāng)然 EFK 作為業(yè)界成熟的日志聚合解決方案也是大家應(yīng)該需要熟悉和掌握的。

        簡介

        Loki 是 Grafana Labs 團隊最新的開源項目,是一個水平可擴展,高可用性,多租戶的日志聚合系統(tǒng)。

        它的設(shè)計非常經(jīng)濟高效且易于操作,因為它不會為日志內(nèi)容編制索引,而是為每個日志流編制一組標(biāo)簽,專門為 Prometheus 和 Kubernetes 用戶做了相關(guān)優(yōu)化。

        該項目受 Prometheus 啟發(fā),官方的介紹就是:Like Prometheus,But For Logs。類似于 Prometheus 的日志系統(tǒng)。

        項目地址:

        https://github.com/grafana/loki/

        與其他日志聚合系統(tǒng)相比,Loki 具有下面的一些特性:

        • 不對日志進(jìn)行全文索引。通過存儲壓縮非結(jié)構(gòu)化日志和僅索引元數(shù)據(jù),Loki 操作起來會更簡單,更省成本。
        • 通過使用與 Prometheus 相同的標(biāo)簽記錄流對日志進(jìn)行索引和分組,這使得日志的擴展和操作效率更高,能對接 alertmanager。
        • 特別適合儲存 Kubernetes Pod 日志;諸如 Pod 標(biāo)簽之類的元數(shù)據(jù)會被自動刪除和編入索引。
        • 受 Grafana 原生支持,避免 kibana 和 grafana 來回切換。

        架構(gòu)說明

        圖片

        組件說明

        說明如下:

        • Promtail 作為采集器,類比 filebeat
        • Loki 相當(dāng)于服務(wù)端,類比 es

        Loki 進(jìn)程包含四種角色:

        • querier 查詢器
        • inester 日志存儲器
        • query-frontend 前置查詢器
        • distributor 寫入分發(fā)器

        可以通過 Loki 二進(jìn)制的 -target 參數(shù)指定運行角色。

        read path

        如下:

        • 查詢器接受 HTTP/1 數(shù)據(jù)請求
        • 查詢器將查詢傳遞給所有 ingesters 請求內(nèi)存中的數(shù)據(jù)
        • 接收器接受讀取的請求,并返回與查詢匹配的數(shù)據(jù)(如果有)
        • 如果沒有接受者返回數(shù)據(jù),則查詢器會從后備存儲中延遲加載數(shù)據(jù)并對其執(zhí)行查詢
        • 查詢器將迭代所有接收到的數(shù)據(jù)并進(jìn)行重復(fù)數(shù)據(jù)刪除,從而通過 HTTP/1 連接返回最終數(shù)據(jù)集

        write path

        圖片

        如上圖:

        • 分發(fā)服務(wù)器收到一個 HTTP/1 請求,以存儲流數(shù)據(jù)
        • 每個流都使用散列環(huán)散列
        • 分發(fā)程序?qū)⒚總€流發(fā)送到適當(dāng)?shù)?inester 和其副本(基于配置的復(fù)制因子)
        • 每個實例將為流的數(shù)據(jù)創(chuàng)建一個塊或?qū)⑵渥芳拥浆F(xiàn)有塊中,, 每個租戶和每個標(biāo)簽集的塊都是唯一的
        • 分發(fā)服務(wù)器通過 HTTP/1 鏈接以成功代碼作為響應(yīng)

        部署

        本地化模式安裝

        下載 Promtail 和 Loki:

        wget??https://github.com/grafana/loki/releases/download/v2.2.1/loki-linux-amd64.zip
        wget?https://github.com/grafana/loki/releases/download/v2.2.1/promtail-linux-amd64.zip
        安裝 Promtail:
        $?mkdir?/opt/app/{promtail,loki}?-pv

        #?promtail配置文件
        $?cat?<?/opt/app/promtail/promtail.yaml
        server:
        ??http_listen_port:?9080
        ??grpc_listen_port:?0

        positions:
        ??filename:?/var/log/positions.yaml?#?This?location?needs?to?be?writeable?by?promtail.

        client:
        ??url:?http://localhost:3100/loki/api/v1/push

        scrape_configs:
        ?-?job_name:?system
        ???pipeline_stages:
        ???static_configs:
        ???-?targets:
        ??????-?localhost
        ?????labels:
        ??????job:?varlogs
        ??????host:?yourhost
        ??????__path__:?/var/log/*.log
        EOF

        #?解壓安裝包
        unzip?promtail-linux-amd64.zip
        mv?promtail-linux-amd64?/opt/app/promtail/promtail

        #?service文件
        $?cat?</etc/systemd/system/promtail.service
        [Unit]
        Description=promtail?server
        Wants=network-online.target
        After=network-online.target

        [Service]
        ExecStart=/opt/app/promtail/promtail?-config.file=/opt/app/promtail/promtail.yaml
        StandardOutput=syslog
        StandardError=syslog
        SyslogIdentifier=promtail
        [Install]
        WantedBy=default.target
        EOF

        systemctl?daemon-reload
        systemctl?restart?promtail
        systemctl?status?promtail

        安裝 Loki:

        $?mkdir?/opt/app/{promtail,loki}?-pv

        #?promtail配置文件
        $?cat?<?/opt/app/loki/loki.yaml
        auth_enabled:?false

        server:
        ??http_listen_port:?3100
        ??grpc_listen_port:?9096

        ingester:
        ??wal:
        ????enabled:?true
        ????dir:?/opt/app/loki/wal
        ??lifecycler:
        ????address:?127.0.0.1
        ????ring:
        ??????kvstore:
        ????????store:?inmemory
        ??????replication_factor:?1
        ????final_sleep:?0s
        ??chunk_idle_period:?1h???????#?Any?chunk?not?receiving?new?logs?in?this?time?will?be?flushed
        ??max_chunk_age:?1h???????????#?All?chunks?will?be?flushed?when?they?hit?this?age,?default?is?1h
        ??chunk_target_size:?1048576??#?Loki?will?attempt?to?build?chunks?up?to?1.5MB,?flushing?first?if?chunk_idle_period?or?max_chunk_age?is?reached?first
        ??chunk_retain_period:?30s????#?Must?be?greater?than?index?read?cache?TTL?if?using?an?index?cache?(Default?index?read?cache?TTL?is?5m)
        ??max_transfer_retries:?0?????#?Chunk?transfers?disabled

        schema_config:
        ??configs:
        ????-?from:?2020-10-24
        ??????store:?boltdb-shipper
        ??????object_store:?filesystem
        ??????schema:?v11
        ??????index:
        ????????prefix:?index_
        ????????period:?24h

        storage_config:
        ??boltdb_shipper:
        ????active_index_directory:?/opt/app/loki/boltdb-shipper-active
        ????cache_location:?/opt/app/loki/boltdb-shipper-cache
        ????cache_ttl:?24h?????????#?Can?be?increased?for?faster?performance?over?longer?query?periods,?uses?more?disk?space
        ????shared_store:?filesystem
        ??filesystem:
        ????directory:?/opt/app/loki/chunks

        compactor:
        ??working_directory:?/opt/app/loki/boltdb-shipper-compactor
        ??shared_store:?filesystem

        limits_config:
        ??reject_old_samples:?true
        ??reject_old_samples_max_age:?168h

        chunk_store_config:
        ??max_look_back_period:?0s

        table_manager:
        ??retention_deletes_enabled:?false
        ??retention_period:?0s


        ruler:
        ??storage:
        ????type:?local
        ????local:
        ??????directory:?/opt/app/loki/rules
        ??rule_path:?/opt/app/loki/rules-temp
        ??alertmanager_url:?http://localhost:9093
        ??ring:
        ????kvstore:
        ??????store:?inmemory
        ??enable_api:?true
        EOF

        #?解壓包
        unzip?loki-linux-amd64.zip?
        mv?loki-linux-amd64?/opt/app/loki/loki

        #?service文件

        $?cat?</etc/systemd/system/loki.service
        [Unit]
        Description=loki?server
        Wants=network-online.target
        After=network-online.target

        [Service]
        ExecStart=/opt/app/loki/loki?-config.file=/opt/app/loki/loki.yaml
        StandardOutput=syslog
        StandardError=syslog
        SyslogIdentifier=loki
        [Install]
        WantedBy=default.target
        EOF

        systemctl?daemon-reload
        systemctl?restart?loki
        systemctl?status?loki

        使用

        grafana 上配置 loki 數(shù)據(jù)源

        如下圖:

        圖片

        grafana-loki-dashsource

        在數(shù)據(jù)源列表中選擇 Loki,配置 Loki 源地址:

        圖片

        grafana-loki-dashsource-config

        源地址配置 http://loki:3100 即可,保存。

        保存完成后,切換到 grafana 左側(cè)區(qū)域的 Explore,即可進(jìn)入到 Loki 的頁面:

        圖片

        grafana-loki

        然后我們點擊 Log labels 就可以把當(dāng)前系統(tǒng)采集的日志標(biāo)簽給顯示出來,可以根據(jù)這些標(biāo)簽進(jìn)行日志的過濾查詢:

        圖片

        grafana-loki-log-labels

        比如我們這里選擇 /var/log/messages,就會把該文件下面的日志過濾展示出來,不過由于時區(qū)的問題,可能還需要設(shè)置下時間才可以看到數(shù)據(jù):

        圖片

        grafana-loki-logs

        這里展示的是 promtail 容器里面 / var/log 目錄中的日志。

        promtail 容器 /etc/promtail/config.yml:

        server:
        ??http_listen_port:?9080
        ??grpc_listen_port:?0

        positions:
        ??filename:?/tmp/positions.yaml

        clients:
        ??-?url:?http://loki:3100/loki/api/v1/push

        scrape_configs:
        -?job_name:?system
        ??static_configs:
        ??-?targets:
        ??????-?localhost
        ????labels:
        ??????job:?varlogs
        ??????__path__:?/var/log/*log

        這里的 job 就是 varlog,文件路徑就是 /var/log/*log。

        在 grafana explore 上配置查看日志

        查看日志?rate({job="message"}?|="kubelet"

        算 qps rate({job=”message”} |=”kubelet” [1m])

        只索引標(biāo)簽

        之前多次提到 loki 和 es 最大的不同是 loki 只對標(biāo)簽進(jìn)行索引而不對內(nèi)容索引。下面我們舉例來看下。

        靜態(tài)標(biāo)簽匹配模式

        以簡單的 promtail 配置舉例:

        scrape_configs:
        ?-?job_name:?system
        ???pipeline_stages:
        ???static_configs:
        ???-?targets:
        ??????-?localhost
        ?????labels:
        ??????job:?message
        ??????__path__:?/var/log/messages

        配置解讀:

        • 上面這段配置代表啟動一個日志采集任務(wù)
        • 這個任務(wù)有 1 個固定標(biāo)簽 job=”syslog”
        • 采集日志路徑為 /var/log/messages,會以一個名為 filename 的固定標(biāo)簽
        • 在 promtail 的 web 頁面上可以看到類似 prometheus 的 target 信息頁面

        可以和使用 Prometheus 一樣的標(biāo)簽匹配語句進(jìn)行查詢。

        {job="syslog"}:

        scrape_configs:
        ?-?job_name:?system
        ???pipeline_stages:
        ???static_configs:
        ???-?targets:
        ??????-?localhost
        ?????labels:
        ??????job:?syslog
        ??????__path__:?/var/log/syslog
        ?-?job_name:?system
        ???pipeline_stages:
        ???static_configs:
        ???-?targets:
        ??????-?localhost
        ?????labels:
        ??????job:?apache
        ??????__path__:?/var/log/apache.log

        如果我們配置了兩個 job,則可以使用job=~”apachesyslog”進(jìn)行多 job 匹配;同時也支持正則和正則非匹配。

        標(biāo)簽匹配模式的特點

        原理如下:
        • 和 prometheus 一致,相同標(biāo)簽對應(yīng)的是一個流 prometheus 處理 series 的模式
        • prometheus 中標(biāo)簽一致對應(yīng)的同一個 hash 值和 refid(正整數(shù)遞增的 id),也就是同一個 series
        • 時序數(shù)據(jù)不斷的 append 追加到這個 memseries 中
        • 當(dāng)有任意標(biāo)簽發(fā)生變化時會產(chǎn)生新的 hash 值和 refid,對應(yīng)新的 series

        loki 處理日志的模式和 prometheus 一致,loki 一組標(biāo)簽值會生成一個 stream。日志隨著時間的遞增會追加到這個 stream 中,最后壓縮為 chunk。當(dāng)有任意標(biāo)簽發(fā)生變化時會產(chǎn)生新的 hash 值,對應(yīng)新的 stream。

        查詢過程
        • 所以 loki 先根據(jù)標(biāo)簽算出 hash 值在倒排索引中找到對應(yīng)的 chunk?
        • 然后再根據(jù)查詢語句中的關(guān)鍵詞等進(jìn)行過濾,這樣能大大的提速
        • 因為這種根據(jù)標(biāo)簽算哈希在倒排中查找 id,對應(yīng)找到存儲的塊在 prometheus 中已經(jīng)被驗證過了
        • 屬于開銷低
        • 速度快

        動態(tài)標(biāo)簽和高基數(shù)

        所以有了上述知識,那么就得談?wù)剟討B(tài)標(biāo)簽的問題了。

        兩個概念:

        • 何為動態(tài)標(biāo)簽:說白了就是標(biāo)簽的 value 不固定
        • 何為高基數(shù)標(biāo)簽:說白了就是標(biāo)簽的 value 可能性太多了,達(dá)到 10 萬,100 萬甚至更多

        比如 apache 的 access 日志:

        11.11.11.11?-?frank?[25/Jan/2000:14:00:01?-0500]?"GET?/1986.js?HTTP/1.1"?200?932?"-"?"Mozilla/5.0?(Windows;?U;?Windows?NT?5.1;?de;?rv:1.9.1.7)?Gecko/20091221?Firefox/3.5.7?GTB6"

        在 Promtail 中使用 regex 想要匹配 action 和 status_code 兩個標(biāo)簽:

        scrape_configs:
        ?-?job_name:?system
        ???pipeline_stages:
        ???static_configs:
        ???-?targets:
        ??????-?localhost
        ?????labels:
        ??????job:?syslog
        ??????__path__:?/var/log/syslog
        ?-?job_name:?system
        ???pipeline_stages:
        ???static_configs:
        ???-?targets:
        ??????-?localhost
        ?????labels:
        ??????job:?apache
        ??????__path__:?/var/log/apache.log

        ??-?job_name:?system
        ????pipeline_stages:
        ???????-?regex:
        ?????????expression:?"^(?P\\S+)?(?P\\S+)?(?P\\S+)?\\[(?P[\\w:/]+\\s[+\\-]\\d{4})\\]?\"(?P\\S+)\\s?(?P\\S+)?\\s?(?P\\S+)?\"?(?P\\d{3}|-)?(?P\\d+|-)\\s?\"?(?P[^\"]*)\"?\\s?\"?(?P[^\"]*)?\"?$"
        ?????-?labels:
        ?????????action:
        ?????????status_code:
        ????static_configs:
        ????-?targets:
        ???????-?localhost
        ??????labels:
        ???????job:?apache
        ???????env:?dev
        ???????__path__:?/var/log/apache.log

        那么對應(yīng) action=get/post 和 status_code=200/400 則對應(yīng) 4 個流:

        11.11.11.11?-?frank?[25/Jan/2000:14:00:01?-0500]?"GET?/1986.js?HTTP/1.1"?200?932?"-"?"Mozilla/5.0?(Windows;?U;?Windows?NT?5.1;?de;?rv:1.9.1.7)?Gecko/20091221?Firefox/3.5.7?GTB6"
        11.11.11.12?-?frank?[25/Jan/2000:14:00:02?-0500]?"POST?/1986.js?HTTP/1.1"?200?932?"-"?"Mozilla/5.0?(Windows;?U;?Windows?NT?5.1;?de;?rv:1.9.1.7)?Gecko/20091221?Firefox/3.5.7?GTB6"
        11.11.11.13?-?frank?[25/Jan/2000:14:00:03?-0500]?"GET?/1986.js?HTTP/1.1"?400?932?"-"?"Mozilla/5.0?(Windows;?U;?Windows?NT?5.1;?de;?rv:1.9.1.7)?Gecko/20091221?Firefox/3.5.7?GTB6"
        11.11.11.14?-?frank?[25/Jan/2000:14:00:04?-0500]?"POST?/1986.js?HTTP/1.1"?400?932?"-"?"Mozilla/5.0?(Windows;?U;?Windows?NT?5.1;?de;?rv:1.9.1.7)?Gecko/20091221?Firefox/3.5.7?GTB6"

        那四個日志行將變成四個單獨的流,并開始填充四個單獨的塊。

        如果出現(xiàn)另一個獨特的標(biāo)簽組合(例如 status_code =“500”),則會創(chuàng)建另一個新流。

        高基數(shù)問題

        就像上面,如果給 ip 設(shè)置一個標(biāo)簽,現(xiàn)在想象一下,如果您為設(shè)置了標(biāo)簽 ip,來自用戶的每個不同的 ip 請求不僅成為唯一的流??梢钥焖偕沙汕先f的流,這是高基數(shù),這可以殺死 Loki。

        如果字段沒有被當(dāng)做標(biāo)簽被索引,會不會查詢很慢,Loki 的超級能力是將查詢分解為小塊并并行分發(fā),以便您可以在短時間內(nèi)查詢大量日志數(shù)據(jù)。

        全文索引問題

        大索引既復(fù)雜又昂貴。通常,日志數(shù)據(jù)的全文索引的大小等于或大于日志數(shù)據(jù)本身的大小。

        要查詢?nèi)罩緮?shù)據(jù),需要加載此索引,并且為了提高性能,它可能應(yīng)該在內(nèi)存中。這很難擴展,并且隨著您攝入更多日志,索引會迅速變大。

        Loki 的索引通常比攝取的日志量小一個數(shù)量級,索引的增長非常緩慢。

        加速查詢沒標(biāo)簽字段:以上邊提到的 ip 字段為例 - 使用過濾器表達(dá)式查詢。

        {job="apache"}?|=?"11.11.11.11"

        loki 查詢時的分片(按時間范圍分段 grep):

        • Loki 將把查詢分解成較小的分片,并為與標(biāo)簽匹配的流打開每個區(qū)塊,并開始尋找該 IP 地址。
        • 這些分片的大小和并行化的數(shù)量是可配置的,并取決于您提供的資源
        • 如果需要,您可以將分片間隔配置為 5m,部署 20 個查詢器,并在幾秒鐘內(nèi)處理千兆字節(jié)的日志
        • 或者,您可以發(fā)瘋并設(shè)置 200 個查詢器并處理 TB 的日志!

        兩種索引模式對比:

        • es 的大索引,不管你查不查詢,他都必須時刻存在。比如長時間占用過多的內(nèi)存
        • loki 的邏輯是查詢時再啟動多個分段并行查詢
        日志量少時少加標(biāo)簽:
        • 因為每多加載一個 chunk 就有額外的開銷
        • 舉例,如果該查詢是 {app=”loki”,level!=”debug”}
        • 在沒加 level 標(biāo)簽的情況下只需加載一個 chunk 即 app=“l(fā)oki” 的標(biāo)簽
        • 如果加了 level 的情況,則需要把 level=info,warn,error,critical 5 個 chunk 都加載再查詢
        需要標(biāo)簽時再去添加:
        • 當(dāng) chunk_target_size=1MB 時代表 以 1MB 的壓縮大小來切割塊
        • 對應(yīng)的原始日志大小在 5MB-10MB,如果日志在 max_chunk_age 時間內(nèi)能達(dá)到 10MB,考慮添加標(biāo)簽
        日志應(yīng)當(dāng)按時間遞增:
        • 這個問題和 tsdb 中處理舊數(shù)據(jù)是一樣的道理
        • 目前 loki 為了性能考慮直接拒絕掉舊數(shù)據(jù)



        END

        關(guān)Java導(dǎo),Java,Java發(fā)!

        瀏覽 71
        點贊
        評論
        收藏
        分享

        手機掃一掃分享

        分享
        舉報
        評論
        圖片
        表情
        推薦
        點贊
        評論
        收藏
        分享

        手機掃一掃分享

        分享
        舉報
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            啊轻点灬太粗嗯太深了视频在线观看 | 操穴视频网站 | 懂色AV色吟AV夜夜嗨 | 打飞机免费网站 | 日韩av成人电影在线观看 | 一级毛片视频免费 | 广东少妇大战黑人34厘米视频 | 极品粉穴 | 日本久久网站 | 三洞齐开国语版免费观看高清 |