天天看点

SLS告警响应升级——通知对接FC进行自动化操作

前言

所谓监控,直白来说就是“监测并进行控制”。通过对数据的监测,我们可以发现其中的异常,例如机器的CPU使用率异常。异常会触发告警,然后告警会被通知到相应的负责人,以便进行后续的处理。通常我们对告警会有多种方式进行通知,例如通过短信、电话、钉钉等方式。

但是告警并不是目的,异常产生后最终的目的是消除异常,因此除了人为接收通知之外,在某些场景下,我们还需要程序去接收,然后做一些自动化的事情。例如发送通知到一个 Web 服务,然后根据告警详情进行后续的自动操作(比如根据业务规则做一些自动运维操作)等。但是如果从头开始编写一个Web服务然后部署,又是一件比较麻烦的事情,SLS告警加入了对函数计算(FC)的支持,让告警的自动化响应变得简单。

SLS告警响应升级——通知对接FC进行自动化操作

告警通知对接FC

1. 授权RAM访问角色

为了告警触发后,日志服务可以调用你的函数计算里的函数,需要授权日志服务相应的权限。进入告警中心后,可以“点击授权”进行一键授权。

SLS告警响应升级——通知对接FC进行自动化操作

也可以在配置行动策略的时候进行授权:

SLS告警响应升级——通知对接FC进行自动化操作

这里需要注意,如果登录的是子账号,需要具备如下RAM权限才可以授权成功,否则会有相应的错误提示。

{
  "Statement": [{
    "Action": "ram:CreateServiceLinkedRole",
    "Resource": "*",
    "Effect": "Allow",
    "Condition": {
      "StringEquals": {
        "ram:ServiceName": "alert.log.aliyuncs.com"
      }
    }
  }],
  "Version": "1"
}      

2. 创建FC函数

需要在函数计算控制台创建函数,这里需要注意的是:

  • SLS告警通知渠道中,FC通知仅支持非HTTP函数,如果是HTTP函数,直接使用自定义Webhook通知渠道就可以了。
  • 由于安全限制,因此SLS仅能访问名称以 "sls-ops-" 开头的函数,例如 "sls-ops-test",而例如 "test-function" 这样的函数则无权限访问。

这里我们创建一个非常简单的函数,示例代码如下:

'use strict';
exports.handler = (event, context, callback) => {
  console.log(event.toString());
  callback(null, 'hello world');
}      

3. 创建行动策略

我们可以创建一个行动策略,在行动组中配置相应的函数,例如:

SLS告警响应升级——通知对接FC进行自动化操作

4. 创建告警规则

在通知中选择刚才创建的行动策略。

SLS告警响应升级——通知对接FC进行自动化操作

告警触发后可以看到函数的调用日志里已经有相应的记录:

SLS告警响应升级——通知对接FC进行自动化操作

这里需要注意的是,告警通知对接到FC函数默认都是异步调用的方式。

案例:限制OSS Bucket必须为私有访问

考虑一个场景,无论是新建 OSS Bucket 还是修改 Bucket 的 ACL权限,都必须限制为私有访问,如果发现有公共读或者公共读写,就需要快速发现并立即自动修复。在这个场景下,如果完全依赖于人工去修复,就会比较麻烦,因此我们的解决思路如下:

  • 开通 OSS 操作审计日志
  • 由于新建 Bucket 或者修改 Bucket 的 ACL 权限,最终都是一条 PutBucket 的审计日志,因此我们可以检测该日志,然后抽取出地域、Bucket名称等信息,触发一条告警。
  • 告警通知发送到FC函数,FC对该Bucket的ACL权限进行检测,如果发现是不合规的,则自动修复。

1. 新建FC函数

我们可以新建一个FC函数,用来检测 Bucket 的 ACL 权限设置是否为私有,如果不是私有,则将其修改为私有。示例代码如下:

const OSS = require('ali-oss')
const accessKeyId = '**********'
const accessKeySecret = '**********'
async function checkBucketAcl(region, bucket) {
  const client = new OSS({
    region: `oss-${region}`,
    accessKeyId,
    accessKeySecret
  })
  const result = await client.getBucketACL(bucket)
  if (result.acl !== 'private') {
    await client.putBucketACL(bucket, 'private')
  }
}
exports.handler = async (event, context, callback) => {
  const alert = JSON.parse(event.toString())
  for (const result of alert.fire_results) {
    const { region, bucket } = result
    await checkBucketAcl(region, bucket)
  }
  callback(null, '')
}      

2. 开通OSS操作审计日志

打开日志服务控制台,进入日志审计服务,开启OSS访问日志。

SLS告警响应升级——通知对接FC进行自动化操作
SLS告警响应升级——通知对接FC进行自动化操作

3. 新建告警

在操作审计日志里,我们可以看到,创建 Bucket 或者修改 Bucket ACL 会记录如下日志:

SLS告警响应升级——通知对接FC进行自动化操作

因此我们可以通过如下查询分析语句筛选出 Bucket 的地域和名称:

event.ServiceName: Oss and  event.eventName: PutBucket | select "event.acsRegion" as region, split("event.eventSource", '.')[1] as bucket      

然后新建告警:

SLS告警响应升级——通知对接FC进行自动化操作

4. 事件触发

我们将 Bucket 的 ACL 修改为公共读:

SLS告警响应升级——通知对接FC进行自动化操作

然后会发现有一条告警触发:

SLS告警响应升级——通知对接FC进行自动化操作

FC的函数调用日志可以看到调用记录:

SLS告警响应升级——通知对接FC进行自动化操作

再回到 OSS 看,Bucket 的 ACL 已经是私有:

SLS告警响应升级——通知对接FC进行自动化操作

进一步参考

对我们工作感兴趣的,可以通过如下方式了解更多,谢谢关注!

SLS告警响应升级——通知对接FC进行自动化操作