轻量级Grafana Loki日志系统部署指南(2025最新版)

2,797 阅读5分钟

解锁更多k8s相关文章,欢迎关注微信公众号“运维日常手记”。

介绍

受Prometheus启发,Loki是一个水平可扩展、高可用性、多租户日志收集系统,它非常具有成本效益和易于操作。它不索引日志的内容,而是为每个日志流创建一组标签,与其他日志收集系统相比,Loki 可以:

  • 不对日志进行全文索引,通过存储压缩的非结构化日志和仅索引元数据,Loki操作更简单,运行成本更低。
  • 使用与Prometheus相同的标签对日志流进行索引和分组。
  • 特别适合存储 Kubernetes Pod 日志,Pod 标签等元数据会自动抓取和索引。
  • 日志原生支持在Grafana 中展示。

使用helm部署loki

loki chart支持三种不同的部署架构,分别是Monolithic(整体),Simple Scalable (简单可扩展)和Microservice (微服务),Monolithic架构适合快速体验loki,它适合每天20GB左右的少量日志读写,Simple Scalable是大规模部署loki的最简单的方法,它可以扩展到每天几TB的日志量,如果你的日志量远大于几TB,那Microservice的部署架构更适合你,本次使用Simple Scalable的部署架构。

环境

k8s集群版本1.33.1

k8s-master-01 172.16.10.200  (8核16g)

k8s-master-02 172.16.10.201  (8核16g)

k8s-master-03 172.16.10.202 (8核16g)

要求

k8s集群至少要有3个节点,否则loki一些反亲和性部署的pod可能会调度失败,每个节点的内存不少于9个G,否则loki-chunks-cache会因为资源不足调度失败,当然如果你实在没有这么多资源,可以通过修改chart模板删除反亲和和资源请求相关配置,应该也可以运行起来。

下载镜像

运行以下脚本,先从国内下载所有依赖的镜像

#!/bin/bash
reg=crpi-u3f530xi0zgtvmy0.cn-beijing.personal.cr.aliyuncs.com/image-infra
ctr -n k8s.io images pull $reg/memcached:1.6.38-alpinectr -n k8s.io images tag  $reg/memcached:1.6.38-alpine docker.io/library/memcached:1.6.38-alpine
ctr -n k8s.io images pull $reg/memcached-exporter:v0.15.2ctr -n k8s.io images tag  $reg/memcached-exporter:v0.15.2 docker.io/prom/memcached-exporter:v0.15.2
ctr -n k8s.io images pull $reg/loki:3.5.0ctr -n k8s.io images tag  $reg/loki:3.5.0 docker.io/grafana/loki:3.5.0
ctr -n k8s.io images pull $reg/k8s-sidecar:1.30.3ctr -n k8s.io images tag  $reg/k8s-sidecar:1.30.3  docker.io/kiwigrid/k8s-sidecar:1.30.3
ctr -n k8s.io images pull $reg/minio:RELEASE.2024-12-18T13-15-44Zctr -n k8s.io images tag  $reg/minio:RELEASE.2024-12-18T13-15-44Z  quay.io/minio/minio:RELEASE.2024-12-18T13-15-44Z
ctr -n k8s.io images pull $reg/nginx-unprivileged:1.28-alpinectr -n k8s.io images tag  $reg/nginx-unprivileged:1.28-alpine docker.io/nginxinc/nginx-unprivileged:1.28-alpine 
ctr -n k8s.io images pull $reg/loki-canary:3.5.0ctr -n k8s.io images tag  $reg/loki-canary:3.5.0  docker.io/grafana/loki-canary:3.5.0
ctr -n k8s.io images pull $reg/nfs-subdir-external-provisioner:v4.0.2ctr -n k8s.io images tag  $reg/nfs-subdir-external-provisioner:v4.0.2 registry.k8s.io/sig-storage/nfs-subdir-external-provisioner:v4.0.2
ctr -n k8s.io images pull $reg/alloy:v1.9.1ctr -n k8s.io images tag  $reg/alloy:v1.9.1 docker.io/grafana/alloy:v1.9.1
ctr -n k8s.io images pull $reg/grafana:12.0.1ctr -n k8s.io images tag  $reg/grafana:12.0.1  docker.io/grafana/grafana:12.0.1
ctr -n k8s.io images pull $reg/busybox:1.31.1ctr -n k8s.io images tag  $reg/busybox:1.31.1  docker.io/library/busybox:1.31.1 

搭建nfs storageclass

loki需要使用到pv和pvc,由于我的测试环境没有商业的存储,所以在开始之前部署一个nfs-subdir-external-provisioner,来给k8s集群自动提供pv和pvc。

搭建nfs服务器(直接在k8s集群中找了一个节点安装)

yum -y install nfs-utils rpcbind

创建目录并添加配置

# 创建目录
mkdir /data/nfs

# 添加配置
cat > /etc/exports << EOF
/data/nfs  *(rw,sync,no_root_squash)
EOF

启动nfs服务

systemctl start rpcbind.service
systemctl enable rpcbind
systemctl status rpcbind

systemctl start nfs-server
systemctl enable nfs-server
systemctl status nfs-server

添加nfs-subdir-external-provisioner chart repo

# 添加repo
helm repo add nfs-subdir-external-provisioner https://kubernetes-sigs.github.io/nfs-subdir-external-provisioner/

部署nfs-subdir-external-provisioner

helm install nfs-subdir-external-provisioner nfs-subdir-external-provisioner/nfs-subdir-external-provisioner \    
--set nfs.server=172.16.10.202 \    
--set nfs.path=/data/nfs \    
-n kube-system

将nfs-subdir-external-provisioner设置为默认是storageclass

kubectl patch storageclass nfs-client -p '{"metadata": {"annotations":{"storageclass.kubernetes.io/is-default-class":"true"}}}'

安装loki

添加Loki chart repo

helm repo add grafana https://grafana.github.io/helm-charts

更新repo信息

helm repo update

创建values.yaml文件,这里minio设置为了true,它会创建一个测试用的minio对象存储来保存日志,在生产环境中应该替换掉它,比如在阿里云上可以使用oss。

  loki:
    auth_enabled: false
    schemaConfig:
      configs:
        - from: "2024-04-01"
          store: tsdb
          object_store: s3
          schema: v13
          index:
            prefix: loki_index_
            period: 24h
    ingester:
      chunk_encoding: snappy
    querier:
      # Default is 4, if you have enough memory and CPU you can increase, reduce if OOMing
      max_concurrent: 4
    pattern_ingester:
      enabled: true
    limits_config:
      allow_structured_metadata: true
      volume_enabled: true

  deploymentMode: SimpleScalable

  backend:
    replicas: 2
  read:
    replicas: 2
  write:
    replicas: 3 # To ensure data durability with replication

  # Enable minio for storage
  minio:
    enabled: true

  gateway:
    service:
      type: LoadBalancer

安装loki

# 创建命名空间
kubectl create ns loki
# 安装
helm install --values values.yaml loki grafana/loki -n loki

安装日志收集客户端alloy

alloy是最新功能强大的日志收集客户端,官方建议用alloy替换原来的promtail,创建values.yaml配置文件,配置alloy收集k8s容器的日志。

alloy:
  mounts:
    varlog: true
  configMap:
    content: |
      logging {
        level  = "info"
        format = "logfmt"
      }

      discovery.kubernetes "pods" {
        role = "pod"
      }

      loki.source.kubernetes "pods" {
        targets    = discovery.kubernetes.pods.targets
        forward_to = [loki.write.endpoint.receiver]
      }

      loki.write "endpoint" {
        endpoint {
            url = "http://loki-gateway.loki.svc.cluster.local:80/loki/api/v1/push"
            tenant_id = "local"
        }
      }

安装alloy

helm install alloy grafana/alloy -f values.yaml -n loki

安装grafana

创建values.yaml文件

persistence:
  type: pvc
  enabled: true

安装grafana

helm install grafana grafana/grafana -f values.yaml -n loki

获取grafana默认密码

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

临时暴露grafana端口(后续可用nodeport或ingress暴露)

export POD_NAME=$(kubectl get pods --namespace loki -l "app.kubernetes.io/name=grafana,app.kubernetes.io/instance=grafana" -o jsonpath="{.items[0].metadata.name}")
kubectl --namespace loki port-forward --address 0.0.0.0 $POD_NAME 3000

添加loki数据源,浏览器访问grafana(集群任意节点ip加3000端口),用户名是admin,密码是上一步获取的密码,登录后添加数据源。

​编辑

编辑添加数据源,name按需要填写url输入loki-gateway.loki.svc.cluster.local,注意要添加一个header,key为X-Scope-OrgID,值可以随意,然后点击下方测试并保存按钮即可。

至此完结,如果觉得文章对你有用,麻烦给个关注,谢谢。