云原生
Kubernetes基础
容器技术介绍
Docker快速入门
Containerd快速入门
K8S主要资源罗列
认识YAML
API资源对象
Kubernetes安全掌控
Kubernetes网络
Kubernetes高级调度
Kubernetes 存储
Kubernetes集群维护
Skywalking全链路监控
ConfigMap&Secret场景应用
Kubernetes基础概念及核心组件
水平自动扩容和缩容HPA
Jenkins
k8s中部署jenkins并利用master-slave模式实现CICD
Jenkins构建过程中常见问题排查与解决
Jenkins部署在k8s集群之外使用动态slave模式
Jenkins基于Helm的应用发布
Jenkins Pipeline语法
EFKStack
EFK日志平台部署管理
海量数据下的EFK架构优化升级
基于Loki的日志收集系统
Ingress
基于Kubernetes的Ingress-Nginx解决方案
Ingress-Nginx高级配置
使用 Ingress-Nginx 进行灰度(金丝雀)发布
Ingress-nginx优化配置
APM
Skywalking全链路监控
基于Helm部署Skywalking
应用接入Skywalking
服务网格
Istio
基于Istio的微服务可观察性
基于Istio的微服务Gateway实战
Kubernetes高可用集群部署
Kuberntes部署MetalLB负载均衡器
Ceph
使用cephadm部署ceph集群
使用Rook部署Ceph存储集群
openstack
glance上传镜像失败
mariadb运行不起来
创建域和项目错误_1
创建域和项目错误_2
安装计算节点
时钟源
网络创建失败
本文档使用 MrDoc 发布
-
+
首页
基于Loki的日志收集系统
K8S轻量级日志收集方案LPG(Loki+Promtail+Grafana) # 1、EFK vs LPG **架构和组件** - Loki:Loki 是一个开源的水平可扩展日志聚合系统,由 Promtail、Loki 和 Grafana组成。 - EFK:EFK 是一个集成的解决方案,由 Elasticsearch、Fluentd 和 Kibana 组成。 **存储和查询** - Loki:Loki 使用了基于日志流的存储方式,将日志数据存储为可压缩的块文件,并达到高度压缩效率。 - EFK:EFK 使用 Elasticsearch 作为中心化的日志存储和索引引擎。 **可扩展性和资源消耗** - Loki:Loki 的水平可扩展性非常好,可以处理大规模的日志数据。 - EFK:Elasticsearch 是一个高度可扩展的分布式存储系统,但它对硬件资源的要求较高,特别是在存储大规模日志数据时。 **配置和部署复杂性** - Loki:Loki 的配置和部署较为简单。通过使用 Promtail 收集日志,并使用 Grafana进行查询和可视化,可以相对快速地启动和使用。 - EFK:EFK 的配置和部署相对复杂一些。需要配置 Fluentd 的输入、过滤和输出插件,以及 Elasticsearch 和 Kibana 的集群设置。 # 2、LPG简介 Grafana Loki:https://grafana.com/docs/loki/latest/Github Loki:https://github.com/grafana/helm-charts/tree/main/charts/loki-stack **1、Loki架构** 1. Promtail(采集器):Loki 默认客户端,负责采集并上报日志。 2. Distributor(分发器): Distributor 是 Loki 的入口组件,负责接收来自客户端的日志数据,并将其分发给不同的 ingester 节点。 3. Ingester(摄取器): Ingester 负责接收并保存来自 Distributor 的日志数据。它将数据写入本地存储,并将索引相关的元数据发送给 index 组件。 4. Index(索引): Index 组件负责管理和维护 Loki 中的索引数据结构。 5. Chunks(块文件): Chunks 是 Loki 中日志数据的物理存储形式。 6. Querier(查询器): Querier 是用于查询 Loki 中日志数据的组件。  **2、日志收集方式** Promtail 客户端采集日志数据,将其索引并存储在后端持久化存储中。 用户可以使用 LogQL 查询语言来过滤和检索特定的日志记录,并通过 Grafana 的集成来进行可视化分析。  # 3、部署配置 **1、数据配置** 添加 Loki 的 Chart 仓库: ```shell $ helm repo add grafana https://grafana.github.io/helm-charts $ helm repo update ``` 获取 `loki-stack` 的 Chart 包并解压: ```shell $ helm search repo loki $ helm pull grafana/loki-stack --untar --version 2.9.10 ``` 修改所需的 `values.yaml` ```yaml test_pod: enabled: true image: bats/bats:1.8.2 pullPolicy: IfNotPresent ... loki: enabled: true persistence: enabled: true storageClassName: nfs-storage accessModes: - ReadWriteOnce size: 30Gi isDefault: true url: http://{{(include "loki.serviceName" .)}}:{{ .Values.loki.service.port }} ... promtail: enabled: true config: logLevel: info serverPort: 3101 clients: - url: http://{{ .Release.Name }}:3100/loki/api/v1/push limits_config: ingestion_rate_strategy: local ingestion_rate_mb: 15 ingestion_burst_size_mb: 20 ... grafana: enabled: true persistence: enabled: true storageClassName: nfs-storage accessModes: - ReadWriteOnce size: 10Gi ``` **2、部署验证** ```shell $ kubectl create ns logging $ helm upgrade --install loki -n logging -f values.yaml . ``` 查看验证: ```shell $ kubectl get pods -n logging |grep loki $ kubectl -n logging get svc |grep loki ``` 获取grafana的密码: ```shell $ kubectl get secret --namespace logging loki-grafana -o jsonpath="{.data.admin-password}" | base64 --decode ; echo ``` 创建ing: ```yaml apiVersion: networking.k8s.io/v1 kind: Ingress metadata: namespace: logging name: grafana-ingress spec: ingressClassName: nginx rules: - host: grafana-logging.kubernets.cn http: paths: - pathType: Prefix backend: service: name: loki-grafana port: number: 80 path: / ``` 测试验证: ```shell $ curl grafana-logging.kubernets.cn -i ``` 使用用户名`admin`和上面的获取的密码即可登录 Grafana; 由于 Helm Chart 已经为 Grafana 配置好了 Loki 的数据源,所以我们可以直接获取到日志数据了。 点击左侧`Explore`菜单,然后就可以筛选 Loki 的日志数据了:    使用 Helm 安装的 Promtail 默认已经帮我们做好了配置,已经针对 Kubernetes 做了优化,我们可以查看其配置: ```yaml $ kubectl get secret loki-promtail -n logging -o json | jq -r '.data."promtail.yaml"' | base64 --decode server: log_level: info http_listen_port: 3101 clients: - url: http://loki:3100/loki/api/v1/push positions: filename: /run/promtail/positions.yaml scrape_configs: # See also https://github.com/grafana/loki/blob/master/production/ksonnet/promtail/scrape_config.libsonnet for reference - job_name: kubernetes-pods pipeline_stages: - cri: {} kubernetes_sd_configs: - role: pod relabel_configs: - source_labels: - __meta_kubernetes_pod_controller_name regex: ([0-9a-z-.]+?)(-[0-9a-f]{8,10})? action: replace target_label: __tmp_controller_name - source_labels: - __meta_kubernetes_pod_label_app_kubernetes_io_name - __meta_kubernetes_pod_label_app - __tmp_controller_name - __meta_kubernetes_pod_name regex: ^;*([^;]+)(;.*)?$ action: replace target_label: app - source_labels: - __meta_kubernetes_pod_label_app_kubernetes_io_instance - __meta_kubernetes_pod_label_release regex: ^;*([^;]+)(;.*)?$ action: replace target_label: instance - source_labels: - __meta_kubernetes_pod_label_app_kubernetes_io_component - __meta_kubernetes_pod_label_component regex: ^;*([^;]+)(;.*)?$ action: replace target_label: component - action: replace source_labels: - __meta_kubernetes_pod_node_name target_label: node_name - action: replace source_labels: - __meta_kubernetes_namespace target_label: namespace - action: replace replacement: $1 separator: / source_labels: - namespace - app target_label: job - action: replace source_labels: - __meta_kubernetes_pod_name target_label: pod - action: replace source_labels: - __meta_kubernetes_pod_container_name target_label: container - action: replace replacement: /var/log/pods/*$1/*.log separator: / source_labels: - __meta_kubernetes_pod_uid - __meta_kubernetes_pod_container_name target_label: __path__ - action: replace regex: true/(.*) replacement: /var/log/pods/*$1/*.log separator: / source_labels: - __meta_kubernetes_pod_annotationpresent_kubernetes_io_config_hash - __meta_kubernetes_pod_annotation_kubernetes_io_config_hash - __meta_kubernetes_pod_container_name target_label: __path__ ``` # 4、Loki查询案例 **1、日志选择器** ```shell 对于查询表达式的标签部分,将其用大括号括起来{},然后使用键值语法选择标签。多个标签表达式用逗号分隔: = 完全相等。 != 不相等。 =~ 正则表达式匹配。 !~ 不进行正则表达式匹配。 # 根据任务名称来查找日志 {app="ingress-nginx"} {job="devops/metallb"} {namespace="default",app="podstdr2"} {app=~"kube-state-metrics|prometheus|zookeeper"} ``` **2、使用日志过滤器来查找** ```shell 编写日志流选择器后,您可以通过编写搜索表达式来进一步过滤结果 |= 行包含字符串 != 行不包含字符串。 |~ 行匹配正则表达式。 !~ 行与正则表达式不匹配。 regex表达式接受RE2语法。默认情况下,匹配项区分大小写,并且可以将regex切换为不区分大小写的前缀(?i)。 1. 精确查找名称空间为logging下container为zookeeper且包含有INFO关键字的日志 {namespace="logging",container="zookeeper"} |= "INFO" 2. 正则查找 {job="huohua/svc-huohua-batch"} |~ "(duration|latency)s*(=|is|of)s*[d.]+" 3. 不包含。 {job="mysql"} |= "error" != "timeout" ``` # 5、常见问题 **问题一** 提示找不到**/var/log/pods**目录下的日志文件,无法tail。 ```shell level=error ts=2023-07-17T03:22:11.682802445Z caller=filetarget.go:307 msg="failed to tail file, stat failed" error="stat /var/log/pods/kube-system_kube-apiserver-master3_a8daf137c2a2ea7ef925aaef1e82ac16/kube-apiserver/13.log: no such file or directory" filename=/var/log/pods/kube-system_kube-apiserver-master3_a8daf137c2a2ea7ef925aaef1e82ac16/kube-apiserver/13.log level=error ts=2023-07-17T03:22:11.682823944Z caller=filetarget.go:307 msg="failed to tail file, stat failed" error="stat /var/log/pods/kube-system_kube-scheduler-master3_bdef86673f60f833d12eb8a3ad337fac/kube-scheduler/1.log: no such file or directory" filename=/var/log/pods/kube-system_kube-scheduler-master3_bdef86673f60f833d12eb8a3ad337fac/kube-scheduler/1.log ``` ``` { "name": "docker", "hostPath": { "path": "/var/lib/docker/containers", "type": "" } }, { "name": "pods", "hostPath": { "path": "/var/log/pods", "type": "" } } ``` 但是我们这边真实的企业场景是将docker的数据目录挂载磁盘**/data**目录下,所以需要修改默认volumes配置。 修改步骤: ```shell $ vim values.yaml ``` ```yaml promtail: enabled: true extraVolumes: - name: docker hostPath: path: /data/docker/containers extraVolumeMounts: - name: docker mountPath: /data/docker/containers readOnly: true config: logLevel: info serverPort: 3101 clients: - url: http://{{ .Release.Name }}:3100/loki/api/v1/push ``` ```cobol [root@node1 log]# ll /var/log/pods/monitoring_promtail-bs5cs_5bc5bc90-bac9-480d-b291-4caadeff2236/promtail/ total 4 lrwxrwxrwx 1 root root 162 Dec 17 14:04 0.log -> /data/docker/containers/db45d5118e9508817e1a2efa3c9da68cfe969a2b0a3ed42619ff61a29cc64e5f/db45d5118e9508817e1a2efa3c9da68cfe969a2b0a3ed42619ff61a29cc64e5f-json.log ``` **问题二** Loki日志系统收集日志报429错误: ```shell level=warn ts=2023-07-17T03:42:34.456086325Z caller=client.go:369 component=client host=loki:3100 msg="error sending batch, will retry" status=429 error="server returned HTTP status 429 Too Many Requests (429): Ingestion rate limit exceeded for user fake (limit: 4194304 bytes/sec) while attempting to ingest '5381' lines totaling '1048504' bytes, reduce log volume or contact your Loki administrator to see if the limit can be increased" level=warn ts=2023-07-17T03:42:35.144739805Z caller=client.go:369 component=client host=loki:3100 msg="error sending batch, will retry" status=429 error="server returned HTTP status 429 Too Many Requests (429): Ingestion rate limit exceeded for user fake (limit: 4194304 bytes/sec) while attempting to ingest '5381' lines totaling '1048504' bytes, reduce log volume or contact your Loki administrator to see if the limit can be increased" ``` 收集的日志太多了,超过了 loki 的限制,所以会报 429 错误,如果你要增加限制可以修改 loki 的配置文件: ```yaml promtail: enabled: true extraVolumes: - name: docker hostPath: path: /data/docker/containers extraVolumeMounts: - name: docker mountPath: /data/docker/containers readOnly: true config: logLevel: info serverPort: 3101 clients: - url: http://{{ .Release.Name }}:3100/loki/api/v1/push limits_config: # 将直接将日志数据发送到运行在本地的 Loki 实例 ingestion_rate_strategy: local # 每个用户每秒的采样率限制 ingestion_rate_mb: 15 # 每个用户允许的采样突发大小 ingestion_burst_size_mb: 20 ```
阿星
2024年1月27日 16:36
转发文档
收藏文档
上一篇
下一篇
手机扫码
复制链接
手机扫一扫转发分享
复制链接
Markdown文件
PDF文档(打印)
分享
链接
类型
密码
更新密码