概要
Amazon Linux 2023でEC2(ssh)サーバを平日8:00-20:00の間起動するCloudformationテンプレートを作成しました。
起動テンプレートのUserdataやLambda、autoscalingを使って実装している記事もありましたが、UIからも管理しやすいCloudwatchRuleで運用する方針としています。
前提
VPC/Subnet関連は、他のスタックで作成済みの前提です。
また、AL2023のAMIの詳細については以下をご参考ください。
サンプルテンプレート
AWSTemplateFormatVersion: 2010-09-09
################################################################################
# Parameters
################################################################################
Parameters:
########################################
# Common
########################################
SystemTag:
Type: String
Default: "sample"
SampleIP:
Type: String
Default: "111.222.333.444/32"
########################################
# EC2
########################################
Ec2InstanceType:
Type: String
Default: "t3.micro"
Ec2InstanceAMI:
Type: AWS::SSM::Parameter::Value<AWS::EC2::Image::Id>
Default: /aws/service/ami-amazon-linux-latest/al2023-ami-kernel-default-x86_64
Ec2EbsVolumeSize1:
Type: Number
Default: 10
################################################################################
# Resources
################################################################################
Resources:
SshRole:
Type: "AWS::IAM::Role"
Properties:
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
-
Effect: "Allow"
Principal:
Service:
- "ec2.amazonaws.com"
- "codedeploy.amazonaws.com"
Action:
- "sts:AssumeRole"
Path: "/"
ManagedPolicyArns:
- arn:aws:iam::aws:policy/AmazonEC2FullAccess
- arn:aws:iam::aws:policy/AmazonRDSFullAccess
- arn:aws:iam::aws:policy/AWSCodeDeployFullAccess
- arn:aws:iam::aws:policy/IAMFullAccess
- arn:aws:iam::aws:policy/AmazonSSMFullAccess
SshSecurityGroup:
Type: "AWS::EC2::SecurityGroup"
Properties:
GroupName: !Sub ${SystemTag}-SSH
GroupDescription: !Sub ${SystemTag}-SSH
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 22
ToPort: 22
CidrIp: !Ref SampleIP
VpcId: !ImportValue VpcSample # Vpc/Subnet関連は他で作成してインポート
Tags:
- Key: Name
Value: !Sub ${SystemTag}-SSH
EC2InstanceProfile:
Type: "AWS::IAM::InstanceProfile"
Properties:
Path: "/"
Roles:
- !Ref SshRole
SshEc2Template:
Type: AWS::EC2::LaunchTemplate
Properties:
LaunchTemplateData:
IamInstanceProfile:
Arn: !GetAtt EC2InstanceProfile.Arn
NetworkInterfaces:
- AssociatePublicIpAddress: true
DeleteOnTermination: true
DeviceIndex: 0
SubnetId: !ImportValue PublicSubnet1 # Vpc/Subnet関連は他で作成してインポート
Groups: !Ref SshSecurityGroup
InstanceInitiatedShutdownBehavior: "stop"
ImageId: !Ref Ec2InstanceAMI
KeyName: !Sub ${SystemTag}-ssh # KeyPairはマネコンから手動作成
Monitoring:
Enabled: false
CreditSpecification:
CpuCredits: "standard"
InstanceType: !Ref Ec2InstanceType
BlockDeviceMappings:
- DeviceName: "/dev/xvda"
Ebs:
VolumeSize: !Ref Ec2EbsVolumeSize1
VolumeType: "gp2"
DeleteOnTermination: false
UserData:
Fn::Base64: |
#!/bin/bash
timedatectl set-timezone Asia/Tokyo
# MySQL Client
dnf -y localinstall https://dev.mysql.com/get/mysql80-community-release-el7-1.noarch.rpm
dnf config-manager --disable mysql80-community
dnf config-manager --enable mysql57-community
dnf install -y mysql
if ! command -v aws &> /dev/null
then
dnf install -y unzip
cd /tmp
curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
unzip awscliv2.zip
sudo ./aws/install
fi
Ec2Instance:
Type: AWS::EC2::Instance
Properties:
LaunchTemplate:
LaunchTemplateId: !Ref "SshEc2Template"
Version: !GetAtt "SshEc2Template.LatestVersionNumber"
Tags:
- Key: Name
Value: !Sub ${SystemTag}-SSH
ElasticIP:
Type: AWS::EC2::EIP
Properties:
Domain: vpc
Tags:
- Key: Name
Value: !Sub ${SystemTag}-SSH
ElasticIPAssociate:
Type: AWS::EC2::EIPAssociation
Properties:
AllocationId: !GetAtt ElasticIP.AllocationId
InstanceId: !Ref Ec2Instance
もし、このEC2を平日8:00-20:00の間だけ起動したい、という場合は以下を追加すればOKです。Cron式はUTC表記になっているので気を付けてください。
CloudWatchEventsRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: '2012-10-17'
Statement:
-
Effect: Allow
Principal:
Service:
- events.amazonaws.com
Action:
- sts:AssumeRole
Path: "/"
RoleName: CloudWatchEventsRole
ManagedPolicyArns:
- arn:aws:iam::aws:policy/AmazonSSMFullAccess
- arn:aws:iam::aws:policy/AmazonRDSFullAccess
- arn:aws:iam::aws:policy/AmazonEC2FullAccess
SSHEventRuleEc2Start:
Type: AWS::Events::Rule
Properties:
Name: EventRuleEc2Start-SSH-sample
Description: 'Rules for starting sample-SSH ec2 instance'
ScheduleExpression: cron(0 23 ? * SUN-THU *)
State: ENABLED
EventBusName: default
Targets:
- Id: !Sub SSHEventRuleEc2Start-${SystemTag}-ssh
Arn: "arn:aws:ssm:ap-northeast-1::automation-definition/AWS-StartEC2Instance:$DEFAULT"
RoleArn: !GetAtt CloudWatchEventsRole.Arn
Input: !Sub '{"InstanceId":["${Ec2Instance}"]}'
SSHEventRuleEc2Stop:
Type: AWS::Events::Rule
Properties:
Name: EventRuleEc2Stop-SSH-sample
Description: 'Rules for stopping sample-SSH ec2 instance'
ScheduleExpression: cron(0 11 * * ? *)
State: ENABLED
EventBusName: default
Targets:
- Id: !Sub SSHEventRuleEc2Stop-${SystemTag}-ssh
Arn: "arn:aws:ssm:ap-northeast-1::automation-definition/AWS-StopEC2Instance:$DEFAULT"
RoleArn: !GetAtt CloudWatchEventsRole.Arn
Input: !Sub '{"InstanceId":["${Ec2Instance}"]}'
補足1: AL2023のUserdata
Amazon Linux 2023は、以前のバージョンのAmazon Linuxとは異なり、yum
ではなくdnf
パッケージマネージャーを使用します。AL2のようにyum update
としても更新されません。
dnf
はyum
の後継であり、より高速で依存関係の解決が改善されているとのこと。
基本的に、従来のyum
コマンドをdnf
に置き換えればOKです。
また、AL2023ではデフォルトでAWS CLI v2系がインストールされています。念の為、既にインストールされているかどうかを確認し、インストールされていない場合のみインストールプロセスを実行するようにしています。
補足2:セキュリティグループの位置
EC2インスタンスを作成する際に、インスタンスレベルでのセキュリティグループとネットワークインターフェースを同時に指定しようとした場合に以下のエラーが発生しました。
Resource handler returned message: "Network interfaces and an instance-level security groups may not be specified on the same request
ネットワークインターフェースを明示的に指定する場合、そのネットワークインターフェースにセキュリティグループを割り当てる必要があり、インスタンスレベルで別途セキュリティグループを指定するとエラーになるのです。
上述の通り、NetworkInterfaces
以下にセキュリティグループの指定があれば問題ありません。
参考: