- k8s平台部署智能化日志收集平台采集Pod业务日志
- 1.为什么要收集日志?
- 2.日志级别
- 3.传统物理机下部署应用采集哪些日志?
- 4.K8S集群应该采集哪些日志?
- 2.分布式搜索引擎elasticsearch深度解读
- 2.1 elasticsearch概述
- 2.2 elasticsearch特点
- 2.3 elasticearch基本概念
- 3.高效的日志收集组件fluentd原理
- 3.1 fluentd概述
- 3.2 常见的日志收集组件对比分析
- 4.数据的探索和可视化分析:kibana
- 5.EFK日志处理流程
- 6.搭建NFS作为默认sc
- 6.1 搭建NFS服务器
- 6.2 创建provisioner
- 6.3 创建storageclass
- 6.4 改变默认sc
- 7.实战: 安在k8s中安装EFK组件
- 7.1 安装Elasticsearch组件
- 7.2 安装kibana组件
- 7.3 安装fluentd组件
- 7.4 实战: 测试收集pod业务日志
k8s平台部署智能化日志收集平台采集Pod业务日志
1.为什么要收集日志?
不管是在项目开发还是测试过程中,项目运行一旦出现问题日志信息就非常重要了,日志是定位问题的重要手段,就像侦探人员要根据现场留下的线索来推断案情。
2.日志级别
- 第一级:DEBUG: 调试信息,也是最详细的日志信息
- 第二级:INOF:证明事件按照预期工作
- 第三级:WARNING: 表明发生了一些暂时不影响运行的错误
- 第四级:ERROR: 这一级就是比较重要的错误了,软件的某些功能已经不能继续执行了。
3.传统物理机下部署应用采集哪些日志?
- 系统日志: 所有的系统应用都会在/var/log 目录下创建日志文件,系统日志主要存放系统内部程序或系统内核之类的日志信息,如btmp等
- 应用日志: 应用日志主要是安装的第三方应用产生的日志,如tomcat7、apache2等
4.K8S集群应该采集哪些日志?
K8S系统的组件日志:apiserver/scheduler/crontroller-manager/etcd/kubelet/kube-proxy等
K8S集群里面部署的应用程序日志
在Kubernetes集群上运行多个服务和应用程序时,日志收集系统可以帮助你快速分类和分析由Pod生成的大量日志数据。Kubernetes中比较流行的日志收集解决方案是Elasticsearch、Fluentd和Kibana(EFK)技术栈,也是官方推荐的一种方案。
在k8s集群中应用一般有如下日志输出方式:
直接遵循docker官方建议把日志输出到标准输出或者标准错误输出
输出日志到容器内指定目录中
应用直接发送日志给日志收集系统采集日志的方案:
Filebeat(日志采集工具)+Logstach(数据处理引擎)+Elasticserch(数据存储、全文检索、分布式搜索引擎)+Kibana(展示数据、绘图、搜索)
2.分布式搜索引擎elasticsearch深度解读
2.1 elasticsearch概述
Elasticsearch是一个实时的,分布式的,可扩展的搜索引擎,它允许进行全文本和结构化搜索以及对日志进行分析。它通常用于索引和搜索大量日志数据,也可以用于搜索许多不同种类的文档。,elasticsearch具有三大功能,搜索、分析、存储数据。
Elasticsearch通常与Kibana一起部署,kibana是Elasticsearch 的功能强大的数据可视化的dashboard(仪表板)。Kibana允许你通过Web界面浏览Elasticsearch日志数据,也可自定义查询条件快速检索出elasticccsearch中的日志数据。
2.2 elasticsearch特点
1、分布式的文档存储引擎
2、分布式的搜索引擎和分析引擎
3、可以横向扩展至数百甚至数千个服务器节点,同时可以处理PB级数据。
2.3 elasticearch基本概念
1、集群(cluster):包含多个节点,每个节点属于哪个集群是通过一个配置(集群名称)来决定,节点可以分散到各个机器上。有一个主节点,通过选举产生,从外部来看es集群,在逻辑上是个整体,你与任何一个节点的通信和与整个es集群通信是等价的。
2、节点(node),集群中的一个节点,如果默认启动1个或者多个节点,那么他们自动组成一个集群。一个elasticsearch实例就是一个节点。每个节点可以有多个shard,但是primary shard和对应replica shard不能在同一个节点上。
3、document文档,es中最小的数据单元,由json串组成,里面包含多个field,每个field即是一个数据字段。
4、index索引,包含一堆具有相似结构的文档数据,一个索引默认有5个primary shard,一个primary shard 对应一个replica shard,即5个primary shard 和5个replica shard。一个完整索引可以分成多个分片分布到不同节点,分布式存储分布式搜索分片的数量只能在索引创建前指定,并且索引创建后不能更改。
5、type类型,每个索引有一个或者多个type,type是index中的一个逻辑数据分类,一个type下的document,应该都有相同field。es6时,官方就提到了es7会删除type,并且es6时已经规定每一个index只能有一个type。在es7中使用默认的_doc作为type,官方说在8.x版本会彻底移除type。
3.高效的日志收集组件fluentd原理
3.1 fluentd概述
Fluentd是一个流行的开源数据收集器,专为处理数据流设计,使用JSON作为数据格式。我们在Kubernetes集群节点上安装Fluentd,通过获取容器日志文件、过滤和转换日志数据,然后将数据传递到 Elasticsearch 集群,在该集群中对其进行索引和存储。
3.2 常见的日志收集组件对比分析
1.Logstash
Logstash是一个开源数据收集引擎,具有实时管道功能。Logstash可以动态地将来自不同数据源的数据统一起来,并将数据标准化输出到你所选择的目的地。
logstash 具有filter功能,能过滤分析日志.
优势:
Logstash主要的优点就是它的灵活性,主要因为它有很多插件,我们基本上可以在网上找到很多资源,几乎可以处理任何问题。
劣势:
Logstash 的问题是它的性能以及资源消耗(默认的堆大小是 1GB)。另一个问题是它目前不支持缓存,目前的典型替代方案是将 Redis 或 Kafka 作为中心缓冲池:2.Filebeat
Filebeat 是一个轻量级的日志传输工具,它的存在正弥补了 Logstash 的缺点:Filebeat 作为一个轻量级的日志传输工具可以将日志推送到中心Logstash。在版本5.x 中,Elasticsearch 具有解析的能力(像 Logstash 过滤器)— Ingest。这也就意味着可以将数据直接用 Filebeat 推送到 Elasticsearch,并让 Elasticsearch 既做解析的事情,又做存储的事情。
不需要使用缓冲,因为 Filebeat 也会和 Logstash 一样记住上次读取的偏移,如果需要缓冲(例如,不希望将日志服务器的文件系统填满),可以使用 Redis/Kafka,因为 Filebeat 可以与它们进行通信。
优势:
Filebeat只是一个二进制文件没有任何依赖,占用资源极少。
一般结构都是filebeat采集日志,然后发送到消息队列,redis,kafaka。然后logstash去获取,利用filter功能过滤分析,然后存储到elasticsearch中3、Fluentd
fluentd是一个针对日志的收集、处理、转发系统。通过丰富的插件系统,可以收集来自于各种系统或应用的日志,转化为用户指定的格式后,转发到用户所指定的日志存储系统之中。
fluentd 常常被拿来和Logstash比较,我们常说ELK,L就是这个agent。fluentd 是随着Docker,和es一起流行起来的agent。
fluentd 比 logstash 更省资源。
4.数据的探索和可视化分析:kibana
kibana是一个基于Web的图形界面,用于搜索、分析和可视化存储在Elasticsearch指标中的日志数据。Kibana功能众多,在“Visualize” 菜单界面可以将查询出的数据进行可视化展示,“Dev Tools” 菜单界面可以让户方便地通过浏览器直接与 Elasticsearch 进行交互,发送 RESTFUL对 Elasticsearch 数据进行增删改查。。它操作简单,基于浏览器的用户界面可以快速创建仪表板(dashboard)实时显示Elasticsearch查询动态。设置Kibana非常简单。无需编码或者额外的基础架构,几分钟内就可以完成Kibana安装并启动Elasticsearch索引监测。
5.EFK日志处理流程
fluentd 从各个节点的 Docker 容器中提取日志信息
fluentd 将日志转发到 ElasticSearch 进行索引和保存
Kibana 负责分析和可视化日志信息
6.搭建NFS作为默认sc
6.1 搭建NFS服务器
在k8s-node2/10.23.46.210 节点上安装NFS
yum install -y nfs-utils
#执行命令 vi /etc/exports,创建 exports 文件,文件内容如下:
echo "/nfs/data/ *(insecure,rw,sync,no_root_squash)" > /etc/exports
#执行以下命令,启动 nfs 服务
# 创建共享目录
mkdir -p /nfs/data
systemctl enable rpcbind
systemctl enable nfs-server
systemctl start rpcbind
systemctl start nfs-server
exportfs -r
#检查配置是否生效
[root@k8s-node2 ~]# exportfs
/nfs/data <world>
6.2 创建provisioner
字段名称 | 填入内容 | 备注 |
---|---|---|
名称 | nfs-storage | 自定义存储 |
NFS Server | 10.23.46.210 | NFS服务的IP地址 |
NFS Path | /nfs/data | NFS服务所共享的路径 |
# 先创建授权
# vi nfs-rbac.yaml
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: nfs-provisioner
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: nfs-provisioner-runner
rules:
- apiGroups: [""]
resources: ["persistentvolumes"]
verbs: ["get", "list", "watch", "create", "delete"]
- apiGroups: [""]
resources: ["persistentvolumeclaims"]
verbs: ["get", "list", "watch", "update"]
- apiGroups: ["storage.k8s.io"]
resources: ["storageclasses"]
verbs: ["get", "list", "watch"]
- apiGroups: [""]
resources: ["events"]
verbs: ["watch", "create", "update", "patch"]
- apiGroups: [""]
resources: ["services", "endpoints"]
verbs: ["get","create","list", "watch","update"]
- apiGroups: ["extensions"]
resources: ["podsecuritypolicies"]
resourceNames: ["nfs-provisioner"]
verbs: ["use"]
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: run-nfs-provisioner
subjects:
- kind: ServiceAccount
name: nfs-provisioner
namespace: default
roleRef:
kind: ClusterRole
name: nfs-provisioner-runner
apiGroup: rbac.authorization.k8s.io
---
#vi nfs-deployment.yaml;创建nfs-client的授权
kind: Deployment
apiVersion: apps/v1
metadata:
name: nfs-client-provisioner
spec:
replicas: 1
strategy:
type: Recreate
selector:
matchLabels:
app: nfs-client-provisioner
template:
metadata:
labels:
app: nfs-client-provisioner
spec:
serviceAccount: nfs-provisioner
containers:
- name: nfs-client-provisioner
image: hebye/nfs-subdir-external-provisioner:v4.0.
volumeMounts:
- name: nfs-client-root
mountPath: /persistentvolumes
env:
- name: PROVISIONER_NAME #供应者的名字
value: storage.pri/nfs #名字虽然可以随便起,以后引用要一致
- name: NFS_SERVER
value: 10.23.46.210
- name: NFS_PATH
value: /nfs/data
volumes:
- name: nfs-client-root
nfs:
server: 10.23.46.210
path: /nfs/data
##这个镜像中volume的mountPath默认为/persistentvolumes,不能修改,否则运行时会报错
[root@k8s-master1 ~]# kubectl apply -f nfs-rbac.yaml
[root@k8s-master1 ~]# kubectl apply -f nfs-deployment.yaml
[root@k8s-master1 ~]# kubectl get pods|grep nfs-client
nfs-client-provisioner-6c4d7c6989-rktdp 1/1 Running 0 119s
[root@k8s-master1 ~]#
查看日志:
[root@k8s-master1 ~]# kubectl logs -f nfs-client-provisioner-6c4d7c6989-rktdp
如有报错:unexpected error getting claim reference: selfLink was empty, can't make reference
请解决:找了找资料发现,kubernetes 1.20版本 禁用了 selfLink。
解决方法
资料连接:
https://stackoverflow.com/questions/65376314/kubernetes-nfs-provider-selflink-was-empty
https://github.com/kubernetes-sigs/nfs-subdir-external-provisioner/issues/25
当前的解决方法是编辑/opt/kubernetes/cfg/kube-apiserver.conf
添加启动参数
--feature-gates=RemoveSelfLink=false \
然后重启kube-apiserver
systemctl restart kube-apiserver
6.3 创建storageclass
#创建storageclass
# vi storageclass-nfs.yaml
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: storage-nfs
provisioner: storage.pri/nfs
reclaimPolicy: Delete
#扩展"reclaim policy"有三种方式:Retain、Recycle、Deleted。
Retain
#保护被PVC释放的PV及其上数据,并将PV状态改成"released",不将被其它PVC绑定。集群管理员手动通过如下步骤释放存储资源:
手动删除PV,但与其相关的后端存储资源如(AWS EBS, GCE PD, Azure Disk, or Cinder volume)仍然存在。
手动清空后端存储volume上的数据。
手动删除后端存储volume,或者重复使用后端volume,为其创建新的PV。
Delete
删除被PVC释放的PV及其后端存储volume。对于动态PV其"reclaim policy"继承自其"storage class",
默认是Delete。集群管理员负责将"storage class"的"reclaim policy"设置成用户期望的形式,否则需要用
户手动为创建后的动态PV编辑"reclaim policy"
Recycle
保留PV,但清空其上数据,已废弃
[root@k8s-master1 ~]# kubectl apply -f storageclass-nfs.yaml
storageclass.storage.k8s.io/storage-nfs created
[root@k8s-master1 ~]# kubectl get sc
NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION AGE
storage-nfs storage.pri/nfs Delete Immediate false 3s
[root@k8s-master1 ~]#
6.4 改变默认sc
##改变系统默认sc
[root@k8s-master1 ~]# kubectl patch storageclass storage-nfs -p '{"metadata": {"annotations":{"storageclass.kubernetes.io/is-default-class":"true"}}}'
storageclass.storage.k8s.io/storage-nfs patched
[root@k8s-master1 ~]#
[root@k8s-master1 ~]# kubectl get sc
NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION AGE
storage-nfs (default) storage.pri/nfs Delete Immediate false 3m33s
7.实战: 安在k8s中安装EFK组件
我们先来配置启动一个可扩展的 Elasticsearch 集群,然后在Kubernetes集群中创建一个Kibana应用,最后通过DaemonSet来运行Fluentd,以便它在每个Kubernetes工作节点上都可以运行一个 Pod。
软件版本:elasticsearch-7-12-1 、kibana-7-12-1、fluentd-v1-9-1。
7.1 安装Elasticsearch组件
在安装Elasticsearch集群之前,我们先创建一个名称空间,在这个名称空间下安装日志收工具elasticsearch、fluentd、kibana。我们创建一个kube-logging名称空间,将EFK组件安装到该名称空间中。
- 创建名称空间
[root@k8s-master1 efk-v2]# cat kube-logging.yaml
kind: Namespace
apiVersion: v1
metadata:
name: kube-logging
[root@k8s-master1 efk-v2]# kubectl apply -f kube-logging.yaml
namespace/kube-logging created
- 安装elasticsearch组件
#创建headless service
[root@k8s-master1 efk-v2]# cat elasticsearch_svc.yaml
kind: Service
apiVersion: v1
metadata:
name: elasticsearch
namespace: kube-logging
labels:
app: elasticsearch
spec:
selector:
app: elasticsearch
clusterIP: None
ports:
- port: 9200
name: rest
- port: 9300
name: inter-node
[root@k8s-master1 efk-v2]# kubectl apply -f elasticsearch_svc.yaml
service/elasticsearch created
[root@k8s-master1 efk-v2]# kubectl get svc -n kube-logging
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
elasticsearch ClusterIP None <none> 9200/TCP,9300/TCP 10s
[root@k8s-master1 efk-v2]#
#创建storageclass
[root@k8s-master1 efk-v2]# cat es_class.yaml
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: do-block-storage
provisioner: storage.pri/nfs
[root@k8s-master1 efk-v2]# kubectl apply -f es_class.yaml
#创建es statefulse控制器
[root@k8s-master1 efk-v2]# cat elasticsearch-statefulset.yaml
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: es-cluster
namespace: kube-logging
spec:
serviceName: elasticsearch
replicas: 3
selector:
matchLabels:
app: elasticsearch
template:
metadata:
labels:
app: elasticsearch
spec:
containers:
- name: elasticsearch
image: docker.elastic.co/elasticsearch/elasticsearch:7.12.1
imagePullPolicy: IfNotPresent
resources:
limits:
cpu: 1000m
requests:
cpu: 100m
ports:
- containerPort: 9200
name: rest
protocol: TCP
- containerPort: 9300
name: inter-node
protocol: TCP
volumeMounts:
- name: data
mountPath: /usr/share/elasticsearch/data
env:
- name: cluster.name
value: k8s-logs
- name: node.name
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: discovery.seed_hosts
value: "es-cluster-0.elasticsearch,es-cluster-1.elasticsearch,es-cluster-2.elasticsearch"
- name: cluster.initial_master_nodes
value: "es-cluster-0,es-cluster-1,es-cluster-2"
- name: ES_JAVA_OPTS
value: "-Xms512m -Xmx512m"
initContainers:
- name: fix-permissions
image: busybox
imagePullPolicy: IfNotPresent
command: ["sh", "-c", "chown -R 1000:1000 /usr/share/elasticsearch/data"]
securityContext:
privileged: true
volumeMounts:
- name: data
mountPath: /usr/share/elasticsearch/data
- name: increase-vm-max-map
image: busybox
imagePullPolicy: IfNotPresent
command: ["sysctl", "-w", "vm.max_map_count=262144"]
securityContext:
privileged: true
- name: increase-fd-ulimit
image: busybox
imagePullPolicy: IfNotPresent
command: ["sh", "-c", "ulimit -n 65536"]
securityContext:
privileged: true
volumeClaimTemplates:
- metadata:
name: data
labels:
app: elasticsearch
spec:
accessModes: [ "ReadWriteOnce" ]
storageClassName: do-block-storage
resources:
requests:
storage: 10Gi
[root@k8s-master1 efk-v2]# kubectl apply -f elasticsearch-statefulset.yaml
statefulset.apps/es-cluster created
[root@k8s-master1 efk-v2]#
[root@k8s-master1 efk-v2]# kubectl get pods -n kube-logging
NAME READY STATUS RESTARTS AGE
es-cluster-0 1/1 Running 0 15m
es-cluster-1 1/1 Running 0 15s
es-cluster-2 1/1 Running 0 10s
[root@k8s-master1 efk-v2]#
7.2 安装kibana组件
[root@k8s-master1 efk-v2]# cat kibana.yaml
apiVersion: v1
kind: Service
metadata:
name: kibana
namespace: kube-logging
labels:
app: kibana
spec:
ports:
- port: 5601
selector:
app: kibana
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: kibana
namespace: kube-logging
labels:
app: kibana
spec:
replicas: 1
selector:
matchLabels:
app: kibana
template:
metadata:
labels:
app: kibana
spec:
containers:
- name: kibana
image: docker.elastic.co/kibana/kibana:7.12.1
imagePullPolicy: IfNotPresent
resources:
limits:
cpu: 1000m
requests:
cpu: 100m
env:
- name: ELASTICSEARCH_URL
value: http://elasticsearch:9200
ports:
- containerPort: 5601
[root@k8s-master1 efk-v2]#
[root@k8s-master1 efk-v2]#
[root@k8s-master1 efk-v2]# kubectl apply -f kibana.yaml
service/kibana created
deployment.apps/kibana created
[root@k8s-master1 efk-v2]# kubectl get pods -n kube-logging
NAME READY STATUS RESTARTS AGE
es-cluster-0 1/1 Running 0 21m
es-cluster-1 1/1 Running 0 6m17s
es-cluster-2 1/1 Running 0 6m12s
kibana-dcc597cbf-qjn8j 1/1 Running 0 8s
[root@k8s-master1 efk-v2]#
上面我们定义了两个资源对象,一个 Service 和 Deployment,为了测试方便,我们将 Service 设置为了 NodePort 类型,Kibana Pod 中配置都比较简单,唯一需要注意的是我们使用 ELASTICSEARCH_URL 这个环境变量来设置Elasticsearch 集群的端点和端口,直接使用 Kubernetes DNS 即可,此端点对应服务名称为 elasticsearch,由于是一个 headless service,所以该域将解析为3个 Elasticsearch Pod 的 IP 地址列表。
修改service的type类型为NodePort
[root@k8s-master1 efk-v2]# kubectl edit svc kibana -n kube-logging
type: NodePort
保存退出:
[root@k8s-master1 efk-v2]# kubectl get svc -n kube-logging
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
elasticsearch ClusterIP None <none> 9200/TCP,9300/TCP 64m
kibana NodePort 10.0.0.217 <none> 5601:31021/TCP 115s
[root@k8s-master1 efk-v2]#
#访问kibana,如果看到如下欢迎界面证明 Kibana 已经成功部署到了Kubernetes集群之中。
在浏览器中打开http://<k8s集群任意节点IP>:31021
http://113.31.168.173:31021/
7.3 安装fluentd组件
我们使用daemonset控制器部署fluentd组件,这样可以保证集群中的每个节点都可以运行同样fluentd的pod副本,这样就可以收集k8s集群中每个节点的日志,在k8s集群中,容器应用程序的输入输出日志会重定向到node节点里的json文件中
,fluentd可以tail和过滤以及把日志转换成指定的格式发送到elasticsearch集群中。除了容器日志,fluentd也可以采集kubelet、kube-proxy、docker的日志。
[root@k8s-master1 efk-v2]# cat fluentd.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
name: fluentd
namespace: kube-logging
labels:
app: fluentd
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: fluentd
labels:
app: fluentd
rules:
- apiGroups:
- ""
resources:
- pods
- namespaces
verbs:
- get
- list
- watch
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: fluentd
roleRef:
kind: ClusterRole
name: fluentd
apiGroup: rbac.authorization.k8s.io
subjects:
- kind: ServiceAccount
name: fluentd
namespace: kube-logging
---
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: fluentd
namespace: kube-logging
labels:
app: fluentd
spec:
selector:
matchLabels:
app: fluentd
template:
metadata:
labels:
app: fluentd
spec:
serviceAccount: fluentd
serviceAccountName: fluentd
tolerations:
- key: node-role.kubernetes.io/master
effect: NoSchedule
containers:
- name: fluentd
image: fluentd:v1.9.1-debian-1.0
imagePullPolicy: IfNotPresent
env:
- name: FLUENT_ELASTICSEARCH_HOST
value: "elasticsearch.kube-logging.svc.cluster.local"
- name: FLUENT_ELASTICSEARCH_PORT
value: "9200"
- name: FLUENT_ELASTICSEARCH_SCHEME
value: "http"
- name: FLUENTD_SYSTEMD_CONF
value: disable
resources:
limits:
memory: 512Mi
requests:
cpu: 100m
memory: 200Mi
volumeMounts:
- name: varlog
mountPath: /var/log
- name: varlibdockercontainers
mountPath: /var/lib/docker/containers
readOnly: true
terminationGracePeriodSeconds: 30
volumes:
- name: varlog
hostPath:
path: /var/log
- name: varlibdockercontainers
hostPath:
path: /var/lib/docker/containers
[root@k8s-master1 efk-v2]#
[root@k8s-master1 efk-v2]# kubectl apply -f fluentd.yaml
serviceaccount/fluentd created
clusterrole.rbac.authorization.k8s.io/fluentd configured
clusterrolebinding.rbac.authorization.k8s.io/fluentd configured
daemonset.apps/fluentd created
[root@k8s-master1 efk-v2]# kubectl get pods -n kube-logging
NAME READY STATUS RESTARTS AGE
es-cluster-0 1/1 Running 0 28m
es-cluster-1 1/1 Running 0 13m
es-cluster-2 1/1 Running 0 13m
fluentd-4wdms 1/1 Running 0 7s
fluentd-m292k 1/1 Running 0 7s
fluentd-q555s 1/1 Running 0 7s
kibana-dcc597cbf-qjn8j 1/1 Running 0 7m35s
[root@k8s-master1 efk-v2]#
Fluentd 启动成功后,我们可以前往 Kibana 的 Dashboard 页面中,点击左侧的Discover,可以看到如下配置页面:
在这里可以配置我们需要的 Elasticsearch 索引,前面 Fluentd 配置文件中我们采集的日志使用的是 logstash 格式,这里只需要在文本框中输入logstash-*即可匹配到 Elasticsearch 集群中的所有日志数据,然后点击下一步,进入以下页面:
点击next step,出现如下
选择@timestamp,创建索引
点击左侧的discover,可看到如下
https://www.elastic.co/guide/en/kibana/7.12/kuery-query.html
7.4 实战: 测试收集pod业务日志
[root@k8s-master1 efk-v2]# cat pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: counter
spec:
containers:
- name: count
image: busybox
imagePullPolicy: IfNotPresent
args: [/bin/sh, -c,'i=0; while true; do echo "$i: $(date)"; i=$((i+1)); sleep 1; done']
[root@k8s-master1 efk-v2]# kubectl apply -f pod.yaml
pod/counter created
[root@k8s-master1 efk-v2]# kubectl get pods
NAME READY STATUS RESTARTS AGE
counter 1/1 Running 0 3s
nfs-client-provisioner-76ccfcb6d7-ts7z8 1/1 Running 0 36m
tomcat-deploy-66b67fcf7b-2nt5w 1/1 Running 1 10h
tomcat-deploy-66b67fcf7b-n6nzn 1/1 Running 1 10h
[root@k8s-master1 efk-v2]# kubectl logs -f counter
0: Fri Nov 12 12:47:09 UTC 2021
1: Fri Nov 12 12:47:10 UTC 2021
2: Fri Nov 12 12:47:11 UTC 2021
3: Fri Nov 12 12:47:12 UTC 2021
4: Fri Nov 12 12:47:13 UTC 2021
5: Fri Nov 12 12:47:14 UTC 2021
6: Fri Nov 12 12:47:15 UTC 2021
7: Fri Nov 12 12:47:16 UTC 2021
8: Fri Nov 12 12:47:17 UTC 2021
9: Fri Nov 12 12:47:18 UTC 2021
登录到kibana的控制面板,在discover处的搜索栏中输入kubernetes.pod_name:counter,这将过滤名为的Pod的日志数据counter,如下所示: