[アップデート]CloudFormationでEC2インスタンスの休止機能を有効化できるようになりました!

CloudFormationでEC2インスタンスの休止機能を有効化できるようになったので、テンプレートを作って試してみました。
2020.02.19

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

大阪オフィスのYui(@MayForBlue)です。

タイトルの通り、CloudFormationでEC2インスタンスの休止機能を有効化できるようになったので、実際にやってみました!

公式ドキュメント
AWS CloudFormation を使用して、オンデマンドおよびリザーブドインスタンスの Amazon EC2 の休止機能を有効にする

目次

休止機能とは

インスタンスをシャットダウンする前に現在の作業状態をEBSルートボリュームに保存し、次回起動時にその内容を読み込んで開始させる機能です。
通常のシャットダウンとは違い、作業内容を保持することができます。

公式ドキュメント
Linux インスタンスの休止
Hibernate Your Windows Instance

必要な条件

インスタンスファミリー、インスタンスサイズ、ルートボリュームの暗号化など、休止機能を有効化するためには必要な条件が複数あります。 詳細はこちらをご覧ください。
休止の前提条件

CloudFormationでEC2インスタンスの休止機能を有効化する

実際にやってみました。

まず、休止機能を有効化しなかったインスタンスはこんな感じです。

インスタンスの休止が選択できず、詳細タブでも休止動作が無効になっていることが確認できます。

有効化する

休止機能の有効化に必要なプロパティを書いてテンプレートを流しました。

以下が休止機能を有効化するための設定です。

      HibernationOptions: 
        Configured: true

EC2のテンプレートはこんな感じです。(一部抜粋)
EBSルートデバイスの暗号化やインスタンスタイプなど、今回必要な設定も盛り込んでいます。
(テンプレート全体の内容はコチラ

  EC2Instance01:
    Type: "AWS::EC2::Instance"
    Properties:
      InstanceType: "m4.large"
      HibernationOptions: 
        Configured: true
      BlockDeviceMappings: 
        - DeviceName: "/dev/xvda"
          Ebs:
            DeleteOnTermination: true
            VolumeType: "gp2"
            VolumeSize: "30"
            Encrypted: true

実際に流してみると、インスタンスの休止が選択でき、詳細タブでも休止動作が有効になっていることが確認できました!

今回使用したCloudFormationテンプレート

ネットワーク周りとEC2インスタンス周りでスタックを分け、パラメータのプロジェクト名に同じ値を渡すことで、EC2のスタックからネットワークのリソースを参照するようにしています。

ネットワーク用

AWSTemplateFormatVersion: "2010-09-09"
Description:
  Network Create

Parameters: 
  ProjectName:
    Type: String

Resources:
# -------------------------------
#  VPC
# -------------------------------
# VPC Create
  VPC: 
    Type: "AWS::EC2::VPC"
    Properties:
      CidrBlock: "10.1.0.0/16"
      EnableDnsSupport: true
      EnableDnsHostnames: true
      InstanceTenancy: default
      Tags: 
        - Key: Name
          Value: !Sub "${ProjectName}-vpc"
# InternetGateway
  InternetGateway:
    Type: "AWS::EC2::InternetGateway"
    Properties:
      Tags:
        - Key: Name
          Value: !Sub "${ProjectName}-igw"
# IGW Attach
  InternetGatewayAttachment:
    Type: "AWS::EC2::VPCGatewayAttachment"
    Properties:
      InternetGatewayId: !Ref InternetGateway
      VpcId: !Ref VPC 

# -------------------------------
#  Subnet
# -------------------------------    
# Public SubnetA Create
  PublicSubnetA:
    Type: "AWS::EC2::Subnet"
    Properties:
      AvailabilityZone: "ap-northeast-1a"
      CidrBlock: "10.1.10.0/24"
      VpcId: !Ref VPC
      Tags: 
        - Key: Name
          Value: !Sub "${ProjectName}-public-subnet-a"

# Public RouteTableA
  PublicRouteTableA:
    Type: "AWS::EC2::RouteTable"
    Properties:
      VpcId: !Ref VPC
      Tags: 
        - Key: Name
          Value: !Sub "${ProjectName}-public-route-a"
# Routing
# PublicRouteA
  PublicRouteA:
    Type: "AWS::EC2::Route"
    Properties:
      RouteTableId: !Ref PublicRouteTableA
      DestinationCidrBlock: "0.0.0.0/0"
      GatewayId: !Ref InternetGateway

# RouteTable Associate
# PublicRouteTableA - PublicSubnetA
  PublicSubnetARouteTableAssociation:
    Type: "AWS::EC2::SubnetRouteTableAssociation"
    Properties:
      SubnetId: !Ref PublicSubnetA
      RouteTableId: !Ref PublicRouteTableA

Outputs:
# VPC
  VPC:
    Value: !Ref VPC
    Export:
      Name: !Sub "${ProjectName}-vpc"

  VPCCIDR:
    Value: "10.1.0.0/16"
    Export:
      Name: !Sub "${ProjectName}-vpc-cidr"

# Subnet
  PublicSubnetA:
    Value: !Ref PublicSubnetA
    Export:
      Name: !Sub "${ProjectName}-public-subnet-a"

  PublicSubnetACIDR:
    Value: "10.1.10.0/24"
    Export:
      Name: !Sub "${ProjectName}-public-subnet-a-cidr"

EC2インスタンス用

AWSTemplateFormatVersion: "2010-09-09"
Description: 
  EC2 Instance Create

Metadata: 
  "AWS::CloudFormation::Interface":
    ParameterGroups:
      - Label:
          default: "ProjectName"
        Parameters:
          - ProjectName
      - Label:
          default: "EC2Instance Configuration"
        Parameters:
          - KeyPairName
          - EC2InstanceAMI
          - SSHAccessSourceIP

    ParameterLabels:
      KeyPairName:
        default: "KeyPairName"
      EC2InstanceAMI:
        default: "AMI ID"
      SSHAccessSourceIP:
        default: "SSH AccessSourceIP"

# -------------------------------
# Input Parameters
# -------------------------------
Parameters: 
  ProjectName:
    Type: String

# EC2Instance
  KeyPairName:
    Type: AWS::EC2::KeyPair::KeyName
    Default: ""
  EC2InstanceAMI:
    Type: AWS::SSM::Parameter::Value<AWS::EC2::Image::Id>
    Default: "/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2"
  SSHAccessSourceIP:
    Type: String
    AllowedPattern: '^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/([0-9]|[1-2][0-9]|3[0-2]))$'

Resources: 
# -------------------------------
#  IAM Role for EC2
# -------------------------------
  EC2IAMRole: 
    Type: "AWS::IAM::Role"
    Properties: 
      RoleName: !Sub "${ProjectName}-WebServer-role" 
      AssumeRolePolicyDocument: 
        Version: "2012-10-17"
        Statement: 
          - Effect: Allow
            Principal: 
              Service: 
                - "ec2.amazonaws.com"
            Action: 
              - "sts:AssumeRole"
      Path: "/"
      ManagedPolicyArns: 
        - "arn:aws:iam::aws:policy/service-role/AmazonEC2RoleforSSM"
        - "arn:aws:iam::aws:policy/AmazonEC2ReadOnlyAccess"

  EC2InstanceProfile: 
    Type: "AWS::IAM::InstanceProfile"
    Properties: 
      Path: "/"
      Roles: 
        - Ref: EC2IAMRole
      InstanceProfileName: !Sub "${ProjectName}-WebServer-profile"

# -------------------------------
# EC2Instance AZ-A
# -------------------------------
  EC2Instance01:
    Type: "AWS::EC2::Instance"
    Properties:
      Tags:
        - Key: Name
          Value: !Sub "${ProjectName}-WebServer-01"
      ImageId: !Ref EC2InstanceAMI
      InstanceType: "m4.large"
      KeyName: !Ref KeyPairName
      IamInstanceProfile: !Ref EC2InstanceProfile
      SecurityGroupIds:
        - !Ref ManagedSecurityGroup
        - !Ref WebSecurityGroup
      SubnetId: { "Fn::ImportValue": !Sub "${ProjectName}-public-subnet-a" }
      HibernationOptions: 
        Configured: true
      BlockDeviceMappings: 
        - DeviceName: "/dev/xvda"
          Ebs:
            DeleteOnTermination: true
            VolumeType: "gp2"
            VolumeSize: "30"
            Encrypted: true

# -------------------------------
# SecurityGroup for Managed(SSH)
# -------------------------------
  ManagedSecurityGroup:
    Type: "AWS::EC2::SecurityGroup"
    Properties:
      VpcId: { "Fn::ImportValue": !Sub "${ProjectName}-vpc" }
      GroupName: !Sub "${ProjectName}-managed-sg"
      GroupDescription: "SecurityGroup for Managed"
      Tags:
        - Key: "Name"
          Value: !Sub "${ProjectName}-managed-sg"
# Rule
      SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: 22
          ToPort: 22
          CidrIp: !Ref SSHAccessSourceIP


# -------------------------------
# SecurityGroup for WebServer
# -------------------------------
  WebSecurityGroup:
    Type: "AWS::EC2::SecurityGroup"
    Properties:
      VpcId: { "Fn::ImportValue": !Sub "${ProjectName}-vpc" }
      GroupName: !Sub "${ProjectName}-web-sg"
      GroupDescription: "SecurityGroup for WebServer"
      Tags:
        - Key: "Name"
          Value: !Sub "${ProjectName}-web-sg"

# -------------------------------
# ElasticIP for EC2Instance01
# -------------------------------
  ElasticIP01:
    Type: "AWS::EC2::EIP"
    Properties:
      Domain: vpc

  ElasticIPAssociate01:
    Type: AWS::EC2::EIPAssociation
    Properties: 
      AllocationId: !GetAtt ElasticIP01.AllocationId
      InstanceId: !Ref EC2Instance01

最後に

休止機能を使用する可能性があるインスタンスを作成する場合にもCloudFormationで構築できるようになったので、地味に嬉しいアップデートではないでしょうか!

以上、大阪オフィスのYui(@MayForBlue)でした(`・ω・´)

参考リンク

AWS CloudFormation を使用して、オンデマンドおよびリザーブドインスタンスの Amazon EC2 の休止機能を有効にする

Linux インスタンスの休止
Hibernate Your Windows Instance

【新機能】Amazon EC2がハイバネーション出来るようになりました #reinvent