# 日志聚合工具Loki

本文章简要介绍了如何在腾讯云的TKE集群中搭建Loki日志采集工具。

## Loki日志系统介绍

Loki是受Prometheus启发的水平可扩展，高度可用的多租户日志聚合系统。它的设计具有很高的成本效益，并且易于操作。它不索引日志的内容，而是为每个日志流设置一组标签。

与其他日志聚合系统相比，Loki的特点

* 不对日志进行全文本索引。通过存储压缩的，非结构化的日志以及仅索引元数据，Loki更加易于操作且运行成本更低。
* 使用与Prometheus相同的标签对日志流进行索引和分组，从而使您能够使用与Prometheus相同的标签在指标和日志之间无缝切换。
* 特别适合存储Kubernetes Pod日志。诸如Pod标签之类的元数据会自动被抓取并建立索引。
* 在Grafana中具有本机支持（需要Grafana v6.0）。

基于Loki的日志记录堆栈包含3个组件：

* promtail是代理，负责收集日志并将其发送给Loki。
* loki是主服务器，负责存储日志和处理查询。
* Grafana用于查询和显示日志。

![upload-image](https://1743139827-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MMy-ccvHJYp-MpGyagk%2Fsync%2F34bbf2b255b5925efb8163ee85b23f7869783d62.png?generation=1606373434878641\&alt=media)

Loki其实类似于elk和prometheus的架构，部署在k8s中，通过DaemonSet的方式部署promtail用来采集节点的日志，将采集的日志数据投递到loki，最后通过grafana来进行前端的界面查询和展示。

Loki像Prometheus一样，但是对于日志：我们更喜欢基于多维标签的索引方法，并且想要一个没有依赖性的，易于操作的单二进制系统。 Loki与Prometheus的不同之处在于，它侧重于日志而不是指标，并通过推送而不是拉动交付日志。

## 部署Loki和grafana到k8s集群

### 部署loki和promtail

这里我们通过helm来部署loki和promtail到集群中，这里使用的环境是腾讯云上的托管TKE集群，在腾讯云上的容器服务有直接提供loki应用让我们直接部署到集群中，下面我们说一下部署方式

#### 控制台部署loki应用到集群

点击腾讯云容器服务，点击应用，选择你的集群，点击新建。

![upload-image](https://1743139827-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MMy-ccvHJYp-MpGyagk%2Fsync%2Fd335586fe0be208270bd86c2f218df3e4295f1ac.png?generation=1606373436695789\&alt=media)

输入你的应用名和应用部署的命名空间，在日志分析中找到loki-stack，然后点击完成即可。

![upload-image](https://1743139827-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MMy-ccvHJYp-MpGyagk%2Fsync%2F5ab20cba63f99031c7cb62cb6bf4bde20c6f8667.png?generation=1606373435072176\&alt=media)

这边部署成功后可以去控制台进入loki查看应用，你会发现部署loki和对应的promtail，这些pod都正常启动，说明loki和promtail都部署成功了。

![upload-image](https://1743139827-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MMy-ccvHJYp-MpGyagk%2Fsync%2F4845c4c03d40da73c99b454fdd8fcaa76f13a08b.png?generation=1606373435839024\&alt=media)

![upload-image](https://1743139827-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MMy-ccvHJYp-MpGyagk%2Fsync%2Fd3859deaf4d2409f41de1d6503f4ce190e20dc2f.png?generation=1606373445117947\&alt=media)

#### helm命令部署loki应用到集群

当然如果你习惯用helm命令操作部署也是可以的，下面讲一下helm命名的部署方式

```
//添加loki仓库
$ helm repo add loki https://grafana.github.io/loki/charts
$ helm repo update
//采用默认配置部署
$ helm upgrade --install loki --namespace=loki --name=nwx-loki loki/loki-stack 
//部署Loki和Fluent Bit到您的集群
$ helm upgrade --install loki --namespace=loki --name=nwx-loki \
    --set fluent-bit.enabled=true,promtail.enabled=false
```

### 部署grafana

#### 部署grafana及对应的service

下面我们部署grafana作为前端界面来查询loki所采集的日志，这里在选择grafana版本需要注意，版本需要6.0以上的版本。

```
apiVersion: apps/v1beta2
kind: Deployment
metadata:
  labels:
    k8s-app: gafana
    qcloud-app: gafana
  name: gafana
  namespace: loki
spec:
  progressDeadlineSeconds: 600
  replicas: 1
  revisionHistoryLimit: 10
  selector:
    matchLabels:
      k8s-app: gafana
      qcloud-app: gafana
  strategy:
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 0
    type: RollingUpdate
  template:
    metadata:
      labels:
        k8s-app: gafana
        qcloud-app: gafana
    spec:
      containers:
      - image: grafana/grafana:master
        imagePullPolicy: Always
        name: gafana
        resources:
          limits:
            cpu: 500m
            memory: 1Gi
          requests:
            cpu: 250m
            memory: 256Mi
        securityContext:
          privileged: false
        terminationMessagePath: /dev/termination-log
        terminationMessagePolicy: File
      dnsPolicy: ClusterFirst
      imagePullSecrets:
      - name: qcloudregistrykey
      restartPolicy: Always
      schedulerName: default-scheduler
      securityContext: {}
      terminationGracePeriodSeconds: 30
```

```
apiVersion: v1
kind: Service
metadata:
  name: gafana
  namespace: loki
spec:
  externalTrafficPolicy: Cluster
  ports:
  - name: 3000-3000-tcp
    nodePort: 32074
    port: 3000
    protocol: TCP
    targetPort: 3000
  selector:
    k8s-app: gafana
    qcloud-app: gafana
  sessionAffinity: None
  type: NodePort
```

直接kubectl apply上面2个yaml文件创建grafana应用和对应的service，也可以控制台创建

![upload-image](https://1743139827-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MMy-ccvHJYp-MpGyagk%2Fsync%2Fc5fc18e1c42d1518f68dd9425435e431b02f6be3.png?generation=1606373435552425\&alt=media)

![upload-image](https://1743139827-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MMy-ccvHJYp-MpGyagk%2Fsync%2Fe1d94e7b8cd9c3bdb17560664abb7de58ef7add4.png?generation=1606373435230624\&alt=media)

#### 通过treafik给grafana配置域名访问

这里集群部署的treafik是2.0版本，关于treafik2.0部署可以参考 <https://cloud.tencent.com/developer/article/1642306>

```
---
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
  name: loki
  namespace: loki
spec:
  entryPoints:
    - web
  routes:
  - match: Host(`loki.tx.niewx.cn`)
    kind: Rule
    services:
    - name: gafana
      port: 3000
```

直接添加一个IngressRoute就可以了，下面我们通过配置的域名看看是否可以成功。

![upload-image](https://1743139827-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MMy-ccvHJYp-MpGyagk%2Fsync%2F8d27cb95aad372d38f7f2ae3d9847bd3e455e042.png?generation=1606373435514555\&alt=media)

可以进入登陆界面表示部署成功。

## 通过grafana界面查询日志

### grafana配置loki数据源

下面我们需要在grafana配置一下loki的数据源，这样我们才可以在grafana上查询loki的日志，首先我们登录grafana，初始化账号密码是admin/admin，第一次登录会要求你修改密码，登录成功后有一个grafana介绍。

![upload-image](https://1743139827-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MMy-ccvHJYp-MpGyagk%2Fsync%2F8272a036cadf260373a4046d02d72a94633bae3c.png?generation=1606373437806575\&alt=media)

找到配置选项的Data Sources，点击添加数据源，选择loki，在loki数据源的url配置上你的service名称地址，我的service名称是nwx-loki，因此我们这里配置的是这个地址 [http://nwx-loki:3100，配置好后点击测试，如果能连接成功说明添加成功。](http://nwx-loki/:3100%EF%BC%8C%E9%85%8D%E7%BD%AE%E5%A5%BD%E5%90%8E%E7%82%B9%E5%87%BB%E6%B5%8B%E8%AF%95%EF%BC%8C%E5%A6%82%E6%9E%9C%E8%83%BD%E8%BF%9E%E6%8E%A5%E6%88%90%E5%8A%9F%E8%AF%B4%E6%98%8E%E6%B7%BB%E5%8A%A0%E6%88%90%E5%8A%9F%E3%80%82)

![upload-image](https://1743139827-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MMy-ccvHJYp-MpGyagk%2Fsync%2F46f93286817f36d0f99b90cbbbbd5d8f05827014.png?generation=1606373435208303\&alt=media)

![upload-image](https://1743139827-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MMy-ccvHJYp-MpGyagk%2Fsync%2Fbb4cce4468d0146ea5fac5635f5d54954bb88c8e.png?generation=1606373435316694\&alt=media)

![upload-image](https://1743139827-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MMy-ccvHJYp-MpGyagk%2Fsync%2F41e4cacbc57c5c280bbc6f777d6f7c5bf297681f.png?generation=1606373437299052\&alt=media)

![upload-image](https://1743139827-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MMy-ccvHJYp-MpGyagk%2Fsync%2F1caadaaca4c984e435b770d46f42a5add4e41bb0.png?generation=1606373435827523\&alt=media)

### 界面上查询日志

添加数据源后，点击explore可以直接进到loki的查询界面

![upload-image](https://1743139827-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MMy-ccvHJYp-MpGyagk%2Fsync%2Fd4684d0ef98a491d331f7cd801dbe8337a7a8aae.png?generation=1606373436574596\&alt=media)

![upload-image](https://1743139827-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MMy-ccvHJYp-MpGyagk%2Fsync%2F64dcd59f2b94b26a121afb583eb0b897c9acc5f6.png?generation=1606373436091105\&alt=media)

我们这边查询一下loki的日志看看，点击log label选择app中的loki就可以看到loki的业务日志

![upload-image](https://1743139827-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MMy-ccvHJYp-MpGyagk%2Fsync%2Fc4f8b3da02c3891ffdb7910634fd9e6c64bad288.png?generation=1606373436233455\&alt=media)

![upload-image](https://1743139827-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MMy-ccvHJYp-MpGyagk%2Fsync%2F24f3ba13dcddde92db6b5acf52f5a682f0d0a615.png?generation=1606373436630950\&alt=media)

### loki查询语法

下面我们简单的测试一下loki的查询语法

#### job日志流

```
{job="efk/elasticsearch-master"}
```

![upload-image](https://1743139827-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MMy-ccvHJYp-MpGyagk%2Fsync%2F6971b656e9d7ea0986fa4a0274a84e6eaa697c43.png?generation=1606373435674798\&alt=media)

#### 合并流选择器

```
{app ="elasticsearch-master",namespace ="efk"}
```

![upload-image](https://1743139827-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MMy-ccvHJYp-MpGyagk%2Fsync%2Fef90137a9aea247733ebcc1df5e14ae7b7ae2b03.png?generation=1606373437072675\&alt=media)

#### 标签匹配的运算符

* \=： 完全相等。
* !=： 不相等。
* \=\~： 正则表达式匹配。
* !\~： 正则表达式不匹配。

  ```
  {app != "kibana",namespace ="efk"}
  ```

![upload-image](https://1743139827-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MMy-ccvHJYp-MpGyagk%2Fsync%2Fa5e30d8d6de2e163f6da4218af47df88df3fc1e8.png?generation=1606373437001429\&alt=media)

#### 行筛选器表达式

* |=：日志行包含字符串。
* !=：日志行不包含字符串。
* |\~：日志行与正则表达式匹配。
* !\~：日志行与正则表达式不匹配。

```
{app = "kibana",namespace ="efk"} |= "172.16.2.108"
```

![upload-image](https://1743139827-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MMy-ccvHJYp-MpGyagk%2Fsync%2F359f1a2bd0b30cea66471fe1eaf49179af326cf6.png?generation=1606373436338371\&alt=media)

筛选器运算符可以多个并将按顺序筛选表达式 - 生成的日志行必须同时满足所有条件。

```
{app = "kibana",namespace ="efk"} |= "172.16.2.108" != "04:58:40"
```

![upload-image](https://1743139827-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MMy-ccvHJYp-MpGyagk%2Fsync%2F0bdf64610bb75ed880d576836e19f330d70ad0ec.png?generation=1606373436619547\&alt=media)

#### 统计某一时间段的日志数

```
count_over_time({app = "kibana",namespace ="efk" }[1m])
```

![upload-image](https://1743139827-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MMy-ccvHJYp-MpGyagk%2Fsync%2F6445e5af0139b3e9e474c4fdc7c6bf530f7b2ab9.png?generation=1606373436562732\&alt=media)

获取过去1个小时的日志计数，按级别分组

```
sum(count_over_time({job="default/nginx"}[60m])) by (level)
```

![upload-image](https://1743139827-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MMy-ccvHJYp-MpGyagk%2Fsync%2F94bae0a19d724ba528d4fde71c36c22d24a1e026.png?generation=1606373436409633\&alt=media)

loki配备了自己的查询LogQL，详细的查询语法参考<https://github.com/grafana/loki/blob/master/docs/sources/logql/_index.md>

有两种类型的 LogQL 查询：

* 日志查询返回日志行的内容。
* 指标查询扩展日志查询，并基于日志查询中的日志内容计算示例值。

logQL基本上能满足我们的日常查询需求。大家可以多多学习实际操作下。

## 参考链接

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

<https://github.com/grafana/loki/blob/master/docs/sources/logql/_index.md>
