k8s日志收集管理解决方案
·
全栈监控的软件
商业的监控软件:阿里云 ARMS
全球做监控最好的公司:Datadog SAAS all-in-one agent(将复杂性整合,直接安装就可以全部监控),收费贵,不做国内市场。
日志统一采集
ELK
Logstash Elasticsearch Kibana
采集端 存储端 展示端
EFK
Filebeat Elasticsearch Kibana
Fluentd
Logstash + Filebeat 联合使用,实现集群内日志拆分方便检索;在k8s中 Filebeat 使用 DaemonSet 部署,Logstash 使用 Deployment 部署。
Fluentd 和 Loki 适合k8s内使用
部署 EFK
1、传统架构 rpm 日志输出文件
cd efk-rpm/
rpm -ivh elasticsearch-7.17.16-x86_64.rpm #自己带了JDK
cd /etc/elasticsearch/
vim elasticsearch.yml #注意前面不能有空格
----------------------- Cluster -------------------------
cluster.name: cluster-01 # 打开注释并修改
------------------------ Node ---------------------------
node.name: node-1
------------------------ Paths --------------------------
path.data: /data/elasticsearch
----------------------- Network -------------------------
network.host: 0.0.0.0
http.port: 9200
---------------------- Discovery ------------------------
discovery.seed_hosts: ["192.168.118.132"] #这里用主机名或者IP
cluster.initial_master_nodes: ["192.168.118.132"]
chown -R elasticsearch:elasticsearch elasticsearch
id elasticsearch
vim jvm.options
-Xms2g #分的最小内存
-Xmx2g #分的最大内存
systemctl start elasticsearch.service
netstat -lnpt
检查集群状态
# 列出节点健康状态
curl -XGET 127.0.0.1:9200/_cat/health?v
# 显示cluster状态
curl -XGET 127.0.0.1:9200/_cluster/health\?pretty
# 列出 master节点
curl -XGET 127.0.0.1:9200/_cat/master?v
# 列出节点及利用率
curl -XGET 127.0.0.1:9200/_cat/nodes?v
# 显示索引
curl localhost:9200/_cat/indices?v
安装前端
rpm -ivh kibana-7.17.16-x86_64.rpm #展示用的
cd /etc/kibana/
vim kibana.yml
server.port: 5601
server.host: "0.0.0.0"
elasticsearch.hosts: ["http://192.168.118.132:9200"] #若是有多个,可以加逗号隔开["",""]这样的
systemctl start kibana.service # 监听5601
ps -ef | grep node
http://192.168.118.132:5601/
INPUT 输入 日志来自文件
filestream 日志文件
container 容器中日志
OUTPUT
Elasticsearch
rpm -ivh filebeat-7.17.15-x86_64.rpm
cd /etc/filebeat/
vim filebeat.yml
...
enabled: true
- /var/log/message* # 添加需要收集的日志,日志有变化就会把新的日志采集上来
- /var/log/elasticsearch/*
...
output.elasticsearch:
# Array of hosts to connect to.
hosts: ["192.168.118.132:9200"]
systemctl start filebeat.service
索引 index
索引是 Elasticsearch 中用于存储和管理相关数据的逻辑容器。索引可以看作数据库中的一个表,它包含了一组具有相似结构的文档
分片 shard # 可以做高可用
分片包含索引数据的一个子集,并且其本身具有完整的功能和独立性,可以将分片近似看作“独立索引“,分片是Elasticsearch 分布式存储的基石,是底层的基本读写单元。
Harvester 收割日志
Index 索引 建议按天创建索引
2. Kubernetes 架构下如何采集日志,应用在容器中、Pod 中
应用被放到 Pod 中如何输出日志,不建议日志输出时生成为文件,建议应用日志直接输出为 stdout
以下为容器运行时真正存放日志目录:
- container log: /var/log/containers/*.log
- Pod log:/var/log/pods
使用边车容器运行日志代理 sidecar # 容器可以挂一些容器,这些容器是做辅助功能的,这种容器就叫做边车容器
从应用中直接暴露日志目录
使用节点级日志代理(建议)
cd 20-log/elk/elasticsearch/
# 添加镜像
helm repo add elastic https://helm.elastic.co
# 使用7.17.3版本
helm pull elastic/elasticsearch --version=7.17.3
helm upgrade --install els -n logging -f elasticsearch/els-values.yaml ./elasticsearch --create-namespace --namespace logging
# 部署kibana
helm search repo elastic/kibana -l
helm -n logging upgrade --install kibana -f kibana/kibana-values.yaml ./kibana
# 验证
curl 10.109.192.69:9200/_cluster/health\?pretty
# 部署filebeat
helm -n logging install filebeat -f filebeat/filebeat-values-1.yaml ./filebeat
# 可以去访问网站了
192.168.118.18:31523 # 这个端口号是随机的,记得查看svc
# 配置是在filebeat中定义的
vim filebeat-values-2.yaml
helm -n logging upgrade filebeat -f filebeat/filebeat-values-2.yaml filebeat
日志方案之Loki
Log-agent (采集器) Alloy 或 Promtail #Alloy是新出的,推荐使用这个
Log-agent 是 Loki 日志代理(agent)的重要组件。它的功能是从系统中收集每个日志,标记它,然后将其发送给 Loki。
Distributor (分发器)
Distributor 是一个无状态组件,负责处理和验证从日志代理(如 Promtail)接收的日志,并将日志分发到 ingester。
当 Distributor 收到日志时,它首先验证日志是否符合配置,例如有效标签、不是较旧的时间戳以及日志是否太长。验证完成后,Distributor 会根据一致性哈希将日志分发到每个 ingester,以确保平均分配给每个可用的 ingester。
Ingester (接收器)
Ingester 负责在其文件系统上存储和索引从 Distributor 收到的日志,并定期将日志传输到持久性存储(长期存储),如 S3。
Ingester 根据配置设置保留策略(自动日志删除时间)。
它使用时间序列数据库以一定的结构格式存储日志,这简化了高效查询和日志过期的过程。
Ruler (规则器)
Ruler 是 Loki 的监控和告警组件,其作用是记录指标并根据收到的日志数据触发告警。它不是直接衡量指标,而是将日志数据转换为指标。
Ruler 监控日志并在检测到任何问题时发出通知,并通过电子邮件或 Slack 发送通知。
Querier (查询器)
Querier 负责使用 LogQL 查询语言从存储和 ingester 中查询日志。它根据用户查询(如时间戳、标签等)过滤和聚合日志。
查询器缓存之前的查询,以防止一次又一次地查询相同的日志,它只查询一次具有相同时间戳、标签和日志消息的日志。
Query Frontend (查询前端)
Query Frontend 是一个与用户交互的无状态组件,它负责处理查询请求、执行查询以及通过 Grafana 仪表板可视化日志。
Query Frontend 将大型查询拆分为多个较小的查询,并同时运行所有查询,这可以防止大型查询在单个查询中导致内存问题,并有助于加快执行速度。
Grafana (前端展示)
Grafana 是一个开源工具,可帮助查询、可视化和监控日志。我们可以将 Loki 与 Grafana 集成,并在仪表板、图表等方式可视化日志数据。
Grafana 使用查询语言 LogQL 与 Grafana 集成,我们也可以在 Grafana 中编写 LogQL 查询来过滤和查询日志。
Log Storage (后端存储)
Loki 存储日志数据,提高查询和接收日志的效率。将日志数据压缩成块,根据时间进行组织,并为其提供标签和时间戳。然后,它以键值对格式为每个块创建一个索引,包含块时间戳和标签等。
例如,将块的索引视为一本书的索引。
Chunks 和 Index 可以存储在各种后端对象存储或文件系统中。
一旦存储了块,它就会为数据创建一个保留期,并根据保留期自动删除。
如果使用文件系统作为存储,则块和索引的默认存储路径是 /var/lib/loki/chunks 和 /var/lib/loki/index。
部署案例:
- Flog: 日志生成器,模拟应用程序产生日志。
- Alloy:日志代理,用来抓取日志并把日志发给Loki,类似 filebeat 的角色。
- Gateway: 接收请求并根据请求的URL 转发给后端应用。
- Loki read component: 运行 Query Frontend 和 Querier。
- Loki write component: 运行 Distributor 和 Ingester。
- Loki backend component: Index Gateway、Compactor 和 Ruler。
- Minio: 存储日志 index and chunks #开源的对象存储,内网部署优选
- Grafana: 展示和搜索日志
vim docker-compose.yaml
---
networks:
loki:
services:
read:
image: grafana/loki:3.5
command: "-config.file=/etc/loki/config.yaml -target=read"
ports:
- 3101:3100
- 7946
- 9095
volumes:
- ./loki-config.yaml:/etc/loki/config.yaml
depends_on:
- minio
healthcheck:
test: [ "CMD-SHELL", "wget --no-verbose --tries=1 --spider http://localhost:3100/ready || exit 1" ]
interval: 10s
timeout: 5s
retries: 5
networks: &loki-dns
loki:
aliases:
- loki
write:
image: grafana/loki:3.5
command: "-config.file=/etc/loki/config.yaml -target=write"
ports:
- 3102:3100
- 7946
- 9095
volumes:
- ./loki-config.yaml:/etc/loki/config.yaml
healthcheck:
test: [ "CMD-SHELL", "wget --no-verbose --tries=1 --spider http://localhost:3100/ready || exit 1" ]
interval: 10s
timeout: 5s
retries: 5
depends_on:
- minio
networks:
<<: *loki-dns
alloy:
image: grafana/alloy:v1.8.2
volumes:
- ./alloy-local-config.yaml:/etc/alloy/config.alloy:ro
- /var/run/docker.sock:/var/run/docker.sock
command: run --server.http.listen-addr=0.0.0.0:12345 --storage.path=/var/lib/alloy/data /etc/alloy/config.alloy
ports:
- 12345:12345
depends_on:
- gateway
networks:
- loki
minio:
image: minio/minio:RELEASE.2025-04-08T15-41-24Z
entrypoint:
- sh
- -euc
- |
mkdir -p /data/loki-data && \
mkdir -p /data/loki-ruler && \
minio server /data
environment:
- MINIO_ROOT_USER=loki
- MINIO_ROOT_PASSWORD=supersecret
- MINIO_PROMETHEUS_AUTH_TYPE=public
- MINIO_UPDATE=off
ports:
- 9000
volumes:
- ./.data/minio:/data
healthcheck:
test: [ "CMD", "curl", "-f", "http://localhost:9000/minio/health/live" ]
interval: 15s
timeout: 20s
retries: 5
networks:
- loki
grafana:
image: grafana/grafana:11.4.4
environment:
- GF_PATHS_PROVISIONING=/etc/grafana/provisioning
- GF_AUTH_ANONYMOUS_ENABLED=true
- GF_AUTH_ANONYMOUS_ORG_ROLE=Admin
depends_on:
- gateway
entrypoint:
- sh
- -euc
- |
mkdir -p /etc/grafana/provisioning/datasources
cat <<EOF > /etc/grafana/provisioning/datasources/ds.yaml
apiVersion: 1
datasources:
- name: Loki
type: loki
access: proxy
url: http://gateway:3100
jsonData:
httpHeaderName1: "X-Scope-OrgID"
secureJsonData:
httpHeaderValue1: "tenant1"
EOF
/run.sh
ports:
- "3000:3000"
healthcheck:
test: [ "CMD-SHELL", "wget --no-verbose --tries=1 --spider http://localhost:3000/api/health || exit 1" ]
interval: 10s
timeout: 5s
retries: 5
networks:
- loki
backend:
image: grafana/loki:3.5
volumes:
- ./loki-config.yaml:/etc/loki/config.yaml
ports:
- "3100"
- "7946"
command: "-config.file=/etc/loki/config.yaml -target=backend -legacy-read-mode=false"
depends_on:
- gateway
networks:
- loki
gateway:
image: nginx:1.27.5
depends_on:
- read
- write
entrypoint:
- sh
- -euc
- |
cat <<EOF > /etc/nginx/nginx.conf
user nginx;
worker_processes 5; ## Default: 1
events {
worker_connections 1000;
}
http {
resolver 127.0.0.11;
server {
listen 3100;
location = / {
return 200 'OK';
auth_basic off;
}
location = /api/prom/push {
proxy_pass http://write:3100\$$request_uri; #发给写的Loki
}
location = /api/prom/tail {
proxy_pass http://read:3100\$$request_uri; #发给读的Loki
proxy_set_header Upgrade \$$http_upgrade;
proxy_set_header Connection "upgrade";
}
location ~ /api/prom/.* {
proxy_pass http://read:3100\$$request_uri;
}
location = /loki/api/v1/push {
proxy_pass http://write:3100\$$request_uri;
}
location = /loki/api/v1/tail {
proxy_pass http://read:3100\$$request_uri;
proxy_set_header Upgrade \$$http_upgrade;
proxy_set_header Connection "upgrade";
}
location ~ /loki/api/.* {
proxy_pass http://read:3100\$$request_uri;
}
}
}
EOF
/docker-entrypoint.sh nginx -g "daemon off;"
ports:
- "3100:3100"
healthcheck:
test: ["CMD", "service", "nginx", "status"]
interval: 10s
timeout: 5s
retries: 5
networks:
- loki
flog:
image: mingrammer/flog:0.4.3
command: -f json -d 200ms -l
networks:
- loki
# 然后就可以通过ip:3000访问grafana了
侧导航栏选择Explore ——> Loki
用logQL语法查日志
例如:
查询容器 loki-flog-1 产生的所有日志 {container="loki-flog-1"}
查询包含 status 的日志行 {container="loki-flog-1"} |= `status`
查询 status=404 的日志行 {container="loki-flog-1"} | json | status=`404`
更多推荐




所有评论(0)