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>

        日志多租戶架構(gòu)下的 Loki 方案

        共 7973字,需瀏覽 16分鐘

         ·

        2021-07-05 14:28

        當(dāng)我們?cè)诳碙oki的架構(gòu)文檔時(shí),社區(qū)都會(huì)宣稱Loki是一個(gè)可以支持多租戶模式下運(yùn)行的日志系統(tǒng),但我們?cè)傧脒M(jìn)一步了解時(shí),它卻含蓄的表示Loki開啟多租戶只需要滿足兩個(gè)條件:

        • 配置文件中添加 auth_enabled: true
        • 請(qǐng)求頭內(nèi)帶上租戶信息X-Scope-OrgID

        這一切似乎都在告訴你,"快來用我吧,這很簡單",事實(shí)上當(dāng)我們真的要在kubernetes中構(gòu)建一個(gè)多租戶的日志系統(tǒng)時(shí),我們需要考慮的遠(yuǎn)不止于此。

        通常當(dāng)我們?cè)诿鎸?duì)一個(gè)多租戶的日志系統(tǒng)架構(gòu)時(shí),出于對(duì)日志存儲(chǔ)的考慮,我們一般會(huì)有兩種模式來影響系統(tǒng)的架構(gòu)。

        1. 日志集中存儲(chǔ)(后文以方案A代稱)

        和Loki原生一樣,在日志進(jìn)入到集群內(nèi),經(jīng)過一系列校驗(yàn)和索引后集中的將日志統(tǒng)一寫入后端存儲(chǔ)上。

        2. 日志分區(qū)存儲(chǔ)(后文以方案B代稱)

        反中心存儲(chǔ)架構(gòu),每個(gè)租戶或項(xiàng)目都可以擁有獨(dú)立的日志服務(wù)和存儲(chǔ)區(qū)塊來保存日志。

        從直覺上來看,日志分區(qū)帶來的整體結(jié)構(gòu)會(huì)更為復(fù)雜,除了需要自己開發(fā)控制器來管理loki服務(wù)的生命周期外,它還需要為網(wǎng)關(guān)提供正確的路由策略。不過,不管多租戶的系統(tǒng)選擇何種方案,在本文我們也需從日志的整個(gè)流程來闡述不同方案的實(shí)現(xiàn)。

        第一關(guān):Loki劃分

        Loki是最終承載日志存儲(chǔ)和查詢的服務(wù),在多租戶的模式下,不管是大集群還是小服務(wù),Loki本身也存在一些配置空間需要架構(gòu)者去適配。其中特別是在面對(duì)大集群場(chǎng)景下,保證每個(gè)租戶的日志寫入和查詢所占資源的合理分配調(diào)度就顯得尤為重要。

        在原生配置中,大部分關(guān)于租戶的調(diào)整可以在下面兩個(gè)配置區(qū)塊中完成:

        • query_frontend_config
        • limits_config

        query_frontend_config

        query_frontend是Loki分布式集群模式下的日志查詢最前端,它承擔(dān)著用戶日志查詢請(qǐng)求的分解和聚合工作。那么顯然,query_frontend對(duì)于請(qǐng)求的處理資源應(yīng)避免被單個(gè)用戶過分搶占。

        每個(gè)frontend處理的租戶

        [max_outstanding_per_tenant: <int> | default = 100]

        limits_config

        limits_config基本控制了Loki全局的一些流控參數(shù)和局部的租戶資源分配,這里面可以通過Loki的-runtime-config啟動(dòng)參數(shù)來讓服務(wù)動(dòng)態(tài)定期的加載租戶限制。這部分可以通過runtime_config.go中的runtimeConfigValues結(jié)構(gòu)體內(nèi)看到

        type runtimeConfigValues struct {
         TenantLimits map[string]*validation.Limits `yaml:"overrides"`

         Multi kv.MultiRuntimeConfig `yaml:"multi_kv_config"`
        }

        可以看到對(duì)于TenantLimits內(nèi)的限制配置是直接繼承l(wèi)imits_config的,那么這部分的結(jié)構(gòu)應(yīng)該就是下面這樣:

        overrides:
          tenantA:
            ingestion_rate_mb: 10
            max_streams_per_user: 100000
            max_chunks_per_query: 100000
          tenantB:
            max_streams_per_user: 1000000
            max_chunks_per_query: 1000000

        當(dāng)我們?cè)谶x擇采用方案A的日志架構(gòu)時(shí),關(guān)于租戶部分的限制邏輯就應(yīng)該要根據(jù)租戶內(nèi)的日志規(guī)模靈活的配置。如果選擇方案B,由于每個(gè)租戶占有完整的Loki資源,所以這部分邏輯就直接由原生的limits_config控制。

        第二關(guān):日志客戶端

        在Kubernetes環(huán)境下,最重要是讓日志客戶端知道被采集的容器所屬的租戶信息。這部分實(shí)現(xiàn)可以是通過日志Operator或者是解析kubernetes元數(shù)據(jù)來實(shí)現(xiàn)。雖然這兩個(gè)實(shí)現(xiàn)方式不同,不過最終目的都是讓客戶端在采集日之后,在日志流的請(qǐng)求上添加租戶信息頭。下面我分別以logging-operator和fluentbit/fluentd這兩種實(shí)現(xiàn)方式來描述他們的實(shí)現(xiàn)邏輯

        Logging Operator

        Logging Operator是BanzaiCloud下開源的一個(gè)云原生場(chǎng)景下的日志采集方案。它可以通過創(chuàng)建NameSpace級(jí)別的CRD資源flow和output來控制日志的解析和輸出。

        通過Operator的方式可以精細(xì)的控制租戶內(nèi)的日志需要被采集的容器,以及控制它們的流向。以輸出到loki舉例,通常在只需在租戶的命名空間內(nèi)創(chuàng)建如下資源就能滿足需求。

        • output.yaml,在創(chuàng)建資源時(shí)帶入租戶相關(guān)的信息
        apiVersion: logging.banzaicloud.io/v1beta1
        kind: Output
        metadata:
         name: loki-output
         namespace: <tenantA-namespace>
        spec:
          loki:
            url: http://loki:3100
            username: <tenantA>
            password: <tenantA>
            tenant: <tenantA>
        ...
        • flow.yaml,在創(chuàng)建資源時(shí)關(guān)聯(lián)租戶需要被采集日志的容器,以及指定輸出
        apiVersion: logging.banzaicloud.io/v1beta1
        kind: Flow
          metadata:
            name: flow
            namespace:  <tenantA-namespace>
          spec:
            localOutputRefs:
            - loki-output
            match:
              - select:
                  labels:
                    app: nginx
            filters:
              - parser:
                  remove_key_name_field: true
                  reserve_data: true
                  key_name: "log"

        可以看到通過operator來管理多租戶的日志是一個(gè)非常簡單且優(yōu)雅的方式,同時(shí)通過CRD的方式創(chuàng)建資源對(duì)開發(fā)者集成到項(xiàng)目也十分友好。這也是我比較推薦的日志客戶端方案。

        FluentBit/FluentD

        FluentBit和FluentD的Loki插件同樣支持對(duì)多租戶的配置。對(duì)于它們而言最重要的是讓其感知到日志的租戶信息。與Operator在CRD中直接聲明租戶信息不同,直接采用客戶端方案就需要通過Kubernetes Metadata的方式來主動(dòng)抓取租戶信息。對(duì)租戶信息的定義,我們會(huì)聲明在資源的label中。不過對(duì)于不同的客戶端,label定義的路徑還是比較有講究的。它們總體處理流程如下:

        • FluentD

        fluentd的kubernetes-metadata-filter可以抓取到namespaces_label,所以我比較推薦將租戶信息定義在命名空間內(nèi)。

        apiVersion: v1
        kind: Namespace
        metadata:
          labels:
            tenant: <tenantA>
          name: <taenant-namespace>

        這樣在就可以loki的插件中直接提取namespace中的租戶標(biāo)簽內(nèi)容,實(shí)現(xiàn)邏輯如下

        <match loki.**>
          @type loki
          @id loki.output
          url "http://loki:3100"
          # 直接提取命名空間內(nèi)的租戶信息
          tenant ${$.kubernetes.namespace_labels.tenant}
          username <username>
          password <password>
          <label>
            tenant ${$.kubernetes.namespace_labels.tenant}
          </label>
        • FluentBit

        fluentbit的metadata是從pod中抓取,那么我們就需要將租戶信息定義在workload的template.metadata.labels當(dāng)中,如下:

        apiVersion: apps/v1
        kind: Deployment
        metadata:
         labels:
           app:  nginx
        spec:
         template:
           metadata:
             labels:
               app: nginx
               tenant: <tanant-A>

        之后就需要利用rewrite_tag將容器的租戶信息提取出來進(jìn)行日志管道切分。并在output階段針對(duì)不同日志管道進(jìn)行輸出。它的實(shí)現(xiàn)邏輯如下:

        [FILTER]
           Name           kubernetes
           Match          kube.*
           Kube_URL       https://kubernetes.default.svc:443
           Merge_Log      On
        [FILTER]
           Name           rewrite_tag
           Match          kube.*
           #提取pod中的租戶信息,并進(jìn)行日志管道切分
           Rule           $kubernetes['labels']['tenant'] ^(.*)$ tenant.$kubernetes['labels']['tenant'].$TAG false
           Emitter_Name   re_emitted
        [Output]
           Name           grafana-loki
           Match          tenant.tenantA.*
           Url            http://loki:3100/api/prom/push
           TenantID       "tenantA"
        [Output]
           Name           grafana-loki
           Match          tenant.tenantB.*
           Url            http://loki:3100/api/prom/push
           TenantID       "tenantB"

        可以看到不管是用FluentBit還是Fluentd的方式進(jìn)行多租戶的配置,它們不但對(duì)標(biāo)簽有一定的要求,對(duì)日志的輸出路徑配置也不是非常靈活。所以fluentd它比較做適合方案A的日志客戶端,而fluentbit比較適合做方案B的日志客戶端。

        第三層:日志網(wǎng)關(guān)

        日志網(wǎng)關(guān)準(zhǔn)確的說是Loki服務(wù)的網(wǎng)關(guān),對(duì)于方案A來說,一個(gè)大Loki集群前面的網(wǎng)關(guān),只需要簡單滿足能夠橫向擴(kuò)展即可,租戶的頭信息直接傳遞給后方的Loki服務(wù)處理。這類方案相對(duì)簡單,并無特別說明。只需注意針對(duì)查詢接口的配置需調(diào)試優(yōu)化,例如網(wǎng)關(guān)服務(wù)與upstream之間的連接超時(shí)時(shí)間、網(wǎng)關(guān)服務(wù)response數(shù)據(jù)包大小等。

        本文想說明的日志網(wǎng)關(guān)是針對(duì)方案B場(chǎng)景下,解決針對(duì)不同租戶的日志路由問題。從上文可以看到,在方案B中,我們引入了一個(gè)控制器來解決租戶Loki實(shí)例的管理問題。但是這樣就帶來一個(gè)新的問題需要解決,那就是Loki的服務(wù)需要注冊(cè)到網(wǎng)關(guān),并實(shí)現(xiàn)路由規(guī)則的生成。這部分可以由集群的控制器CRD資源作為網(wǎng)關(guān)的upsteam源配置??刂破鞯倪壿嬋缦拢?/p>

        網(wǎng)關(guān)服務(wù)在處理租戶頭信息時(shí),路由部分的邏輯為判斷Header中X-Scope-OrgID帶租戶信息的日志請(qǐng)求,并將其轉(zhuǎn)發(fā)到對(duì)應(yīng)的Loki服務(wù)。我們以nginx作為網(wǎng)關(guān)舉個(gè)例,它的核心邏輯如下:

        #upstream內(nèi)地址由sidecar從CRD中獲取loki實(shí)例后渲染生成

        upstream tenantA {
         server x.x.x.x:3100;
        }
        upstream tenantB {
         server y.y.y.y:3100;
        }
        server {
            location / {
                set tenant $http_x_scope_orgid;
                proxy_pass http://$tenant;
                include proxy_params;

        總結(jié)

        本文介紹了基于Loki在多租戶模式下的兩種日志架構(gòu),分別為日志集中存儲(chǔ)日志分區(qū)存儲(chǔ)。他們分別具備如下的特點(diǎn):

        方案Loki架構(gòu)客戶端架構(gòu)網(wǎng)關(guān)架構(gòu)開發(fā)難度運(yùn)維難度自動(dòng)化程度
        日志集中存儲(chǔ)集群、復(fù)雜fluentd / fluentbit簡單簡單中等
        日志分區(qū)存儲(chǔ)簡單Logging Opeator較復(fù)雜較復(fù)雜(控制器部分)中等

        對(duì)于團(tuán)隊(duì)內(nèi)具備kubernetes operator相關(guān)開發(fā)經(jīng)驗(yàn)的同學(xué)可以采用日志分區(qū)存儲(chǔ)方案,如果團(tuán)隊(duì)內(nèi)偏向運(yùn)維方向,可以選擇日志集中存儲(chǔ)方案。

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

        手機(jī)掃一掃分享

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

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        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>
            亚洲天堂777 | 免费看小男生裸体 | 蜜桃av久久久亚洲精品 | 少妇又色又紧又黄又爽又刺激视频 | 蜜桃狠狠色伊人亚洲综合网站 | 国产草久久 | 亚洲作爱视频 | 国产片婬乱18一级毛片视頻 | 大香蕉婷婷在线 | 欧美老妇性爱视频 |