<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>

          還在用ES查日志嗎,快看看石墨文檔 Clickhouse 日志架構(gòu)玩法

          共 8352字,需瀏覽 17分鐘

           ·

          2022-02-26 15:00

          1 背景

          石墨文檔全部應(yīng)用部署在Kubernetes上,每時(shí)每刻都會(huì)有大量的日志輸出,我們之前主要使用SLSES作為日志存儲(chǔ)。但是我們?cè)谑褂眠@些組件的時(shí)候,發(fā)現(xiàn)了一些問題。

          • 成本問題:

            • SLS個(gè)人覺得是一個(gè)非常優(yōu)秀的產(chǎn)品,速度快,交互方便,但是SLS索引成本比較貴

            • 我們想減少SLS索引成本的時(shí)候,發(fā)現(xiàn)云廠商并不支持分析單個(gè)索引的成本,導(dǎo)致我們無法知道是哪些索引構(gòu)建的不夠合理

            • ES使用的存儲(chǔ)非常多,并且耗費(fèi)大量的內(nèi)存

          • 通用問題:

            • 如果業(yè)務(wù)是混合云架構(gòu),或者業(yè)務(wù)形態(tài)有SAAS和私有化兩種方式,那么SLS并不能通用

            • 日志和鏈路,需要用兩套云產(chǎn)品,不是很方便

          • 精確度問題:SLS存儲(chǔ)的精度只能到秒,但我們實(shí)際日志精度到毫秒,如果日志里面有traceidSLS中無法通過根據(jù)traceid信息,將日志根據(jù)毫秒時(shí)間做排序,不利于排查錯(cuò)誤

          我們經(jīng)過一番調(diào)研后,發(fā)現(xiàn)使用Clickhouse能夠很好的解決以上問題,并且Clickhouse省存儲(chǔ)空間,非常省錢,所以我們選擇了Clickhouse方案存儲(chǔ)日志。但當(dāng)我們深入研究后,Clickhouse作為日志存儲(chǔ)有許多落地的細(xì)節(jié),但業(yè)界并沒有很好闡述相關(guān)Clickhouse采集日志的整套流程,以及沒有一款優(yōu)秀的Clickhouse日志查詢工具幫助分析日志,為此我們寫了一套Clickhouse日志系統(tǒng)貢獻(xiàn)給開源社區(qū),并將Clickhouse的日志采集架構(gòu)的經(jīng)驗(yàn)做了總結(jié)。先上個(gè)Clickhouse日志查詢界面,讓大家感受下石墨最懂前端的后端程序員。

          2 架構(gòu)原理圖

          我們將日志系統(tǒng)分為四個(gè)部分:日志采集、日志傳輸、日志存儲(chǔ)、日志管理。

          • 日志采集:LogCollector采用Daemonset方式部署,將宿主機(jī)日志目錄掛載到LogCollector的容器內(nèi),LogCollector通過掛載的目錄能夠采集到應(yīng)用日志、系統(tǒng)日志、K8S審計(jì)日志等

          • 日志傳輸:通過不同Logstore映射到Kafka中不同的Topic,將不同數(shù)據(jù)結(jié)構(gòu)的日志做了分離

          • 日志存儲(chǔ):使用Clickhouse中的兩種引擎數(shù)據(jù)表和物化視圖

          • 日志管理:開源的Mogo系統(tǒng),能夠查詢?nèi)罩荆O(shè)置日志索引,設(shè)置LogCollector配置,設(shè)置Clickhouse表,設(shè)置報(bào)警等

          以下我們按照這四大部分,闡述其中的架構(gòu)原理

          3 日志采集

          3.1 采集方式

          Kubernetes容器內(nèi)日志收集的方式通常有以下三種方案

          • DaemonSet方式采集:在每個(gè)?node?節(jié)點(diǎn)上部署LogCollector,并將宿主機(jī)的目錄掛載為容器的日志目錄,LogCollector讀取日志內(nèi)容,采集到日志中心。

          • 網(wǎng)絡(luò)方式采集:通過應(yīng)用的日志?SDK,直接將日志內(nèi)容采集到日志中心 。

          • SideCar方式采集:在每個(gè)?pod?內(nèi)部署LogCollector,LogCollector只讀取這個(gè)?pod?內(nèi)的日志內(nèi)容,采集到日志中心。

          以下是三種采集方式的優(yōu)缺點(diǎn):


          DaemonSet方式網(wǎng)絡(luò)方式SideCar方式
          采集日志類型標(biāo)準(zhǔn)輸出+文件應(yīng)用日志文件
          部署運(yùn)維一般,維護(hù)DaemonSet低,維護(hù)配置文件較高,每個(gè)pod部署sidecar容器
          日志分類存儲(chǔ)可通過容器/路徑等映射業(yè)務(wù)獨(dú)立配置每個(gè)POD可單獨(dú)配置,靈活性高
          支持集群規(guī)模取決于配置數(shù)無限制無限制
          適用場(chǎng)景日志分類明確、功能較單一性能要求極高的場(chǎng)景大型、混合型、PAAS型集群
          性能資源消耗

          我們主要采用DaemonSet方式和網(wǎng)絡(luò)方式采集日志。DaemonSet方式用于ingress、應(yīng)用日志的采集,網(wǎng)絡(luò)方式用于大數(shù)據(jù)日志的采集(可能需要簡(jiǎn)單的說明下原因)。以下我們主要介紹下DeamonSet方式的采集方式。

          3.2 日志輸出

          從上面的介紹中可以看到,我們的DaemonSet會(huì)有兩種方式采集日志類型,一種是標(biāo)準(zhǔn)輸出,一種是文件。引用元乙的描述:雖然使用?Stdout?打印日志是?Docker?官方推薦的方式,但大家需要注意:這個(gè)推薦是基于容器只作為簡(jiǎn)單應(yīng)用的場(chǎng)景,實(shí)際的業(yè)務(wù)場(chǎng)景中我們還是建議大家盡可能使用文件的方式,主要的原因有以下幾點(diǎn):

          • Stdout?性能問題,從應(yīng)用輸出?stdout?到服務(wù)端,中間會(huì)經(jīng)過好幾個(gè)流程(例如普遍使用的JSON?LogDriver):應(yīng)用?stdout?->?DockerEngine?->?LogDriver?-> 序列化成?JSON?-> 保存到文件 ->?Agent?采集文件 -> 解析?JSON?-> 上傳服務(wù)端。整個(gè)流程相比文件的額外開銷要多很多,在壓測(cè)時(shí),每秒 10 萬行日志輸出就會(huì)額外占用?DockerEngine?1 個(gè)?CPU?核;

          • Stdout?不支持分類,即所有的輸出都混在一個(gè)流中,無法像文件一樣分類輸出,通常一個(gè)應(yīng)用中有?AccessLog、ErrorLogInterfaceLog(調(diào)用外部接口的日志)、TraceLog?等,而這些日志的格式、用途不一,如果混在同一個(gè)流中將很難采集和分析;

          • Stdout?只支持容器的主程序輸出,如果是?daemon/fork?方式運(yùn)行的程序?qū)o法使用?stdout

          • 文件的?Dump?方式支持各種策略,例如同步/異步寫入、緩存大小、文件輪轉(zhuǎn)策略、壓縮策略、清除策略等,相對(duì)更加靈活。

          從這個(gè)描述中,我們可以看出在docker中輸出文件在采集到日志中心是一個(gè)更好的實(shí)踐。所有日志采集工具都支持采集文件日志方式,但是我們?cè)谂渲萌罩静杉?guī)則的時(shí)候,發(fā)現(xiàn)開源的一些日志采集工具,例如fluentbitfilebeatDaemonSet部署下采集文件日志是不支持追加例如pod、namespace、container_name、container_idlabel信息,并且也無法通過這些label做些定制化的日志采集。

          agent類型采集方式daemonset部署sidecar部署
          ilogtail文件日志能夠追加label信息,能夠根據(jù)label過濾采集能夠追加label信息,能夠根據(jù)label過濾采集
          fluentbit文件日志無法追加label信息,無法根據(jù)label過濾采集能夠追加abel信息,能夠根據(jù)label過濾采集
          filebeat文件日志無法追加label信息,無法根據(jù)label過濾采集能夠追加label信息,能夠根據(jù)label過濾采集
          ilogtail標(biāo)準(zhǔn)輸出能夠追加label信息,能夠根據(jù)label過濾采集能夠追加label信息,能夠根據(jù)label過濾采集
          fluentbit標(biāo)準(zhǔn)輸出能夠追加label信息,能夠根據(jù)label過濾采集能夠追加abel信息,能夠根據(jù)label過濾采集
          filebeat標(biāo)準(zhǔn)輸出能夠追加label信息,能夠根據(jù)label過濾采集能夠追加label信息,能夠根據(jù)label過濾采集

          基于無法追加label信息的原因,我們暫時(shí)放棄了DeamonSet部署下文件日志采集方式,采用的是基于DeamonSet部署下標(biāo)準(zhǔn)輸出的采集方式。

          3.3 日志目錄

          以下列舉了日志目錄的基本情況

          目錄描述類型
          /var/log/containers存放的是軟鏈接,軟鏈到/var/log/pods里的標(biāo)準(zhǔn)輸出日志標(biāo)準(zhǔn)輸出
          /var/log/pods存放標(biāo)準(zhǔn)輸出日志標(biāo)準(zhǔn)輸出
          /var/log/kubernetes/master存放Kubernetes 審計(jì)輸出日志標(biāo)準(zhǔn)輸出
          /var/lib/docker/overlay2存放應(yīng)用日志文件信息文件日志
          /var/run獲取docker.sock,用于docker通信文件日志
          /var/lib/docker/containers用于存儲(chǔ)容器信息兩種都需要

          因?yàn)槲覀儾杉罩臼鞘褂玫臉?biāo)準(zhǔn)輸出模式,所以根據(jù)上表我們的LogCollector只需要掛載/var/log,/var/lib/docker/containers兩個(gè)目錄。

          3.3.1 標(biāo)準(zhǔn)輸出日志目錄

          應(yīng)用的標(biāo)準(zhǔn)輸出日志存儲(chǔ)在/var/log/containers目錄下,文件名是按照K8S日志規(guī)范生成的。這里以nginx-ingress的日志作為一個(gè)示例。我們通過ls /var/log/containers/ | grep nginx-ingress指令,可以看到nginx-ingress的文件名。

          nginx-ingress-controller-mt2wx_kube-system_nginx-ingress-controller-be3741043eca1621ec4415fd87546b1beb29480ac74ab1cdd9f52003cf4abf0a.log

          我們參照K8S日志的規(guī)范:/var/log/containers/%{DATA:pod_name}_%{DATA:namespace}_%{GREEDYDATA:container_name}-%{DATA:container_id}.log??梢詫?code style="box-sizing: border-box;font-size: 13.6px;font-family: mononoki, Consolas, "Liberation Mono", Menlo, Courier, monospace, "Apple Color Emoji", "Segoe UI Emoji", "Noto Color Emoji", "Segoe UI Symbol", "Android Emoji", EmojiSymbols;padding: 0.2em 0.4em;border-radius: 3px;word-break: break-word;background-size: 20px 20px;white-space: pre-wrap;background-color: rgba(27, 31, 35, 0.05);">nginx-ingress日志解析為:

          • pod_name:nginx-ingress-controller-mt2w

          • namespace:kube-system

          • container_name:nginx-ingress-controller

          • container_id:be3741043eca1621ec4415fd87546b1beb29480ac74ab1cdd9f52003cf4abf0a

          通過以上的日志解析信息,我們的LogCollector?就可以很方便的追加pod、namespace、container_namecontainer_id的信息。

          3.3.2 容器信息目錄

          應(yīng)用的容器信息存儲(chǔ)在/var/lib/docker/containers目錄下,目錄下的每一個(gè)文件夾為容器ID,我們可以通過cat config.v2.json獲取應(yīng)用的docker基本信息。

          3.4 LogCollector采集日志

          3.4.1 配置

          我們LogCollector采用的是fluent-bit,該工具是cncf旗下的,能夠更好的與云原生相結(jié)合。通過Mogo系統(tǒng)可以選擇Kubernetes集群,很方便的設(shè)置fluent-bit?configmap的配置規(guī)則。

          3.4.2 數(shù)據(jù)結(jié)構(gòu)

          fluent-bit的默認(rèn)采集數(shù)據(jù)結(jié)構(gòu)

          • @timestamp字段:string or float,用于記錄采集日志的時(shí)間

          • log字段:string,用于記錄日志的完整內(nèi)容

          Clickhouse如果使用@timestamp的時(shí)候,因?yàn)槔锩嬗?code style="box-sizing: border-box;font-size: 13.6px;font-family: mononoki, Consolas, "Liberation Mono", Menlo, Courier, monospace, "Apple Color Emoji", "Segoe UI Emoji", "Noto Color Emoji", "Segoe UI Symbol", "Android Emoji", EmojiSymbols;padding: 0.2em 0.4em;border-radius: 3px;word-break: break-word;background-size: 20px 20px;white-space: pre-wrap;background-color: rgba(27, 31, 35, 0.05);">@特殊字符,會(huì)處理的有問題。所以我們?cè)谔幚?code style="box-sizing: border-box;font-size: 13.6px;font-family: mononoki, Consolas, "Liberation Mono", Menlo, Courier, monospace, "Apple Color Emoji", "Segoe UI Emoji", "Noto Color Emoji", "Segoe UI Symbol", "Android Emoji", EmojiSymbols;padding: 0.2em 0.4em;border-radius: 3px;word-break: break-word;background-size: 20px 20px;white-space: pre-wrap;background-color: rgba(27, 31, 35, 0.05);">fluent-bit的采集數(shù)據(jù)結(jié)構(gòu),會(huì)做一些映射關(guān)系,并且規(guī)定雙下劃線為Mogo系統(tǒng)日志索引,避免和業(yè)務(wù)日志的索引沖突。

          • _time_字段:string or float,用于記錄采集日志的時(shí)間

          • _log_字段:string,用于記錄日志的完整內(nèi)容

          例如你的日志記錄的是{"id":1},那么實(shí)際fluent-bit采集的日志會(huì)是{"_time_":"2022-01-15...","_log_":"{\"id\":1}"?該日志結(jié)構(gòu)會(huì)直接寫入到kafka中,Mogo系統(tǒng)會(huì)根據(jù)這兩個(gè)字段_time_、_log_設(shè)置clickhouse中的數(shù)據(jù)表。

          3.4.3 采集

          如果我們要采集ingress日志,我們需要在input配置里,設(shè)置ingress的日志目錄,fluent-bit會(huì)把ingress日志采集到內(nèi)存里。

          然后我們?cè)?code style="box-sizing: border-box;font-size: 13.6px;font-family: mononoki, Consolas, "Liberation Mono", Menlo, Courier, monospace, "Apple Color Emoji", "Segoe UI Emoji", "Noto Color Emoji", "Segoe UI Symbol", "Android Emoji", EmojiSymbols;padding: 0.2em 0.4em;border-radius: 3px;word-break: break-word;background-size: 20px 20px;white-space: pre-wrap;background-color: rgba(27, 31, 35, 0.05);">filter配置里,將log改寫為_log_

          然后我們?cè)?code style="box-sizing: border-box;font-size: 13.6px;font-family: mononoki, Consolas, "Liberation Mono", Menlo, Courier, monospace, "Apple Color Emoji", "Segoe UI Emoji", "Noto Color Emoji", "Segoe UI Symbol", "Android Emoji", EmojiSymbols;padding: 0.2em 0.4em;border-radius: 3px;word-break: break-word;background-size: 20px 20px;white-space: pre-wrap;background-color: rgba(27, 31, 35, 0.05);">ouput配置里,將追加的日志采集時(shí)間設(shè)置為_time_,設(shè)置好日志寫入的kafka borkerskafka topics,那么fluent-bit里內(nèi)存的日志就會(huì)寫入到kafka

          日志寫入到Kafka_log_需要為json,如果你的應(yīng)用寫入的日志不是json,那么你就需要根據(jù)fluent-bitparser文檔,調(diào)整你的日志寫入的數(shù)據(jù)結(jié)構(gòu):https://docs.fluentbit.io/manual/pipeline/filters/parser

          4 日志傳輸

          Kafka主要用于日志傳輸。上文說到我們使用fluent-bit采集日志的默認(rèn)數(shù)據(jù)結(jié)構(gòu),在下圖kafka工具中我們可以看到日志采集的內(nèi)容。

          在日志采集過程中,會(huì)由于不用業(yè)務(wù)日志字段不一致,解析方式是不一樣的。所以我們?cè)谌罩緜鬏旊A段,需要將不同數(shù)據(jù)結(jié)構(gòu)的日志,創(chuàng)建不同的Clickhouse表,映射到Kafka不同的Topic。這里以ingress為例,那么我們?cè)?code style="box-sizing: border-box;font-size: 13.6px;font-family: mononoki, Consolas, "Liberation Mono", Menlo, Courier, monospace, "Apple Color Emoji", "Segoe UI Emoji", "Noto Color Emoji", "Segoe UI Symbol", "Android Emoji", EmojiSymbols;padding: 0.2em 0.4em;border-radius: 3px;word-break: break-word;background-size: 20px 20px;white-space: pre-wrap;background-color: rgba(27, 31, 35, 0.05);">Clickhouse中需要?jiǎng)?chuàng)建一個(gè)ingress_stdout_stream的Kafka引擎表,然后映射到Kafkaingress-stdout Topic里。

          5 日志存儲(chǔ)

          我們會(huì)使用三種表,用于存儲(chǔ)一種業(yè)務(wù)類型的日志。

          • Kafka引擎表:將數(shù)據(jù)從Kafka采集到Clickhouseingress_stdout_stream數(shù)據(jù)表中

          create?table?logger.ingress_stdout_stream
          (
          _source_?String,
          _pod_name_?String,
          _namespace_?String,
          _node_name_?String,
          _container_name_?String,
          _cluster_?String,
          _log_agent_?String,
          _node_ip_?String,
          _time_?Float64,
          _log_?String
          )
          engine?=?Kafka?SETTINGS?kafka_broker_list?=?'kafka:9092',?kafka_topic_list?=?'ingress-stdout',?kafka_group_name?=?'logger_ingress_stdout',?kafka_format?=?'JSONEachRow',?kafka_num_consumers?=?1;
          • 物化視圖:將數(shù)據(jù)從ingress_stdout_stream數(shù)據(jù)表讀取出來,_log_根據(jù)Mogo配置的索引,提取字段在寫入到ingress_stdout結(jié)果表里

          CREATE?MATERIALIZED?VIEW?logger.ingress_stdout_view?TO?logger.ingress_stdout?AS
          SELECT
          toDateTime(toInt64(_time_))?AS?_time_second_,
          fromUnixTimestamp64Nano(toInt64(_time_*1000000000),'Asia/Shanghai')?AS?_time_nanosecond_,
          _pod_name_,
          _namespace_,
          _node_name_,
          _container_name_,
          _cluster_,
          _log_agent_,
          _node_ip_,
          _source_,
          _log_?AS?_raw_log_,JSONExtractInt(_log_,?'status')?AS?status,JSONExtractString(_log_,?'url')?AS?url
          FROM?logger.ingress_stdout_stream?where?1=1;
          • 結(jié)果表:存儲(chǔ)最終的數(shù)據(jù)

            create?table?logger.ingress_stdout
            (
            _time_second_?DateTime,
            _time_nanosecond_?DateTime64(9,?'Asia/Shanghai'),
            _source_?String,
            _cluster_?String,
            _log_agent_?String,
            _namespace_?String,
            _node_name_?String,
            _node_ip_?String,
            _container_name_?String,
            _pod_name_?String,
            _raw_log_?String,
            status?Nullable(Int64),
            url?Nullable(String),
            )
            engine?=?MergeTree?PARTITION?BY?toYYYYMMDD(_time_second_)
            ORDER?BY?_time_second_
            TTL?toDateTime(_time_second_)?+?INTERVAL?7?DAY
            SETTINGS?index_granularity?=?8192;

          6 總結(jié)流程

          • 日志會(huì)通過fluent-bit的規(guī)則采集到kafka,在這里我們會(huì)將日志采集到兩個(gè)字段里

            • _time_字段用于存儲(chǔ)fluent-bit采集的時(shí)間

            • _log_字段用于存放原始日志

          • 通過mogo,在clickhouse里設(shè)置了三個(gè)表

            • app_stdout_stream:將數(shù)據(jù)從Kafka采集到ClickhouseKafka引擎表

            • app_stdout_view:視圖表用于存放mogo設(shè)置的索引規(guī)則

            • app_stdout:根據(jù)app_stdout_view索引解析規(guī)則,消費(fèi)app_stdout_stream里的數(shù)據(jù),存放于app_stdout結(jié)果表中

          • 最后mogoUI界面,根據(jù)app_stdout的數(shù)據(jù),查詢?nèi)罩拘畔?/p>

          7 Mogo界面展示

          • 查詢?nèi)罩窘缑?/p>

          • 設(shè)置日志采集配置界面

          以上文檔描述是針對(duì)石墨Kubernetes的日志采集,想了解物理機(jī)采集日志方案的,可以在下文中找到《Mogo使用文檔》的鏈接,運(yùn)行docker-compose體驗(yàn)Mogo?全部流程,查詢Clickhouse日志。限于篇幅有限,Mogo的日志報(bào)警功能,下次在講解。

          8 資料

          • github地址:?https://github.com/shimohq/mogo

          • Mogo文檔:https://mogo.shimo.im

          • Mogo使用文檔:https://mogo.shimo.im/doc/AV62KU4AABMRQ

          • fluent-bit文檔:https://docs.fluentbit.io/

          • K8S日志

            • 6 個(gè) K8S 日志系統(tǒng)建設(shè)中的典型問題,你遇到過幾個(gè):https://developer.aliyun.com/article/718735

            • 一文看懂 K8S 日志系統(tǒng)設(shè)計(jì)和實(shí)踐:https://developer.aliyun.com/article/727594

            • 9 個(gè)技巧,解決 K8S 中的日志輸出問題:https://developer.aliyun.com/article/747821

            • 直擊痛點(diǎn),詳解 K8S 日志采集最佳實(shí)踐:https://developer.aliyun.com/article/749468?spm=a2c6h.14164896.0.0.24031164UoPfIX

          • Clickhouse


          瀏覽 48
          點(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>
                  亚洲AV手机在线免费观看 | 亚洲三地区电影 | 成人视频国产日本韩国欧美豆花 | a 天堂网 | www蜜桃久久 |