基于IaC自动化部署事件总线

本文介绍如何应用IaC(Infrastructure as Code)理念自动化部署事件总线EventBridge,帮助您解决大量云产品手工管理负担沉重的问题。

背景信息

IaC是一种以代码来配置和管理虚拟机、网络等基础设施的实践方法。通过将基础设施代码化、版本化来取代传统的手工操作基础设施。传统的基础设施管理方法是人工手动处理模式,不仅效率低下,而且还有很多人为操作的风险。在IaC的实践中,开发者通过代码描述基础设施的配置及变更,再执行代码完成配置和变更,就可以在几分钟后得到所需的虚拟机、网络等云上的服务,极大地缩短了部署时间,同时还能够保证多个环境的配置一致性,减少人为操作,降低了引入错误的概率。

HashiCorp Terraform是一个IT基础架构自动化编排工具。作为最主流的IaC工具之一,它提供了强大的自动化管理基础设施的能力。Terraform的命令行接口(CLI)提供一种简单机制,用于将配置文件部署到阿里云或其他任意支持的云上,并对其进行版本控制。阿里云的大多数产品(包括事件总线EventBridge)都对Terraform进行支持,使得跨多云部署基础设施变得简单。更多信息,请参见什么是Terraform

本文以Terraform为例介绍两个基于IaC理念自动化部署基础设施的案例。

前提条件

您已完成以下操作:

场景一:通过钉钉监控云上资源状态变化

若您使用了大量云资源作为生产环境,传统的手工操作控制台方式虽然简单易操作,但是不能很好地感知云上资源的变更操作。使用事件总线EventBridge将事件的状态变更投递到钉钉,用户可以通过钉钉机器人的消息通知更加直观地感知云上资源的变更。此处以ActionTrail:ApiCall事件为例,为您演示使用Terraform工具将所有云产品事件源的ActionTrail:ApiCall事件投递给钉钉。

  1. 创建一个钉钉机器人,记录Webhook地址和密钥。详细操作,请参见钉钉官方文档

  2. 创建terraform.tf文件。Terraform可以通过此文件调用阿里云上的资源。

    # AccessKey ID和AccessKey Secret请参照前提条件在阿里云控制台的AccessKey管理页面获取。
    # Region Id为您部署钉钉监控资源变化的目标地域,例如"cn-hangzhou"。
    provider "alicloud" {
      access_key = "<your AccessKey Id>"             
      secret_key = "<your AccessKey Secret>"         
      region = "<Region Id>"                        
    }
  3. 创建1_actiontrail2dingding.tf文件,声明一个default总线上的规则:audit_notify,通过后缀匹配的方式将所有云产品事件源的ActionTrail:ApiCall事件路由到钉钉上。

    resource "alicloud_event_bridge_rule" "audit_notify" {
      # default总线默认存在,这里可以直接使用。
      event_bus_name = "default"
      # 规则名称,您可以自定义名称。
      rule_name      = "audit_notify"              
      description    = "demo"
      # 通过后缀匹配的方式过滤来自所有云产品事件源的ActionTrail:ApiCall事件。
      filter_pattern = jsonencode(
        {
          "type" : [
            {
              "suffix" : ":ActionTrail:ApiCall"
            }
          ]
        }
      )
    
      targets {
        target_id = "test-target"
        endpoint  = "<your Dingtalk Robot Webhook url>"         #您创建的钉钉机器人的Webhook地址。
        type      = "acs.dingtalk"                              #投递的事件类型为钉钉。
        param_list {
          resource_key = "URL"
          form         = "CONSTANT"
          value        = "<your Dingtalk Robot Webhook url>"    #您创建的钉钉机器人的Webhook地址。
        }
        param_list {
          resource_key = "SecretKey"
          form         = "CONSTANT"
          value        = "<your Dingtalk Robot Secret Key>"     #您创建的钉钉机器人的密钥。
        }
        # 这里展示了TEMPLATE类型的事件转换描述。
        # value是使用jsonpath引用事件内容的字典,template则是模板内容,事件总线EventBridge最终会根据这两者结合事件本身渲染出这个参数的值。
        param_list {
          resource_key = "Body"
          form         = "TEMPLATE"
          value        = jsonencode(
            {
              "source": "$.source",
              "type": "$.type"
              "region": "$.data.acsRegion",
              "accountId" : "$.data.userIdentity.accountId",
              "eventName" : "$.data.eventName",
            }
          )
          template = jsonencode(
            {
              "msgtype" : "text",
              "text" : {
                "content": "来自 $${source} 的 $${type} 审计事件: $${accountId} 在 $${region} 执行了 $${eventName} 操作"
              }
            }
          )
        }
      }
    }
                            
  4. 使用Terraform工具部署1_actiontrail2dingding.tf中创建的规则。

    1. 在命令行窗口执行初始化命令:terraform init。出现以下结果则表示初始化成功:

      Terraform has been successfully initialized!
    2. 执行预览变更命令:terraform plan。在运行结果中可以预览到audit_notify规则将被创建。

      alicloud_event_bridge_rule.audit_notify will be created
    3. 执行应用变更命令:terraform apply。出现以下结果则表示规则被创建成功:

      Apply complete! Resources: 1 added, 0 changed, 0 destroyed.
  5. 触发事件。以密钥管理服务产品为例,创建一个ActionTrail:ApiCall事件。

    1. 登录密钥管理服务控制台,在左侧导航栏,单击凭据管理

    2. 在顶部菜单栏,选择地域。

    3. 凭据页面,单击创建凭据,根据提示创建凭据。

  6. 结果验证。

    1. 查看钉钉机器人推送的消息通知。

      钉钉机器人

    2. 查看事件详情。

      1. 事件总线EventBridge控制台

      2. 在左侧导航栏,单击事件总线

      3. 在顶部菜单栏,选择地域。

      4. 事件总线页面,找到audit_notify,在其右侧操作列,单击事件追踪查看事件轨迹。

场景二:自定义总线触发函数计算

当您的应用产生的事件是通过函数计算FC(Function Compute)进行处理,那么就可以通过事件总线EventBridge的自定义事件源和函数计算事件目标来实现,与传统控制台部署方式不同,本案例使用Terraform工具自动化部署自定义总线与函数计算服务。

  1. 创建terraform.tf文件。Terraform可以通过此文件调用阿里云上的资源。

    # AccessKey ID和AccessKey Secret请在阿里云控制台的AccessKey管理页面获取。
    # Region Id为您部署自定义总线触发函数计算的目标地域,例如"cn-hangzhou"。
    provider "alicloud" {
      access_key = "<your Access Key Id>"            
      secret_key = "<your Access Key Secret>"        
      region = "<Region Id>"                        
    }
  2. 创建Python脚本文件src/index.py,模拟对事件进行处理。

    # -*- coding: utf-8 -*-
    import logging
    
    def handler(event, context):
      logger = logging.getLogger()
      logger.info('evt: ' + str(event))
      return str(event)
  3. 创建2_trigger_function.tf文件,声明自定义总线、自定义事件源、函数计算服务、函数和过滤自定义事件源的规则。

    # 声明一个叫demo_event_bus的自定义总线。
    resource "alicloud_event_bridge_event_bus" "demo_event_bus" {
      event_bus_name = "demo_event_bus"
      description    = "demo"
    }
    
    # 声明一个在demo_event_bus总线上的自定义事件源。
    resource "alicloud_event_bridge_event_source" "demo_event_source" {
      event_bus_name         = alicloud_event_bridge_event_bus.demo_event_bus.event_bus_name
      event_source_name      = "demo_event_source"
      description            = "demo"
      linked_external_source = false
    }
    
    # 声明一个叫fc_service的函数计算服务,publish=true意味着会立即部署上传的函数代码。
    resource "alicloud_fc_service" "fc_service" {
      name        = "eb-fc-service"
      description = "demo"
      publish     = true
    }
    
    # 将前面准备的Python脚本文件打包成ZIP用于部署到函数计算。
    data "archive_file" "code" {
      type        = "zip"
      source_file = "${path.module}/src/index.py"
      output_path = "${path.module}/code.zip"
    }
    
    # 声明一个fc_service服务中的函数,其中filename引用了上面描述的ZIP包,会将这个代码包上传。
    resource "alicloud_fc_function" "fc_function" {
      service     = alicloud_fc_service.fc_service.name
      name        = "eb-fc-function"
      description = "demo"
      filename    = data.archive_file.code.output_path
      memory_size = "128"
      runtime     = "python3"
      handler     = "index.handler"
    }
    
    # 声明一个在demo_event_bus总线上的规则。
    resource "alicloud_event_bridge_rule" "demo_rule" {
      event_bus_name = alicloud_event_bridge_event_bus.demo_event_bus.event_bus_name
      rule_name      = "demo_rule"
      description    = "demo"
      # 通过匹配source过滤来自于前面创建的自定义事件源的事件。
      filter_pattern = jsonencode(
        {
          "source" : ["${alicloud_event_bridge_event_source.demo_event_source.id}"]
        }
      )
    
      targets {
        target_id = "demo-fc-target"
        type      = "acs.fc.function"
        # <Region Id>填写您的阿里云账号地域ID,<your Account Id>填写您的阿里云账号ID。
        endpoint  = "acs:fc:<Region Id>:<your Account Id>:services/${alicloud_fc_service.fc_service.name}.LATEST/functions/${alicloud_fc_function.fc_function.name}"
        param_list {
          resource_key = "serviceName"
          form         = "CONSTANT"
          value        = alicloud_fc_service.fc_service.name
        }
        param_list {
          resource_key = "functionName"
          form         = "CONSTANT"
          value        = alicloud_fc_function.fc_function.name
        }
        param_list {
          resource_key = "Qualifier"
          form         = "CONSTANT"
          value        = "LATEST"
        }
        # 注意form=ORIGINAL意味着每次投递事件都会将事件的原始内容作为这个参数的值。
        param_list {
          resource_key = "Body"
          form         = "ORIGINAL"
        }
      }
    }                        
  4. 使用Terraform工具部署2_trigger_function.tf中创建的资源。

    1. 在命令行窗口执行初始化命令:terraform init。出现以下结果则表示初始化成功:

      Terraform has been successfully initialized!
    2. 执行预览变更命令:terraform plan。在结果中可以预览到即将被创建的资源:

      alicloud_event_bridge_event_bus.demo_event_bus will be created
      alicloud_event_bridge_event_source.demo_event_source will be created
      alicloud_event_bridge_rule.demo_rule will be created
      alicloud_fc_service.fc_service will be created
      alicloud_fc_function.fc_function will be created
    3. 执行应用变更命令:terraform apply。出现以下结果则表示资源被创建成功:

      Apply complete! Resources: 5 added, 0 changed, 0 destroyed.
  5. 在控制台上验证创建好的资源,即自定义总线、自定义事件源、函数计算服务、函数和过滤自定义事件源的规则。

    1. 查看自定义事件总线和自定义事件源是否创建成功。

      1. 登录事件总线EventBridge控制台,在左侧导航栏,单击事件总线

      2. 在顶部菜单栏,选择地域。

      3. 事件总线页面,单击demo_event_bus

      4. 在左侧导航栏,单击事件源,在事件源页面,单击demo_event_source查看详情。

    2. 查看函数计算服务和函数是否创建成功。

      1. 登录函数计算控制台,在左侧导航栏,单击服务及函数

      2. 在顶部菜单栏,选择地域。

      3. 服务列表页面,单击eb-fc-service

      4. 在左侧导航栏,单击函数管理,然后单击eb-fc-function查看函数详情。

    3. 触发事件。

      1. 登录事件总线EventBridge控制台,在左侧导航栏,单击事件总线

      2. 在顶部菜单栏,选择地域。

      3. 事件总线页面,单击demo_event_bus

      4. 在左侧导航栏,单击事件规则,单击demo_rule

      5. demo_rule页面,单击发布事件

      6. 发布事件至自定义事件总线 demo_event_bus面板,从自定义事件源下拉列表,选择demo_event_source,单击确认

    4. 查看事件详情。

      1. demo_event_bus页面,单击事件追踪

      2. 找到发布的事件,在其操作列,单击事件轨迹,查看事件已经被成功投递到函数eb-fc-function上。事件投递成功