使用 ServiceNow 管理预警

本主题介绍如何在发生警报时提交自动 ServiceNow 票证。

在此方案中,只要 CPU 使用量超过预警指定的阈值,就会为您的呼叫工程师创建 ServiceNow 票证。

通过 Oracle Cloud Infrastructure 控制台、API 或 CLI 为云资源分配说明、标记或友好名称时,请勿输入机密信息。

此方案包括编写文件 ServiceNow 票证的函数(以及创建用于存储 ServiceNow 凭证的密钥)、将该函数和可选电子邮件作为订阅添加到主题,以及创建报警,以便在超过报警阈值时向该主题发送消息。消息将风扇传出到主题的订阅,其中除了包含函数外还包括组电子邮件地址。在收到消息时调用函数。

除此功能以外的所有内容都可以在控制台中设置。或者,您也可以使用 Oracle Cloud Infrastructure CLI 或 API,这样您就可以自己执行各个操作。

下图说明了常规处理流程:



服务通知 -oracle.zip

将您的 ServiceNow 凭据存储在密钥中

创建后面的函数时将引用的密钥。

使用控制台创建密钥(还可以使用命令行界面 (command line interface,CLI) 或应用程序编程接口 (application programming interface,API) 创建密钥。

  1. 打开导航菜单,单击 Identity & Security ,然后单击 Vault
  2. 在“List Scope(列表范围)”下的“Compartment(区间)”列表中,单击要创建密钥的区间的名称。
  3. 从区间中的 Vault 列表中,执行以下操作之一:
    • 单击要创建密钥的 Vault 的名称。
    • 为密钥创建新的 Vault,然后单击 Vault 的名称。
  4. 创建 username 密钥:
    1. 单击安全,然后单击创建密钥
    2. 在“创建密钥”对话框中,从“在区间中创建”列表中选择区间。密钥可以存在于 Vault 所在的区间之外。)
    3. 单击名称,然后输入名称以标识密钥。避免在此字段中输入任何机密信息。
      示例名称:servicenow_username_plain_text
    4. 单击说明,然后输入密钥的简要说明以帮助标识该密钥。避免在此字段中输入任何机密信息。
      示例说明:servicenow_username_plain_text
    5. 选择要用于在密钥导入到 Vault 时加密密钥内容的主加密密钥(密钥必须属于同一 Vault)。
    6. 对于密钥类型模板,请选择纯文本
    7. 单击秘密内容,然后输入您的 ServiceNow 用户名:
      <your-servicenow-username>
    8. 单击创建密钥
    9. 请注意密钥 OCID。

创建函数

从以下示例代码开始,创建用于提交 ServiceNow 票证的函数,然后授权该函数在使用 Oracle Cloud Infrastructure Vault 服务创建的密钥中访问 ServiceNow 凭证。

代码示例包括虚拟函数中使用的变量 SNOW_URL、SNOW_USER_ID_SEC 和 SNOW_USER_PWD_SEC。您可以选择直接从函数读取这些值,或者将值作为定制配置参数传递。

#####################################################
# THIS SAMPLE CODE IS FOR DEMO PURPOSES ONLY
#*************************************************
# ******** DO NOT USE IN PRODUCTION *************
# ************************************************
#####################################################
import io
import sys
import oci
import json
import base64
import requests
from fdk import response
SNOW_URL = '<Provide Service Now URL here>'
SNOW_USER_ID_SEC = '<Provide the OCID of OCI Secret for Service Now User ID>'
SNOW_USER_PWD_SEC = '<Provide the OCID of OCI Secret for Service Now User Password>'
OCI_TO_SNOW_SEV_MAP =
{    'CRITICAL'  : '1',    'WARNING'   : '2',    'ERROR'     : '3',    'INFO'      : '4' }
def handler(ctx, data: io.BytesIO = None):
    try:
        funDataStr = data.read().decode('utf-8')
        funDataJSON =  json.loads(funDataStr)
        alarmData = {}
        alarmData['type'] = funDataJSON['type']
        alarmData['metaDataList'] = funDataJSON['alarmMetaData']
        alarmData['title'] = funDataJSON['title']
        alarmData['body'] = funDataJSON['body']
        alarmData['sev'] = OCI_TO_SNOW_SEV_MAP[funDataJSON['severity'].upper()]
        if alarmData['type'].upper() == 'OK_TO_FIRING':
            snowURL = SNOW_URL
            snowUsrIDSec = SNOW_USER_ID_SEC
            snowUsrPwdSec = SNOW_USER_PWD_SEC
            ociResPrncplSigner = oci.auth.signers.get_resource_principals_signer()
            ociSecSvc = oci.secrets.SecretsClient(config={}, signer=ociResPrncplSigner)
            snowUserID = readSecValueFromSecSvc(ociSecSvc, snowUsrIDSec)
            snowPswd = readSecValueFromSecSvc(ociSecSvc, snowUsrPwdSec)
            snowData = getSNOWData(alarmData)
            sendDataToSnow(snowURL, snowUserID, snowPswd, snowData)
    except Exception as e:
        sys.stderr.write("Exception : " + str(e))
        sys.stderr.write("Exception Class : " + str(e._class_))
    return response.Response(ctx, response_data="", headers={"Content-Type": "application/json"})
def sendDataToSnow(snowURL, uid, pwd, snowData):
    try:
{ 
snowHdrs =
      "Content-Type" : "application/json",
counter = 0
for sd in snowData:
"Accept" : "application/json"         }
        snowResp = requests.post(snowURL, auth=(uid, pwd), headers=snowHdrs, data=json.dumps(sd))
except Exception as e:
    sys.stderr.write("Exception : " + str(e))
    sys.stderr.write("Exception Class : " + str(e._class_))
   def getSNOWData(alarmData):
       snowData = []
       if alarmData['type'].upper() == 'OK_TO_FIRING':
           alrmMD = alarmData['metaDataList'][0]
           for d in alrmMD['dimensions']:
               snowDataElem = {}
               snowDataElem['node'] = d['resourceDisplayName']
               snowDataElem['source'] = 'OCI'
               snowDataElem['severity'] = alarmData['sev']
               snowDataElem['description'] = alarmData['body']
               snowDataElem['type'] = alarmData['title']
               snowData.append(snowDataElem)
       return snowData
   def readSecValueFromSecSvc(ociSecSvc, secID):
       secResp = ociSecSvc.get_secret_bundle(secID)
       secContent = secResp.data.secret_bundle_content.content
       secret_content = base64.b64decode(secContent).decode('utf-8')
       return secret_content

使用动态组授予功能读取密钥的能力。您的函数必须具有此授权才能访问 ServiceNow 凭证,这些凭证存储在您之前创建的密钥中。

  1. 查找并记下采用以下格式的函数 OCID:
    ocid1.fnfunc.oc1.iad.<exampleuniqueID>

    通过指定以下规则,将函数包括在相关的动态组中:

    resource.id = '<function-ocid>'

    或者,您可以创建一个包含所有功能的动态组:

    ALL{resource.type=’fnfunc’, resource.compartment.id=’<compartment_OCID>’}
  2. 通过添加以下策略授予动态组对密钥的访问权限。
    allow dynamic-group <dynamic-group-name> to read secret-family in tenancy

    要授权您的功能访问其他 Oracle Cloud Infrastructure 资源(例如计算实例),请将该功能包含在动态组中,并创建一个策略来授予动态组对这些资源的访问权限。

创建话题

创建将用于订阅和预警的主题。

主题是用于向订阅发送消息的通信渠道。每个主题名称在租户中都是唯一的。可以使用控制台、命令行界面 (command line interface,CLI) 或应用程序编程接口 (application programming interface,API) 创建主题。

必须部署函数,然后才能将其用于主题。

  1. 要使用控制台创建主题,请执行以下操作:
    1. 打开导航菜单,然后单击开发人员服务。在“应用程序集成”下,单击通知
    2. 单击主题列表顶部的创建主题
    3. 在“Create Topic(创建主题)”对话框中,配置主题:
      • 名称:为主题指定友好名称。它在租户中必须唯一;验证区分大小写。请避免输入机密信息。
      • 说明:根据需要输入主题的说明。请避免输入机密信息。
    4. 单击创建
  2. 要使用 CLI 创建主题,请打开命令提示符并输入类似于以下内容的命令:
    oci ons topic create
    --name "My Topic"
    --compartment-id "<compartment-ocid>"
  3. 要使用 API 创建主题,请使用类似于以下内容的操作:
    POST /20181201/topics
    Host: notification.us-phoenix-1.oraclecloud.com
    <authorization and other headers>
    {
      "name": "My Topic",
      "compartmentId": "<compartment_OCID>"
    }
    

创建订阅

为主题创建订阅。

订阅是主题的端点。已发布消息会发送到主题的每个订阅。

您必须先部署此功能,然后才能将其用于订阅,并且您必须具有 FN_INVOCATION 权限才能将该功能作为订阅添加到主题。

  1. 要使用控制台创建功能订阅,请执行以下操作:
    1. 打开导航菜单,然后单击开发人员服务。在“应用程序集成”下,单击通知。单击要将订阅添加到的主题的名称。
    2. 在主题详细信息页面上,单击创建订阅
    3. 在“创建订阅”对话框中,配置功能订阅。功能订阅不需要确认。
      • 对于订阅协议,单击函数
      • 对于函数区间,单击包含函数的区间。
      • 对于“Function Application(函数应用程序)”,单击包含函数的应用程序。
      • 对于“Function(函数)”,单击您的函数。
    4. 单击创建
  2. 要使用控制台创建可选电子邮件订阅,请执行以下操作:
    1. 打开导航菜单,然后单击开发人员服务。在“应用程序集成”下,单击通知。单击要将订阅添加到的主题的名称。
    2. 在主题详细信息页面上,单击创建订阅
    3. 在“创建订阅”对话框中,配置电子邮件订阅。
      • 对于订阅协议,单击电子邮件
      • 对于“电子邮件”,指定电子邮件地址。
    4. 单击创建
      将创建电子邮件订阅,并将订阅确认 URL 发送到指定的电子邮件地址。订阅保持待定状态,直到得到确认为止。要确认您的新电子邮件订阅,请打开电子邮件并单击确认 URL。
  3. 要使用 CLI 创建订阅:
    1. 要创建函数订阅,请打开命令提示符并输入类似于以下内容的命令:
      oci ons subscription create
      --compartment-id "<compartment-ocid>"
      --topic-id "<topic-ocid>" 
      --protocol "ORACLE_FUNCTIONS"
      --subscription-endpoint "<function-ocid>"
    2. 要创建电子邮件订阅,请打开命令提示符并输入类似于以下内容的命令:
      oci ons subscription create
      --compartment-id "<compartment-ocid>"
      --topic-id "<topic-ocid>" 
      --protocol "EMAIL"
      --subscription-endpoint "team@example.com"
  4. 要使用 API 创建订阅:
    1. 要使用 API 创建功能订阅,请使用类似于以下内容的操作:
      POST /20181201/subscriptions
      Host: notification.us-phoenix-1.oraclecloud.com
      <authorization and other headers>
      {
        "topicId": "<topic_OCID>",
        "compartmentId": "<compartment_OCID>",
        "protocol": "ORACLE_FUNCTIONS",
        "endpoint": "<function_OCID>"
      } 
    2. 要使用 API 创建电子邮件订阅,请使用类似如下的操作:
      POST /20181201/subscriptions
      Host: notification.us-phoenix-1.oraclecloud.com
      <authorization and other headers>
      {
        "topicId": "<topic_OCID>",
        "compartmentId": "<compartment_OCID>",  
        "protocol": "EMAIL",
        "endpoint": "team@example.com"
      
      } 

创建预警

创建在超过预警阈值时向主题发送消息的预警。然后,通知会向该主题中的活动订阅发送消息。

  1. 要使用控制台创建预警,请执行以下操作:
    1. 打开导航菜单,然后单击观测和管理。在监视下,单击预警定义
    2. 单击创建预警
    3. 创建预警页的定义预警下,设置阈值:
      在“Metric Description(度量说明)”下:
      • 区间:选择包含感兴趣的计算实例的区间。
      • 度量名称空间:oci_computeagent
      • 度量名:CpuUtilization
      • 间隔: 1m
      • 统计信息: Count
      在触发规则下:
      • 运算符: greater than
      • 值: 90
      • 触发延迟分钟数: 1
    4. 要定义预警通知,请将以前创建的主题添加为目标。
      在“Destination(目标)”下:
      • 目标服务:通知
      • 区间:(选择包含您的主题的区间)
      • 主题:(选择您的主题)
    5. 单击保存预警
  2. 要使用 CLI 创建预警,请打开命令提示符并输入类似于以下内容的命令:
    oci monitoring alarm create
    --display-name "My Alarm"
    --compartment-id "<compartment-ocid>" 
    --metric-compartment-id "<compartment-ocid>" 
    --namespace "oci_computeagent" 
    --query-text "CPUUtilization[1m].count() > 90"
    --severity "CRITICAL"
    --destinations "<topic-ocid>"
    --is-enabled true
  3. 要使用 API 创建预警,请使用类似于以下内容的操作:
    POST /20180401/alarms
    Host: telemetry.us-phoenix-1.oraclecloud.com
    <authorization and other headers>
    {
      "displayName": "My Alarm",
      "compartmentId": "<compartment_OCID>",
      "metricCompartmentId": "<compartment_OCID>",
      "namespace": "oci_computeagent",
      "query": "MemoryUtilization[1m].max() > 90",
      "severity": "CRITICAL",
      "destinations":
        [
          "<topic_OCID>"
        ],
      "isEnabled": true
    }