Loki
是 Grafana Labs 团队最新的开源项目,是一个水平可扩展,高可用性,多租户的日志聚合系统。它的设计非常经济高效且易于操作,因为它不会为日志内容编制索引,而是为每个日志流编制一组标签。项目受 Prometheus 启发,官方的介绍就是:Like Prometheus, but for logs.
,类似于 Prometheus 的日志系统。
与其他日志聚合系统相比,Loki
具有下面的一些特性:
Loki 由以下3个部分组成:
loki
是主服务器,负责存储日志和处理查询。promtail
是代理,负责收集日志并将其发送给 loki 。Grafana
用于 UI 展示Loki 的功能组件
Loki架构图
Promtail 是负责日志数据的采集、提取、匹配、过滤、打 lables、Push to loki 这写工作的
支持的采集方式包括 File Target、Journal Target、Syslog Target、Stdin Target
整个 Promtail 对日志数据处理流程如下 Promtail数据处理流程图
Distributor 主要接收 Promtail Push 过来的日志数据,并把日志数据分发给 Ingester
Distributor 与 Ingester 之间以 RPC 的方式进行通信,它通过对元数据进行 hash 算法计算出将日志数据分发到哪一个 Ingester 上
Distributor 以日志数据的 TenantID、Labels 作为 Hash key
Ingester 负责接收数据并构建 chunk,存储日志索引及数据
Ingester构建chunk
当一个 chunk 填充满之后,ingester 将其刷新到数据库,块和索引分别进行存储
Ingester存储chunk和index
刷新完一个 chunk 之后,Ingester 会创建一个空的 chunk
Querier 负责数据读取,它通过给定的一个时间范围和标签选择器,查看索引以确定哪些块匹配,并通过 greps 聚合各个 Ingester 中的数据,并将结果返回给 client
Loki 的数据查询,都是通过 Grafana,在 Grafana 中支持 loki 的数据源,通过配置 Loki 的接口地址即可
Grafana 的查询,支持 LogQL,在 Grafana 中查询都是通过 Label 或 log 文本,支持语法如下:
Lable 的操作符:
对于查询表达式的标签部分,将其包装在花括号中{}
,然后使用键值对的语法来选择标签,多个标签表达式用逗号分隔,比如
精确匹配:|=“2020-11-16 "
{app_kubernetes_io_instance="x'x'x'x"}|="2020-11-16 "
模糊匹配:|~“2020-11-16 "
{app_kubernetes_io_instance="x'x'x'x'x"}|~"2020-11-16 "
排除过滤:!=/!~ “数据中心”
{app_kubernetes_io_instance="x'x'x'x'x"}!="数据中心"
{app_kubernetes_io_instance="x'x'x'x'x'x'x'x'x"}!~"数据中心"
正则匹配: |~ “()”
{app_kubernetes_io_instance="x'x'x'x'x'x"}!~"(admin|web)"
{app_kubernetes_io_instance="x'x'x'x'x'x'x"}|~"ERROR|error"
三十分钟日志行记录
count_over_time({app_kubernetes_io_instance="UUUU"}[30m])
12h小时内出现错误的速率
rate({app_kubernetes_io_instance=~".*UUUUU.*"} |~ "ERROR|error" [12h])
与PromQL一样,LogQL支持内置聚合运算符的一个子集,可用于聚合单个向量的元素,从而产生具有更少元素但具有集合值的新向量:
统计1个小时日志量最大的前10个服务
topk(10,sum(rate({app_kubernetes_io_instance=~".*uuuu.*"}[60m])) by(container))
统计最近6小时内错误日志计数
sum(count_over_time({app_kubernetes_io_instance=~".*uuuuuu.*"}|~"ERROR"[6h])) by (container)
url如下
https://localhost:3100/explore?orgId=1&left=%5B%22now-1h%22,%22now%22,%22Loki%22,%7B%22expr%22:%22%7Bapp_kubernetes_io_instance%3D~%5C%22user-service%5C%22%7D%7C~%5C%222020-11-05%5C%22%7C~%5C%22ERROR%5C%22%7C~%5C%22.aaa.%5C%22%22,%22maxLines%22:5000%7D%5D
分析
url加解密
进入指定网站中,https://www.sojson.com/encodeurl.html
上例中解密如下:
https://localhsot/explore?orgId=1&left=["now-1m","now","Loki",{"expr":"{app_kubernetes_io_instance%3D\"user-service-\"}|\"2020-11-05\"|\"ERROR\"|\".aaaaa.\"","maxLines":5000}]
根据日期查询
https://lcoalhsot/explore?orgId=1&left=["now-1h","now","Loki",{"expr":"{app_kubernetes_io_instance=~\"user-service\"}|~\"2020-11-18\"","maxLines":5000}]
https://lcoalhsot/explore?orgId=1&left=%5B%22now-1h%22,%22now%22,%22Loki%22,%7B%22expr%22:%22%7Bapp_kubernetes_io_instance=~%5C%22user-service%5C%22%7D%7C~%5C%222020-11-18%5C%22%22,%22maxLines%22:5000%7D%5D
根据服务名称查询
https://localhost/explore?orgId=1&left=["now-1h","now","Loki",{"expr":"{app_kubernetes_io_instance=~\"data-service\"}|~\"2020-11-18\"","maxLines":5000}]
https://localhost/explore?orgId=1&left=%5B%22now-1h%22,%22now%22,%22Loki%22,%7B%22expr%22:%22%7Bapp_kubernetes_io_instance=~%5C%22data-service%5C%22%7D%7C~%5C%222020-11-18%5C%22%22,%22maxLines%22:5000%7D%5D
根据对应的数据库查询
https://localhost/explore?orgId=1&left=["now-1h","now","Loki",{"expr":"{app_kubernetes_io_instance=~\"data-service\"}|~\"2020-11-18\"|~\"database\"","maxLines":5000}]
https://localhost/explore?orgId=1&left=%5B%22now-1h%22,%22now%22,%22Loki%22,%7B%22expr%22:%22%7Bapp_kubernetes_io_instance=~%5C%22data-service%5C%22%7D%7C~%5C%222020-11-18%5C%22%7C~%5C%22database%5C%22%22,%22maxLines%22:5000%7D%5D
加密好的url直接粘贴到浏览器中即可查询
查询标签
curl -G -s "http://localhost:3100/loki/api/v1/labels" | jq
curl -G -s "http://lcoalhpst:3100/loki/api/v1/labels" | jq .data[]
"__name__"
"app"
"app_kubernetes_io_component"
"app_kubernetes_io_instance"
"app_kubernetes_io_managed_by"
"app_kubernetes_io_name"
"app_kubernetes_io_version"
"chart"
"component"
"container"
"controller_revision_hash"
"filename"
"helm_sh_chart"
"heritage"
"job"
"k8s_app"
"name"
"namespace"
"pod"
"pod_template_generation"
"pod_template_hash"
"release"
"releaseRevision"
"statefulset_kubernetes_io_pod_name"
"stream"
"task"
根据标签查询对应标签值
curl -G -s http://localhost:3100/loki/api/v1/label/<name>/values |jq
curl -G -s "http://lcoalhost:3100/loki/api/v1/label/app_kubernetes_io_instance/values" | jq .data[]
"web-service"
"user-service"
根据标签查询对应的日志
curl -G -s http://localhost:3100/loki/api/v1/query_range | jq
curl -G -s "http://lcoalhost:3100/loki/api/v1/query_range" --data-urlencode 'query={app_kubernetes_io_instance=~".*user-service.*"}|~"ERROR|error"' | jq .data.result | jq .[].values[0][1]
首先需要确保已经部署了 Kubernetes 集群,并安装配置了 Helm 客户端,然后添加 Loki 的 chart 仓库:
helm repo add loki https://grafana.github.io/loki/charts
可以使用如下命令更新chart仓库:
helm repo update
使用默认配置部署
helm upgrade --install loki loki/loki-stack
指定命名空间
helm upgrade --install loki --namespace=logging 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 fluent-bit.enabled=true,promtail.enabled=false,grafana.enabled=true,prometheus.enabled=true,prometheus.alertmanager.persistentVolume.enabled=false,prometheus.server.persistentVolume.enabled=false
使用 Helm 安装 Grafana 到 Kubernetes 集群,可以使用如下所示命令:
helm install stable/grafana -n loki-grafana
要获取 Grafana 管理员密码,可以使用如下所示命令:
kubectl get secret --namespace <YOUR-NAMESPACE> loki-grafana -o jsonpath="{.data.admin-password}" | base64 --decode ; echo
要访问 Grafana UI 页面,可以使用下面的命令:
kubectl port-forward --namespace <YOUR-NAMESPACE> service/loki-grafana 3000:80
然后在浏览器中打开http://localhost:3000
,用 admin 和上面输出的密码进行登录。然后 按照提示添加 Loki 数据源,Loki 地址为http://loki:3100
。
执行完成后,loki-config.yaml 和 promtail-config.yaml 两个配置文件会被下载到我们使用的目录下面,Docker 容器会使用这些配置文件来运行 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
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