环境说明

  • k8s版本:1.20.0
  • elfk版本:7.6.2
  • elastalert:3.0.0

主要功能是通过ELFK收集业务日志进行处理,然后elastalert根据日志中的关键字进行匹配,将相对应的日志通过邮件或其它方式告警通知

ELFK部署

博客之前有部署过ELFK可以参考,也可以直接使用以下的

ES集群部署

[root@k8s01 elk]# vim es-statefulset.yaml
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: es
  namespace: tools-env
spec:
  serviceName: elasticsearch
  replicas: 3
  selector:
    matchLabels:
      app: elasticsearch
  template:
    metadata:
      labels: 
        app: elasticsearch
    spec:
      initContainers:
      - 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
      containers:
      - name: elasticsearch
        image: elasticsearch:7.6.2
        imagePullPolicy: IfNotPresent
        ports:
        - name: rest
          containerPort: 9200
        - name: inter
          containerPort: 9300
        resources:
          limits:
            cpu: 1000m
          requests:
            cpu: 1000m
        volumeMounts:
        - name: data
          mountPath: /usr/share/elasticsearch/data
        - name: localtime
          mountPath: /etc/localtime
        env:
        - name: cluster.name
          value: elasticsearch
        - name: node.name
          valueFrom:
            fieldRef:
              fieldPath: metadata.name
        - name: cluster.initial_master_nodes
          value: "es-0,es-1,es-2"
        - name: discovery.zen.minimum_master_nodes
          value: "2"
        - name: discovery.seed_hosts
          value: "elasticsearch"
        - name: ES_JAVA_OPTS
          value: "-Xms512m -Xmx512m"
        - name: network.host
          value: "0.0.0.0"
      volumes:
      - name: localtime
        hostPath:
          path: /etc/localtime          
  volumeClaimTemplates:
  - metadata:
      name: data
      labels:
        app: elasticsearch
    spec:
      accessModes: [ "ReadWriteOnce" ]
      storageClassName: managed-nfs-storage
      resources:
        requests:
          storage: 50Gi    
---
kind: Service
apiVersion: v1
metadata:
  name: elasticsearch
  namespace: tools-env
  labels:
    app: elasticsearch
spec:
  selector:
    app: elasticsearch
  clusterIP: None
  ports:
    - port: 9200
      name: rest
    - port: 9300
      name: inter-node
---
kind: Service
apiVersion: v1
metadata:
  name: elasticsearch-client
  namespace: tools-env
  labels:
    app: elasticsearch
spec:
  selector:
    app: elasticsearch
  ports:
    - port: 9200
      name: rest
      nodePort: 30920
    - port: 9300
      name: inter-node
      nodePort: 30930
  type: NodePort
  
[root@k8s01 elk]# kubectl apply -f es.yaml 
statefulset.apps/es created
service/elasticsearch created
service/elasticsearch-client created

Logstash部署

[root@k8s01 elk]# vim logstash-config.yaml 
apiVersion: v1
kind: ConfigMap
metadata:
  name: logstash-config
  namespace: tools-env
  labels:
    app: logstash
data:
  logstash.conf: |-
    input {
       beats {
         host => "0.0.0.0"
         port => 5044
       }
    }
               
    output {
      if [filetype] == "gts-center" {
        elasticsearch {
          hosts => ["elasticsearch:9200"]
          index => "prod-gts-center_%{+YYYY-MM-dd}"
        }
      }
...
      if [filetype] == "promotion-center" {
        elasticsearch {
          hosts => ["elasticsearch:9200"]
          index => "prod-promotion-center_%{+YYYY-MM-dd}"
        } 
      }  
    }

[root@k8s01 elk]# vim logstash.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: logstash
  namespace: tools-env
spec:
  replicas: 1
  selector:
    matchLabels:
      app: logstash
  template:
    metadata:
      labels:
        app: logstash
    spec:
      containers:
      - name: logstash
        image: logstash:7.6.2
        imagePullPolicy: IfNotPresent
        volumeMounts:
        - name: config
          mountPath: /usr/share/logstash/pipeline/logstash.conf
          subPath: logstash.conf
        command:
        - "/bin/sh"
        - "-c"
        - "/usr/share/logstash/bin/logstash -f /usr/share/logstash/pipeline/logstash.conf"
      volumes:
      - name: config
        configMap:
          name: logstash-config
---
apiVersion: v1
kind: Service
metadata:
  labels:
    app: logstash
  name: logstash
  namespace: tools-env
spec:
  ports:
    - port: 5044       
      targetPort: 5044
      nodePort: 30504
  selector:
    app: logstash
  type: NodePort
 
[root@k8s01 elk]# kubectl apply -f logstash-config.yaml 
configmap/logstash-config created 
[root@k8s01 elk]# kubectl apply -f logstash.yaml 
deployment.apps/logstash created
service/logstash created
[root@k8s01 elk]# kubectl get -n tools-env po|grep logstash
logstash-679cb9c998-hpt6w        1/1     Running   1          25s

Kibana部署

[root@k8s01 elk]#  vim kibana-config.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: kibana-config
  namespace: tools-env
  labels:
    app: kibana
data:
  kibana.yml: |-
    server.name: kibana
    server.host: "0"
    elasticsearch.hosts: [ "http://elasticsearch:9200" ]
    xpack.monitoring.ui.container.elasticsearch.enabled: true

[root@k8s01 elk]# vim kibana.yaml
apiVersion: v1
kind: Service
metadata:
  name: kibana
  namespace: tools-env
  labels:
    app: kibana
spec:
  ports:
  - port: 5601
    nodePort: 30561
  type: NodePort
  selector:
    app: kibana
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: kibana
  namespace: tools-env
  labels:
    app: kibana
spec:
  selector:
    matchLabels:
      app: kibana
  template:
    metadata:
      labels:
        app: kibana
    spec:
      containers:
      - name: kibana
        image: kibana:7.6.2
        imagePullPolicy: IfNotPresent
        env:
          - name: ELASTICSEARCH_HOSTS
            value: http://elasticsearch:9200
        ports:
        - containerPort: 5601
        volumeMounts:
          - name: config
            mountPath: /usr/share/kibana/config/kibana.yml
            subPath: kibana.yml
          - name: localtime
            mountPath: /etc/localtime
      volumes:
        - name: config
          configMap:
            name: kibana-config
        - name: localtime
          hostPath:
            path: /usr/share/zoneinfo/Asia/Shanghai
            
[root@k8s01 elk]# kubectl apply -f kibana-config.yaml 
configmap/kibana-config created
[root@k8s01 elk]# kubectl apply -f kibana.yaml 
service/kibana created
deployment.apps/kibana created

Filebeat部署

由于业务日志通过pvc持久化到NAS上,本文就直接采用rpm安装并收集对应NAS挂载目录日志,也可以使用DaemeSet的部署模式直接收集业务pod的日志,就看实际需求了。这里采用rpm安装

#下载filebeat的rpm文件
[root@elk ~]# wget https://repo.huaweicloud.com/filebeat/7.6.2/filebeat-7.6.2-x86_64.rpm

#安装filebeat
[root@elk ~]# rpm -ivh filebeat-7.6.2-x86_64.rpm

#修改配置文件(根据实际情况)
[root@elk ~]# cat /etc/filebeat/filebeat.yml
filebeat.inputs:
- type: log
  enabled: true
  backoff: "1s"
  tail_files: false
  paths:
    - /home/logs/*.log   #这里根据实际路径填写,可以多个path
  fields:
    filetype: crm-center
  fields_under_root: true
  multiline.pattern: '^\['
  multiline.negate: true
  multiline.match: after
setup.kibana:
  host: "x.x.x.x:30561"      #kibana地址
output.logstash:
  enabled: true
  hosts: ["x.x.x.x:30504"]     #logstash地址

Elastalert部署

创建secret

用作邮件告警的账号及密码

[root@elk ~]# vim email_auth.yaml 
user: monitor@xxx.cn
password: 123456

#根据email_auth.yaml创建 secret
[root@k8s01 elk]# kubectl create secret generic smtp-auth --from-file=email_auth.yaml -n tools-env
secret/smtp-auth created

创建configmap

elastalert的配置文件、告警规则及邮箱账号密码

[root@k8s01 elk]# vim elastalert-config.yaml 
apiVersion: v1
kind: ConfigMap
metadata:
  name: elastalert-config
  namespace: tools-env
data:
  prod.yaml: |
    es_host: elasticsearch
    es_port: 9200
    name: prod-server-rules
    type: frequency
    query_key:              #不进行重复提醒的字段
      - message
    aggregation:            #聚合1分钟内的结果,合并在一起发送
      minutes: 1
    realert:                #同一规则的两次警报之间的最短时间
      minutes: 2
    #指数级扩大realert时间,中间如果有报警,则按照5->10->20->40->60不断增大报警时间到制定的最大时间,如果之后报警减少,则会慢慢恢复原始realert 时间
    exponential_realert:
      hours: 1    
    index: test-log*         # 匹配索引,支持正则
    num_events: 1           # 与规则匹配的日志出现次数
    timeframe:              # 在timeframe时间内出现num_events次与规则匹配的日志,将会触发报警
      minutes: 1
    #过滤规则
    #根据报警的内,将相同的报警按照name来聚合
    aggregation_key: name     
    filter:
    - query:
        query_string:
          query: "message: ERRORMESSAGE"        
    alert:
    - "email"
    - "dingtalk"

    email_format: html
    alert_text_type: alert_text_only
    #标题
    alert_subject: "生产环境日志告警通知"
    #主题模板
    alert_text: "<br><a href='https://kibana.xxx.cn/app/kibana'target='_blank'style='padding: 8px 16px;background-color: #46bc99;text-decoration:none;color:white;border-radius: 5px;'>立刻前往Kibana查看</a><br>
    <table>
    <tr><td style='padding:5px;text-align: right;font-weight: bold;border-radius: 5px;background-color: #eef;'>告警时间</td>
    <td style='padding:5px;border-radius: 5px;background-color: #eef;'>{}</td></tr>
    <tr><td style='padding:5px;text-align: right;font-weight: bold;border-radius: 5px;background-color: #eef;'>服务名称</td>
    <td style='padding:5px;border-radius: 5px;background-color: #eef;'>{}</td></tr>
    <tr><td style='padding:5px;text-align: right;font-weight: bold;border-radius: 5px;background-color: #eef;'>服务器ID</td>
    <td style='padding:5px;border-radius: 5px;background-color: #eef;'>{}</td></tr>
    <tr><td style='padding:5px;text-align: right;font-weight: bold;border-radius: 5px;background-color: #eef;'>索引名称</td>
    <td style='padding:5px;border-radius: 5px;background-color: #eef;'>{}</td></tr>
    <tr><td style='padding:5px;text-align: right;font-weight: bold;border-radius: 5px;background-color: #eef;'>告警详情</td>
    <td style='padding:10px 5px;border-radius: 5px;background-color: #F8F9FA;'>{}</td></tr>
    <tr><td style='padding:5px;text-align: right;font-weight: bold;border-radius: 5px;background-color: #eef;'>规则命中数</td>
    <td style='padding:5px;border-radius: 5px;background-color: #eef;'>{}</td></tr>
    <tr><td style='padding:5px;text-align: right;font-weight: bold;border-radius: 5px;background-color: #eef;'>匹配触发数</td>
    <td style='padding:5px;border-radius: 5px;background-color: #eef;'>{}</td></tr>
    </table>"
    # 告警模板引用
    alert_text_args:
    - "@timestamp"
    - filetype
    - host.name
    - _index
    - message
    - num_hits
    - num_matches
    - path
    
    email:
    - "xxx@xxx.com.cn"
    - "monitor@xxx.cn"
    smtp_host: mail.xxx.cn
    smtp_port: 25
    smtp_auth_file: /opt/elastalert/smtp_auth.yaml      
    from_addr: monitor@xxx.cn

    dingtalk_webhook_url: "https://oapi.dingtalk.com/robot/send?access_token=3fe29834a80edxxxxxxxx802071xxx630e34e3"
    dingtalk_webhook_secret: "SEC7a5a905exxxx1a19860bfcxxxx62c3e117b4c1b72"  #加签
    dingtalk_msgtype: text

  config.json: |
    {
      "appName": "elastalert-server",
      "port": 3030,
      "wsport": 3333,
      "elastalertPath": "/opt/elastalert",
      "verbose": false,
      "es_debug": false,
      "debug": false,
      "rulesPath": {
        "relative": true,
        "path": "/rules"
      },
      "templatesPath": {
        "relative": true,
        "path": "/rule_templates"
      },
      "es_host": "elasticsearch",
      "es_port": 9200,
      "writeback_index": "elastalert_status"
    }
  elastalert.yaml: |
    rules_folder: rules
    run_every:
      seconds: 60
    buffer_time:
      minutes: 15
    es_host: elasticsearch
    es_port: 9200
    use_ssl: False
    verify_certs: False
    writeback_index: elastalert_status
    writeback_alias: elastalert_alerts
    alert_time_limit:
      days: 2
  smtp_auth.yaml: |
    user: op@xxxx.cn
    password: 123456

[root@k8s01 elk]# kubectl apply -f elastalert-config.yaml 
configmap/elastalert-config created

部署elastalert

[root@k8s01 elk]# vim elastalert.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: elastalert
  name: elastalert
  namespace: tools-env
spec:
  replicas: 1
  selector:
    matchLabels:
      app: elastalert
  template:
    metadata:
      labels:
        app: elastalert
      name: elastalert
    spec:
      containers:
        - env:
            - name: TZ
              value: Asia/Shanghai
          image: brycehuang/elastalert-dingtalk:3.0.0-beta.1   #这个镜像是加了钉钉模块的
          #image: bitsensor/elastalert:3.0.0-beta.1   
          imagePullPolicy: IfNotPresent
          name: elastalert
          ports:
            - containerPort: 3030
              name: tcp-3030
              protocol: TCP
            - containerPort: 3333
              name: tcp-3333
              protocol: TCP
          resources:
            limits:
              cpu: '2'
            requests:
              cpu: '1'
          volumeMounts:
            - mountPath: /opt/elastalert/config.yaml
              name: elastalert-config
              subPath: elastalert.yaml
            - mountPath: /opt/elastalert/smtp_auth.yaml
              name: elastalert-config
              subPath: smtp_auth.yaml
            - mountPath: /opt/elastalert-server/config/config.json
              name: elastalert-config
              subPath: config.json
            - mountPath: /opt/elastalert/rules/prod.yaml
              name: elastalert-config
              subPath: prod.yaml            
      dnsPolicy: ClusterFirst
      restartPolicy: Always
      volumes:
        - configMap:
            defaultMode: 420
            name: elastalert-config
          name: elastalert-config
---
apiVersion: v1
kind: Service
metadata:
  name: elastalert
  namespace: tools-env
spec:
  ports:
  - name: serverport
    port: 3030
    protocol: TCP
    targetPort: 3030
  - name: transport
    port: 3333
    protocol: TCP
    targetPort: 3333
  selector:
    app: elastalert
    
[root@k8s01 elk]# kubectl apply -f elastalert.yaml 
statefulset.apps/elastalert created
service/elastalert created

模拟生产ERROR触发告警

正常下,kibana收集到日志如下:(这里是模拟产生的日志)
elastalert
直接开始模拟日志产生ERROR,手动echo一些错误到日志文件中,结果如下:
elastalert1
邮件收到告警
elastalert2

文章作者: 鲜花的主人
版权声明: 本站所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 爱吃可爱多
监控服务 EFLK Kubernetes Kubernetes EFLK 监控服务
喜欢就支持一下吧
打赏
微信 微信
支付宝 支付宝