部署 Lambda 函数以定期删除 EC2 实例

我叫寺冈,是一名基础设施工程师。
今天我想总结一下我在公司内部部署 Lambda 函数的经验。

除了客户服务器运行所在的 AWS 账户外,我们还
管理着内部工程师用于进行技术验证的账户。

此账户已设置登录安全设置(IAM 用户/角色/MFA 身份验证),并定义了相关规则,但
任何授权成员均可不受限制地自由操作该账户。如果
测试账户的规则过多,将难以使用。

在我们的案例中,验证过程中创建频率最高的资源是 EC2 实例,
虽然可以随意创建,但有不少情况下忘记停止或删除它们。

当然,如果这种情况频繁发生,就会产生不必要的成本。
虽然我们假设您
在使用完毕后会停止或删除 EC2 实例,但为了以防万一您忘记,我们引入了一种机制,可以使用 Lambda 定期自动删除 EC2 实例。

以下是我所做工作的总结。

创建 Lambda 函数

我用Python写的。
不过我个人更熟悉Go语言,所以我应该用Go语言写的。

import json import boto3 import os import requests def terminate(event, context): EXCLUDE_TERMINATE_TAG = os.environ['EXCLUDE_TERMINATE_TAG'] CHATWORK_API_KEY = os.environ['CHATWORK_API_KEY'] CHATWORK_ROOM_ID = os.environ['CHATWORK_ROOM_ID'] CHATWORK_ENDPOINT = os.environ['CHATWORK_ENDPOINT'] ec2 = boto3.client('ec2') without_tag = ec2.describe_instances() with_tag = ec2.describe_instances( Filters=[{ 'Name': 'tag:' + EXCLUDE_TERMINATE_TAG, 'Values': ['true'] }] ) without_tag_set = set(ec2['InstanceId'] for resId in without_tag['Reservations'] for ec2 in resId['Instances']) with_tag_set = set(ec2['InstanceId'] for resId in with_tag['Reservations'] for ec2 in resId['Instances']) target_instances = without_tag_set - with_tag_set list_target_instances = list(target_instances) if len(list_target_instances) != 0: terminateInstances = ec2.terminate_instances( InstanceIds=list_target_instances ) notify_instances = '' if len(with_tag['Reservations']) != 0: for reservation in with_tag['Reservations']: for instance in reservation['Instances']: if len(instance['Tags']) != 0: instance_name = '' for在 instance['Tags'] 中:如果 tag['Key'] == 'Name':instance_name = tag['Value'] instance_state_enc = json.dumps(instance['State']) instance_state_dec = json.loads(instance_state_enc) 如果 instance_name != '':notify_instances += instance['InstanceId'] + ' -> ' + instance_name + '(' + instance_state_dec['Name'] + ')' + '\n' 否则:notify_instances += instance['InstanceId'] + ' -> ' + 'None' + '(' + instance_state_dec['Name'] + ')' + '\n' message = '[To:350118][To:1786285][info][title][Beyond POC] There are returned instances (devil)[/title]' + notify_instances + '[/info]' PostChatwork(CHATWORK_ENDPOINT,CHATWORK_API_KEY,CHATWORK_ROOM_ID,message) response = { "TerminateInstances": list_target_instances } print (response) return response def PostChatwork(ENDPOINT,API_KEY,ROOM_ID,MESSAGE): post_message_url = '{}/rooms/{}/messages'.format(ENDPOINT, ROOM_ID) headers = { 'X-ChatWorkToken': API_KEY } params = { 'body': MESSAGE } resp = requests.post(post_message_url, headers=headers, params=params)

我想你看了代码就能明白了。

  • 删除没有排除标签的实例
  • 通知 Chatwork 哪些实例已被排除在删除范围之外


如果帖子在没有任何解释的情况下被删除,
可能会
我们公司制定了一条规则,在这种情况下添加排除标签“EXCLUDE_TERMINATE: true”

Serverless Framework 配置

本次演讲将讲解如何将您编写的代码部署到 Lambda。

我们使用名为 Serverless Framework 的工具。https
://serverless.com


一个 CLI 工具,它根据指定的配置文件将函数部署
到 Lambda 等无服务器服务;对于 Lambda,它与 CloudFormation 协同工作以执行部署。

准备一个名为 serverless.yml 的配置文件。

# 欢迎使用 Serverless!# # 此文件是您服务的主要配置文件。# 目前它非常简洁,使用默认值。# 您可以随时添加更多配置选项以获得更精细的控制。# 我们在此处提供了一些注释掉的配置示例。# 只需取消注释即可启用相应的配置选项。# # 有关完整的配置选项,请查看文档:# docs.serverless.com # # 祝您编码愉快!服务:beyond-poc 插件:- serverless-prune-plugin 提供程序:名称:aws 运行时:python3.8 配置文件:${opt:profile, ''} 区域:ap-northeast-1 角色:[IAM 角色名称] 环境变量:EXCLUDE_TERMINATE_TAG:EXCLUDE_TERMINATE CHATWORK_API_KEY:[ChatWark API 密钥] CHATWORK_ROOM_ID:[ChatWark 房间 ID] CHATWORK_ENDPOINT:https://api.chatwork.com/v2 超时:10 # 我的自定义环境变量 custom: prune: automatic: true number: 5 # 您可以在此处覆盖默认值 # stage: dev # region: us-east-1 # 您可以在此处添加打包信息 #package: # include: # - include-me.py # - include-me-dir/** # exclude: # - exclude-me.py # - exclude-me-dir/** functions: terminate-instance: handler: handler.terminate events: - schedule: cron(0 15 ? * * *) timeout: 120 memorySize: 128 reservedConcurrency: 1

在环境变量中,我们将排除标签和 ChatWork 身份验证信息设置为环境变量。
在函数部分,我们直接设置函数。
在事件部分,我们设置了事件调度

即日本标准时间午夜)定期执行事件

将要部署的代码保存到此配置文件所在的目录中。

$ sis deploy --profile [AWS Profile Name]

由 Serverless Framework 自动创建的
CloudFormation 堆栈

最后

我一直把它当作博客的主题,但
说实话,我是公司里最容易忘记删除东西的人,所以很抱歉……

如果您觉得这篇文章有用,请点击【点赞】!
1
加载中...
1票,平均分:1.00/11
2,772
X Facebook Hatena书签 口袋

这篇文章的作者

关于作者

寺冈由纪

他于 2016 年加入 Beyond 公司,目前已是第六年
担任 MSP(托管服务提供商)的基础设施工程师,负责故障排除以及
使用 AWS 等公有云设计和构建基础设施。近期,他开始

使用 HashiCorp 的 Terraform 和 Packer 等工具,用于构建和运维
Docker 和 Kubernetes 等容器基础设施的自动化流程。此外,他还扮演着技术推广者的角色,经常在外部学习小组和研讨会上发表演讲。

・GitHub
https://github.com/nezumisannn

・讲述历史
https://github.com/nezumisannn/my-profile

・演示材料(SpeakerDeck)
https://speakerdeck.com/nezumisannn

・认证:
AWS认证解决方案架构师 - 助理级、
Google Cloud专业云架构师