こんにちは、AWS事業本部のニシヤマです。
最近、CloudFormationでEC2インスタンスを起動する機会があったのですが、その際にAMIを定期的に取得する必要がありました。 弊社ご契約のAWSアカウントですとAWS運用自動化ツールの「opswitch」を利用してAMIを定期的に取得することも可能です。 https://opswitch.io/
ただ今回はAWS Backupを利用して同じCloudFormationテンプレートで設定してみましたのでご紹介します。
テンプレート
テンプレートでは以下のリソースを作成しています。
- EC2インスタンス用のセキュリティグループ
- EC2インスタンス用のIAMRole
- EC2インスタンス
- AWS Backupボールト
- AWS Backupプラン
- AWS Backup用のIAMRole
そしてテンプレートがこちらです。
EC2インスタンス構築とAWS Backupを利用したバックアップ設定をするCloudFormationテンプレート
AWSTemplateFormatVersion: 2010-09-09
Description:
This is template of test Server EC2
Parameters:
ProjectPrefix:
Type: String
Default: "test"
Description: Project Prefix
Environment:
Description: Environment
Type: String
Default: dev
AllowedValues:
- dev
- stg
- prd
VpcId:
Type: "String"
Default: "vpc-XXXXXXXXXXXXXXXXX"
EC2SubnetId:
Type: "String"
Default: "subnet-XXXXXXXXXXXXXXXXX"
InstanceType:
Type: String
Default: "t3.micro"
Description: InstanceType for EC2
ImageId:
Type: String
Default: "ami-XXXXXXXXXXXXXXXXX"
Description: AMI-ID for EC2
RootVolumeSize:
Type: String
Default: "30"
Description: Size of Root Device
KeyName:
Type: String
Default: "test-keypair"
Description: EC2 Keypair Name
EC2InstanceName:
Type: String
Default: "test-ec2"
Description: EC2 Instance Name
SSHIPAddress:
Type: String
Default: "192.168.0.0/24"
Description: Allow SSH IPAddress
AllowedPattern: (\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})/(\d{1,2})
BackupCron:
Type: String
Default: cron(00 15 * * ? *)
Description: Exec Backup Time.(UTC)
BackupGeneration:
Type: Number
Default: 7
Description: Backup File Generation
Metadata:
AWS::CloudFormation::Interface:
ParameterGroups:
- Label:
default: Common Settings
Parameters:
- ProjectPrefix
- Environment
- Label:
default: EC2 Settings
Parameters:
- VpcId
- EC2SubnetId
- InstanceType
- ImageId
- RootVolumeSize
- KeyName
- EC2InstanceName
- SSHIPAddress
- Label:
default: Backup Settings
Parameters:
- BackupCron
- BackupGeneration
Resources:
# ------------------------------------------------------------#
# SecurityGroup for EC2 Instance
# ------------------------------------------------------------#
TestServerEC2SG:
Type: AWS::EC2::SecurityGroup
Properties:
GroupName: !Sub ${ProjectPrefix}-${Environment}-sg-ec2-TestServer
GroupDescription: Security Group for Test Server
Tags:
- Key: Name
Value: !Sub ${ProjectPrefix}-${Environment}-sg-ec2-TestServer
VpcId:
!Ref VpcId
TestServerEC2SGIngressSSHNTD:
Type: AWS::EC2::SecurityGroupIngress
Properties:
GroupId: !Ref TestServerEC2SG
IpProtocol: tcp
FromPort: 22
ToPort: 22
CidrIp: !Ref SSHIPAddress
# ------------------------------------------------------------#
# IAM Role for EC2 Instance
# ------------------------------------------------------------#
TestServerEC2IAMRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
-
Effect: "Allow"
Principal:
Service:
- "ec2.amazonaws.com"
Action:
- "sts:AssumeRole"
ManagedPolicyArns:
- arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore
Path: /
RoleName: !Sub ${ProjectPrefix}-${Environment}-iam-role-ec2-TestServer
TestServerEC2InstanceProfile:
Type: AWS::IAM::InstanceProfile
Properties:
Path: /
Roles:
- Ref: TestServerEC2IAMRole
InstanceProfileName: !Ref TestServerEC2IAMRole
# ------------------------------------------------------------#
# EC2 Instance
# ------------------------------------------------------------#
TestServerEC2Instance:
Type: AWS::EC2::Instance
Properties:
InstanceType: !Sub ${InstanceType}
ImageId: !Sub ${ImageId}
KeyName: !Sub ${KeyName}
IamInstanceProfile: !Ref TestServerEC2InstanceProfile
BlockDeviceMappings:
- DeviceName: /dev/xvda
Ebs:
VolumeType: gp2
VolumeSize: !Sub ${RootVolumeSize}
DeleteOnTermination: true
NetworkInterfaces:
- SubnetId:
!Ref EC2SubnetId
AssociatePublicIpAddress: false
GroupSet:
- !Ref TestServerEC2SG
DeviceIndex: 0
DeleteOnTermination: true
DisableApiTermination: false
EbsOptimized: true
Tags:
- Key: Name
Value: !Sub ${EC2InstanceName}
- Key: Backup
Value: true
# ------------------------------------------------------------#
# AWS Backup
# ------------------------------------------------------------#
EC2BackupIAMRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
-
Effect: Allow
Principal:
Service:
- backup.amazonaws.com
Action:
- sts:AssumeRole
ManagedPolicyArns:
- arn:aws:iam::aws:policy/service-role/AWSBackupServiceRolePolicyForBackup
- arn:aws:iam::aws:policy/service-role/AWSBackupServiceRolePolicyForRestores
Path: /service-role/
RoleName: !Sub ${ProjectPrefix}-${Environment}-iam-role-ec2-backup
TestBackupVaultforEC2:
Type: AWS::Backup::BackupVault
Properties:
BackupVaultName: TestEC2BackupVault
TestBackupPlan:
Type: AWS::Backup::BackupPlan
Properties:
BackupPlan:
BackupPlanName: TestBackupPlan
AdvancedBackupSettings:
-
ResourceType: EC2
BackupOptions:
WindowsVSS: disabled
BackupPlanRule:
-
RuleName: RuleForDailyBackups
TargetBackupVault: !Ref TestBackupVaultforEC2
ScheduleExpression: !Ref BackupCron
Lifecycle:
DeleteAfterDays: !Ref BackupGeneration
TagBasedBackupSelection:
Type: AWS::Backup::BackupSelection
Properties:
BackupSelection:
SelectionName: TagBasedBackupSelection
IamRoleArn: !GetAtt EC2BackupIAMRole.Arn
ListOfTags:
-
ConditionType: STRINGEQUALS
ConditionKey: Backup
ConditionValue: true
BackupPlanId: !Ref TestBackupPlan
DependsOn: TestBackupPlan
こちらのテンプレートではEC2の終了保護は有効化していないので必要に応じて設定してください。
説明
それではテンプレートを説明していきます。
Parameters
セクションでは以下のパラメータを指定します。
パラメータのキー | 説明 |
---|---|
ProjectPrefix | リソースに付与する接頭語 |
Environment | リソースの環境文字列(dev、stg、prdから選択) |
VpcId | EC2を起動するVPCのID |
EC2SubnetId | EC2を起動するサブネットのID |
InstanceType | EC2のインスタンスタイプ |
ImageId | AMIのID |
RootVolumeSize | EC2のルートボリュームのサイズ |
KeyName | EC2の接続に利用するキーペア |
EC2InstanceName | EC2の名前(Nameタグの値) |
SSHIPAddress | EC2へのSSH接続を許可するIPアドレス |
BackupCron | AWS Backupの実行タイミング(UTCでcron表記、デフォルト0時) |
BackupGeneration | AWS Backupで管理するAMIの世代数 |
次にResources
セクションの中のAWS Backupに関わる部分を説明します。
# ------------------------------------------------------------#
# AWS Backup
# ------------------------------------------------------------#
EC2BackupIAMRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
-
Effect: Allow
Principal:
Service:
- backup.amazonaws.com
Action:
- sts:AssumeRole
ManagedPolicyArns:
- arn:aws:iam::aws:policy/service-role/AWSBackupServiceRolePolicyForBackup
- arn:aws:iam::aws:policy/service-role/AWSBackupServiceRolePolicyForRestores
Path: /service-role/
RoleName: !Sub ${ProjectPrefix}-${Environment}-iam-role-ec2-backup
まず上記でAWS Backupで利用するIAMロールを作成しています。すでにAWS Backupを利用している環境の場合は自動的にサービスにリンクされたロールAWSServiceRoleForBackup
が作成されている場合もありますが、今回はCloudFormationで作成しました。
ポリシーは以下の2つをアタッチしています。
- AWSBackupServiceRolePolicyForBackup
- AWSBackupServiceRolePolicyForRestores
TestBackupVaultforEC2:
Type: AWS::Backup::BackupVault
Properties:
BackupVaultName: TestEC2BackupVault
次に上記のブロックでAWS Backupボールトを作成しています。ボールト名はTestEC2BackupVault
で決め打ちしています。
TestBackupPlan:
Type: AWS::Backup::BackupPlan
Properties:
BackupPlan:
BackupPlanName: TestBackupPlan
AdvancedBackupSettings:
-
ResourceType: EC2
BackupOptions:
WindowsVSS: disabled
BackupPlanRule:
-
RuleName: RuleForDailyBackups
TargetBackupVault: !Ref TestBackupVaultforEC2
ScheduleExpression: !Ref BackupCron
Lifecycle:
DeleteAfterDays: !Ref BackupGeneration
TagBasedBackupSelection:
Type: AWS::Backup::BackupSelection
Properties:
BackupSelection:
SelectionName: TagBasedBackupSelection
IamRoleArn: !GetAtt EC2BackupIAMRole.Arn
ListOfTags:
-
ConditionType: STRINGEQUALS
ConditionKey: Backup
ConditionValue: true
BackupPlanId: !Ref TestBackupPlan
DependsOn: TestBackupPlan
最後に上記でAWS Backupプランとバックアップ対象の割り当てをしています。 パラメータで指定したAWS Backupの実行タイミング、AMIの世代数を利用しています。
ListOfTags:
-
ConditionType: STRINGEQUALS
ConditionKey: Backup
ConditionValue: true
BackupPlanId: !Ref TestBackupPlan
DependsOn: TestBackupPlan
また、バックアップ対象のEC2に関しては上記の部分でBackup
タグの値がtrue
の対象をバックアップ取得するようにしています。
既存のEC2インスタンスに対して同じタグを付与することで一緒にバックアップ対象にすることもできます。
以上です。
まとめ
いかがでしたでしょうか。踏み台サーバが必要になった場合にも、他のシステムとの依存はないけど一応バックアップを取得しておきたいといった際にこちらのテンプレートで簡単に構築&バックアップが可能になりました。 EC2インスタンスをサクッと構築したい時にマネジメントコンソールで起動するのも良いですが再現性が薄かったり、EC2構築したあとにバックアップ設定もしたいけど諸々設定が...のような場合にはこちらのテンプレートを利用していただければサクッと一式設定が可能です。
この記事がどなたかの参考になれば幸いです。