找回密码
立即注册
搜索
热搜: Java Python Linux Go
发回帖 发新帖

4226

积分

0

好友

580

主题
发表于 1 小时前 | 查看: 3| 回复: 0

在云原生与微服务架构日益普及的今天,对于运行在 Kubernetes 集群中应用的监控和日志记录变得至关重要。集群本身和应用会产生海量日志,如何高效地收集、存储和查询这些日志,是保障系统可观测性与稳定运行的关键一环。Grafana Loki 作为一款设计灵巧的日志聚合系统,因其与 Grafana 无缝集成的特性和较低的资源消耗,成为了许多团队的选择。它允许您在一个统一的界面中,像查询指标一样查询日志。

本文将手把手带你完成在 Kubernetes 集群中使用 Helm 一键部署完整的 Loki 日志收集套件,并通过 Grafana 进行可视化查询。

整体架构

下图清晰地展示了基于 Grafana Loki 的 Kubernetes 日志收集与监控架构:
Kubernetes日志收集与监控架构示意图

核心流程如下:

  • 日志采集:每个 Kubernetes 工作节点(Worker Node)上运行的 Promtail 代理,负责收集节点上所有 Pod 的应用程序日志。
  • 日志汇聚:Promtail 将收集到的日志发送至中央的 Loki 服务。
  • 查询与展示:用户通过 Grafana 界面(默认端口 3000)连接到 Loki 数据源,对日志进行检索和监控。

前提条件

本教程采用 Helm Chart 进行一键式部署,因此你需要准备以下环境:

  1. 一个可用的 Kubernetes 集群
    确保你的 kubectl 可以正常连接集群。例如:

    [root@k8smaster ~]# kubectl get nodes
    NAME        STATUS   ROLES           AGE   VERSION
    k8smaster   Ready    control-plane   10d   v1.35.2
    k8sworker   Ready    <none>          10d   v1.35.2
  2. 安装 Helm 工具
    如果你的环境尚未安装 Helm,可以通过官方脚本快速安装:

    [root@k8smaster ~]# curl https://raw.githubusercontent.com/helm/helm/master/scripts/get-helm-3 | bash
      % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                     Dload  Upload   Total   Spent    Left  Speed
    100 11929  100 11929    0     0   2825      0  0:00:04  0:00:04 --:--:--  2968
    [WARNING] Could not find git. It is required for plugin installation.
    Downloading https://get.helm.sh/helm-v3.20.1-linux-amd64.tar.gz
    Verifying checksum... Done.
    Preparing to install helm into /usr/local/bin
    helm installed into /usr/local/bin/helm

    安装后验证版本:

    [root@k8smaster ~]# helm version
    version.BuildInfo{Version:"v3.20.1", GitCommit:"a2369ca71c0ef633bf6e4fccd66d634eb379b371", GitTreeState:"clean", GoVersion:"go1.25.8"}

部署步骤

1. 添加 Grafana Helm 仓库

首先,将 Grafana 官方的 Helm 仓库添加到本地。

[root@k8smaster ~]# helm repo add grafana https://grafana.github.io/helm-charts
"grafana" has been added to your repositories

添加成功后,更新仓库以获取最新的 Chart 信息。

[root@k8smaster ~]# helm repo update
Hang tight while we grab the latest from your chart repositories...
...Successfully got an update from the "grafana" chart repository
Update Complete. ⎈Happy Helming!⎈

接下来,搜索与 Loki 相关的 Chart。我们会发现一个名为 grafana/loki-stack 的 Chart,它集成了 Loki、Promtail 和 Grafana 等组件,非常适合一键部署。

[root@k8smaster ~]# helm search repo loki
NAME                            CHART VERSION   APP VERSION     DESCRIPTION
grafana/loki                    6.55.0          3.6.7           Helm chart for Grafana Loki and Grafana Enterpr...
grafana/loki-canary             0.14.1          2.9.1           Helm chart for Grafana Loki Canary
grafana/loki-distributed        0.80.6          2.9.13          Helm chart for Grafana Loki in microservices mode
grafana/loki-simple-scalable    1.8.11          2.6.1           Helm chart for Grafana Loki in simple, scalable...
grafana/loki-stack              2.10.3          v2.9.3          Loki: like Prometheus, but for logs.
grafana/fluent-bit              2.6.0           v2.1.0          Uses fluent-bit Loki go plugin for gathering lo...
grafana/lgtm-distributed        3.0.1           ^12.1.1         Umbrella chart for a distributed Loki, Grafana,...
grafana/meta-monitoring         1.3.0           0.0.1           A Helm chart for meta monitoring Grafana Loki, ...
grafana/promtail                6.17.1          3.5.1           Promtail is an agent which ships the contents o...

本教程将使用 grafana/loki-stack 这个一体化 Chart。

2. 自定义 Helm Chart 配置值

默认配置可能不完全符合需求,例如 Grafana 组件默认是关闭的。我们可以通过自定义 Values 文件来启用所需组件并调整配置。

首先,将默认的配置值导出到一个 YAML 文件中:

[root@k8smaster ~]# helm show values grafana/loki-stack > loki-custom-values.yaml

然后,编辑这个文件。我们需要关注几个关键部分,确保以下组件被正确启用:

# 查看配置文件的关键部分
[root@k8smaster ~]# cat loki-custom-values.yaml
test_pod:
  enabled: true
  image: bats/bats:1.8.2
  pullPolicy: IfNotPresent

loki:
  enabled: true
  isDefault: true
  url: http://{{(include "loki.serviceName" .)}}:{{ .Values.loki.service.port }}
  readinessProbe:
    httpGet:
      path: /ready
      port: http-metrics
    initialDelaySeconds: 45
  livenessProbe:
    httpGet:
      path: /ready
      port: http-metrics
    initialDelaySeconds: 45
  datasource:
    jsonData: "{}"
    uid: ""

promtail:
  enabled: true
  config:
    logLevel: info
    serverPort: 3101
    clients:
      - url: http://{{ .Release.Name }}:3100/loki/api/v1/push

fluent-bit:
  enabled: false

grafana:
  enabled: true
  sidecar:
    datasources:
      label: ""
      labelValue: ""
      enabled: true
      maxLines: 1000
  image:
    tag: 10.3.3
  service:
    type: NodePort

prometheus:
  enabled: false
  isDefault: false
  url: http://{{ include "prometheus.fullname" .}}:{{ .Values.prometheus.server.service.servicePort }}{{ .Values.prometheus.server.prefixURL }}
  datasource:
    jsonData: "{}"

filebeat:
  enabled: false
  filebeatConfig:
    filebeat.yml: |
      # logging.level: debug
      filebeat.inputs:
      - type: container
        paths:
          - /var/log/containers/*.log
        processors:
        - add_kubernetes_metadata:
            host: ${NODE_NAME}
            matchers:
            - logs_path:
                logs_path: "/var/log/containers/"
      output.logstash:
        hosts: ["logstash-loki:5044"]

logstash:
  enabled: false
  image: grafana/logstash-output-loki
  imageTag: 1.0.1
  filters:
    main: |-
      filter {
        if [kubernetes] {
          mutate {
            add_field => {
              "container_name" => "%{[kubernetes][container][name]}"
              "namespace" => "%{[kubernetes][namespace]}"
              "pod" => "%{[kubernetes][pod][name]}"
            }
            replace => { "host" => "%{[kubernetes][node][name]}"}
          }
        }
        mutate {
          remove_field => ["tags"]
        }
      }
  outputs:
    main: |-
      output {
        loki {
          url => "http://loki:3100/loki/api/v1/push"
          #username => "test"
          #password => "test"
        }
        # stdout { codec => rubydebug }
      }

# proxy is currently only used by loki test pod
# Note: If http_proxy/https_proxy are set, then no_proxy should include the
# loki service name, so that tests are able to communicate with the loki
# service.
proxy:
  http_proxy: ""
  https_proxy: ""
  no_proxy: ""

配置要点说明:

  • loki.enabled: true: 启用 Loki 主服务。
  • promtail.enabled: true: 启用 Promtail 日志收集代理,它以 DaemonSet 形式运行在每个节点上。
  • grafana.enabled: truegrafana.service.type: NodePort: 关键! 启用 Grafana 并将其服务类型设置为 NodePort,以便从集群外部访问。这是默认配置中需要修改的核心部分。
  • prometheus, filebeat, logstash, fluent-bit 均设为 false: 本教程聚焦于 Loki+Promtail 方案,故禁用其他可选的日志收集器。

3. 使用 Helm 部署 Loki Stack

配置好 Values 文件后,就可以开始部署了。我们将在名为 grafana-loki 的命名空间中安装所有组件。

[root@k8smaster ~]# helm upgrade --install --values loki-custom-values.yaml loki grafana/loki-stack -n grafana-loki --create-namespace
Release "loki" does not exist. Installing it now.
WARNING: This chart is deprecated
NAME: loki
LAST DEPLOYED: Sun Mar 22 15:21:26 2026
NAMESPACE: grafana-loki
STATUS: deployed
REVISION: 1
NOTES:
The Loki stack has been deployed to your cluster. Loki can now be added as a datasource in Grafana.

See http://docs.grafana.org/features/datasources/loki/ for more detail

部署成功后,查看相关 Pod 和 Service 的状态,确认所有组件运行正常。

[root@k8smaster ~]# kubectl get pods -n grafana-loki
NAME                             READY   STATUS    RESTARTS   AGE
loki-0                           1/1     Running   0          26m
loki-grafana-6bb45f476b-xxqgk   2/2     Running   0          26m
loki-promtail-cp24p              1/1     Running   0          26m
loki-promtail-d95c2              1/1     Running   0          26m
[root@k8smaster ~]# kubectl get svc -n grafana-loki
NAME              TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE
loki              ClusterIP   10.96.74.47     <none>        3100/TCP       26m
loki-grafana      NodePort    10.96.51.130    <none>        80:32650/TCP   26m
loki-headless     ClusterIP   None            <none>        3100/TCP       26m
loki-memberlist   ClusterIP   None            <none>        7946/TCP       26m

可以看到 loki-grafana 服务已分配了一个 NodePort 32650

4. 访问 Grafana 并配置 Loki 数据源

首先,获取访问 Grafana 所需的端口和凭据。

  • 获取 NodePort:
    [root@k8smaster ~]# kubectl get svc loki-grafana -n grafana-loki  -o jsonpath="{.spec.ports[0].nodePort}"
    32650
  • 获取管理员用户名 (默认为 admin):
    [root@k8smaster ~]# kubectl get secret loki-grafana -n grafana-loki -o jsonpath="{.data.admin-user}" | base64 --decode
    admin
  • 获取管理员密码:
    [root@k8smaster ~]# kubectl get secret loki-grafana -n grafana-loki -o jsonpath="{.data.admin-password}" | base64 --decode
    3exqqaQhlQoi9xpfoC8TObCYmIasokKKcR4wcnFZ

现在,通过浏览器访问 http://<你的K8s节点IP>:32650,使用上面获取的用户名和密码登录。
Grafana登录界面

登录成功后,你会看到 Grafana 的主页。
Grafana仪表盘首页

接下来,需要将 Loki 添加为数据源。点击左侧导航栏的 Connections -> Data sources
Grafana数据源连接页面

在搜索框输入 “loki”,然后选择 Loki 数据源。由于我们在 Helm 配置中已经通过 Sidecar 自动完成了数据源配置,这里应该能看到一个名为 “Loki” 的已连接数据源,其地址指向了集群内的 Loki 服务 (http://loki:3100)。
已配置的Loki数据源

5. 探索与查询日志

点击数据源列表右侧的 “Explore” 按钮,进入 Loki 的日志查询界面。
Loki Explore初始查询界面

在 “Label filters” 区域,你可以通过添加标签对日志进行筛选。这是 Loki 强大的地方,它使用与 Prometheus 类似的标签系统来索引日志。

例如,我们可以选择 namespace 标签,其值为 grafana-loki,来查看我们刚部署的这套系统自身产生的日志。点击 “Run query”。
查询指定命名空间的日志

查询结果会显示在下方。你还可以进一步细化查询,例如,增加一个 pod 标签过滤器,只查看某个特定 Pod(如 loki-promtail-d95c2)的日志。
通过命名空间和Pod标签组合查询日志

总结与后续

至此,我们成功在 Kubernetes 集群中使用 Helm 部署了 Grafana Loki 日志收集栈。通过自定义 Values 文件,我们启用了核心的 Loki、Promtail 和 Grafana 组件,并配置 Grafana 以 NodePort 方式对外暴露,方便访问。

本文重点在于快速搭建和验证基础日志流水线,因此并未涉及持久化存储配置、日志保留策略、资源配额限制等生产环境需要考虑的高级话题。在实际生产部署前,请务必根据业务需求规划存储方案并调整资源限制。

Grafana Loki 以其简洁的架构和与 Grafana 生态的深度整合,为 Kubernetes 环境下的日志管理提供了一个高效且低成本的选项。希望这篇实战指南能帮助你快速上手。如果你在部署过程中遇到问题,或想探讨更多关于云原生可观测性的实践,欢迎到云栈社区的相关板块交流讨论。




上一篇:WebGPU实战:基于Rust/WASM构建浏览器端专业非线性视频编辑器
下一篇:KiCad V10.0.0发布,带来PCB设计与原理图编辑多项革新
您需要登录后才可以回帖 登录 | 立即注册

手机版|小黑屋|网站地图|云栈社区 ( 苏ICP备2022046150号-2 )

GMT+8, 2026-3-23 05:13 , Processed in 0.670174 second(s), 39 queries , Gzip On.

Powered by Discuz! X3.5

© 2025-2026 云栈社区.

快速回复 返回顶部 返回列表