k8s平台部署智能化日志收集平台采集Pod业务日志

1.为什么要收集日志?

不管是在项目开发还是测试过程中,项目运行一旦出现问题日志信息就非常重要了,日志是定位问题的重要手段,就像侦探人员要根据现场留下的线索来推断案情。

2.日志级别

  1. 第一级:DEBUG: 调试信息,也是最详细的日志信息
  2. 第二级:INOF:证明事件按照预期工作
  3. 第三级:WARNING: 表明发生了一些暂时不影响运行的错误
  4. 第四级:ERROR: 这一级就是比较重要的错误了,软件的某些功能已经不能继续执行了。

3.传统物理机下部署应用采集哪些日志?

  1. 系统日志: 所有的系统应用都会在/var/log 目录下创建日志文件,系统日志主要存放系统内部程序或系统内核之类的日志信息,如btmp等

  1. 应用日志: 应用日志主要是安装的第三方应用产生的日志,如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,如下所示:

文档更新时间: 2021-11-12 20:48   作者:xtyang