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>

        Grafana Loki 簡(jiǎn)明教程

        共 22107字,需瀏覽 45分鐘

         ·

        2020-08-21 10:15

        Loki 是 Grafana Labs 團(tuán)隊(duì)最新的開(kāi)源項(xiàng)目,是一個(gè)水平可擴(kuò)展,高可用性,多租戶的日志聚合系統(tǒng)。它的設(shè)計(jì)非常經(jīng)濟(jì)高效且易于操作,因?yàn)樗粫?huì)為日志內(nèi)容編制索引,而是為每個(gè)日志流配置一組標(biāo)簽。項(xiàng)目受 Prometheus 啟發(fā),官方的介紹就是:Like Prometheus, but for logs,類(lèi)似于 Prometheus 的日志系統(tǒng)。

        1. 概述

        和其他日志系統(tǒng)不同的是,Loki 只會(huì)對(duì)你的日志元數(shù)據(jù)標(biāo)簽(就像 Prometheus 的標(biāo)簽一樣)進(jìn)行索引,而不會(huì)對(duì)原始的日志數(shù)據(jù)進(jìn)行全文索引。然后日志數(shù)據(jù)本身會(huì)被壓縮,并以 chunks(塊)的形式存儲(chǔ)在對(duì)象存儲(chǔ)(比如 S3 或者 GCS)甚至本地文件系統(tǒng)。一個(gè)小的索引和高度壓縮的 chunks 可以大大簡(jiǎn)化操作和降低 Loki 的使用成本。有關(guān)本文檔更詳細(xì)的版本,可以查看《Loki 架構(gòu)》章節(jié)介紹。

        1.1 多租戶

        Loki 支持多租戶模式,租戶之間的數(shù)據(jù)是完全分開(kāi)的。多租戶是通過(guò)一個(gè)租戶 ID(用數(shù)字字母生成的字符串)實(shí)現(xiàn)的。當(dāng)多租戶模式被禁用后,所有請(qǐng)求都會(huì)在內(nèi)部生成一個(gè)假的租戶 ID。

        1.2 操作模式

        Loki 可以在本地小規(guī)模運(yùn)行也可以橫向擴(kuò)展。Loki 自帶單進(jìn)程模式,可以在一個(gè)進(jìn)程中運(yùn)行所有需要的微服務(wù)。單進(jìn)程模式非常適合于測(cè)試 Loki 或者小規(guī)模運(yùn)行。對(duì)于橫向擴(kuò)展來(lái)說(shuō),Loki 的微服務(wù)是可以被分解成單獨(dú)的進(jìn)程的,使其能夠獨(dú)立擴(kuò)展。

        1.3 組件

        Distributor(分配器)

        分配器服務(wù)負(fù)責(zé)處理客戶端寫(xiě)入的日志。本質(zhì)上它是日志數(shù)據(jù)寫(xiě)入路徑中的第一站。一旦分配器接收到日志數(shù)據(jù),它就會(huì)把它們分成若干批次,并將它們并行地發(fā)送到多個(gè)采集器去。

        分配器通過(guò) gPRC 和采集器進(jìn)行通信。它們是無(wú)狀態(tài)的,所以我們可以根據(jù)實(shí)際需要對(duì)他們進(jìn)行擴(kuò)縮容。

        Hashing

        分配器采用一致性哈希和可配置的復(fù)制因子結(jié)合使用,來(lái)確定哪些采集器服務(wù)應(yīng)該接收日志數(shù)據(jù)。該哈希是基于日志標(biāo)簽和租戶 ID 生成的。

        存儲(chǔ)在 Consul 中的哈希環(huán)被用來(lái)實(shí)現(xiàn)一致性哈希;所有的采集器將他們自己的一組 Token 注冊(cè)到哈希環(huán)中去。然后分配器找到和日志的哈希值最匹配的 Token,并將數(shù)據(jù)發(fā)送給該 Token 的持有者。

        一致性

        由于所有的分配器都共享同一個(gè)哈希環(huán),所以可以向任何分配器發(fā)送寫(xiě)請(qǐng)求。

        為了確保查詢結(jié)果的一致性,Loki 在讀和寫(xiě)上使用了 Dynamo 方式的法定人數(shù)一致性。這意味著分配器將等待至少有一半以上的采集器響應(yīng),再向用戶發(fā)送樣本,然后再響應(yīng)給用戶。

        Ingester(采集器)

        采集器服務(wù)負(fù)責(zé)將日志數(shù)據(jù)寫(xiě)入長(zhǎng)期存儲(chǔ)的后端(DynamoDB、S3、Cassandra 等等)。

        采集器會(huì)校驗(yàn)采集的日志是否亂序。當(dāng)采集器接收到的日志行與預(yù)期的順序不一致時(shí),該行日志將被拒絕,并向用戶返回一個(gè)錯(cuò)誤。有關(guān)更多相關(guān)信息,可以查看時(shí)間戳排序部分內(nèi)容。

        采集器驗(yàn)證接收到的日志行是按照時(shí)間戳遞增的順序接收的(即每條日志的時(shí)間戳都比之前的日志晚)。當(dāng)采集器接收到的日志不按照這個(gè)順序,日志行將被拒絕并返回錯(cuò)誤。

        每一個(gè)唯一的標(biāo)簽集數(shù)據(jù)都會(huì)在內(nèi)存中構(gòu)建成chunks,然后將它們存儲(chǔ)到后端存儲(chǔ)中去。

        如果一個(gè)采集器進(jìn)程崩潰或者突然掛掉了,所有還沒(méi)有被刷新到存儲(chǔ)的數(shù)據(jù)就會(huì)丟失。Loki 通常配置成多個(gè)副本(通常為3個(gè))來(lái)降低這種風(fēng)險(xiǎn)。

        時(shí)間戳排序

        一般來(lái)說(shuō)推送到 Loki 的所有日志行必須比之前收到的行有一個(gè)更新的時(shí)間戳。然而有些情況可能是多行日志具有相同的納秒級(jí)別的時(shí)間戳,可以按照下面兩種情況進(jìn)行處理:

        • 如果傳入的行和之前接收到的行完全匹配(時(shí)間戳和日志文本都匹配),則傳入的行會(huì)被視為完全重復(fù)并會(huì)被忽略。

        • 如果傳入行的時(shí)間戳和前面一行的時(shí)間戳相同,但是日志內(nèi)容不相同,則會(huì)接收該行日志。這就意味著,對(duì)于相同的時(shí)間戳,有可能有兩個(gè)不同的日志行。

        Handoff(交接)

        默認(rèn)情況下,當(dāng)一個(gè)采集器關(guān)閉并視圖離開(kāi)哈希環(huán)時(shí),它將等待查看是否有新的采集器視圖進(jìn)入,然后再進(jìn)行 flush,并嘗試啟動(dòng)交接。交接將把離開(kāi)的采集器擁有的所有 Token 和內(nèi)存中的 chunks 都轉(zhuǎn)移到新的采集器中來(lái)。

        這個(gè)過(guò)程是為了避免在關(guān)閉時(shí) flush 所有的 chunks,因?yàn)檫@是一個(gè)比較緩慢的過(guò)程,比較耗時(shí)。

        文件系統(tǒng)支持

        采集器支持通過(guò) BoltDB 寫(xiě)入到文件系統(tǒng),但這只在單進(jìn)程模式下工作,因?yàn)椴樵兤餍枰L問(wèn)相同的后端存儲(chǔ),而且 BoltDB 只允許一個(gè)進(jìn)程在給定時(shí)間內(nèi)對(duì) DB 進(jìn)行鎖定。

        Querier(查詢器)

        查詢器服務(wù)負(fù)責(zé)處理 LogQL 查詢語(yǔ)句來(lái)評(píng)估存儲(chǔ)在長(zhǎng)期存儲(chǔ)中的日志數(shù)據(jù)。

        它首先會(huì)嘗試查詢所有采集器的內(nèi)存數(shù)據(jù),然后再返回到后端存儲(chǔ)中加載數(shù)據(jù)。

        前端查詢

        該服務(wù)是一個(gè)可選組件,在一組查詢器前面,來(lái)負(fù)責(zé)在它們之間公平地調(diào)度請(qǐng)求,盡可能地并行化它們并緩存請(qǐng)求。

        Chunk(塊)存儲(chǔ)

        塊存儲(chǔ)是 Loki 的長(zhǎng)期數(shù)據(jù)存儲(chǔ),旨在支持交互式查詢和持續(xù)寫(xiě)入,無(wú)需后臺(tái)維護(hù)任務(wù)。它由以下幾部分組成:

        • 塊索引,該索引可以由 DynamoDB、Bigtable 或者 Cassandra 來(lái)支持。

        • 塊數(shù)據(jù)本身的 KV 存儲(chǔ),可以是 DynamoDB、Bigtable、Cassandra,也可以上是對(duì)象存儲(chǔ),比如 S3。

        與 Loki 的其他核心組件不同,塊存儲(chǔ)不是一個(gè)獨(dú)立的服務(wù)、任務(wù)或者進(jìn)程,而是嵌入到需要訪問(wèn) Loki 數(shù)據(jù)的采集器和查詢器中的庫(kù)。

        塊存儲(chǔ)依賴(lài)統(tǒng)一的 ”NoSQL“ 存儲(chǔ)(DynamoDB、Bigtable 和 Cassandra)接口,該接口可以用來(lái)支持塊存儲(chǔ)索引。該接口假設(shè)索引是由以下幾個(gè) key 構(gòu)成的集合:

        • 哈希 KEY - 這是所有的讀和寫(xiě)都需要的。

        • 范圍 KEY - 這是寫(xiě)的時(shí)候需要的,讀的時(shí)候可以省略,可以通過(guò)前綴或者范圍來(lái)查詢。

        上面支持的這些數(shù)據(jù)庫(kù)中接口的工作原理有些不同:

        • DynamoDB 支持范圍和哈希 KEY。所以索引條目直接建模為 DynamoDB 的數(shù)據(jù),哈希 KEY 為分布式 KEY,范圍為范圍 KEY。

        • 對(duì)于 Bigtable 和 Cassandra,索引項(xiàng)被建模為單個(gè)的列值。哈希 KEY 成為行 KEY,范圍 KEY 成為列 KEY。

        一些模式被用于對(duì)塊存儲(chǔ)的讀取和寫(xiě)入時(shí)使用的匹配器和標(biāo)簽集合映射到索引的適當(dāng)操作中來(lái)。隨著 Loki 的發(fā)展也會(huì)增加一些新的模式,主要是為了更好地平衡些和提高查詢性能。

        1.4 對(duì)比其他日志系統(tǒng)

        EFK(Elasticsearch、Fluentd、Kibana)用于從各種來(lái)源獲取、可視化和查詢?nèi)罩尽?/p>

        Elasticsearch 中的數(shù)據(jù)以非結(jié)構(gòu)化 JSON 對(duì)象的形式存儲(chǔ)在磁盤(pán)上。每個(gè)對(duì)象的鍵和每個(gè)鍵的內(nèi)容都有索引。然后可以使用 JSON 對(duì)象來(lái)定義查詢(稱(chēng)為 Query DSL)或通過(guò) Lucene 查詢語(yǔ)言來(lái)查詢數(shù)據(jù)。

        相比之下,單二進(jìn)制模式下的 Loki 可以將數(shù)據(jù)存儲(chǔ)在磁盤(pán)上,但在水平可擴(kuò)展模式下,數(shù)據(jù)存儲(chǔ)需要在云存儲(chǔ)系統(tǒng)中,如 S3、GCS 或 Cassandra。日志以純文本的形式存儲(chǔ),并標(biāo)記了一組標(biāo)簽的名稱(chēng)和值,其中只有標(biāo)簽會(huì)被索引。這種權(quán)衡使其操作起來(lái)比完全索引更便宜。Loki 中的日志使用 LogQL 進(jìn)行查詢。由于這種設(shè)計(jì)上的權(quán)衡,根據(jù)內(nèi)容(即日志行內(nèi)的文本)進(jìn)行過(guò)濾的 LogQL 查詢需要加載搜索窗口內(nèi)所有與查詢中定義的標(biāo)簽相匹配的塊。

        Fluentd 通常用于收集日志并轉(zhuǎn)發(fā)到 Elasticsearch。Fluentd 被稱(chēng)為數(shù)據(jù)收集器,它可以從許多來(lái)源采集日志,并對(duì)其進(jìn)行處理,然后轉(zhuǎn)發(fā)到一個(gè)或多個(gè)目標(biāo)。

        相比之下,Promtail 是為 Loki 量身定做的。它的主要工作模式是發(fā)現(xiàn)存儲(chǔ)在磁盤(pán)上的日志文件,并將其與一組標(biāo)簽關(guān)聯(lián)的日志文件轉(zhuǎn)發(fā)到 Loki。Promtail 可以為在同一節(jié)點(diǎn)上運(yùn)行的 Kubernetes Pods 做服務(wù)發(fā)現(xiàn),作為 Docker 日志驅(qū)動(dòng),從指定的文件夾中讀取日志,并對(duì) systemd 日志不斷獲取。

        Loki 通過(guò)一組標(biāo)簽表示日志的方式與 Prometheus 表示指標(biāo)的方式類(lèi)似。當(dāng)與Prometheus 一起部署在環(huán)境中時(shí),由于使用了相同的服務(wù)發(fā)現(xiàn)機(jī)制,來(lái)自Promtail 的日志通常與你的應(yīng)用指標(biāo)具有相同的標(biāo)簽。擁有相同級(jí)別的日志和指標(biāo),用戶可以在指標(biāo)和日志之間無(wú)縫切換,幫助進(jìn)行根本性原因分析。

        Kibana 被用于可視化和搜索 Elasticsearch 數(shù)據(jù),并且在對(duì)這些數(shù)據(jù)進(jìn)行分析時(shí)非常強(qiáng)大。Kibana 提供了許多可視化工具來(lái)做數(shù)據(jù)分析,例如地圖、用于異常檢測(cè)的機(jī)器學(xué)習(xí),以及關(guān)系圖。也可以配置報(bào)警,當(dāng)出現(xiàn)意外情況時(shí),可以通知用戶。

        相比之下,Grafana 是專(zhuān)門(mén)針對(duì) Prometheus 和 Loki 等數(shù)據(jù)源的時(shí)間序列數(shù)據(jù)定制的。儀表板可以設(shè)置為可視化指標(biāo)(即將推出的日志支持),也可以使用探索視圖對(duì)數(shù)據(jù)進(jìn)行臨時(shí)查詢。和 Kibana 一樣,Grafana 也支持根據(jù)你的指標(biāo)進(jìn)行報(bào)警。

        2. 安裝

        官方推薦使用 Tanka 進(jìn)行安裝,Tanka 是 Grafana 重新實(shí)現(xiàn)的 Ksonnect 版本,在 Grafana 內(nèi)部用于生產(chǎn)環(huán)境部署,但是 Tanka 目前使用并不多,熟悉的人較少,所以我們這里就不介紹這種方式了。主要介紹下面3種方式。

        2.1 使用 Helm 安裝 Loki

        前提

        首先需要確保已經(jīng)部署了 Kubernetes 集群,并安裝配置了 Helm 客戶端,然后添加 Loki 的 chart 倉(cāng)庫(kù):

        $ helm repo add loki https://grafana.github.io/loki/charts

        可以使用如下命令更新 chart 倉(cāng)庫(kù):

        $ helm repo update

        部署 Loki

        使用默認(rèn)配置部署

        $ helm upgrade --install loki loki/loki-stack

        指定命名空間

        $ helm upgrade --install loki --namespace=loki loki/loki

        指定配置

        $ helm upgrade --install loki loki/loki --set "key1=val1,key2=val2,..."

        部署 Loki 工具棧(Loki, Promtail, Grafana, Prometheus)

        $ helm upgrade --install loki loki/loki-stack --set grafana.enabled=true,prometheus.enabled=true,prometheus.alertmanager.persistentVolume.enabled=false,prometheus.server.persistentVolume.enabled=false

        部署 Loki 工具棧(Loki, Promtail, Grafana, Prometheus)

        $ helm upgrade --install loki loki/loki-stack \    --set fluent-bit.enabled=true,promtail.enabled=false,grafana.enabled=true,prometheus.enabled=true,prometheus.alertmanager.persistentVolume.enabled=false,prometheus.server.persistentVolume.enabled=false

        部署 Grafana

        使用 Helm 安裝 Grafana 到 Kubernetes 集群,可以使用如下所示命令:

        $ helm install stable/grafana -n loki-grafana

        要獲取 Grafana 管理員密碼,可以使用如下所示命令:

        $ kubectl get secret --namespace  loki-grafana -o jsonpath="{.data.admin-password}" | base64 --decode ; echo

        要訪問(wèn) Grafana UI 頁(yè)面,可以使用下面的命令:

        $ kubectl port-forward --namespace  service/loki-grafana 3000:80

        然后在瀏覽器中打開(kāi) http://localhost:3000,用 admin 和上面輸出的密碼進(jìn)行登錄。然后按照提示添加 Loki 數(shù)據(jù)源,Loki 地址為 http://loki:3100。

        使用 HTTPS Ingress 訪問(wèn) Loki

        如果 Loki 和 Promtail 部署在不同的集群上,你可以在 Loki 前面添加一個(gè) Ingress 對(duì)象,通過(guò)添加證書(shū),可以通過(guò) HTTPS 進(jìn)行訪問(wèn),為了保證安全性,還可以在 Ingress 上啟用 Basic Auth 認(rèn)證。

        在 Promtail 中,設(shè)置下面的 values 值來(lái)使用 HTTPS 和 Basic Auth 認(rèn)證進(jìn)行通信:

        loki:  serviceScheme: https  user: user  password: pass

        Ingress 的 Helm 模板示例如下所示:

        apiVersion: extensions/v1beta1kind: Ingressmetadata:  annotations:    kubernetes.io/ingress.class: {{ .Values.ingress.class }}    ingress.kubernetes.io/auth-type: "basic"ingress.kubernetes.io/auth-secret: {{ .Values.ingress.basic.secret }}  name: lokispec:  rules:  - host: {{ .Values.ingress.host }}    http:      paths:      - backend:          serviceName: loki          servicePort: 3100  tls:  - secretName: {{ .Values.ingress.cert }}    hosts:    - {{ .Values.ingress.host }}

        2.2 使用 Docker 或 Docker Compose 安裝 Loki

        我們可以使用 Docker 或 Docker Compose 安裝 Loki,用來(lái)評(píng)估、測(cè)試或者開(kāi)發(fā) Lok,但是對(duì)于生產(chǎn)環(huán)境,我們推薦使用 Tanka 或者 Helm 方式。

        前提

        • Docker

        • Docker Compose(可選,只有使用 Docker Compose 方式才需要安裝)

        使用 Docker 安裝

        直接拷貝下面的命令代碼在命令行中執(zhí)行:

        Linux

        執(zhí)行完成后,loki-config.yaml 和 promtail-config.yaml 兩個(gè)配置文件會(huì)被下載到我們使用的目錄下面,Docker 容器會(huì)使用這些配置文件來(lái)運(yùn)行 Loki 和 Promtail。

        $ wget https://raw.githubusercontent.com/grafana/loki/v1.5.0/cmd/loki/loki-local-config.yaml -O loki-config.yaml$ docker run -v $(pwd):/mnt/config -p 3100:3100 grafana/loki:1.5.0 -config.file=/mnt/config/loki-config.yaml$ wget https://raw.githubusercontent.com/grafana/loki/v1.5.0/cmd/promtail/promtail-docker-config.yaml -O promtail-config.yaml$ docker run -v $(pwd):/mnt/config -v /var/log:/var/log grafana/promtail:1.5.0 -config.file=/mnt/config/promtail-config.yaml

        使用 Docker Compose 安裝

        $ wget https://raw.githubusercontent.com/grafana/loki/v1.5.0/production/docker-compose.yaml -O docker-compose.yaml$ docker-compose -f docker-compose.yaml up

        2.3 本地安裝 Loki

        二進(jìn)制文件

        每個(gè)版本都包括 Loki 的二進(jìn)制文件,可以在 GitHub 的 Release 頁(yè)面上找到。

        openSUSE Linux 安裝包

        社區(qū)為 openSUSE Linux 提供了 Loki 的軟件包,可以使用下面的方式來(lái)安裝:

        • 添加倉(cāng)庫(kù) https://download.opensuse.org/repositories/security:/logging/到系統(tǒng)中。比如你在使用 Leap 15.1,執(zhí)行命令 sudo zypper ar https://download.opensuse.org/repositories/security:/logging/openSUSE_Leap_15.1/security:logging.repo ; sudo zypper ref

        • 使用命令 zypper in loki 安裝 Loki 軟件包

        • 啟動(dòng) Loki 和 Promtail 服務(wù):

          • systemd start loki && systemd enable loki

          • systemd start promtail && systemd enable promtail

        • 根據(jù)需求修改配置文件:/etc/loki/promtail.yaml/etc/loki/loki.yaml 。

        手動(dòng)構(gòu)建

        前提

        • Go 1.13+ 版本

        • Make

        • Docker(用于更新 protobuf 文件和 yacc 文件)

        構(gòu)建

        克隆 Loki 代碼到 $GOPATH/src/github.com/grafana/loki 路徑:

        $ git clone https://github.com/grafana/loki $GOPATH/src/github.com/grafana/loki

        然后切換到代碼目錄執(zhí)行 make loki 命令:

        $ cd $GOPATH/src/github.com/grafana/loki$ make loki
        # ./cmd/loki/loki 目錄下面將會(huì)生成最終的二進(jìn)制文件。

        3. 開(kāi)始使用 Loki

        3.1 Loki 在 Grafana 中的配置

        Grafana 在 6.0 以上的版本中內(nèi)置了對(duì) Loki 的支持。建議使用 6.3 或更高版本,就可以使用新的LogQL功能。

        • 登錄 Grafana 實(shí)例,如果這是你第一次運(yùn)行 Grafana,用戶名和密碼都默認(rèn)為admin。

        • 在 Grafana 中,通過(guò)左側(cè)側(cè)邊欄上的圖標(biāo)轉(zhuǎn)到 "配置 > 數(shù)據(jù)源"。

        • 單擊 + Add data source 按鈕。

        • 在列表中選擇 Loki。

        • Http URL 字段是你的 Loki 服務(wù)器的地址,例如,在本地運(yùn)行或使用端口映射的 Docker 運(yùn)行時(shí),地址可能是 http://localhost:3100。使用 docker-compose 或 Kubernetes 運(yùn)行時(shí),地址很可能是 https://loki:3100。

        • 要查看日志,可以單擊側(cè)邊欄上的 "探索",在左上角下拉菜單中選擇 Loki 數(shù)據(jù)源,然后使用日志標(biāo)簽按鈕過(guò)濾日志流。

        3.2 使用 LogCLI 查詢 Loki

        如果您喜歡命令行界面,LogCLI 允許用戶針對(duì) Loki 服務(wù)器使用 LogQL 查詢。

        安裝

        二進(jìn)制(推薦)

        在 Release 頁(yè)面中下載的 release 包中就包含 logcli 的二進(jìn)制文件。

        源碼安裝

        同樣你也可以使用 golang 直接對(duì)源碼進(jìn)行編譯,使用如下所示的 go get 命令獲取 logcli,二進(jìn)制文件會(huì)出現(xiàn)在 $GOPATH/bin 目錄下面:

        $ go get github.com/grafana/loki/cmd/logcli

        使用示例

        假設(shè)你現(xiàn)在使用的是 Grafana Cloud,需要設(shè)置下面幾個(gè)環(huán)境變量:

        $ export LOKI_ADDR=https://logs-us-west1.grafana.net$ export LOKI_USERNAME=$ export LOKI_PASSWORD=

        如果你使用的是本地的 Grafana,則可以直接將 LogCLI 指向本地的實(shí)例,而不需要用戶名和密碼:

        $ export LOKI_ADDR=http://localhost:3100
        注意:如果你在 Loki 前面添加了代理服務(wù)器,并且配置了身份驗(yàn)證,那么還是需要配置對(duì)應(yīng)的 LOKI_USERNAMELOKI_PASSWORD 數(shù)據(jù)。

        配置完成后可以使用如下所示的一些 logcli 命令:

        $ logcli labels jobhttps://logs-dev-ops-tools1.grafana.net/api/prom/label/job/valuescortex-ops/consulcortex-ops/cortex-gw...
        $ logcli query '{job="cortex-ops/consul"}'https://logs-dev-ops-tools1.grafana.net/api/prom/query?query=%7Bjob%3D%22cortex-ops%2Fconsul%22%7D&limit=30&start=1529928228&end=1529931828&direction=backward®exp=Common labels: {job="cortex-ops/consul", namespace="cortex-ops"}2018-06-25T12:52:09Z {instance="consul-8576459955-pl75w"} 2018/06/25 12:52:09 [INFO] raft: Snapshot to 475409 complete2018-06-25T12:52:09Z {instance="consul-8576459955-pl75w"} 2018/06/25 12:52:09 [INFO] raft: Compacting logs from 456973 to 465169...
        $ logcli series -q --match='{namespace="loki",container_name="loki"}'{app="loki", container_name="loki", controller_revision_hash="loki-57c9df47f4", filename="/var/log/pods/loki_loki-0_8ed03ded-bacb-4b13-a6fe-53a445a15887/loki/0.log", instance="loki-0", job="loki/loki", name="loki", namespace="loki", release="loki", statefulset_kubernetes_io_pod_name="loki-0", stream="stderr"}

        批量查詢

        從 Loki 1.6.0 開(kāi)始,logcli 會(huì)分批向 Loki 發(fā)送日志查詢。

        如果你將查詢的--limit 參數(shù)(默認(rèn)為30)設(shè)置為一個(gè)較大的數(shù),比如 10000,那么 logcli 會(huì)自動(dòng)將此請(qǐng)求分批發(fā)送到 Loki,默認(rèn)的批次大小是 1000。

        Loki 對(duì)查詢中返回的最大行數(shù)有一個(gè)服務(wù)端的限制(默認(rèn)為5000)。批量發(fā)送允許你發(fā)出比服務(wù)端限制更大的請(qǐng)求,只要 --batch 大小小于服務(wù)器限制。

        請(qǐng)注意,每個(gè)批次的查詢?cè)獢?shù)據(jù)都會(huì)被打印在 stderr 上,可以通過(guò)設(shè)置--quiet 參數(shù)來(lái)停止這個(gè)動(dòng)作。

        對(duì)于配置的值會(huì)根據(jù)環(huán)境變量和命令行標(biāo)志從低到高生效。

        命令詳情

        logcli 命令行工具詳細(xì)的使用信息如下所示:

        $ logcli helpusage: logcli []  [ ...]
        A command-line for loki.
        Flags: --help Show context-sensitive help (also try --help-long and --help-man). --version Show application version. -q, --quiet Suppress query metadata. --stats Show query statistics. -o, --output=default Specify output mode [default, raw, jsonl]. raw suppresses log labels and timestamp. -z, --timezone=Local Specify the timezone to use when formatting output timestamps [Local, UTC]. --cpuprofile="" Specify the location for writing a CPU profile. --memprofile="" Specify the location for writing a memory profile. --addr="http://localhost:3100" Server address. Can also be set using LOKI_ADDR env var. --username="" Username for HTTP basic auth. Can also be set using LOKI_USERNAME env var. --password="" Password for HTTP basic auth. Can also be set using LOKI_PASSWORD env var. --ca-cert="" Path to the server Certificate Authority. Can also be set using LOKI_CA_CERT_PATH env var. --tls-skip-verify Server certificate TLS skip verify. --cert="" Path to the client certificate. Can also be set using LOKI_CLIENT_CERT_PATH env var. --key="" Path to the client certificate key. Can also be set using LOKI_CLIENT_KEY_PATH env var. --org-id="" adds X-Scope-OrgID to API requests for representing tenant ID. Useful for requesting tenant data when bypassing an auth gateway.
        Commands: help [...] Show help.
        query [] <query> Run a LogQL query.
        The "query" command is useful for querying for logs. Logs can be returned in a few output modes:
        raw: log line default: log timestamp + log labels + log line jsonl: JSON response from Loki API of log line
        The output of the log can be specified with the "-o" flag, for example, "-o raw" for the raw output format.
        The "query" command will output extra information about the query and its results, such as the API URL, set of common labels, and set of excluded labels. This extra information can be suppressed with the --quiet flag.
        While "query" does support metrics queries, its output contains multiple data points between the start and end query time. This output is used to build graphs, like what is seen in the Grafana Explore graph view. If you are querying metrics and just want the most recent data point (like what is seen in the Grafana Explore table view), then you should use the "instant-query" command instead.
        instant-query [] <query> Run an instant LogQL query.
        The "instant-query" command is useful for evaluating a metric query for a single point in time. This is equivalent to the Grafana Explore table view; if you want a metrics query that is used to build a Grafana graph, you should use the "query" command instead.
        This command does not produce useful output when querying for log lines; you should always use the "query" command when you are running log queries.
        For more information about log queries and metric queries, refer to the LogQL documentation:
        https://grafana.com/docs/loki/latest/logql/
        labels [] [ Find values for a given label.
        series [] Run series query.
        $ logcli help queryusage: logcli query [] <query>
        Run a LogQL query.
        The "query" command is useful for querying for logs. Logs can be returned in a few output modes:
        raw: log line default: log timestamp + log labels + log line jsonl: JSON response from Loki API of log line
        The output of the log can be specified with the "-o" flag, for example, "-o raw" for the raw output format.
        The "query" command will output extra information about the query and its results, such as the API URL, set of common labels, andset of excluded labels. This extra information can be suppressed with the --quiet flag.
        While "query" does support metrics queries, its output contains multiple data points between the start and end query time. Thisoutput is used to build graphs, like what is seen in the Grafana Explore graph view. If you are querying metrics and just want themost recent data point (like what is seen in the Grafana Explore table view), then you should use the "instant-query" commandinstead.
        Flags: --help Show context-sensitive help (also try --help-long and --help-man). --version Show application version. -q, --quiet Suppress query metadata. --stats Show query statistics. -o, --output=default Specify output mode [default, raw, jsonl]. raw suppresses log labels and timestamp. -z, --timezone=Local Specify the timezone to use when formatting output timestamps [Local, UTC]. --cpuprofile="" Specify the location for writing a CPU profile. --memprofile="" Specify the location for writing a memory profile. --addr="http://localhost:3100" Server address. Can also be set using LOKI_ADDR env var. --username="" Username for HTTP basic auth. Can also be set using LOKI_USERNAME env var. --password="" Password for HTTP basic auth. Can also be set using LOKI_PASSWORD env var. --ca-cert="" Path to the server Certificate Authority. Can also be set using LOKI_CA_CERT_PATH env var. --tls-skip-verify Server certificate TLS skip verify. --cert="" Path to the client certificate. Can also be set using LOKI_CLIENT_CERT_PATH env var. --key="" Path to the client certificate key. Can also be set using LOKI_CLIENT_KEY_PATH env var. --org-id="" adds X-Scope-OrgID to API requests for representing tenant ID. Useful for requesting tenant data when bypassing an auth gateway. --limit=30 Limit on number of entries to print. --since=1h Lookback window. --from=FROM Start looking for logs at this absolute time (inclusive). --to=TO Stop looking for logs at this absolute time (exclusive). --step=STEP Query resolution step width, for metric queries. Evaluate the query at the specified step over the time range. --interval=INTERVAL Query interval, for log queries. Return entries at the specified interval, ignoring those between. **This parameter is experimental, please see Issue 1779**. --batch=1000 Query batch size to use until 'limit' is reached. --forward Scan forwards through logs. --no-labels Do not print any labels. --exclude-label=EXCLUDE-LABEL ... Exclude labels given the provided key during output. --include-label=INCLUDE-LABEL ... Include labels given the provided key during output. --labels-length=0 Set a fixed padding to labels. --store-config="" Execute the current query using a configured storage from a given Loki configuration file. -t, --tail Tail the logs. --delay-for=0 Delay in tailing by number of seconds to accumulate logs for re-ordering. --colored-output Show ouput with colored labels.
        Args: <query> eg '{foo="bar",baz=~".*blip"} |~ ".*error.*"'
        $ logcli help labelsusage: logcli labels [] [
        Find values for a given label.
        Flags: --help Show context-sensitive help (also try --help-long and --help-man). --version Show application version. -q, --quiet Suppress query metadata. --stats Show query statistics. -o, --output=default Specify output mode [default, raw, jsonl]. raw suppresses log labels and timestamp. -z, --timezone=Local Specify the timezone to use when formatting output timestamps [Local, UTC]. --cpuprofile="" Specify the location for writing a CPU profile. --memprofile="" Specify the location for writing a memory profile. --addr="http://localhost:3100" Server address. Can also be set using LOKI_ADDR env var. --username="" Username for HTTP basic auth. Can also be set using LOKI_USERNAME env var. --password="" Password for HTTP basic auth. Can also be set using LOKI_PASSWORD env var. --ca-cert="" Path to the server Certificate Authority. Can also be set using LOKI_CA_CERT_PATH env var. --tls-skip-verify Server certificate TLS skip verify. --cert="" Path to the client certificate. Can also be set using LOKI_CLIENT_CERT_PATH env var. --key="" Path to the client certificate key. Can also be set using LOKI_CLIENT_KEY_PATH env var. --org-id="" adds X-Scope-OrgID to API requests for representing tenant ID. Useful for requesting tenant data when bypassing an auth gateway. --since=1h Lookback window. --from=FROM Start looking for labels at this absolute time (inclusive). --to=TO Stop looking for labels at this absolute time (exclusive).
        Args: [
        $ logcli help seriesusage: logcli series --match=MATCH []
        Run series query.
        Flags: --help Show context-sensitive help (also try --help-long and --help-man). --version Show application version. -q, --quiet Suppress query metadata. --stats Show query statistics. -o, --output=default Specify output mode [default, raw, jsonl]. raw suppresses log labels and timestamp. -z, --timezone=Local Specify the timezone to use when formatting output timestamps [Local, UTC]. --cpuprofile="" Specify the location for writing a CPU profile. --memprofile="" Specify the location for writing a memory profile. --addr="http://localhost:3100" Server address. Can also be set using LOKI_ADDR env var. --username="" Username for HTTP basic auth. Can also be set using LOKI_USERNAME env var. --password="" Password for HTTP basic auth. Can also be set using LOKI_PASSWORD env var. --ca-cert="" Path to the server Certificate Authority. Can also be set using LOKI_CA_CERT_PATH env var. --tls-skip-verify Server certificate TLS skip verify. --cert="" Path to the client certificate. Can also be set using LOKI_CLIENT_CERT_PATH env var. --key="" Path to the client certificate key. Can also be set using LOKI_CLIENT_KEY_PATH env var. --org-id="" adds X-Scope-OrgID to API requests for representing tenant ID. Useful for requesting tenant data when bypassing an auth gateway. --since=1h Lookback window. --from=FROM Start looking for logs at this absolute time (inclusive). --to=TO Stop looking for logs at this absolute time (exclusive). --match=MATCH ... eg '{foo="bar",baz=~".*blip"}'

        3.3 Label 標(biāo)簽

        Label 標(biāo)簽是一個(gè)鍵值對(duì),可以定義任何東西,我們喜歡稱(chēng)它們?yōu)槊枋鋈罩玖鞯脑獢?shù)據(jù)。如果你熟悉 Prometheus,那么一定對(duì) Label 標(biāo)簽有一定的了解,在 Loki 的 scrape 配置中也定義了這些標(biāo)簽,和 Prometheus 擁有一致的功能,這些標(biāo)簽非常容易將應(yīng)用程序指標(biāo)和日志數(shù)據(jù)關(guān)聯(lián)起來(lái)。

        Loki 中的標(biāo)簽執(zhí)行一個(gè)非常重要的任務(wù):它們定義了一個(gè)流。更具體地說(shuō),每個(gè)標(biāo)簽鍵和值的組合定義了流。如果只是一個(gè)標(biāo)簽值變化,這將創(chuàng)建一個(gè)新的流。

        如果你熟悉 Prometheus,那里的術(shù)語(yǔ)叫序列,而且 Prometheus 中還有一個(gè)額外的維度:指標(biāo)名稱(chēng)。Loki 中簡(jiǎn)化了這一點(diǎn),因?yàn)闆](méi)有指標(biāo)名,只有標(biāo)簽,所以最后決定使用流而不是序列。

        標(biāo)簽示例

        下面的示例將說(shuō)明 Loki 中 Label 標(biāo)簽的基本使用和概念。

        首先看下下面的示例:

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

        這個(gè)配置將獲取日志文件數(shù)據(jù)并添加一個(gè) job=syslog 的標(biāo)簽,我們可以這樣來(lái)查詢:

        {job="syslog"}

        這將在 Loki 中創(chuàng)建一個(gè)流?,F(xiàn)在我們?cè)傩略鲆恍┤蝿?wù)配置:

        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

        現(xiàn)在我們采集兩個(gè)日志文件,每個(gè)文件有一個(gè)標(biāo)簽與一個(gè)值,所以 Loki 會(huì)存儲(chǔ)為兩個(gè)流。我們可以通過(guò)下面幾種方式來(lái)查詢這些流:

        {job="apache"} <- 顯示 job 標(biāo)簽為 apache 的日志{job="syslog"} <- 顯示 job 標(biāo)簽為 syslog 的日志{job=~"apache|syslog"} <- 顯示 job 標(biāo)簽為 apache 或者 syslog 的日志

        最后一種方式我們使用的是一個(gè) regex 標(biāo)簽匹配器來(lái)獲取 job 標(biāo)簽值為 apache 或者 syslog 的日志。接下來(lái)我們看看如何使用額外的標(biāo)簽:

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

        要獲取這兩個(gè)任務(wù)的日志可以用下面的方式來(lái)代替 regex 的方式:

        {env="dev"} <- 將返回所有帶有 env=dev 標(biāo)簽的日志

        通過(guò)使用一個(gè)標(biāo)簽就可以查詢很多日志流了,通過(guò)組合多個(gè)不同的標(biāo)簽,可以創(chuàng)建非常靈活的日志查詢。

        Label 標(biāo)簽是 Loki 日志數(shù)據(jù)的索引,它們用于查找壓縮后的日志內(nèi)容,這些內(nèi)容被單獨(dú)存儲(chǔ)為。標(biāo)簽和值的每一個(gè)唯一組合都定義了一個(gè) ,一個(gè)流的日志被分批,壓縮,并作為塊進(jìn)行存儲(chǔ)。

        Cardinality(勢(shì))

        前面的示例使用的是靜態(tài)定義的 Label 標(biāo)簽,只有一個(gè)值;但是有一些方法可以動(dòng)態(tài)定義標(biāo)簽。比如我們有下面這樣的日志數(shù)據(jù):

        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"

        我們可以使用下面的方式來(lái)解析這條日志數(shù)據(jù):

        - job_name: system   pipeline_stages:      - regex:        expression: "^(?P<ip>\\S+) (?P<identd>\\S+) (?P<user>\\S+) \\[(?P<timestamp>[\\w:/]+\\s[+\\-]\\d{4})\\] \"(?P<action>\\S+)\\s?(?P<path>\\S+)?\\s?(?P<protocol>\\S+)?\" (?P<status_code>\\d{3}|-) (?P<size>\\d+|-)\\s?\"?(?P<referer>[^\"]*)\"?\\s?\"?(?P<useragent>[^\"]*)?\"?$"    - labels:        action:        status_code:   static_configs:   - targets:      - localhost     labels:      job: apache      env: dev      __path__: /var/log/apache.log

        這個(gè) regex 匹配日志行的每個(gè)組件,并將每個(gè)組件的值提取到一個(gè) capture 組里面。在 pipeline 代碼內(nèi)部,這些數(shù)據(jù)被放置到一個(gè)臨時(shí)的數(shù)據(jù)結(jié)構(gòu)中,允許在處理該日志行時(shí)將其用于其他處理(此時(shí),臨時(shí)數(shù)據(jù)將被丟棄)。

        從該 regex 中,我們就使用其中的兩個(gè) capture 組,根據(jù)日志行本身的內(nèi)容動(dòng)態(tài)地設(shè)置兩個(gè)標(biāo)簽:

        action (例如 action="GET", action="POST") status_code (例如 status_code="200", status_code="400")

        假設(shè)我們有下面幾行日志數(shù)據(jù):

        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"

        則在 Loki 中收集日志后,會(huì)創(chuàng)建為如下所示的流:

        {job="apache",env="dev",action="GET",status_code="200"} 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"{job="apache",env="dev",action="POST",status_code="200"} 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"{job="apache",env="dev",action="GET",status_code="400"} 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"{job="apache",env="dev",action="POST",status_code="400"} 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"

        這4行日志將成為4個(gè)獨(dú)立的流,并開(kāi)始填充4個(gè)獨(dú)立的塊。任何與這些 標(biāo)簽/值 組合相匹配的額外日志行將被添加到現(xiàn)有的流中。如果有另一個(gè)獨(dú)特的標(biāo)簽組合進(jìn)來(lái)(比如 status_code="500")就會(huì)創(chuàng)建另一個(gè)新的流。

        比如我們?yōu)?IP 設(shè)置一個(gè) Label 標(biāo)簽,不僅用戶的每一個(gè)請(qǐng)求都會(huì)變成一個(gè)唯一的流,每一個(gè)來(lái)自同一用戶的不同 action 或 status_code 的請(qǐng)求都會(huì)得到自己的流。

        如果有4個(gè)共同的操作(GET、PUT、POST、DELETE)和4個(gè)共同的狀態(tài)碼(可能不止4個(gè)?。@將會(huì)是16個(gè)流和16個(gè)獨(dú)立的塊。然后現(xiàn)在乘以每個(gè)用戶,如果我們使用 IP 的標(biāo)簽,你將很快就會(huì)有數(shù)千或數(shù)萬(wàn)個(gè)流了。

        這個(gè) Cardinality 太高了,這足以讓 Loki 掛掉。

        當(dāng)我們談?wù)?Cardinality 的時(shí)候,我們指的是標(biāo)簽和值的組合,以及他們創(chuàng)建的流的數(shù)量,高 Cardinality 是指使用具有較大范圍的可能值的標(biāo)簽,如 IP,或結(jié)合需要其他標(biāo)簽,即使它們有一個(gè)小而有限的集合,比如 status_code 和 action。

        高 Cardinality 會(huì)導(dǎo)致 Loki 建立一個(gè)巨大的索引(????),并將成千上萬(wàn)的微小塊存入對(duì)象存儲(chǔ)中(慢),Loki 目前在這種配置下的性能非常差,運(yùn)行和使用起來(lái)非常不劃算的。

        Loki 性能優(yōu)化

        現(xiàn)在我們知道了如果使用大量的標(biāo)簽或有大量值的標(biāo)簽是不好的,那我應(yīng)該如何查詢我的日志呢?如果沒(méi)有一個(gè)數(shù)據(jù)是有索引的,那么查詢不會(huì)真的很慢嗎?

        我們看到使用 Loki 的人習(xí)慣了其他重索引的解決方案,他們就覺(jué)得需要定義很多標(biāo)簽,才可以有效地查詢?nèi)罩?,畢竟很多其他的日志解決方案都是為了索引,這是之前的慣性思維方式。

        在使用 Loki 的時(shí)候,你可能需要忘記你所知道的東西,看看如何用并行化的方式來(lái)解決這個(gè)問(wèn)題。Loki 的超強(qiáng)之處在于將查詢拆成小塊,并行調(diào)度,這樣你就可以在少量時(shí)間內(nèi)查詢大量的日志數(shù)據(jù)了。

        大型索引是非常復(fù)雜而昂貴的,通常情況下,你的日志數(shù)據(jù)的全文索引與日志數(shù)據(jù)本身的大小相當(dāng)或更大。要查詢你的日志數(shù)據(jù),需要加載這個(gè)索引,為了性能,可能在內(nèi)存中,這就非常難擴(kuò)展了,當(dāng)你采集了大量的日志時(shí),你的索引就會(huì)變得很大。

        現(xiàn)在我們來(lái)談?wù)?Loki,索引通常比你采集的日志量小一個(gè)數(shù)量級(jí)。所以,如果你很好地將你的流保持在最低限度,那么指數(shù)的增長(zhǎng)和采集的日志相比就非常緩慢了。

        Loki 將有效地使你的靜態(tài)成本盡可能低(索引大小和內(nèi)存需求以及靜態(tài)日志存儲(chǔ)),并使查詢性能可以在運(yùn)行時(shí)通過(guò)水平伸縮進(jìn)行控制。

        為了了解是如何工作的,讓我們回過(guò)頭來(lái)看看上面我們查詢?cè)L問(wèn)日志數(shù)據(jù)的特定 IP 地址的例子,我們不使用標(biāo)簽來(lái)存儲(chǔ) IP,相反,我們使用一個(gè)過(guò)濾器表達(dá)式來(lái)查詢它。

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

        在背后 Loki 會(huì)將該查詢分解成更小的碎片(shards),并為標(biāo)簽匹配的流打開(kāi)每個(gè)塊(chunk),并開(kāi)始查找這個(gè) IP 地址。

        這些碎片的大小和并行化的數(shù)量是可配置的,并基于你提供的資源。如果你愿意,可以將 shard 間隔配置到 5m,部署20個(gè)查詢器,并在幾秒內(nèi)處理千兆字節(jié)的日志。或者你可以更加瘋狂地配置200個(gè)查詢器,處理 TB 級(jí)別的日志!

        這種較小的索引和并行查詢與較大/較快的全文索引之間的權(quán)衡,是讓 Loki 相對(duì)于其他系統(tǒng)節(jié)省成本的原因。操作大型索引的成本和復(fù)雜度很高,而且通常是固定的,無(wú)論是是否在查詢它,你都要一天24小時(shí)為它付費(fèi)。

        這種設(shè)計(jì)的好處是,你可以決定你想擁有多大的查詢能力,而且你可以按需變更。查詢性能成為你想花多少錢(qián)的函數(shù)。同時(shí)數(shù)據(jù)被大量壓縮并存儲(chǔ)在低成本的對(duì)象存儲(chǔ)中,比如 S3 和 GCS。這就將固定的運(yùn)營(yíng)成本降到了最低,同時(shí)還能提供難以置信的快速查詢能力。




        K8S進(jìn)階訓(xùn)練營(yíng),點(diǎn)擊下方圖片了解詳情

        瀏覽 269
        點(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>
            扒开美女狂揉羞羞3 | 成人免费 做受观看 | 操操免费网站 | 91大神羞羞熊猫视频 | 香蕉久久国产AV一区二区 | 啪一啪日一日 | 蜜臀操逼 | 色综合丁香 | 欧美一区二区三区影视 | 俺来也色色 |