简介
Grafana Labs开源的日志收集组件,特点有:
- Loki 只对元数据建立索引,不做全文索引,将原始日志压缩存储在对象存储上,因此具有操作简单、低成本的优势;
- 通过使用与 Prometheus 相同的标签对日志进行索引和分组,这使得日志的扩展和操作效率更高;
- 专门为 Prometheus 和 Kubernetes 用户做了相关优化,更适合云原生场景。
Grafana Loki stack 主要由以下三个部分组成:
- Grafana负责前端监控以及可视化
- promtail负责客户端采集
- Loki则负责了最重要的日志存储分析等功能.
架构功能及读写流程
整体上来看, 采集agent(默认为promtail)会将日志推送至Loki提供的基于HTTP的API, Loki则继续将收到的日志按照标签进行分发存储, 并在需要时使用LogQL进行查询
Loki实现由众多的组件组成, 每个组件都会拉起一个gRPC的服务来实现内部互通, 同时也对外暴露了一个HTTP/1的服务用来提供外部服务以应答API请求. 不同的组件会根据角色的差异提供不同的API, 目前loki主要由以下几个组件构成
- Distributor
- Ingester
- Query frontend(Optional)
- Querier
- Chunk Store
Distributor
主要负责分发从客户端上报的日志, 在进行完日志的校验之后便会分发给ingester处理. Distributor使用了一致性哈希以及一个可以配置的副本数来决定不同的日志流的后端ingester. 哈希环信息的存储使用了Consul. Ingester会根据自身的状态注册在哈希环上来标识自身可提供服务的状态. Distributor会使用注册租户id和标签集时作为哈希的输入, 计算出对应的哈希环位置, 并找到对应的ingester.
Ingester
Ingester是loki中比较核心的服务, 该服务将从Distributor发送来的日志进行转储到后端存储, 并给Querier提供仍在内存中未写盘的数据查询功能.
Ingester注册在哈希环上的状态有PENDING, JOINING, ACTIVE, LEAVING, UNHEALTHY, 除了ACTIVE状态外, 其余状态都只会提供部分服务
在存储到真正的存储前, 日志流只有按顺序收到才会被处理, Ingester会按照标签的组合set构建若干压缩过的chunks, 间隔一段时间将chunks作为整体刷写到后端存储. 刷进后端存储的chunks被标记为只读.
Querier Frontend
可以为查询提供加速, 他提供了排队, 切分大请求, 缓存等机制.
Querier
用来提供查询服务, 他使用了LogQL, 一种类似于PromQL的语言作为用户界面. Querier会查询已经写入后端存储的chunks以及仍在ingester内存中的数据, 根据label查找数据后, 再遍历数据查找到满足条件的日志
Chunk Store
是Loki的后端存储框架, 可以支持多种存储方式, 存储分为两部分:索引的存储和真正的日志数据存储. 索引存储目前可以使用 Amazon DynamoDB, Google Bigtable, Apsache Cassandra服务提供 日志存储使用了KV存储,目前可以使用Amazon DynamoDB, Google Bigtable, Apsache Cassandra, Amazon S3, Google Cloud Store来实现.
另外在Loki 2.0中实现了一个叫做boltdb-shipper的机制, 可以实现将索引和数据同时存在同一个对象存储仓库里. 除了使用云服务以外, Loki提供了叫做BoltDB的基于本地磁盘的数据库, 但由于副本数和锁的实现限制, 本地存储仅可在使用单进程部署时使用.
部署方式
模块设计
正因为Loki采用模块设计, Loki有很灵活的部署方式, 单模块部署或单进程部署.
单模块部署相对比较复杂, 每个模块可以单独启动, 不同的模块间通过gRPC服务互相配合提供服务.
单进程部署则是把所有的模块打包到一个二进制应用中, 通过配置文件来选择启动哪些模块, 实现了灵活方便的单机部署体验.
从运维角度来看, Loki提供了多种安装方式:
- helm
- docker
- tanka
- native
本文后端chunk存储采用minio。关于minio的部署、桶创建、权限管理不作赘述,参考Minio部署及本地安装loki
最终minio的信息如下:
桶名:loki
账号:loki
密码:loki123456
Loki安装-Helm方式
官方文档:官方文档
官方提供了多个Chart版本,说明如下:
- grafana/loki:单体Loki,性能支持线性伸缩;
- grafana/loki-stack:Loki的整套工具栈,包括loki、promtail、grafana等,缺点就是没有提供对接外部对象存储的配置;
- grafana/loki-distributed:微服务模式的loki集群,性能上线最高,可以对各个组件(distributed、ingester、querier、frontend querier等)的副本数进行分别扩展,推荐生产环境使用。
loki-distributed部署
前提条件
因为ingester和querier均需要保留index相关信息,使用blotdb的方式进行存储,所以需要考虑持久化,通过k8s 的storageclass来进行提供。本次部署已提前部署好以nfs为基础的存储类(已配置为默认类)。
创建命名空间
kubectl create ns logging
helm添加仓库
helm repo add grafana https://grafana.github.io/helm-charts
下载Chart
# 查看helm仓库是否配置完成
helm repo list
# 下载到本地
helm pull grafana/loki-distributed
# 如因网络问题可以通过timeout信息获取需要下载的链接,使用国内代理进行下载。
# 如果连接是https://grafana.github.io/helm-charts/releases/download/loki-distributed.tar.gz,使用如下命令下载:
wget https://www.ghproxy.cn/https://grafana.github.io/helm-charts/releases/download/loki-distributed-0.72.0.tgz
# 解压chart资源
tar xf loki-distributed-0.72.0.tgz
cd loki-distributed
# 修改values.yaml文件,自定义需求。
配置
loki:
schemaConfig:
configs:
- from: 2020-09-07 # 此时间后的日志数据存储方案使用本策略,下方的schema: v11通过不同版本号来进行区分,此项多次配置,系统达到时间后可以自动切换。
store: boltdb-shipper
object_store: aws # 更改项,对象存储配置选择为aws存储,此处需符合官方规定的方案。
schema: v11
index:
prefix: loki_index_
period: 24h
storageConfig:
boltdb_shipper:
shared_store: aws # 更改项,chunk存储所使用的为aws方式
active_index_directory: /var/loki/index
cache_location: /var/loki/cache
cache_ttl: 48h
# aws块内容为新增内容,用于表明aws的连接方式及配置。
aws:
s3: http://loki:loki123456@192.168.15.11:9000/loki
s3forcepathstyle: true
## 修改structuredConfig,新增ingester部分内容
structuredConfig:
ingester:
max_transfer_retries: 0
chunk_idle_period: 1h
chunk_target_size: 1536000
max_chunk_age: 1h
ingester:
replicas: 3 # 副本,调整为3,自行选择
maxUnavailable: 1 # 副本调整后,需要调整最大不可能的副本数,一般填写为副本数的1/3
persistence:
enabled: true # 启用持久化存储,将index数据存储于此前已创建的nfs为基础的storageclass中
inMemory: false
claims:
- name: data
size: 20Gi
storageClass: nfs-storage # 需要和storageclass的名称一致。
distributor:
replicas: 3
maxUnavailable: 1
querier:
replicas: 3
maxUnavailable: 1
persistence:
enabled: true
size: 20Gi
storageClass: nfs-storage
ingress:
enabled: true
annotations:
# 关于ingress配置的认证方式,basic-auth需要手动提前配置,如何配置可以参考:http://my.conficker.space:33333/archives/ingressnginx-chang-yong-li-zi中常用示例-->基本认证的内容
nginx.ingress.kubernetes.io/auth-type: basic
nginx.ingress.kubernetes.io/auth-secret: basic-auth
nginx.ingress.kubernetes.io/configuration-snippet: |
proxy_set_header X-Scope-OrgID $remote_user;
hosts:
- loki.conficker.space # 域名随便写了一个,可以通过修改hosts文件来访问。
gateway:
# 使用ingress后,可以关闭gateway
enabled: false
安装
helm install -n logging loki .
查看所有pod启动正常后,可以通过浏览器查看服务是否正常(安装promtail后)
访问:loki.conficker.com/loki/api/v1/labels,需要输入上方定义的认证账号和密码(ingress annotation中的内容)
如果status为success即为正常
Helm部署Promtail
# 下载chart
# 因为网络原因,直接使用代理下载
wget https://ghproxy.com/https://github.com/grafana/helm-charts/releases/download/promtail-6.15.1/promtail-6.15.1.tgz
tar xf promtail-6.15.1.tgz
cd promtail
# 修改values.yaml配置
configmap:
enabled: true
config:
clients:
- url: http://loki-loki-distributed-distributor:3100/loki/api/v1/push
# 安装
helm install -n logging promtail .
收集k8s Pod日志配置中修改
Promtail配置文件,对格式进行调整,保持grafana和控制台格式一致。
位置:.config.snippets.pipelineStages
snippets:
pipelineStages:
- json:
expressions:
output: log
stream: stream
timestamp: time
- labels:
stream:
- timestamp:
source: timestamp
format: RFC3339Nano
- output:
source: output
common:
Helm部署Grafana
# 下载chart
helm pull grafana/grafana
tar xf grafana-6.59.1.tgz
cd grafana
# 修改values.yaml,修改内容如下
ingress:
enabled: true
hosts:
- grafana.conficker.space
persistence:
type: pvc
enabled: true
storageClassName: nfs-storage
accessModes:
- ReadWriteOnce
size: 20Gi
# 安装
helm install -n logging grafana .
安装完成后访问grafana.conficker.space(提前配置hosts解析)
grafana 连接 loki
因为grafana和loki都安装在同一个命名空间内,且loki已经通过service进行暴露,可以直接使用内部dns地址进行访问,添加loki数据源时,使用:http://loki-loki-distributed-querier:3100即可,此处不需要使用认证,因为loki自身服务并未开启auth认证功能.