2023-07-25
在基础设施的选择上,很多用户选择多云部署,云端与线下数据中心结合的方式来最大限度的整合优势资源,保证应用程序的高可用和低成本。在日常运维的过程中,用户不可避免的接触不同平台的资源与告警系统,对运维和安全工作提出了挑战。尤其是在高级别告警发生的时候,告警系统需要在第一时间用电话的方式直接联系运维与安全人员,这就要保证电话告警系统的可靠性和高可用性。同时在多应用,多项目的场景中,需要按照应用与项目区分负责的运维人员。由于告警,尤其是高级别告警并非是持续发生,对应的成本也需要控制在合理范围内。
Amazon Connect 是亚马逊构建的云联络中心服务。本文主要介绍利用 Amazon Connect 的电话外呼功能,结合 Amazon SQS,Amazon DynamoDB,AWS Lambda 这三种无服务器服务,构建低成本,高可用的电话告警系统。并且方便多云与线下数据中心的接入。
本文解决方案利用 Amazon SQS 队列做为接受告警信息的消息队列,使用 Amazon DynamoDB 表按应用或项目储存相应运维人员的电话,并储存每次告警事件的记录。由 AWS Lambda 函数按事件触发 Amazon Connect 流,实现电话告警。
简要流程:
至此,无论用户的应用在其他云服务商或者线下数据中心,客户只需要配置相应的 Amazon SQS 队列权限,就可以接入到这个电话告警系统,并将每次事件的电话告警记录保存在 Amazon DynamoDB 表中。这个架构中使用的 Amazon SQS,Amazon DynamoDB,AWS Lambda 均为无服务器资源,保证了服务的可靠性、可用性的同时,极大的降低了使用与维护成本。
从 AWS 控制台进入 Amazon Connect 服务页面,选择添加实例, 我们需要创建一个有对外呼出功能的实例,具体配置步骤参考此处文档。注意在设置通话时,通话选项为允许出站呼叫。
创建成功后,通过 Amazon Connect 页面进入 Instance,显示状态为活跃。
点击进入访问 URL, 通过上一步中管理员账户登陆。在左侧列表申请对外拨打的源电话号码。根据要拨打的对象国家,选择合适的源号码属地,对应列表参考此处文档。本文选择了泰国的免费电话进行测试,如下图所示。
从 Amazon Connect 管理页面通过访问 URL 进入服务页面,使用管理员身份登录。从左侧菜单中选择流,点击创建联系流,进入流页面。在流页面右上选择导入选项。
将下面的配置代码复制粘贴到本地 demo.txt 文档,选择此 demo.txt 文档导入。
导入后可见如下流页面:
Amazon SQS 队列用于触发 AWS Lambda 函数,同时可使用死信队列 DLQ 接收无法交付的消息。
进入 Amazon SQS 页面,点击创建队列。输入队列名称 demo_queue_amazon_connect_dlq
,其他选择为默认即可,点击创建队列。此队列将作为死信队列。
待队列创建完成,进入 Amazon SQS 页面,点击创建队列。输入队列名称 demo_queue_amazon_connect
。 配置可见性超时为 90 秒,这保证了可见性超时大于 AWS Lambda 函数的超时数值。死信队列 ARN 为上面 demo_queue_amazon_connect_dlq
队列 ARN,其他配置保持不变,点击创建队列。
创建完成状态如下图所示:
此表用于根据不同的项目名称存储运维团队电话号码。假设每个项目都有一个 3 层的运维支持团队,当第一层运维人员没有接到告警电话后,Amazon Connect 会获取上一层的运维人员电话,继续拨打。
进入 Amazon DynamoDB 界面,点击创建表。输入表名称 connect-contact-info
。 输入分区键名称 projectName
。选择自定义设置,表类为 DynamoDB 标准,读/写容量设置为按需。其他配置为默认,点击创建表。
表创建成功后,点击操作,选择创建项目,输入项目名称 project1。 点击添加新属性,选择字符串,并输入 3 层运维人员电话。点击创建项目。
此表用于存储 Amazon Connect 的外呼事件。
进入 Amazon DynamoDB 界面,点击创建表。输入表名称 connect-event-info
。 输入分区键名称 eventId
。选择自定义设置,表类为 DynamoDB 标准,读/写容量设置为按需。其他配置为默认,点击创建表。
从 AWS 控制台进入 AWS Lambda 函数,点击创建函数。输入函数名称 amazon_connect_function
。选择 python3.9 运行时环境,其他参数为默认。点击创建函数。
点击配置,选择常规配置,编辑超时时间为 1 分 15 秒。由于 Amazon Connect 在做 start_outbound_voice_contact
API 呼叫时超时为 60 秒,在代码中我们配置了 65 秒的 sleep 时间,用来抓取外呼电话是否被接听。
在同页面点击权限,选择角色名称进入 AWS IAM 管理页面。点击添加权限,创建内联策略。此处我们要创建三个内联策略给 AWS Lambda 函数赋权,分别对应 Amazon Connect 权限,Amazon DynamoDB 表权限,和 Amazon SQS 队列权限。点击进入 JSON 模式,配置策略如下:
配置后如下图:
返回 AWS Lambda 函数页面,点击配置,选择触发器,选择添加触发器。选择的 Amazon SQS 队列作为触发源,选择之前创建 demo_queue_amazon_connect
队列 ARN,将批处理大小设置为 1。完成后点击添加。本文提供的 AWS Lambda 函数代码不包含批处理逻辑。
点击进入函数,将下面的代码复制到 lambda_function.py
中,点击 Deploy 生效。
根据之前创建的资源,更新代码中的 Global Variable 部分:
InstanceId
是 Amazon Connect 的实例 idContactFlowId
是 Amazon Connect 流 idSourcePhoneNumber
是从 Amazon Connect 申请到的源电话号码QueueUrl
是 Amazon SQS 消息队列的 URLContactInfoTableName
是 Amazon DynamoDB 通讯表的名字EventTableName
是 Amazon DynamoDB 事件表的名字ContactLayer
是在 Amazon DynamoDB 通讯表中一个项目里面联系人数量RoundCallLimit
是在电话未接通的情况下,需要重复呼叫几轮联系人DelaySeconds
是指在电话未接通的情况下,AWS Lambda 函数将事件重新放回队列中,间隔多久变为可见,被函数重新处理在告警端配置权限,告警服务器只需要将告警事件发送到队列的权限。可以通过创建 AWS IAM 用户实现。
从管理控制台进入AWS IAM 页面,选择用户,添加用户,输入用户名 demo-connect-user
。 此用户我们将不会用于管理控制台登录。点击下一步,使用默认设置。在此处不需添加任何权限,点击下一步,选择创建用户。
创建成功后, 选择该用户,点击添加权限,创建内联策略,选择 JSON,复制如下策略到 JSON 中,复制后替换 Resource 中 ARN。
点击查看策略,输入策略名称 demo-connect-policy
, 点击创建策略。
点击安全凭证,创建访问密钥,选择本地代码,点击下一步。描述标签可填写 demo-connect
。点击创建访问密钥,将访问密钥保存到本地使用。此处 AWS IAM 用户密钥将用于测试,AWS IAM 权限管理安全最佳实践请参考此处文档。
将得到的 IAM 用户密钥 aws_access_key_id
和 aws_secret_access_key
配置到本地 ~/.aws/ credentials
中,此处我们资源部署使用在 ap-southeast-1
区域,并将输出定为 json
格式。
[demo-connect-user]
aws_access_key_id=<your access key>
aws_secret_access_key=<your secret access key>
region = ap-southeast-1
output = json
我们使用 AWS 提供的 Python SDK 环境进行测试,配置环境参考此处文档。配置完成后将以下测试代码复制粘贴到 test.py
中。更新其中 QueueUrl 变量,可以从 Amazon SQS 管理页面获取此 URL。
运行测试脚本,此处测试成功打通电话,我们可以选择不接起电话,此时程序会从 Amazon DynamoDB 通讯表中获取上一层运维人员电话,继续拨打,直到接通。
接通后按 1 听取留言。
此时我们查看 Amazon DynamoDB 事件表 connect-event-info
中会有事件已经相关的电话记录:
进入项目可以看到每次 Amazon Connect 拨打的 ContactId
。
同时我们也可以根据 eventId
与 ContactId
在 AWS Lambda 函数的日志中查找相关记录。
本文展示了通过使用 Amazon SQS,Amazon DynamoDB,AWS Lambda 这三种无服务器服务,配合 Amazon Connect 搭建多层级运维告警系统,使用简单的 AWS IAM 用户配置,打通多云及线下数据中心的告警需求。