让我们继续我们的AWS Lambda函数之旅,它将把EC2的AWS标签复制到所有EBS卷上,连接到它。
在第一部分中,AWS:Lambda--将EC2的标签复制到EBS,第一部分--Python和boto3,我们写了一个Python脚本,可以获得AWS区域内的所有EC2实例,然后为每个EC2抓取其EBS卷,然后将所有的AWS标签从EC2复制到其所有EBS,并将添加一个额外的标签。
在这一部分,我们将创建一个AWS Lambda函数,它将被AWS CloudWatch事件触发。
创建一个AWS Lambda函数
进入AWS Lambda,从 "Author from scratch"中创建一个新函数,运行时间设置为Python 3.8。
在执行角色中留下 "创建新角色"--稍后,我们将用IAM策略为其添加额外权限。
将脚本的代码粘贴到函数中,在代码的最后更新lambda_hanlder() 执行,并在其参数中代替上一篇文章中的 "0*,0″*,设置为event, context 。
为了检查context 对象的内容,我们稍后将使用它来获得EC2 ID,将其输出添加到函数的日志中。
添加import json 和print("CONTEXT: " + json.dumps(event)) 。
另外,对于ec2 = boto3.resource() 调用,删除AWS密钥,并留下资源的唯一类型--"ec2"。
不要忘记按下Deploy按钮,将你的改变应用到AWS Lambda上。
添加一个亚马逊EventBridge(CloudWatch事件)触发器
接下来,我们需要在每次在一个地区启动新的EC2时运行这个函数。
在这里,我们可以使用Amazon EventBridge(原CloudWatch Events)。转到CloudWatch Events > Rules,点击Create rule。
在事件模式中选择服务名称==EC2,在事件类型中选择 "EC2实例状态变化通知",在特定状态中选择运行。
在右侧的 "添加目标"中,选择我们上面创建的AWS Lambda函数。
在页面的最后,在*Show sample event(s)中,*我们可以看到一个event 对象的例子,该对象将被传递给函数以获得EC2 ID。
保存新的规则。
检查它是否作为一个触发器被添加到Lambda函数中。
让我们检查一下这将如何工作。
在CloudWatch规则中,打开规则的监控。
旋转一个新的EC2,例如通过触发一个自动扩展组。
在CloudWatch图表中,我们可以看到,该规则被触发了。
检查Lambda函数的日志。
AWS Lambda。未经授权的操作(UnauthorizedOperation
在日志中,我们对两条记录感兴趣。
第一条--是event 的内容,它是由print("CONTEXT: " + json.dumps(event)) 保存在日志中的。
而第二个是 ***"ClientError:在调用DescribeInstances操作时发生了一个错误(UnauthorizedOperation)。你没有被授权执行这个操作"***错误。
这里的问题很明显:我们的Lambda函数现在正在使用一个IAM角色,这个角色是在函数的创建过程中创建的,它没有对EC2操作的API调用的权限。
进入AWS IAM,找到该角色,点击附加策略。
创建一个新的政策。
在这里描述EC2的权限。
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "VisualEditor0",
"Effect": "Allow",
"Action": [
"ec2:DescribeInstances",
"ec2:DeleteTags",
"ec2:CreateTags",
"ec2:DescribeVolumes"
],
"Resource": "*"
}
]
}
保存它。
回到Lambda函数的IAM角色,添加一个新政策。
重复一次新的EC2启动,再次检查函数的日志。
Yay! "它成功了!" (c)
接下来,需要更新代码,从event 对象中获取instance-id 。
解析一个Lambda event
我们在创建CloudWatch规则时已经看到了event 的例子,我们知道它将作为一个带有一组键的python-dictionary被传递给lambda_handler() 函数。
{
"version": "0",
"id": "a99597e5-90a5-5ac3-3aba-da3ecd51452a",
"detail-type": "EC2 Instance State-change Notification",
"source": "aws.ec2",
"account": "534***385",
"time": "2021-10-11T09:02:09Z",
"region": "eu-west-3",
"resources": [
"arn:aws:ec2:eu-west-3:534***385:instance/i-0cc24729109ba61e5"
],
"detail": {
"instance-id": "i-0cc24729109ba61e5",
"state": "running"
}
}
而从这里我们需要抓取detail.instance-id 元素的一个值。
在脚本中添加一个新的变量,让我们称之为instance_id ,它将保留一个来自event["detail"]["instance-id"] 的值,然后通过使用这个ID,我们将创建一个新的ec2.Instance 类的对象,即ec2.Instance(instance_id) 。
我们不需要手动运行一个新的EC2,而是通过向它传递一个event 对象来为我们的Lambda使用测试。
创建一个新的测试事件。
添加一个类似于我们将从CloudWatch获得的数据。
{
"version": "0",
"id": "a99597e5-90a5-5ac3-3aba-da3ecd51452a",
"detail-type": "EC2 Instance State-change Notification",
"source": "aws.ec2",
"account": "534***385",
"time": "2021-10-11T09:02:09Z",
"region": "eu-west-3",
"resources": [
"arn:aws:ec2:eu-west-3:534***385:instance/i-0cc24729109ba61e5"
],
"detail": {
"instance-id": "i-0cc24729109ba61e5",
"state": "running"
}
}
运行测试。
"它成功了!"**(c)
现在让我们启动一个普通的EC2来检查整个方案,包括CloudWatch事件、Lambda的触发器以及其执行结果。
触发一个自动扩展组。
一个新的EC2i-051f2e1f1bc8d332b 被创建,检查Lambda的日志。
找到这个EC2的一个EBS。
并检查其标签。
而现在函数的代码是下一个。
#!/usr/bin/env python
import os
import json
import boto3
def lambda_handler(event, context):
ec2 = boto3.resource('ec2')
instance_id = event["detail"]["instance-id"]
instance = ec2.Instance(instance_id)
print("[DEBUG] EC2\n\t\tID: " + str(instance))
print("\tEBS")
for vol in instance.volumes.all():
vol_id = str(vol)
print("VOLUME: " + str(vol))
device_id = "ec2.vol.Device('" + str(vol.attachments[0]['Device']) + "')"
print("\t\tID: " + vol_id + "\n\t\tDev: " + device_id)
role_tag = vol.create_tags(Tags=set_role_tag(vol))
ec2_tags = vol.create_tags(Tags=copy_ec2_tags(instance))
print("\t\tTags set:\n\t\t\t" + str(role_tag) + "\n\t\t\t" + str(ec2_tags) + "\n")
def is_pvc(vol):
try:
for tag in vol.tags:
if tag['Key'] == 'kubernetes.io/created-for/pvc/name':
return True
break
except TypeError:
return False
def set_role_tag(vol):
device = vol.attachments[0]['Device']
tags_list = []
values = {}
if is_pvc(vol):
values['Key'] = "Role"
values['Value'] = "PvcDisk"
tags_list.append(values)
elif device == "/dev/xvda":
values['Key'] = "Role"
values['Value'] = "RootDisk"
tags_list.append(values)
else:
values['Key'] = "Role"
values['Value'] = "DataDisk"
tags_list.append(values)
return tags_list
def copy_ec2_tags(instance):
tags_list = []
values = {}
for instance_tag in instance.tags:
if instance_tag['Key'] == 'Env':
tags_list.append(instance_tag)
elif instance_tag['Key'] == 'Tier':
tags_list.append(instance_tag)
elif instance_tag['Key'] == 'DataClass':
tags_list.append(instance_tag)
elif instance_tag['Key'] == 'JiraTicket':
tags_list.append(instance_tag)
return tags_list
if __name__ == "__main__":
lambda_handler(event, context)
完成了。
-
[
](twitter.com/share?text=…: Linux, DevOps, and system administration "Tweet This Post")
-
[
](www.linkedin.com/shareArticl…: Linux, DevOps, and system administration)
类似的帖子
-
10/13/2021 aws:Lambda--将EC2的标签复制到其EBS,第一部分--Python和boto3 (0)
-
08/18/2021 aws:Lambda函数--概述,以及与AWS API Gateway的集成 (0)
-
07/19/2021 aws:Web应用防火墙概述、配置及其监控 (0)
-
07/15/2021aws:CloudTrail概述以及与CloudWatch和Opsgenie的集成( 0)
-
07/14/2021 aws:简单电子邮件服务的退订率以及与普罗米修斯的监控 (0)
The postAWS:Lambda--复制EC2标签到其EBS,第二部分--创建Lambda函数首次出现在RTFM:Linux、DevOps和系统管理上。






























