10 分钟在K8s 中部署轻量级日志系统 Loki

转载至我的博客 https://www.infrastack.cn ,公众号:架构成长指南

Loki 是什么?

Loki是由Grafana Labs开源的一个水平可扩展、高可用性,多租户的日志聚合系统的日志聚合系统。它的设计初衷是为了解决在大规模分布式系统中,处理海量日志的问题。Loki采用了分布式的架构,并且与Prometheus、Grafana密切集成,可以快速地处理大规模的日志数据。该项目受 Prometheus 启发

  • Promtail是代理,负责收集日志并将其发送给 Loki 。
  • Loki 是主服务器,负责存储日志和处理查询。
  • Grafana则 用于 UI 展示。

与ELK相比优势在哪里?

ELK是大规模日志解决方案中的佼佼者说到Loki,免不了要拿来跟ELK做个对比

  1. 架构简单:Loki 则采用分布式架构、可以将日志存储在多个节点上,也可以存储在一个节点上,其中Promtail进行日志收集、Loki 负责存储查询、Grafana用于展现
  2. 存储更小:Loki使用了紧凑的索引和压缩算法,相比ES 可以减少不少存储空间
  3. 没有采集日志格式要求:提供了更大的灵活性以及在查询时格式化的选项
  4. 与 Prometheus、Grafana 和 K8s 原生集成:可以在单个用户界面中无缝切换查询指标、日志等数据
  5. 轻量级:相比ELK,Loki更加轻量级,因为它不需要一个单独的Elasticsearch集群来存储和索引日志数据

如何采集数据?

k8s 集群不提供日志收集的解决方案,一般来说有3 种方案来做日志收集:

  1. 在Node节点上运行一个 agent 来收集日志(DaemonSet 采集方式)
  2. 在 Pod 中包含一个 sidecar 容器来收集应用日志(sidecar 采集方式)
  3. 由应用程序将日志信息推送到采集后端(主动采集方式)
节点采集方式

日志系统会以DaemonSet 方式是在每个node 节点上部署一个agent,来采集这个节点上所有的日志,默认会收集k8s 下/var/log/pod/var/lib/docker/containers下的日志,对应用程序的要求就是开启控制台打印,否则会收集不到日志,比较适用于功能单一或业务不是很多的集群;

Sidecar采集方式

Sidecar 方式会在每一个Pod中部署一个 sidecar 容器,来进行当前容器的日志采集,有多少个 pod,就会有多少个Sidecar容器,因此Sidecar相对资源占用较多,但灵活性以及多租户隔离性较强,适合大型的 K8s 集群使用,因为除了占用资源多点,采集性能不会有影响

Loki的Pormtail同时支持以上两种方式,默认为节点采集方式,下面我们演示如何在k8s 中快速部署一个Loki日志分析系统

Loki 部署

添加仓库
helm repo add grafana https://grafana.github.io/helm-charts
下载仓库
helm pull grafana/loki-stack
解压包

解压完成以后,可以查看相关参数的使用

tar -xvf loki-stack-2.10.0.tgz
配置概览

此Chart不止包含了Loki 、promtail、grafana,还包括其他组件,但是默认未开启,只开启了Loki 、promtail,这里为了演示,也开启grafana配置,通过grafana.enabled=true指定,同时如果要指定相关子 chart 参数,根据子 chart 名称.参数进行指定,比如要指定的grafana 的admin 密码,可以用grafana.adminPassword=admin指定

启动

注意:启动示例没有对日志数据进行持久化处理,正式部署要进行持久化配置

loki-stack中Grafana 的密码获取比较复杂,所以直接通过参数指定

helm install loki ./loki-stack -n loki-stack \
--set grafana.enabled=true \
--set grafana.adminPassword=admin \
--create-namespace  

以上启动完成以后,会收集/var/log/pod/var/lib/docker/containers日志信息,

查看启动pod,由于本人k8s 集群有 6 个node节点,所以部署了6 个promtail

Grafana访问

修改 Grafana 为 nodeport 访问方式

 kubectl edit svc loki-grafana -n loki-stack

登录成功以后,访问Explore 功能,并点击Log browser按钮,会看到已经采集相关数据,并自动创建

appcomponentcontainernamepsacepod等多个维度的 labels

比如要查看 ingress 的日志,选择命名空间为ingress-nginx并点击 show logs

同时查询结果可以支持换行、日期排序等功能


以上默认的查询界面,使用起来可能没那么顺手,那么可以根据需求去定制不同的查询界面,在https://grafana.com/grafana/dashboards中输入 loki,可以下载感兴趣的Dashboard

loki卸载

helm uninstall loki -n loki-stack

总结

以上我们快速演示了如何在 k8s 中部署一个Loki,可以看到非常简单,由于Loki 对k8s友好支持,默认就可以采集到pod、namespace 等标签数据,不需要额外配置,但是要达到生产级可用,还需要对 Loki的数据进行持久化配置、同时要根据采集日志数据的大小做好采集速率调整、以及日志过期策略设置

又到过年了,龙年红包封面是必备的,大家不要花钱购买了,我制作一款封面红包,数量4千个,效果如下

图片

领取方法,关注公众号架构成长指南,回复「封面」领取

<think>嗯,我现在需要了解如何在Kubernetesk8s)集群中监控那些将日志写入文件的Pod容器,而不是输出到控制台的。用户的问题是说,这些日志是写入文件的,非控制台输出,所以常规的stdout/stderr收集方法可能不适用。我需要回想一下Kubernetes日志管理机制,以及如何处理这种情况。 首先,Kubernetes默认的日志收集方式,比如使用Fluentd、Fluent Bit或者Filebeat等工具,通常是抓取容器的标准输出和标准错误流。因为这些日志默认存储在节点的/var/log/containers/目录下,以容器ID命名。但问题在于,如果应用程序直接将日志写入容器内的文件,而不是输出到控制台,那么这些日志不会被kubelet捕获,也就不会出现在节点的默认日志路径中。这时候,常规的日志收集方法可能无法捕获这些文件日志,所以需要其他方法。 接下来,我需要考虑如何监控这些文件日志。可能的解决方案有几个方向: 1. **修改应用配置,将日志输出到stdout/stderr**:这是最直接的方法,但用户可能无法或不愿意修改应用代码,所以可能需要其他方法。 2. **使用Sidecar容器收集日志**:在同一个Pod中运行一个Sidecar容器,该容器负责读取应用程序容器写入的日志文件,并将其输出到自己的stdout,这样k8s的默认日志收集器就能捕获到。或者,Sidecar容器可以将日志文件发送到远程存储或日志系统。 3. **在节点上部署日志收集Agent,并配置其读取容器内的日志文件**:例如,配置Fluent Bit或Filebeat来监控容器内的特定日志文件路径,但因为容器文件系统是隔离的,可能需要挂载卷到宿主机,使得日志文件在宿主机上可访问。 4. **使用自定义的日志收集方案**:比如在Pod中挂载持久化卷,将日志文件存储在卷中,然后由外部的日志收集工具从卷中读取日志。 接下来需要详细分析每种方案的实现步骤和注意事项。 首先,Sidecar容器方案。例如,假设应用程序容器将日志写入到/app/logs/目录下的某个文件,比如app.log。那么可以在Pod中定义一个Sidecar容器,该容器挂载相同的volume,然后使用tail -f命令持续读取该文件并输出到stdout。这样,Sidecar的stdout就会被kubelet捕获,进而被集群的日志收集器处理。这种方式需要确保两个容器挂载同一个卷,以便Sidecar能够访问日志文件。 其次,节点上的日志收集Agent。这需要将容器内的日志文件存储到宿主机的某个路径,通常通过volume挂载。例如,在Pod定义中,将/app/logs挂载到宿主机的/var/log/myapp/目录下。然后配置Fluent Bit等Agent监控宿主机上的该目录,收集日志并发送到Elasticsearch、Loki等存储系统。这种方法需要考虑日志文件的轮转(log rotation)问题,以及避免宿主机上的存储空间被占满。 第三种方法,自定义日志收集器。比如在容器内部运行一个轻量级日志转发工具,如fluentd、rsyslog或Vector,这些工具可以监控容器内的日志文件变化,并将日志发送到远程服务器。这种情况下,需要在容器镜像中包含这些工具,并确保它们正确配置。 此外,可能需要考虑使用Kubernetes的DaemonSet部署日志收集器,每个节点上运行一个实例,负责收集该节点上所有Pod的日志。这时候,如果日志文件已经被挂载到宿主机路径,DaemonSet中的Agent可以直接读取这些文件。 接下来需要详细说明每种方法的实现步骤,以及可能需要的YAML配置示例。例如,Sidecar容器的配置可能如下: 在Pod的spec中,定义两个容器:一个是应用容器,另一个是Sidecar。共享一个emptyDir volume,应用容器将日志写入该volume,Sidecar读取并输出到stdout。 例如: ```yaml apiVersion: v1 kind: Pod metadata: name: myapp spec: containers: - name: app image: myapp:latest volumeMounts: - name: log-volume mountPath: /app/logs - name: log-sidecar image: busybox args: [/bin/sh, -c, 'tail -n+1 -F /var/log/app.log'] volumeMounts: - name: log-volume mountPath: /var/log volumes: - name: log-volume emptyDir: {} ``` 这里,应用容器将日志写入/app/logs/app.log,而Sidecar容器挂载该卷到/var/log,然后使用tail命令持续读取该文件并输出到stdout,这样日志就会被kubelet捕获。 另一种情况是使用节点上的Agent,假设将日志目录挂载到宿主机路径: 在Pod的volumeMounts中使用hostPath: ```yaml apiVersion: v1 kind: Pod metadata: name: myapp spec: containers: - name: app image: myapp:latest volumeMounts: - name: host-log-volume mountPath: /app/logs volumes: - name: host-log-volume hostPath: path: /var/log/myapp type: DirectoryOrCreate ``` 然后,在节点上运行的Fluent Bit可以配置监控/var/log/myapp/app.log,并将其转发到目标系统。 此外,对于DaemonSet部署日志收集器,例如Fluent Bit的配置可能需要指定输入插件为tail,监控宿主机上的日志文件路径: 在Fluent Bit的配置文件中: ``` [INPUT] Name tail Path /var/log/myapp/*.log ... ``` 然后输出到Elasticsearch或Loki等。 另外,使用自定义工具如Vector,可以在容器内运行,监控日志文件并直接发送,这可能需要在应用容器中安装Vector,或者使用init容器来设置。 但需要注意,在容器内运行日志收集器可能会增加资源消耗,并且需要处理日志轮转等问题。 此外,还可以考虑使用Project Falco或其他安全工具来监控文件变化,但这可能不是最佳实践。 总结起来,主要的解决方案是: 1. Sidecar容器转发日志到stdout。 2. 宿主机挂载日志目录,使用节点级Agent收集。 3. 在应用容器内集成日志转发工具。 需要根据实际环境和需求选择合适的方法。例如,如果无法修改应用且允许挂载宿主机目录,第二种方法可能更合适。如果希望保持日志收集与应用的解耦,使用Sidecar可能更好。 可能还需要考虑日志的保留策略、存储、以及如何解析和过滤日志内容。此外,权限问题也需要关注,比如宿主机路径的写入权限,以及Sidecar容器是否有权限读取应用容器的日志文件。 最后,需要验证配置是否生效,例如查看节点的日志路径是否有文件生成,或者Sidecar容器的日志是否正常输出到stdout。</think>在Kubernetes集群中监控Pod内容器的文件日志(非控制台输出)需通过额外配置实现。以下是分步解决方案: --- ### 方法一:**Sidecar容器转发日志** 通过Sidecar容器将文件日志重定向到标准输出,使默认日志收集器可捕获。 #### 步骤: 1. **定义共享Volume**:在Pod中创建共享存储卷(如`emptyDir`)。 2. **挂载Volume到容器**:应用容器将日志写入共享目录,Sidecar容器读取并输出。 3. **配置Sidecar命令**:使用`tail -f`持续读取日志文件并输出到stdout。 #### 示例YAML: ```yaml apiVersion: v1 kind: Pod metadata: name: myapp spec: containers: - name: app image: myapp:latest volumeMounts: - name: log-volume mountPath: /app/logs # 应用将日志写入此目录 - name: log-sidecar image: busybox args: [/bin/sh, -c, 'tail -n+1 -F /var/log/app.log'] # 持续读取日志 volumeMounts: - name: log-volume mountPath: /var/log # 挂载到Sidecar容器 volumes: - name: log-volume emptyDir: {} # 临时存储卷 ``` --- ### 方法二:**宿主机挂载日志目录** 将容器内日志目录挂载到宿主机路径,通过节点级日志收集Agent监控。 #### 步骤: 1. **挂载`hostPath`卷**:将容器日志目录绑定到宿主机路径。 2. **配置日志收集Agent**:在节点上部署Agent(如Fluent Bit),监控宿主机日志文件。 #### 示例YAML(Pod配置): ```yaml apiVersion: v1 kind: Pod metadata: name: myapp spec: containers: - name: app image: myapp:latest volumeMounts: - name: host-log-volume mountPath: /app/logs # 容器内日志路径 volumes: - name: host-log-volume hostPath: path: /var/log/myapp # 宿主机路径 type: DirectoryOrCreate # 自动创建目录 ``` #### Fluent Bit配置示例(DaemonSet): ```conf [INPUT] Name tail Path /var/log/myapp/*.log # 监控宿主机路径 Tag k8s_filelog ... ``` --- ### 方法三:**容器内集成日志转发工具** 在容器内运行轻量级日志转发工具(如Vector、Fluentd),直接发送日志到远程存储。 #### 步骤: 1. **构建自定义镜像**:在应用镜像中集成日志工具(如Vector)。 2. **配置日志采集规则**:定义监控文件路径和输出目标。 #### 示例Dockerfile片段: ```dockerfile FROM myapp:base COPY vector.toml /etc/vector/ RUN curl -O https://packages.timber.io/vector/0.17.3/vector-0.17.3-x86_64-unknown-linux-gnu.tar.gz \ && tar xzf vector-*.tar.gz && cp vector-*/bin/vector /usr/local/bin/ CMD ["sh", "-c", "/app/start-app.sh && vector -c /etc/vector/vector.toml"] ``` #### Vector配置示例(`vector.toml`): ```toml [sources.app_log] type = "file" include = ["/app/logs/*.log"] [sinks.elastic] type = "elasticsearch" inputs = ["app_log"] endpoint = "http://elasticsearch:9200" ``` --- ### 关键注意事项: 1. **日志轮转(Log Rotation)**:确保应用或工具支持日志文件轮转,避免磁盘占满。 2. **资源限制**:Sidecar或容器内工具需合理分配CPU/内存资源。 3. **权限问题**:挂载宿主机目录时,确保容器有写入权限。 4. **安全性**:敏感日志需加密传输(如TLS),避免泄露。 --- ### 总结 - **推荐方法**:优先使用**Sidecar模式**(无需修改宿主机配置)或**宿主机挂载+DaemonSet Agent**(适合统一日志收集)。 - **验证方式**: - 检查Sidecar容器日志:`kubectl logs myapp -c log-sidecar` - 查看宿主机日志文件:`ls /var/log/myapp/app.log`
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值