Elastic:创建你的第一个Elastic alert - 邮件通知

这是我之前的文章 “Elastic:创建你的第一个Elastic alert” 的续篇。在那篇文章中,我们讲述了如何运用Watcher API来创建一个警报。我们只用了一个logging的简单的展示。可能大家觉得并不过瘾,比较我们很少坐在自己的位子上一直盯着自己的屏幕看log。另外我们可能有些情况,我们希望的情况是有一个错误的信息我们并不紧张,但是如果在规定的时间里,我们的错误或者异常到底规定的一个数值,那么我们希望在这种情况下发送我们想要的警报。针对这种情况,我们该如何应对呢?

在今天的练习中,我们来展示如何使用电子邮件来发送通知。大家是不是感觉到很兴奋啊?毕竟这个更靠近我们实际的应用场景。

 

配置Elasticsearch

为了能够支持邮件的发送,我们必须在Elasticsearch的config/elasticsearch.yml文件里进行一些配置。关于其它的actions,请参阅我们Elastic的官方网站https://www.elastic.co/guide/en/elasticsearch/reference/current/actions.html

对于email的配置,我们可以参阅网址https://www.elastic.co/guide/en/elasticsearch/reference/current/actions-email.html。针对不同的邮件地址,我们需要做不同的配置。针对我的情况,我使用的是hotmail,那么在我的config/elasticsearch.yml文件的最后,我添加了如下的配置:

xpack.notification.email.account:
    exchange_account:
        profile: outlook
        email_defaults:
            from: 'Alert <liu_xiao_guo@hotmail.com>'
        smtp:
            auth: true
            starttls.enable: true
            host: smtp-mail.outlook.com
            port: 587
            user: liu_xiao_guo@hotmail.com

在上面,我们配置了我发送邮件的账号信息。细心的开发者可能会发现,我上面的信息里并没有我的密码信息。由于密码信息是一个敏感的信息,你可能并不希望它保存于你的配置文件中。为此,我们在Elasticsearch的安装目录下打入如下的命令:

bin/elasticsearch-keystore add xpack.notification.email.account.exchange_account.smtp.secure_password

我们把自己的账号的密码粘贴过来就行了。请注意:针对不同的邮件账号,比如gmail等,它们的命令都不同。

等我们修改完上面的配置后,我们需要重新启动我们的Elasticsearch了。

修改Watcher

接下来,我们需要修改我们的watcher接口。如果你已经完成了我之前的那个教程的话,那么我们可以在我们的Kibana中做一个如下的搜索:

GET filebeat-7.6.0/_search
{
  "size": 0,
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "process.name": "JUSTME"
          }
        },
        {
          "match": {
            "message": "error"
          }
        }
      ],
      "filter": [
        {
          "range": {
            "@timestamp": {
              "from": "now-1m",
              "to": "now"
            }
          }
        }
      ]
    }
  },
  "aggs": {
    "failed_messages": {
      "terms": {
        "field": "process.name"
      }
    }
  }
}

在上面,我们做了一个aggregation。它是针对在过去1分钟,process.name为JUSTME的信息,并且message里含有error字样的事件做了一个统计。如果这个数据的统计的个数超过我们规定的一个阈值,比如说5,那么我们希望watcher能给我发送一个警报。如果是5一下的数值,那么我们视为正常。上面的搜索的结果的输出为如下的格式:

{
  "took" : 1,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 4,
      "relation" : "eq"
    },
    "max_score" : null,
    "hits" : [ ]
  },
  "aggregations" : {
    "failed_messages" : {
      "doc_count_error_upper_bound" : 0,
      "sum_other_doc_count" : 0,
      "buckets" : [
        {
          "key" : "JUSTME",
          "doc_count" : 4
        }
      ]
    }
  }
}

上面的这个输出的格式非常重要。这对我们如下的search及condition的书写提供了最基本的信息。

依据上面的搜索及输出,我们尝试修改我们watcher。

PUT _watcher/watch/my-justme-watcher
{
  "trigger": {},
  "input": {},
  "condition": {},
  "actions": {}
}

一个watcher的格式是如上面所示。我们来分别描述:

trigger

这个定义多次实践watcher运行一次。比如我们可以定义如下:

  "trigger": {
    "schedule" : {
      "interval": "1h"
    }
  },

上面表明,我们希望watcher每一个小时运行一次。针对我们的情况,我们定义为:

  "trigger": {
    "schedule": {
      "cron": "0 0/1 * * * ?"
    }
  },

上面表明,我们希望每一分钟运行一次。

input

这个是定义alert想搜索的index,及针对多长时间的index来进行的搜索的。依据上面的搜索条件,我们书写如下:

  "input": {
    "search": {
      "request": {
        "indices": [
          "filebeat-*"
        ],
        "body": {
          "query": {
            "bool": {
              "must": [
                {
                  "match": {
                    "process.name": "JUSTME"
                  }
                },
                {
                  "match": {
                    "message": "error"
                  }
                }
              ],
              "filter": [
                {
                  "range": {
                    "@timestamp": {
                      "from": "{{ctx.trigger.scheduled_time}}||-1m",
                      "to": "{{ctx.trigger.triggered_time}}"
                    }
                  }
                }
              ]
            }
          },
          "aggs": {
            "failed_messages": {
              "terms": {
                "field": "process.name"
              }
            }
          }
        }
      }
    }
  }

我们时间上就是想找到在过去一分钟之内满足条件的所有含有JUSTME的统计信息。

condition

我们定义如下:

 "condition": {
    "compare": {
      "ctx.payload.aggregations.failed_messages.buckets.0.doc_count": {
        "gt": 5
      }
    }
  }

请注意上面的ctx.payload.aggregations.failed_messages.buckets.0.doc_count的写法。它和我们查询结果的格式是一致的。在上面,我们比较查询的结果,并把第一个bucket的数据拿出来。如果doc_count是大于5的话,那么将会触发事件。

actions

这个是定义当上面的condition被满足时,需要采取的一些行动。这些行动可以在地址找到。目前Watcher支持的action为: emailwebhookindexloggingslackpagerduty

在今天的练习中,我们使用邮件的方式:

  "actions": {
    "send_email": {
      "throttle_period": "2m",
      "email": {
        "to": "liu_xiao_guo@yahoo.com",
        "subject": "Watcher Notification",
        "body": "{{ctx.payload.hits.total}} errors found"
      }
    }
  }

在上面,我们把触发的通知发送到我们的一个邮箱里,并冠以Watcher Notification的标题。里面的内容展示了“xx errors found”。另外请注意throttle_period的用法。由于我们的watcher是每一分钟运行一次的。针对有些情况,如果条件满足的话,Watcher会每一次都发送一个通知的信息。这样会造成垃圾邮件。我们不希望Watcher每次运行都发送。上面设置为2m,也就是2分钟的时间。在两分钟时间内发送一次通知。

经过我们的改造后,完整的Watcher配置如下:

PUT _watcher/watch/my-justme-watcher
{
  "trigger": {
    "schedule": {
      "cron": "0 0/1 * * * ?"
    }
  },
  "input": {
    "search": {
      "request": {
        "indices": [
          "filebeat-*"
        ],
        "body": {
          "query": {
            "bool": {
              "must": [
                {
                  "match": {
                    "process.name": "JUSTME"
                  }
                },
                {
                  "match": {
                    "message": "error"
                  }
                }
              ],
              "filter": [
                {
                  "range": {
                    "@timestamp": {
                      "from": "{{ctx.trigger.scheduled_time}}||-1m",
                      "to": "{{ctx.trigger.triggered_time}}"
                    }
                  }
                }
              ]
            }
          },
          "aggs": {
            "failed_messages": {
              "terms": {
                "field": "process.name"
              }
            }
          }
        }
      }
    }
  },
  "condition": {
    "compare": {
      "ctx.payload.aggregations.failed_messages.buckets.0.doc_count": {
        "gt": 5
      }
    }
  },
  "actions": {
    "send_email": {
      "throttle_period": "2m",
      "email": {
        "to": "liu_xiao_guo@yahoo.com",
        "subject": "Watcher Notification",
        "body": "{{ctx.payload.hits.total}} errors found"
      }
    }
  }
}

运行上面的命令。同时在我们的Ubuntu的terminal中连续输入如下的几个命令:

sudo logger `who`  -t JUSTME error

如果在一分钟之内,我们收到含有5个及以上的error信息,那么我们将在我们的邮件中收到通知信息:

我们打开邮件的内容:

下一步

如果你想知道如何创建一个动态的阈值警报,那么请阅读我的文章“Elastic:如何创建一个动态的阈值警报”。

 

展开阅读全文

没有更多推荐了,返回首页

应支付0元
点击重新获取
扫码支付

支付成功即可阅读