K8S日志收集
- Kubernetes
- 9天前
- 1690热度
- 2评论
K8S日志收集
在生产环境下,Kubernetes (K8s) 的日志收集是维护系统稳定性和排查问题的关键环节
1、 Kubernetes 系统日志
(1)API Server 日志:记录所有对 Kubernetes API 的请求与响应。关键日志位置:/var/log/kube-apiserver.log。包括认证、授权和资源变更等信息。
(2)Controller Manager 日志:管理控制器的工作状态,跟踪资源状态的自动调谐。日志位置:/var/log/kube-controller-manager.log
(3)Scheduler 日志:记录 Pod 的调度决策过程。日志位置:/var/log/kube-scheduler.log
(4)Etcd 日志::记录集群状态数据的持久化和操作。日志位置:/var/log/etcd.log
2、节点级别日志
(1)Kubelet 日志:管理节点上的容器运行状态。日志位置:/var/log/kubelet.log
(2)容器运行时日志:包括 Docker 或 containerd 等容器运行时的操作记录。日志位置:Docker: /var/log/docker.log/Containerd: /var/log/containerd.log
(3)Kube-Proxy 日志:管理网络代理规则。日志位置:/var/log/kube-proxy.log
3、应用容器日志
(1)容器的标准输出和错误日志:默认存储在节点的 /var/lib/docker/containers(或其他容器运行时的日志路径)。可以通过 kubectl logs \
(2)应用内自定义日志:由开发人员配置并输出,例如 log4j、fluentd。
4、网络日志
(1)CNI 插件日志:Calico、Flannel 或其他 CNI 插件的网络日志,用于监控网络连通性和性能问题。
(2)Ingress 和 Service 的访问日志:跟踪外部请求的流量和服务内部转发情况。
5、安全与审计日志
(1)API Server 审计日志:用于记录所有 API 操作的审计事件,方便安全合规性审查。配置:启用 audit-policy.yaml。
(2)系统安全日志:包括主机的 auth.log 或 syslog,用以监控未授权访问。
6、第三方组件日志
(1)日志收集工具的日志::如 Fluentd、Logstash、Filebeat 等收集服务的自身运行日志。
(2)监控系统日志:如 Prometheus、Grafana、ElasticSearch 的运行状态日志。
日志收集与集中管理
为了更高效管理日志,可以使用集中化日志管理工具,例如:
(1)ELK/EFK Stack:ElasticSearch + Logstash/Fluentd + Kibana
(2)Promtail + Loki + Grafana
(3)DataDog、Splunk 等 SaaS 解决方案 通过统一收集和分析日志,可以快速定位问题并优化系统性能。
ELK 和 EFK 是两种常见的日志收集和分析架构,它们的核心功能类似,但使用的组件不同。以下是它们的架构简述:
1. ELK 架构
全称:ElasticSearch + Logstash + Kibana
组件说明
-
ElasticSearch (ES)
- 一个分布式搜索和分析引擎。
- 用于存储和索引日志数据。
- 提供快速的全文搜索和复杂查询功能。
-
Logstash
- 数据收集和处理工具。
- 支持多种输入插件(如文件、TCP、Kafka)和输出插件。
- 可以在日志进入 ElasticSearch 前对数据进行解析、过滤和格式化。
-
Kibana
- 数据可视化工具。
- 提供友好的用户界面,用于查看、搜索和分析日志。
- 可创建仪表盘展示日志趋势和重要指标。
数据流:容器或应用产生日志日志。Logstash 收集日志并进行格式化处理。ElasticSearch 存储和索引日志。Kibana 提供日志可视化界面。
优点:数据处理能力强,支持复杂日志处理逻辑。插件丰富,适应多种数据源。查询和可视化功能强大。
缺点:Logstash 资源消耗较高,可能影响性能。部署和维护复杂。
2. EFK 架构
全称:ElasticSearch + Fluentd + Kibana
组件说明
-
ElasticSearch (ES)
- 功能与 ELK 架构中相同。
-
Fluentd
- 日志收集和聚合工具。
- 使用轻量化设计,资源占用低。
- 支持多种输入和输出插件,可以直接将日志发送到 ElasticSearch。
-
Kibana
- 功能与 ELK 架构中相同。
数据流:应用或系统生成日志。Fluentd 收集日志并将其发送至 ElasticSearch。ElasticSearch 存储和索引日志。Kibana 提供日志可视化界面。
优点:Fluentd 更轻量级,适合资源受限的环境。简化部署流程,配置较容易。社区活跃,插件生态丰富。
缺点:数据处理功能不如 Logstash 强大。在需要复杂日志解析时可能表现不足。
特性 | ELK | EFK |
---|---|---|
日志收集器 | Logstash | Fluentd |
资源占用 | 较高,适合高性能集群 | 较低,适合资源受限环境 |
数据处理能力 | 强大,支持复杂过滤和转换 | 较弱,适合轻量日志处理 |
易用性 | 配置复杂,部署相对困难 | 配置简单,部署更轻量 |
在实际应用中,EFK 更适合 Kubernetes 这样的容器化场景,而 ELK 则更适合需要复杂日志处理的大型传统系统。
使用EFK收集控制台日志
拉取资源,读者可以自由选择是否去除控制平面的污点,作者环境为3master+2node,内存为5Gib,2Vcpu
[root@master-01 ~]# kubectl get nodes
NAME STATUS ROLES AGE VERSION
master-01 Ready <none> 22d v1.30.6
master-02 Ready <none> 22d v1.30.6
master-03 Ready <none> 22d v1.30.6
node-01 Ready <none> 22d v1.30.6
node-02 Ready <none> 22d v1.30.6
[root@master-01 ~]# kubectl describe node | grep Taints
Taints: <none>
Taints: <none>
Taints: <none>
Taints: <none>
Taints: <none>
[root@master-01 ~]# git clone https://github.com/dotbalo/k8s.git
Cloning into 'k8s'...
remote: Enumerating objects: 1369, done.
remote: Counting objects: 100% (324/324), done.
remote: Compressing objects: 100% (218/218), done.
remote: Total 1369 (delta 128), reused 224 (delta 92), pack-reused 1045 (from 1)
Receiving objects: 100% (1369/1369), 5.42 MiB | 913.00 KiB/s, done.
Resolving deltas: 100% (568/568), done.
切换到目录下,查看需要创建的资源
[root@master-01 ~]# cd k8s/efk-7.10.2/
[root@master-01 efk-7.10.2]# ls
create-logging-namespace.yaml es-service.yaml es-statefulset.yaml filebeat fluentd-es-configmap.yaml fluentd-es-ds.yaml kafka kibana-deployment.yaml kibana-service.yaml
创建logging命名空间
[root@master-01 efk-7.10.2]# kubectl create -f create-logging-namespace.yaml
namespace/logging created
创建elasticsearch集群相关资源
[root@master-01 efk-7.10.2]# kubectl create -f es-service.yaml
service/elasticsearch-logging created
[root@master-01 efk-7.10.2]# kubectl create -f es-statefulset.yaml
serviceaccount/elasticsearch-logging created
clusterrole.rbac.authorization.k8s.io/elasticsearch-logging created
clusterrolebinding.rbac.authorization.k8s.io/elasticsearch-logging created
statefulset.apps/elasticsearch-logging created
创建kibana相关资源
[root@master-01 efk-7.10.2]# kubectl create -f kibana-deployment.yaml -f kibana-service.yaml
deployment.apps/kibana-logging created
service/kibana-logging created
创建fluentd相关资源,通过label控制fluentd采集日志的节点,在需要采集日志的节点上添加fluentd=true的标签
[root@master-01 efk-7.10.2]# grep 'nodeSelector' -A 1 fluentd-es-ds.yaml
nodeSelector:
fluentd: "true"
[root@master-01 efk-7.10.2]# kubectl label nodes node-01 fluentd=true
node/node-01 labeled
[root@master-01 efk-7.10.2]# kubectl create -f fluentd-es-ds.yaml -f fluentd-es-configmap.yaml
serviceaccount/fluentd-es created
clusterrole.rbac.authorization.k8s.io/fluentd-es created
clusterrolebinding.rbac.authorization.k8s.io/fluentd-es created
daemonset.apps/fluentd-es-v3.1.1 created
configmap/fluentd-es-config-v0.2.1 created
等待镜像拉取,资源初始化完成后,查看容器状态
[root@master-01 efk-7.10.2]# kubectl get pods -n logging
NAME READY STATUS RESTARTS AGE
elasticsearch-logging-0 1/1 Running 0 32h
fluentd-es-v3.1.1-8r2tl 1/1 Running 0 32h
kibana-logging-55bccd5698-4fhqv 1/1 Running 0 32h
附带Fluentd ConfigMap内配置的解析,供读者参考
system.conf: |-
<system>
root_dir /tmp/fluentd-buffers/
</system>
containers.input.conf: |-
<source>
@id fluentd-containers.log
@type tail
path /var/log/containers/*.log
pos_file /var/log/es-containers.log.pos
tag raw.kubernetes.*
read_from_head true
<parse>
@type multi_format
<pattern>
format json
time_key time
time_format %Y-%m-%dT%H:%M:%S.%NZ
</pattern>
<pattern>
format /^(?<time>.+) (?<stream>stdout|stderr) [^ ]* (?<log>.*)$/
time_format %Y-%m-%dT%H:%M:%S.%N%:z
</pattern>
</parse>
</source>
字段 | 含义 |
---|---|
@id | 表示引用该日志源的唯一标识符,该标识可用于进一步过滤和路由结构化日志数据 |
@type | Fluentd 内置的指令,tail 表示 Fluentd 从上次读取的位置通过 tail 不断获取数据,另外一个是 http 表示通过一个 GET 请求来收集数据 |
path | tail 类型下的特定参数,告诉 Fluentd 采集 /var/log/containers 目录下的所有日志,这是 docker 在 Kubernetes 节点上用来存储运行容器 stdout 输出日志数据的目录 |
pos_file | 检查点,用于记录读取日志文件的偏移量(offset),如果 Fluentd 程序重新启动了,它将使用此文件中的位置来恢复日志数据收集 |
tag | 用来将日志源与目标或者过滤器匹配的自定义字符串,Fluentd 匹配源/目标标签来路由日志数据 |
read_from_head | 从日志文件的开头开始读取(而不是文件尾部),适用于首次运行时需要完整读取日志的场景 |
format | 指定为json格式,或者使用正则表达式解析日志。 |
time_key | 指定时间字段的键名为 time |
time_format | 定义时间的格式,如:2024-11-20T15:45:30.123Z |
(?<time>.+):提取时间字段。
(?<stream>stdout|stderr):提取日志流类型(标准输出或标准错误)。
[^ ]*:跳过无用字段。
(?<log>.*):提取日志消息。
路由配置,将日志数据发送到Elasticsearch
<match **>
@id elasticsearch
@type elasticsearch
@log_level info
type_name _doc
include_tag_key true
host elasticsearch-logging
port 9200
logstash_format true
<buffer>
@type file
path /var/log/fluentd-buffers/kubernetes.system.buffer
flush_mode interval
retry_type exponential_backoff
flush_thread_count 2
flush_interval 5s
retry_forever
retry_max_interval 30
chunk_limit_size 2M
total_limit_size 500M
overflow_action block
</buffer>
</match>
字段 | 含义 |
---|---|
\<match **> | 标识一个目标标签,后面是一个匹配日志源的正则表达式,我们这里想要捕获所有的日志并将它们发送给 Elasticsearch,所以需要配置成** |
@id | 目标的一个唯一标识符 |
@type | 支持的输出插件标识符,我们这里要输出到 Elasticsearch,所以配置成 elasticsearch,这是 Fluentd 的一个内置插件 |
@log_level | 指定要捕获的日志级别,我们这里配置成 info,表示任何该级别或者该级别以上(INFO、WARNING、ERROR)的日志都将被路由到 Elsasticsearch |
type_name | 定义 Elasticsearch 索引的文档类型 |
include_tag_key | 将 Fluentd 的标签(tag)包含到日志记录中 |
host/port | 定义 Elasticsearch 的地址,也可以配置认证信息,我们的 Elasticsearch 不需要认证,所以这里直接指定 host 和 port 即可 |
logstash_format | Elasticsearch 服务对日志数据构建反向索引进行搜索,将 logstash_format 设置为 true,Fluentd 将会以 logstash 格式来转发结构化的日志数据 |
\ |
Fluentd 允许在目标不可用时进行缓存,比如,如果网络出现故障或者 Elasticsearch 不可用的时候。缓冲区配置也有助于降低磁盘的 IO |
@type | 缓冲类型设置为文件缓存,日志会临时存储在磁盘中,避免因网络问题导致数据丢失 |
path | 缓冲文件存储路径 |
flush_mode | 设置缓冲区的刷新模式为定期刷新 |
retry_type | 定义重试机制为指数退避(exponential backoff),逐步增加重试间隔时间 |
flush_thread_count | 设置 2 个线程用于处理缓冲区刷新的任务 |
flush_interval | 每隔 5 秒刷新一次缓冲区数据到 Elasticsearch |
retry_forever | 设置重试机制为永不放弃,直到成功写入 Elasticsearch |
retry_max_interval | 最大重试间隔 |
chunk_limit_size | 缓冲区块的最大大小为 2MB |
total_limit_size | 最大缓冲区大小为500MB,超过此限制,将触发溢出策略 |
overflow_action | 溢出策略为block,暂停写入缓冲区 |
过滤和拼接规则
<filter **>
@id filter_concat
@type concat
key message
multiline_end_regexp /\n$/
separator ""
</filter>
# Fixes json fields in Elasticsearch
<filter kubernetes.**>
@id filter_parser
@type parser
key_name log
reserve_data true
remove_key_name_field true
<parse>
@type multi_format
<pattern>
format json
</pattern>
<pattern>
format none
</pattern>
</parse>
</filter>
参数 | 含义 |
---|---|
\<filter **> | 匹配所有日志(** 表示通配符,匹配所有标签) |
multiline_end_regexp | 匹配多行日志的结束标志,这里是以换行符 \n 结束 |
separator | 拼接时不添加任何分隔符 |
reserve_data | 保留原始日志数据,不覆盖其他字段 |
remove_key_name_field | 解析成功后移除原始的 log 字段,避免冗余 |
当所有容器处于Running状态,Ready状态为1/1时(视情况而定),可以通过kibana暴露的nodeport端口进行访问,访问的方式为https://$(配置了kube-proxy的节点IP):$(NodePort暴露端口)/kibana
[root@master-01 efk-7.10.2]# kubectl get svc -n logging
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
elasticsearch-logging ClusterIP None <none> 9200/TCP,9300/TCP 23h
kibana-logging NodePort 10.96.115.179 <none> 5601:32251/TCP 23h
[root@master-01 efk-7.10.2]# curl http://192.168.132.236:32251/kibana
访问成功后,依次单击Explore on my own→Visualize→Add your data→Create index pattern。在弹出的界面添加索引logstash*,随后点击Next step按钮。
继续填写时间字段,填写完成后依次单击左侧菜单栏→Discover按钮即可观察到采集的数据
使用Filebeat收集自定义文件日志
使用Fluentd无法采集容器内部的日志,可以通过Filebeat和emptyDir的方式采集容器内部的日志数据,从而输出到Kibana实现可视化
创建zookeeper和kafka容器
[root@master-01 ~]# cd k8s/efk-7.10.2/filebeat/
[root@master-01 filebeat]# helm install zookeeper zookeeper/ -n logging
NAME: zookeeper
LAST DEPLOYED: Thu Nov 21 08:46:32 2024
NAMESPACE: logging
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
** Please be patient while the chart is being deployed **
ZooKeeper can be accessed via port 2181 on the following DNS name from within your cluster:
zookeeper.logging.svc.cluster.local
To connect to your ZooKeeper server run the following commands:
export POD_NAME=$(kubectl get pods --namespace logging -l "app.kubernetes.io/name=zookeeper,app.kubernetes.io/instance=zookeeper,app.kubernetes.io/component=zookeeper" -o jsonpath="{.items[0].metadata.name}")
kubectl exec -it $POD_NAME -- zkCli.sh
To connect to your ZooKeeper server from outside the cluster execute the following commands:
kubectl port-forward --namespace logging svc/zookeeper 2181:2181 &
zkCli.sh 127.0.0.1:2181
[root@master-01 filebeat]# helm install kafka kafka/ -n logging
NAME: kafka
LAST DEPLOYED: Thu Nov 21 09:18:14 2024
NAMESPACE: logging
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
** Please be patient while the chart is being deployed **
Kafka can be accessed by consumers via port 9092 on the following DNS name from within your cluster:
kafka.logging.svc.cluster.local
Each Kafka broker can be accessed by producers via port 9092 on the following DNS name(s) from within your cluster:
kafka-0.kafka-headless.logging.svc.cluster.local:9092
To create a pod that you can use as a Kafka client run the following commands:
kubectl run kafka-client --restart='Never' --image docker.io/bitnami/kafka:2.8.0-debian-10-r30 --namespace logging --command -- sleep infinity
kubectl exec --tty -i kafka-client --namespace logging -- bash
PRODUCER:
kafka-console-producer.sh \
--broker-list kafka-0.kafka-headless.logging.svc.cluster.local:9092 \
--topic test
CONSUMER:
kafka-console-consumer.sh \
--bootstrap-server kafka.logging.svc.cluster.local:9092 \
--topic test \
--from-beginning
等待容器成功运行
[root@master-01 filebeat]# kubectl get pods -n logging
NAME READY STATUS RESTARTS AGE
elasticsearch-logging-0 1/1 Running 0 6h40m
elasticsearch-logging-1 1/1 Running 1 (6h38m ago) 6h39m
elasticsearch-logging-2 1/1 Running 0 6h37m
fluentd-es-v3.1.1-wgqhc 1/1 Running 1 (6h39m ago) 6h40m
kafka-0 1/1 Running 0 5h20m
kibana-logging-55bccd5698-9wh2g 1/1 Running 0 6h39m
zookeeper-0 1/1 Running 0 5h26m
注意:在上一个章节的代理不太稳定,因为作者更换了一种更为有效的方法,使用clash verge(clash for windows)也可以,前提需要能科学上网。单击左侧导航的设置按钮,打开Tun模式、服务模式、系统代理、局域网连接,单击端口设置,记录下Http(s)代理端口。
在需要使用代理的虚拟机上,写入以下配置,并刷新配置文件。虚拟机就可以直接拉取docker.io开头的镜像了
[root@master-01 filebeat]# vim /etc/profile
export https_proxy="http://192.168.132.1:7899"
export no_proxy='192.168.132.169,192.168.132.236,127.0.0.1,localhost'
[root@master-01 filebeat]# source /etc/profile
创建Logstash服务
[root@master-01 filebeat]# kubectl create -f logstash.yaml -f logstash-cm.yaml -f logstash-service.yaml -n logging
deployment.apps/logstash-deployment created
configmap/logstash-configmap created
service/logstash-service created
针对Logstash配置文件进行解析
logstash.conf: |
# all input will come from filebeat, no local logs
input {
kafka {
enable_auto_commit => true
auto_commit_interval_ms => "1000"
bootstrap_servers => "kafka:9092"
topics => ["filebeat-sidecar"]
type => ["filebeat-sidecar"]
codec => json
}
}
output {
stdout{ codec=>rubydebug}
if [type] == "filebeat-sidecar"{
elasticsearch {
hosts => ["elasticsearch-logging-0.elasticsearch-logging:9200","elasticsearch-logging-1.elasticsearch-logging:9200"]
index => "filebeat-%{+YYYY.MM.dd}"
}
} else{
elasticsearch {
hosts => ["elasticsearch-logging-0.elasticsearch-logging:9200","elasticsearch-logging-1.elasticsearch-logging:9200"]
index => "other-input-%{+YYYY.MM.dd}"
}
}
}
字段 | 含义 |
---|---|
input | 数据来源,本次示例配置的是 Kakfa |
enable_auto_commit | 启用自动提交偏移量,确保 Kafka 的消费者组可以记录消费的进度 |
auto_commit_interval_ms | 偏移量提交的时间间隔,设置为 1000ms |
bootstrap_servers | Kafka 地址,由于是安装在集群内部的,可以直接使用Kafka 集群的 Service 接口,如果是外部地址,按需配置即可 |
topics | Kafka 的 topic,需要和 Filebeat 输出的 topic 一致 |
type | 定义一个 type,可以用于 logstash 输出至不同的 Elasticsearch 集群 |
codec | 指定解码器,将 Kafka 消息解析为 JSON 格式 |
output | 数据输出至哪里,本次示例输出至 Elasticsearch 集群,在里面配置了一个判断语句,当 type 为 filebeat-sidecar 时,将会输出至 Elasticsearch 集群,并且 index 为 filebeat-xxx |
注入Filebeat Sidecar。写入配置文件,其中Pod内包含两个Containerd,第一个Containerd名称为app,容器内部带有一个死循环,会不断打印当前时间并写入到/opt/date.log文件内(此时如果不配置Filebeat,Kibana无法读取app容器内部的日志信息,模拟一些传统的日志文件类型)。第二个Containerd名称为filebeat,通过挂载emptyDir来共享app容器内的日志文件,从而进行采集。
[root@master-01 filebeat]# cat app-filebeat.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: app
labels:
app: app
env: release
spec:
selector:
matchLabels:
app: app
replicas: 1
strategy:
...省略部分输出...
template:
metadata:
labels:
app: app
spec:
containers:
- name: filebeat
image: registry.cn-beijing.aliyuncs.com/dotbalo/filebeat:7.10.2
resources:
requests:
....省略部分输出..
imagePullPolicy: IfNotPresent
env:
- name: podIp
valueFrom:
fieldRef:
apiVersion: v1
fieldPath: status.podIP
- name: podName
valueFrom:
fieldRef:
apiVersion: v1
fieldPath: metadata.name
- name: podNamespace
valueFrom:
fieldRef:
apiVersion: v1
fieldPath: metadata.namespace
- name: podDeployName
value: app
- name: TZ
value: "Asia/Shanghai"
securityContext:
runAsUser: 0
volumeMounts:
- name: logpath
mountPath: /data/log/app/
- name: filebeatconf
mountPath: /usr/share/filebeat/filebeat.yml
subPath: usr/share/filebeat/filebeat.yml
- name: app
image: registry.cn-beijing.aliyuncs.com/dotbalo/alpine:3.6
imagePullPolicy: IfNotPresent
volumeMounts:
- name: logpath
mountPath: /opt/
env:
- name: TZ
value: "Asia/Shanghai"
- name: LANG
value: C.UTF-8
- name: LC_ALL
value: C.UTF-8
command:
- sh
- -c
- while true; do date >> /opt/date.log; sleep 2; done
volumes:
- name: logpath
emptyDir: {}
- name: filebeatconf
configMap:
name: filebeatconf
items:
- key: filebeat.yml
path: usr/share/filebeat/filebeat.yml
Filebeat的配置文件定义了采集的日志路径并且使用fields字段为日志添加自定义字段,并将内容输出(output.kafka)到kafka进行处理
[root@master-01 filebeat]# vim filebeat-cm.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: filebeatconf
data:
filebeat.yml: |-
filebeat.inputs:
- input_type: log
paths:
- /data/log/*/*.log
tail_files: true
fields:
pod_name: '${podName}'
pod_ip: '${podIp}'
pod_deploy_name: '${podDeployName}'
pod_namespace: '${podNamespace}'
output.kafka:
hosts: ["kafka:9092"]
topic: "filebeat-sidecar"
codec.json:
pretty: false
keep_alive: 30s
创建资源,查看容器创建状态
[root@master-01 filebeat]# kubectl create -f app-filebeat.yaml -f filebeat-cm.yaml -n logging
deployment.apps/app created
configmap/filebeatconf created
[root@master-01 filebeat]# kubectl get pods -n logging
NAME READY STATUS RESTARTS AGE
app-5bc7495dd6-pnvlb 2/2 Running 0 6h14m
elasticsearch-logging-0 1/1 Running 0 7h56m
elasticsearch-logging-1 1/1 Running 1 (7h54m ago) 7h55m
elasticsearch-logging-2 1/1 Running 0 7h53m
fluentd-es-v3.1.1-wgqhc 1/1 Running 1 (7h54m ago) 7h55m
kafka-0 1/1 Running 0 6h36m
kibana-logging-55bccd5698-9wh2g 1/1 Running 0 7h55m
logstash-deployment-5f5bdf7bf7-xdhz6 1/1 Running 0 6h32m
zookeeper-0 1/1 Running 0 6h41m
查看容器内部是否有日志输出
[root@master-01 filebeat]# kubectl exec -it -n logging app-5bc7495dd6-pnvlb -c app -- tail -10 /opt/date.log
Thu Nov 21 07:55:01 UTC 2024
Thu Nov 21 07:55:03 UTC 2024
Thu Nov 21 07:55:05 UTC 2024
Thu Nov 21 07:55:07 UTC 2024
Thu Nov 21 07:55:10 UTC 2024
Thu Nov 21 07:55:12 UTC 2024
Thu Nov 21 07:55:14 UTC 2024
Thu Nov 21 07:55:16 UTC 2024
Thu Nov 21 07:55:18 UTC 2024
Thu Nov 21 07:55:20 UTC 2024
打开Kibana的U界面,依次单击左侧导航栏的三条杠→Stack Management→Index Patterns→Createindex pattern,只有在Create index pattern界面下方看到filebeat-2024.xx.xx的索引字段才能认为日志采集成功,如果没有SVC看到该字段,需要读者检查filebeat和app容器的连通性,能否共享日志文件,filebeat输出到kafka的端口和名称是否正常,各个服务的SVC端点是否正常,elasticsearch和kafka服务是否正常。
在Index pattern name的文本框内填写filebeat*,随后单击Next Step按钮
选择时间标签后,单击Create index pattern按钮创建索引
创建完成后,即可在Discover界面看到app容器的日志信息切片,读者也可以学习KQL语法对真正生产环境下的复杂信息进行筛选
Loki架构简述
Loki 是一个轻量级的日志聚合系统,专注于 元数据索引,并与 Prometheus 和 Grafana 紧密集成。以下是 Loki 的主要架构组件:
-
Client (Promtail/Fluentd/Filebeat):
- Promtail 是 Loki 的官方日志收集工具,类似于 Filebeat。
- 它从日志文件或容器日志中收集日志,添加 Kubernetes 等元数据,并推送到 Loki。
-
Loki 服务: Loki 的核心架构包含以下组件:
- Distributor: 接收日志数据,并将其分片后分发到多个 Ingester。
- Ingester: 临时存储日志数据并将其持久化到对象存储(如 S3 或 GCS)或块存储(如 Cassandra)。
- Querier: 根据查询请求从存储和 Ingesters 中检索数据。
- Storage: 使用云对象存储(S3、GCS)、块存储(Cassandra、Bigtable)或文件系统存储日志。
-
Query & Visualization (Grafana):
- Grafana 提供查询和展示 Loki 数据的功能,通过 LogQL(类似 PromQL)查询日志。
Loki 与 EFK/ELK 的区别
- Loki:专注于日志的轻量存储,仅索引元数据(如日志流的标签),而不对日志内容全文索引。
- EFK/ELK:适用于大规模日志的复杂查询和全文索引场景。
日志索引机制
-
Loki:
- 仅索引日志流的标签(如 Kubernetes 的
pod_name
、namespace
等)。 - 日志内容以原始形式存储,查询时按需读取。
- 索引简单,占用存储小,性能较高,但不支持复杂的全文搜索。
- 仅索引日志流的标签(如 Kubernetes 的
-
EFK/ELK:
- 使用 Elasticsearch 对日志内容进行全文索引。
- 提供强大的查询功能(如模糊查询、正则匹配)。
- 适合需要复杂分析和搜索的场景,但索引开销大,存储和计算资源占用较多。
存储和扩展性
-
Loki:
- 依赖对象存储(如 S3)、块存储(如 Cassandra),支持高效存储。
- 天然支持云原生架构,易于水平扩展。
-
EFK/ELK:
- Elasticsearch 存储索引和日志,存储资源需求大,扩展时需要更多计算和内存资源。
性能和资源占用
-
Loki:
- 不需要建立复杂的索引,资源占用低。
- 更适合云原生环境和 Kubernetes 的日志管理。
-
EFK/ELK:
- 性能依赖 Elasticsearch 的集群配置,硬件需求较高。
- 在存储海量日志时可能会遇到性能瓶颈。
查询语言
- Loki:使用 LogQL 查询语言,类似于 Prometheus 的 PromQL,支持简单的过滤和聚合。
- EFK/ELK:Elasticsearch 提供了丰富的 DSL 查询语法,支持复杂的搜索和统计分析。
可视化工具
- Loki:与 Grafana 原生集成,通过 Grafana 提供强大的日志和指标联动查询。
- EFK/ELK:通常使用 Kibana,适合复杂的日志分析和多维度数据展示。
部署和管理
- Loki:
- 部署简单,组件较少。
- 轻量级,适合资源有限的环境。
- EFK/ELK:
- 部署较复杂,特别是在集群和分布式存储配置方面。
- 需要更多运维经验和资源。
Loki 和 EFK/ELK 的选择场景
-
使用 Loki 的场景:
- 云原生环境(如 Kubernetes)下的日志管理。
- 需要与 Prometheus 集成,通过指标联动查询日志。
- 对日志查询的需求简单,不需要全文索引和复杂分析。
- 资源有限的环境,需要低成本的日志解决方案。
-
使用 EFK/ELK 的场景:
- 需要对日志内容进行全文检索。
- 需要复杂的日志分析(如模糊搜索、统计、关联分析)。
- 有足够的硬件资源支持高性能 Elasticsearch 集群。
总结:
- Loki 以轻量化为优势,适用于日志内容检索需求较低的场景,资源占用小,部署简单。
- EFK/ELK 更强大,但资源需求大,适用于需要全文搜索和复杂日志分析的场景。
添加loki仓库,随后安装loki
[root@master-01 ~]# helm repo add grafana https://grafana.github.io/helm-charts
"grafana" has been added to your repositories
[root@master-01 ~]# helm install loki grafana/loki-stack --set grafana.enabled=true --set grafana.service.type=NodePort -n loki
NAME: loki
LAST DEPLOYED: Thu Nov 21 18:11:17 2024
NAMESPACE: 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.
等待一段时间,等待容器全部创建完成,并且处于就绪状态
[root@master-01 ~]# kubectl get pods -n loki
NAME READY STATUS RESTARTS AGE
loki-0 1/1 Running 0 13m
loki-grafana-7fb8487767-npqzg 2/2 Running 0 13m
loki-promtail-grtzb 1/1 Running 0 13m
loki-promtail-gt7xm 1/1 Running 0 13m
loki-promtail-mh9mg 1/1 Running 0 13m
loki-promtail-q9h5v 1/1 Running 0 13m
loki-promtail-tsnkg 1/1 Running 0 13m
查看Grafana服务暴露的端口
[root@master-01 ~]# kubectl get svc -n loki
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
loki ClusterIP 10.96.165.233 <none> 3100/TCP 30s
loki-grafana NodePort 10.96.112.167 <none> 80:32174/TCP 30s
loki-headless ClusterIP None <none> 3100/TCP 30s
loki-memberlist ClusterIP None <none> 7946/TCP 30s
解密存放在Secrets内的Grafana密码
[root@master-01 ~]# kubectl get secrets -n loki loki-grafana -oyaml
apiVersion: v1
data:
admin-password: bUFDRjBtWDYwbFBlSTdlTVIyTVlLNXdrRmdkaWp0azNXVk54MmxWSQ==
admin-user: YWRtaW4=
ldap-toml: ""
kind: Secret
metadata:
annotations:
meta.helm.sh/release-name: loki
meta.helm.sh/release-namespace: loki
creationTimestamp: "2024-11-21T10:11:21Z"
labels:
app.kubernetes.io/instance: loki
app.kubernetes.io/managed-by: Helm
app.kubernetes.io/name: grafana
app.kubernetes.io/version: 10.3.3
helm.sh/chart: grafana-6.43.5
name: loki-grafana
namespace: loki
resourceVersion: "2091857"
uid: 347d8d16-0551-4347-891d-a400d6f9584e
type: Opaque
[root@master-01 ~]# echo 'bUFDRjBtWDYwbFBlSTdlTVIyTVlLNXdrRmdkaWp0azNXVk54MmxWSQ==' | base64 --decode
通过IP+SVC暴露的端口访问Grafana,依次单击左侧导航栏的三道杠→Explore,选择Loki
读者可以通过图形化界面进行简单条件过滤,也可以通过类似正则表达式的语法进行筛选,此处附上官网链接,不在此处过多介绍
https://grafana.com/docs/loki/latest/query/
踩踩
dalao,创建zookeeper和kafka容器
helm install kafka kafka/ -n logging
helm install zookeeper zookeeper/ -n logging
[root@master-01 filebeat]# kubectl get pods -n logging
NAME READY STATUS RESTARTS AGE
elasticsearch-logging-0 1/1 Running 1 (26m ago) 27m
fluentd-es-v3.1.1-gz6ph 1/1 Running 1 (24m ago) 25m
fluentd-es-v3.1.1-wv9vd 1/1 Running 1 (24m ago) 25m
kafka-0 0/1 ImagePullBackOff 0 2m12s
kibana-logging-55bccd5698-m825w 1/1 Running 3 (24m ago) 26m
zookeeper-0 0/1 ImagePullBackOff 0 2m26s
镜像寄了=_=