附047.集群管理-EFK日志解决方案-Fluentd

统一日志管理

日志管理

在Kubernetes集群环境中,一个完整的应用或服务都会涉及为数众多的组件运行,各组件所在的Node及实例数量都是可变的。日志子系统如果不做集中化管理,则会给系统的运维支撑造成很大的困难,因此建议在集群层面对日志进行统一收集和检索等工作。
在容器中输出到控制台的日志,都会以*-json.log的命名方式保存在/var/lib/docker/containers/目录下。
Kubernetes推荐采用Fluentd+Elasticsearch+Kibana完成对系统和容器日志的采集、查询和展现工作。
部署统一的日志管理系统,需要以下两个前提条件。

  • API Server正确配置了CA证书。
  • DNS服务启动、运行。

EFK简介

Kubernetes 配套一个 Elasticsearch 附加组件来实现集群的日志管理。这是一个 Elasticsearch、Fluentd或Filebeat 和 Kibana 的组合。

  • Elasticsearch 是一个搜索引擎,负责存储日志并提供查询接口;
  • Fluentd/Filebeat 负责从 Kubernetes 搜集日志,每个node节点上面的fluentd监控并收集该节点上面的系统日志,并将处理过后的日志信息发送给Elasticsearch;
  • Kibana 提供了一个 Web GUI,用户可以浏览和搜索存储在 Elasticsearch 中的日志。
    通过在每台node上部署一个以DaemonSet方式运行的fluentd来收集每台node上的日志。Fluentd将docker日志目录/var/lib/docker/containers和/var/log目录挂载到Pod中,然后Pod会在node节点的/var/log/pods目录中创建新的目录,可以区别不同的容器日志输出,该目录下有一个日志文件链接到/var/lib/docker/contianers目录下的容器日志输出。

001

即相对应的三个组件整个流程大体如下:

002

在各Node上都运行了一个Fluentd/Filebeat容器,采集本节点/var/log和/var/lib/docker/containers两个目录下的日志进程,将其汇总到Elasticsearch集群,最终通过Kibana完成和用户的交互工作。因此Fluentd必须在每个Node上运行。为了满足这一需求,可通过以下几种方式部署Fluentd/Filebeat。

  • 直接在Node主机上部署Fluentd/Filebeat。
  • 利用kubelet的–config参数, 为每个Node都加载Fluentd/Filebeat Pod。
  • 利用DaemonSet让Fluentd/Filebeat Pod在每个Node上运行。

003

架构设计

节点IP角色组件
master01172.24.8.11Kubernetes master控制平面Kibana、Fluentd
master02172.24.8.12Kubernetes master控制平面Kibana、Fluentd
master03172.24.8.13Kubernetes master控制平面Kibana、Fluentd
worker01172.24.8.14Kubernetes master控制平面elasticsearch、Fluentd
worker02172.24.8.15Kubernetes master控制平面elasticsearch、Fluentd
worker03172.24.8.16Kubernetes master控制平面elasticsearch、Fluentd

elasticsearch:部署在worker节点(172.24.8.14-16),worker节点为业务节点
部署方式:StatefulSet(ES) + Deployment(Kibana)
Fluentd/Filebeat:部署在所有节点(包括master和worker),需要收集每个节点的容器日志
部署方式:DaemonSet(每个节点一个Pod)
Kibana:部署在master节点(172.24.8.11-13),只暴露服务,Elasticsearch不直接暴露。

提示:本环境基于学习目的,把Elasticsearch也暴露。

EFK部署

设置标签

针对需要部署的节点,进行打标签,从而实现定向调度。

[root@master01 ~]# kubectl label nodes worker0{1,2,3} elasticsearch=enable
[root@master01 ~]# kubectl label nodes master0{1,2,3} kibana=enable

获取EFK chart包

[root@master01 ~]# helm repo add elastic https://helm.elastic.co
[root@master01 ~]# helm repo update

[root@master01 ~]# helm search repo elastic/
NAME                            CHART VERSION   APP VERSION     DESCRIPTION                                       
elastic/apm-attacher            1.1.3                           A Helm chart installing the Elastic APM Kuberne...
elastic/apm-server              8.5.1           8.5.1           Official Elastic helm chart for Elastic APM Server
elastic/eck-agent               0.15.0                          Elastic Agent managed by the ECK operator         
elastic/eck-apm-server          0.15.0                          Elastic APM Server managed by the ECK operator    
elastic/eck-beats               0.15.0                          Elastic Beats managed by the ECK operator         
elastic/eck-elasticsearch       0.15.0                          Elasticsearch managed by the ECK operator         
elastic/eck-enterprise-search   0.15.0                          Elastic Enterprise Search managed by the ECK op...
elastic/eck-fleet-server        0.15.0                          Elastic Fleet Server as an Agent managed by the...
elastic/eck-kibana              0.15.0                          Kibana managed by the ECK operator                
elastic/eck-logstash            0.15.0                          Logstash managed by the ECK operator              
elastic/eck-operator            3.0.0           3.0.0           Elastic Cloud on Kubernetes (ECK) operator        
elastic/eck-operator-crds       3.0.0           3.0.0           ECK operator Custom Resource Definitions          
elastic/eck-stack               0.15.0                          Elastic Stack managed by the ECK Operator         
elastic/elastic-agent           9.0.3           9.0.3           Elastic-Agent Helm Chart                          
elastic/elasticsearch           8.5.1           8.5.1           Official Elastic helm chart for Elasticsearch     
elastic/filebeat                8.5.1           8.5.1           Official Elastic helm chart for Filebeat          
elastic/kibana                  8.5.1           8.5.1           Official Elastic helm chart for Kibana            
elastic/kube-state-metrics      5.30.1          2.15.0          Install kube-state-metrics to generate and expo...
elastic/logstash                8.5.1           8.5.1           Official Elastic helm chart for Logstash          
elastic/metricbeat              8.5.1           8.5.1           Official Elastic helm chart for Metricbeat        
elastic/pf-host-agent           8.14.3          8.14.3          Hyperscaler software efficiency. For everybody.   
elastic/profiling-agent         9.0.3           9.0.3           Hyperscaler software efficiency. For everybody.   
elastic/profiling-collector     9.0.3           9.0.3           Universal Profiling. Hyperscaler software effic...
elastic/profiling-symbolizer    9.0.3           9.0.3           Universal Profiling. Hyperscaler software effic...

提示:Elasticsearch Helm Chart

创建证书

默认 elasticsearch 没有开启ingress,本环境已部署ingress,因此规划启用ingress来基于https暴露服务。
同时相关证书使用自签名创建证书,同时使用对应证书创建secret。

  • 脚本快速自签名基于实验目的,采用自签名证书。

[root@master01 ~]# mkdir elasticsearch

[root@master01 ~]# cd elasticsearch/
[root@master01 elasticsearch]# wget http://down.linuxsb.com/myshell/signcert.sh

[root@master01 elasticsearch]# vim signcert.sh
#!/bin/sh
#***************************************************************#
# ScriptName: signcert.sh
# Author: xhy
# Create Date: 2025-02-25 21:49
# Modify Author: xhy
# Modify Date: 2025-04-27 19:11
# Version: v1
#***************************************************************#
# 配置参数
#PARENT_DOMAIN="linuxsb.com"          # 父级域名
#SUB_DOMAINS=("aaa" "bbb" "ccc")      # 子域名列表,可选配置

PARENT_DOMAIN="linuxsb.com"
SUB_DOMAINS=("es" "fluentd" "kibana")
#……                                     #其他保持默认

[root@master01 dashboard]# bash signcert.sh

[root@master01 dashboard]# ll certs/
total 24K
-rw-r--r-- 1 root root 2.4K Jul 19 20:50 fullchain.crt
-rw-r--r-- 1 root root 1.3K Jul 19 20:50 linuxsb.com.crt
-rw------- 1 root root 1.7K Jul 19 20:50 linuxsb.com.key
-rw-r--r-- 1 root root 1.2K Jul 19 20:50 myCA.crt
-rw------- 1 root root 1.7K Jul 19 20:50 myCA.key
-rw-r--r-- 1 root root   41 Jul 19 20:50 myCA.srl

手动创建secret

自定义证书的场景,建议提前使用对应的证书创建secret。
后续用于使用https暴露elasticsearch。

[root@master01 elasticsearch]# kubectl create ns es                #dashboard独立ns
[root@master01 elasticsearch]# kubectl -n es create secret tls elasticsearch-ui-tls \
--cert=/root/elasticsearch/certs/linuxsb.com.crt \
--key=/root/elasticsearch/certs/linuxsb.com.key

[root@master01 elasticsearch]# kubectl -n es get secret kubernetes-elasticsearch-certs -o yaml    #查看证书信息

创建elasticsearch自定义配置

根据实际情况修改默认的chart values,未配置的项表示使用默认值。
如下自定义yaml主要做了几项自定义配置:

  • 指定elasticsearch部署在master节点;
  • 指定了使用自有的TLS证书,及https的ingress域名;
  • 指定了污点能接受master节点;
  • 指定了Pod挂载本地时间文件,使Pod时钟正确;
  • 使用Longhorn提供的持久化存储保存数据。
[root@master01 elasticsearch]# helm show values elastic/elasticsearch > defaults-elasticsearch-values.yaml        #查看默认配置

[root@master01 elasticsearch]# vim my-elasticsearch-values.yaml
---
replicas: 2

# 此部分配置将直接写入elasticsearch.yml
# 此部分配置将直接写入elasticsearch.yml
# 磁盘空间管理 - 防止磁盘写满导致集群崩溃
 # 低水位线(85%) - 达到此使用率时停止分配新分片
 # 高水位线(90%) - 达到此使用率时尝试迁移分片
esConfig:
  elasticsearch.yml: |
    cluster.routing.allocation.disk.threshold_enabled: true
    cluster.routing.allocation.disk.watermark.low: "85%"
    cluster.routing.allocation.disk.watermark.high: "90%"

# 启用密码存储(自动创建Kubernetes Secret)
secret:
  enabled: true
  password: "redhat123"

image: "uhub.service.ucloud.cn/imxhy/elasticsearch"
imageTag: "8.5.1"

# 持久化存储配置
volumeClaimTemplate:
  accessModes: ["ReadWriteOnce"]
  storageClassName: "longhorn"
  resources:
    requests:
      storage: 5Gi

# 时间同步配置
extraVolumeMounts:
  - name: timeconfig
    mountPath: /etc/localtime
    readOnly: true
extraVolumes:
  - name: timeconfig
    hostPath:
      path: /etc/localtime

# 节点调度配置
nodeSelector: {"elasticsearch": "enable"}

# Ingress配置
ingress:
  enabled: true
  annotations: 
    nginx.ingress.kubernetes.io/backend-protocol: "HTTPS" 
    nginx.ingress.kubernetes.io/proxy-body-size: "50m"
  className: "nginx"
  hosts:
    - host: es.linuxsb.com
      paths:
        - path: /
  tls:
    - secretName: elasticsearch-ui-tls
      hosts:
        - es.linuxsb.com

正式部署elasticsearch

根据生产环境最佳实践进行调优,调优完成后开始部署。

[root@master01 elasticsearch]# helm upgrade --install elasticsearch elastic/elasticsearch --create-namespace --namespace es -f my-elasticsearch-values.yaml

确认验证

使用浏览器访问 https://es.linuxsb.com ,使用默认用户 elastic 和自定义的密码登录。

004

部署Fluentd

获取Fluentd yaml包

Fluentd和elastic属于两个公司产品,因此不在elastic的helm仓库里,但通常可以搭配使用。
由于 fluentd 当前 chart 包版本不是最新,因此采用传统 manifest 方式部署。

[root@master01 elasticsearch]# git clone https://github.com/fluent/fluentd-kubernetes-daemonset
创建Fluentd自定义配置

根据实际情况修改默认的yaml,如下自定义yaml主要做了几项自定义配置:

  • 指定Fluentd部署在所有节点,对master打上容忍;
  • 修改镜像为国内;
  • 修改namespace为es,和elasticsearch在同一个命名空间下;
  • 和elasticsearch做认证对接。
[root@master01 fluentd-kubernetes-daemonset]# sed -i 's/namespace: kube-system/namespace: es/g' fluentd-daemonset-elasticsearch-rbac.yaml

[root@master01 fluentd-kubernetes-daemonset]# vim fluentd-daemonset-elasticsearch-rbac.yaml 
---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: fluentd
  namespace: es

---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: 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: es
---
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: fluentd
  namespace: es
  labels:
    k8s-app: fluentd-logging
    version: v1
spec:
  selector:
    matchLabels:
      k8s-app: fluentd-logging
      version: v1
  template:
    metadata:
      labels:
        k8s-app: fluentd-logging
        version: v1
    spec:
      serviceAccount: fluentd
      serviceAccountName: fluentd
      tolerations:
      - key: node-role.kubernetes.io/control-plane
        effect: NoSchedule
      - key: node-role.kubernetes.io/master
        effect: NoSchedule
      containers:
      - name: fluentd
        image: uhub.service.ucloud.cn/imxhy/fluentd-kubernetes-daemonset:v1.18-debian-elasticsearch8-1    # 镜像修改为国内
        env:
          - name: K8S_NODE_NAME
            valueFrom:
              fieldRef:
                fieldPath: spec.nodeName
          - name:  FLUENT_ELASTICSEARCH_HOST
            value: "elasticsearch-master"                                    # elasticsearch 连接的服务名
          - name:  FLUENT_ELASTICSEARCH_PORT                                 # elasticsearch 连接的端口
            value: "9200"
          - name: FLUENT_ELASTICSEARCH_SCHEME                                # elasticsearch 连接的方式
            value: "https"
          # Option to configure elasticsearch plugin with self signed certs
          # ================================================================
          - name: FLUENT_ELASTICSEARCH_SSL_VERIFY                            #自签名证书不校验
            value: "false"
          # Option to configure elasticsearch plugin with tls
          # ================================================================
          - name: FLUENT_ELASTICSEARCH_SSL_VERSION
            value: "TLSv1_2"
          # X-Pack Authentication
          # =====================
          - name: FLUENT_ELASTICSEARCH_USER
            value: "elastic"
          - name: FLUENT_ELASTICSEARCH_PASSWORD
            value: "redhat123"                                                # elasticsearch 连接的密码
          # Logz.io Authentication
          # ======================
          - name: LOGZIO_TOKEN
            value: "ThisIsASuperLongToken"
          - name: LOGZIO_LOGTYPE
            value: "kubernetes"
          - name: TZ
            value: "Asia/Shanghai"                                            #添加时区
        resources:
          limits:
            memory: 200Mi
          requests:
            cpu: 100m
            memory: 200Mi
        volumeMounts:
        - name: varlog
          mountPath: /var/log
        # When actual pod logs in /var/lib/docker/containers, the following lines should be used.
        # - name: dockercontainerlogdirectory
        #   mountPath: /var/lib/docker/containers
        #   readOnly: true
        # When actual pod logs in /var/log/pods, the following lines should be used.
        - name: dockercontainerlogdirectory
          mountPath: /var/log/pods
          readOnly: true
        - name: containerslog                                        # 追加containerd的日志
          mountPath: /var/log/containers
          readOnly: true
      terminationGracePeriodSeconds: 30
      volumes:
      - name: varlog
        hostPath:
          path: /var/log
      # When actual pod logs in /var/lib/docker/containers, the following lines should be used.
      # - name: dockercontainerlogdirectory
      #   hostPath:
      #     path: /var/lib/docker/containers
      # When actual pod logs in /var/log/pods, the following lines should be used.
      - name: dockercontainerlogdirectory
        hostPath:
          path: /var/log/pods
      - name: containerslog                                # 追加containerd的每个节点的日志路径
        hostPath:
          path: /var/log/containers
正式部署fluentd

根据生产环境最佳实践进行调优,调优完成后开始部署。

[root@master01 fluentd-kubernetes-daemonset]# kubectl apply -f fluentd-daemonset-elasticsearch-rbac.yaml
确认验证
[root@master01 elasticsearch]# kubectl -n es get pods -o wide
[root@master01 elasticsearch]# kubectl -n es get svc -o wide
[root@master01 elasticsearch]# kubectl -n es get ingress -o wide

001

创建kibana自定义配置

根据实际情况修改默认的chart values,未配置的项表示使用默认值。
如下自定义yaml主要做了几项自定义配置:

  • 指定kibana部署在所有节点,对master打上容忍;
  • 修改镜像为国内。
[root@master01 elasticsearch]# helm show values elastic/kibana > defaults-kibana-values.yaml        #查看默认配置

[root@master01 elasticsearch]# vim my-kibana-values.yaml
---
replicas: 1

image: "uhub.service.ucloud.cn/imxhy/kibana"
imageTag: "8.5.1"

kibanaConfig:
  kibana.yml: |
    server.publicBaseUrl: "https://kibana.linuxsb.com"
    elasticsearch.ssl.certificateAuthorities: /usr/share/kibana/config/certs/ca.crt

# 时间同步配置
extraVolumeMounts:
  - name: timeconfig
    mountPath: /etc/localtime
    readOnly: true
extraVolumes:
  - name: timeconfig
    hostPath:
      path: /etc/localtime

ingress:
  enabled: true
  className: "nginx"
  hosts:
    - host: kibana.linuxsb.com
      paths:
        - path: /
  tls: 
    - secretName: elasticsearch-ui-tls
      hosts:
        - kibana.linuxsb.com

# 节点调度(与ES相同节点)
nodeSelector: {"kibana": "enable"}
tolerations: 
  - key: node-role.kubernetes.io/control-plane
    operator: "Exists"
    effect: "NoSchedule"

正式部署kibana

根据生产环境最佳实践进行调优,调优完成后开始部署。

[root@master01 elasticsearch]# helm upgrade --install kibana elastic/kibana --create-namespace --namespace es -f my-kibana-values.yaml

提示:若部署kibana过程异常,需要重新卸载再部署,但卸载和重部署报错某个资源already exists,可如下操作:
报错:

Error: failed pre-install: warning: Hook pre-install kibana/templates/pre-install-rolebinding.yaml failed: 1 error occurred:
        * rolebindings.rbac.authorization.k8s.io "pre-install-kibana-kibana" already exists

[root@master01 elasticsearch]# kubectl -n es get configmap,secret,serviceaccount,role,rolebindings,jobs            #查询所有相应的资源
[root@master01 elasticsearch]# kubectl -n es delete configmap/kibana-kibana-config secret/kibana-kibana-es-token secret/sh.helm.release.v1.kibana.v1 configmaps/kibana-kibana-helm-scripts serviceaccounts/pre-install-kibana-kibana roles/pre-install-kibana-kibana rolebindings/pre-install-kibana-kibana jobs.batch/pre-install-kibana-kibana 
    #其他资源类似手动全部删除
[root@master01 elasticsearch]# helm -n es uninstall kibana

确认验证

查看部署的资源

[root@master01 elasticsearch]# kubectl -n es get all -o wide
[root@master01 elasticsearch]# kubectl -n es get ingress -o wide

002

访问验证

浏览器访问 https://kibana.linuxsb.com ,使用elasticsearch默认用户 elastic 和自定义的密码 redhat123 登录。

006

007

基础使用

确认连接

浏览器访问后确认正常连接filebeat-8.5.1 。
进入 Index Management 中的 Data Streams 中可以看到 filebeat-8.5.1 已被列为数据索引项目。

008

测试日志

创建一个生产日志的Pod,用于生成日志,确认能正常获取。

[root@master01 elasticsearch]# vim test-logging-pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: testpods01
spec:
  containers:
  - name: count
    image: uhub.service.ucloud.cn/imxhy/busybox:1.37.0
    args: [/bin/sh, -c,'i=0; while true; do echo "$i: $(date)"; i=$((i+1)); sleep 1; done']
    
[root@master01 elasticsearch]# kubectl apply -f test-logging-pod.yaml
pod/testpods01 created
[root@master01 elasticsearch]# kubectl get pods -o wide
NAME         READY   STATUS    RESTARTS   AGE   IP            NODE       NOMINATED NODE   READINESS GATES
testpods01   1/1     Running   0          6s    10.10.30.91   worker02   <none>           <none>

kibana界面中查看 Observability->Logs->Stream:

009

创建索引

配置Kibana,要查询和分析 Elasticsearch 中的哪些日志,因此需要配置一个 Index Pattern。从 Filebeat 中可知 Index 是 filebeat-timestamp 这种格式,因此需要定义 Index Pattern 为 filebeat-*

提示:当前版本已存在一个包含filebeat-*格式的索引模式。

010

日志查看与搜索

基本日志查看:
左侧菜单 > Analytics > Discover
选择默认创建的视图即可。
可根据时间范围选择: Last 15 minutes

011

也可以使用kubernetes.namespace: “es” 查看特定namespace下的日志。

012

还可以根据需要创建一个dashboard,用于展示。

013

尝试查找error关键字日志。

014

参考:

一文读懂开源日志管理方案 ELK 和 EFK 的区别

Helm实战案例二:在Kubernetes(k8s)上使用helm安装部署日志管理系统EFK

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

木二_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值