Amazon EventBridgeでCloudFormationのCreate StackとDelete Stackを自動化したい
はじめに
皆さんはAmazon EventBridgeのスケジューラ機能使っていますでしょうか。EC2を自動停止したり、特定のLambdaを自動実行したりできてとても便利ですよね。しかし、設定時に記載するjsonパラメータには制約が多く、複雑な処理はできずに使用を断念、、、なんてこともあるのではないでしょうか。本ブログではCloudFormationのCreateStack APIを使用して複雑な処理を自動実行する方法を紹介します
忙しい人向けのまとめ
- EventBridgeのスケジューラ機能でCloudFormationのCreateStack APIを自動実行できる
- この機能により、大量のリソースを自動作成できる。またリソース間の依存関係も気にせず作成できる
- EventBridgeがAssumeするIAMロールに紐づけるポリシーには"s3:GetObject"、及び"iam:PassRole"が必要
- 削除もDeleteStack APIを自動実行することで実現可能
今回やること
今回は、以下のリソースの自動作成を行います。もちろん、CloudFormationで表現できることならなんでもOKです。
- NATゲートウェイ
- Elastic IP(NATゲートウェイ用)
- セキュリティグループのアウトバウンドルール(既存のセキュリティグループにアタッチ)
- ルートテーブルのルート(既存のルートテーブルにNATゲートウェイ宛のルールを追加)
以下のようなユースケースをイメージしています
- EC2は原則としてインターネットを行ってはならない
- その為、インターネットアクセスが可能となってしまうサービスは原則として作成不可(セキュリティグループやルートテーブル)
- ただし、ソフトウェアアップデートの為に週に1回だけインターネットアクセスを許可する必要がある
- 毎週NATゲートウェイ作って、ルートテーブル変更して、、、だとあまりにも大変なので自動化したい
やってみる
CloudFormationテンプレートの作成
以下のようなymlファイルを用意します
セキュリティグループ・ルートテーブルは作成済みであることが前提です
テンプレートはこちら(折りたたんであります)
AWSTemplateFormatVersion: 2010-09-09
Description: EventBridgetest
Parameters:
SecurityGroupId:
Type: String
RouteTableId:
Type: String
PublicSubnetId:
Type: String
Resources:
# ------------------------------------------------------------#
# OutBoundSecurityGroupRule
# ------------------------------------------------------------#
SecurityGroupForEC2ToAllowHTTP:
Type: AWS::EC2::SecurityGroupEgress
Properties:
GroupId: !Ref SecurityGroupId
IpProtocol: tcp
FromPort: 80
ToPort: 80
CidrIp: 0.0.0.0/0
SecurityGroupForEC2ToAllowHTTPS:
Type: AWS::EC2::SecurityGroupEgress
Properties:
GroupId: !Ref SecurityGroupId
IpProtocol: tcp
FromPort: 443
ToPort: 443
CidrIp: 0.0.0.0/0
# ------------------------------------------------------------#
# Routing
# ------------------------------------------------------------#
# PrivateRouteA Create
PrivateRouteA:
Type: "AWS::EC2::Route"
Properties:
RouteTableId: !Ref RouteTableId
DestinationCidrBlock: "0.0.0.0/0"
NatGatewayId: !Ref NATGatewayID
# ------------------------------------------------------------#
# NatGateway
# ------------------------------------------------------------#
# NATGateway Create
NATGatewayID:
Type: "AWS::EC2::NatGateway"
Properties:
AllocationId: !GetAtt NATGatewayCEIP.AllocationId
SubnetId: !Ref PublicSubnetId
# NATGateway For EIP Create
NATGatewayCEIP:
Type: "AWS::EC2::EIP"
Properties:
Domain: vpc
S3の作成及びテンプレートのアップロード
今回のケースではローカルPCからテンプレートをアップロードすることはできません。その為、S3を作成し、そこにテンプレートをアップロードします。
詳細は後述しますが、EventBridgeが引き受けるロールがGetObjectできるようにバケットポリシーを設定します
バケットポリシーはこちら(折りたたんであります)
{
"Version":"2012-10-17",
"Statement":[
{
"Principal":{
"AWS":"arn:aws:iam::AccountID:role/RoleNameForEventBridge"
},
"Effect":"Allow",
"Action":[
"s3:GetObject"
],
"Resource":"arn:aws:s3:::bucketname/*"
}
]
}
※以下はよしなに編集してから使用してください
- AccountID(実行するアカウントのID)
- bucketname(CloudFormationをアップロードするバケット名)
- RoleNameForEventBridge(EventBridgeがAssumeするIAMロール名)
s3バケットに作成したCloudFormationテンプレートをアップロードし、S3のURLを取得しておきましょう(後で使います)
※s3 urlではなく オブジェクトURL をコピーしてください
CloudFotmation用IAMロールの作成
CloudFormation用のIAMロールを作成します。
ロールの信頼関係はこちら(折りたたんであります)
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "",
"Effect": "Allow",
"Principal": {
"Service": "cloudformation.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
ポリシーはこちら(折りたたんであります)
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "VisualEditor0",
"Effect": "Allow",
"Action": [
"ec2:DisassociateAddress",
"ec2:DescribeAddresses",
"ec2:CreateNatGateway",
"ec2:DescribeAddressesAttribute",
"ec2:ReplaceRoute",
"ec2:UnassignPrivateNatGatewayAddress",
"ec2:AssociateRouteTable",
"ec2:CreateRoute",
"ec2:RevokeSecurityGroupEgress",
"ec2:UnassignPrivateIpAddresses",
"ec2:DescribeRouteTables",
"ec2:ReleaseAddress",
"ec2:AuthorizeSecurityGroupEgress",
"ec2:AssociateNatGatewayAddress",
"ec2:UpdateSecurityGroupRuleDescriptionsEgress",
"ec2:ResetAddressAttribute",
"ec2:CreateTags",
"ec2:DeleteRoute",
"ec2:ModifySecurityGroupRules",
"ec2:DescribeNatGateways",
"ec2:AssignPrivateIpAddresses",
"ec2:DisassociateRouteTable",
"ec2:AllocateAddress",
"ec2:DescribeSecurityGroups",
"ec2:DisassociateNatGatewayAddress",
"ec2:DescribeSecurityGroupRules",
"ec2:DescribeSecurityGroupReferences",
"ec2:DeleteSecurityGroup",
"ec2:DeleteNatGateway",
"ec2:AssociateAddress"
],
"Resource": "*"
}
]
}
EventBridge用IAMロールの作成
EventBridge用のIAMロールを作成します
ロールの信頼関係はこちら(折りたたんであります)
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "scheduler.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
ポリシーはこちら(折りたたんであります)
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "VisualEditor0",
"Effect": "Allow",
"Action": [
"s3:GetObject",
"iam:PassRole",
"cloudformation:CreateStack",
"cloudformation:DeleteStack"
],
"Resource": "*"
}
]
}
※後でDeleteもするので合わせてポリシーを記載しています
ここでのポイントはIAMポリシーにs3:GetObject と iam:PassRoleが必要であることです
管理コンソールで操作しているときは意識しづらいポイントではありますが、EventBridgeがCloudFormationのCreateStackを実行するときに
- S3からテンプレートファイルを取得する
- CloudFormation用のロールをpassする
という2つの動作を実行する為です
EventBridgeスケジューラの設定
-
"スケジュール"セクションの"スケジュールを作成"を押下
-
スケジュール名・スケジュールのパターンを設定します。ここはよしなに設定してもらえれば。
ちなみに、スクリーンショットの設定の場合は"平日の午前0時"に自動で実行します
-
"ターゲットの選択"では"すべてのAPI"を選択し、"CloudFormation"と検索の上、選択します
-
CreateStackを選択し、jsonパラメータを入力します
jsonパラメータはこちら(折りたたんであります)
{
"StackName": "EventBridgeTest",
"TemplateURL": "https://xxxxxxxxxx",
"RoleARN": "arn:aws:iam::xxxxxxxxxxxxx:role/eventbridgetest",
"Parameters": [
{
"ParameterKey": "SecurityGroupId",
"ParameterValue": "xxxxxxxxxxxxx"
},
{
"ParameterKey": "RouteTableId",
"ParameterValue": "xxxxxxxxxxxx"
},
{
"ParameterKey": "PublicSubnetId",
"ParameterValue": "xxxxxxxxxxxx"
}
]
}
- "アクセス許可"セクションのロールはこちらで作成したものを使用
結果の確認
事前に設定した時刻にCloudFormationのコンソールを確認すると、スタックが作成されていることがわかります
おまけ_テンプレートの削除
EventBridgeスケジューラの設定画面にてDeleteStackを選択し、jsonファイルパラメータにスタック名と引き受けるロール名を選択することで実現可能です
jsonパラメータはこちら(折りたたんであります)
{
"StackName": "StackName",
"RoleARN": "arn:aws:iam::xxxxx/xxxxxx"
}
まとめ
今回はEventBridgeスケジュール×CloudFormationを使用して大量リソースを同時に作成・削除する手順を紹介しました。
最近ではIaCといえばTerraformという風潮が強いですが、今回のケースのようにCloudFormationを使うべきこともまだまだあるのではないかと思っています。
Discussion