Amazon EC2 Auto Scaling の新機能 Launch Before Terminate(終了前に起動)を試してみた

Amazon EC2 Auto Scaling の新機能 Launch Before Terminate(終了前に起動)を試してみた

Amazon EC2 Auto Scaling の Launch Before Terminate をアカウント単位で有効にし、リフレッシュ中の台数を確認しました。指定なしのリフレッシュでは、新しいインスタンスが healthy になってから旧インスタンスが終了し、healthy ターゲットは4台を下回りませんでした。
2026.10.28

はじめに

2026年10月、Amazon EC2 Auto Scaling で Launch Before Terminate(終了前に起動)をアカウント単位の既定の置き換え動作に設定できるようになりました。

https://aws.amazon.com/about-aws/whats-new/2026/10/ec2-auto-scaling-launch-before-terminate/

Launch Before Terminate を有効にすると、アカウント内のすべての ASG で、代替インスタンスを先に起動し、ヘルスチェックに通ってから置き換え対象のインスタンスを終了します。対象となるのは、インスタンスリフレッシュ、リバランス、ヘルスチェック、インスタンスの最大有効期間の経過による置き換えで、追加費用はかからないとされています。

今回、「終了前に起動」の有効時と無効時の動作の違いについて、東京リージョンの ASG で Preferences を指定しないインスタンスリフレッシュで確認しました。

アカウント設定

設定名は launchBeforeTerminate で、値は enabled と disabled です。

aws autoscaling describe-account-settings
{
    "Settings": [
        {
            "Name": "launchBeforeTerminate",
            "Value": "disabled",
            "EnforcementType": "none"
        }
    ]
}

有効にするコマンドと、無効に戻すコマンドです。

aws autoscaling put-account-setting --name launchBeforeTerminate --value enabled
aws autoscaling put-account-setting --name launchBeforeTerminate --value disabled

検証環境

東京リージョンの既定 VPC(公開サブネット3つ)に、ALB と ASG を CloudFormation で作成しました。

  • インスタンス:t4g.nano、Amazon Linux 2023 arm64、Nginx を起動
  • ASG: 最小4台、希望4台、最大8台。ヘルスチェックの種類は ELB、猶予は60秒。インスタンスメンテナンスポリシーなし
  • ターゲットグループ:ヘルスチェックのパスは /、間隔10秒、正常2回、異常2回。登録解除の遅延は30秒
  • AWS CLI: aws-cli/2.38.6
テンプレート全文とデプロイコマンド
AWSTemplateFormatVersion: '2010-09-09'
Description: ASG Launch Before Terminate account setting verification (ALB + ASG of t4g.nano running Nginx). Delete the stack after the test.

Parameters:
  VpcId:
    Type: AWS::EC2::VPC::Id
  SubnetIds:
    Type: List<AWS::EC2::Subnet::Id>
    Description: Public subnets in at least two AZs (default VPC)
  AmiId:
    Type: AWS::SSM::Parameter::Value<AWS::EC2::Image::Id>
    Default: /aws/service/ami-amazon-linux-latest/al2023-ami-kernel-default-arm64
  InstanceType:
    Type: String
    Default: t4g.nano

Resources:
  AlbSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: ALB (test, HTTP from anywhere)
      VpcId: !Ref VpcId
      SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: 80
          ToPort: 80
          CidrIp: 0.0.0.0/0

  InstanceSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: EC2 (HTTP from ALB only)
      VpcId: !Ref VpcId
      SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: 80
          ToPort: 80
          SourceSecurityGroupId: !Ref AlbSecurityGroup

  LoadBalancer:
    Type: AWS::ElasticLoadBalancingV2::LoadBalancer
    Properties:
      Type: application
      Scheme: internet-facing
      Subnets: !Ref SubnetIds
      SecurityGroups:
        - !Ref AlbSecurityGroup
      LoadBalancerAttributes:
        - Key: deletion_protection.enabled
          Value: 'false'

  TargetGroup:
    Type: AWS::ElasticLoadBalancingV2::TargetGroup
    Properties:
      VpcId: !Ref VpcId
      Protocol: HTTP
      Port: 80
      TargetType: instance
      HealthCheckPath: /
      HealthCheckIntervalSeconds: 10
      HealthCheckTimeoutSeconds: 5
      HealthyThresholdCount: 2
      UnhealthyThresholdCount: 2
      Matcher:
        HttpCode: '200'
      TargetGroupAttributes:
        - Key: deregistration_delay.timeout_seconds
          Value: '30'

  Listener:
    Type: AWS::ElasticLoadBalancingV2::Listener
    Properties:
      LoadBalancerArn: !Ref LoadBalancer
      Protocol: HTTP
      Port: 80
      DefaultActions:
        - Type: forward
          TargetGroupArn: !Ref TargetGroup

  LaunchTemplate:
    Type: AWS::EC2::LaunchTemplate
    Properties:
      LaunchTemplateData:
        ImageId: !Ref AmiId
        InstanceType: !Ref InstanceType
        SecurityGroupIds:
          - !Ref InstanceSecurityGroup
        MetadataOptions:
          HttpTokens: required
        UserData:
          Fn::Base64: |
            #!/bin/bash
            # t4g.nano (0.5 GiB) gets OOM-killed during dnf, so add swap first
            dd if=/dev/zero of=/swapfile bs=1M count=1024
            chmod 600 /swapfile
            mkswap /swapfile
            swapon /swapfile
            dnf install -y nginx
            TOKEN=$(curl -s -X PUT http://169.254.169.254/latest/api/token -H 'X-aws-ec2-metadata-token-ttl-seconds: 60')
            IID=$(curl -s -H "X-aws-ec2-metadata-token: $TOKEN" http://169.254.169.254/latest/meta-data/instance-id)
            echo "instance-id: $IID" > /usr/share/nginx/html/index.html
            systemctl enable --now nginx

  AutoScalingGroup:
    Type: AWS::AutoScaling::AutoScalingGroup
    Properties:
      MinSize: '4'
      DesiredCapacity: '4'
      MaxSize: '8'
      VPCZoneIdentifier: !Ref SubnetIds
      LaunchTemplate:
        LaunchTemplateId: !Ref LaunchTemplate
        Version: !GetAtt LaunchTemplate.LatestVersionNumber
      TargetGroupARNs:
        - !Ref TargetGroup
      HealthCheckType: ELB
      HealthCheckGracePeriod: 60
      Tags:
        - Key: Name
          Value: devio-asg-lbt
          PropagateAtLaunch: true
        - Key: Project
          Value: devio-asg-lbt
          PropagateAtLaunch: true

Outputs:
  AlbDnsName:
    Value: !GetAtt LoadBalancer.DNSName
  AutoScalingGroupName:
    Value: !Ref AutoScalingGroup
  TargetGroupArn:
    Value: !Ref TargetGroup
aws cloudformation deploy --stack-name devio-asg-lbt --template-file template.yaml --parameter-overrides VpcId=<vpc-id> SubnetIds=<subnet-id-1>\,<subnet-id-2>\,<subnet-id-3> --tags Project=devio-asg-lbt --no-fail-on-empty-changeset

計測結果

インスタンスリフレッシュを開始しました。

aws autoscaling start-instance-refresh --auto-scaling-group-name <asg-name>

台数は変化した行だけを示します。合計は終了処理中のインスタンスを含む ASG のインスタンス数です。イベントは describe-scaling-activities の出力から、インスタンスリフレッシュが原因の置き換え1台分を抜き出しました。時刻は JST です。

aws autoscaling describe-scaling-activities --auto-scaling-group-name <asg-name>

disabled

時刻      合計  InService  healthy
13:16:32   4     4          4
13:16:36   ← 古いインスタンスを終了
13:16:38   4     3          3
13:16:38   ← 新しいインスタンスを起動
13:16:44   5     4          3
13:17:49   4     4          3
13:17:55   4     4          4

終了が先で、約2秒後に起動が始まりました。InService と healthy ターゲットは3台まで減りました。InService は6秒後に4台へ戻りましたが、healthy ターゲットは新しいインスタンスが healthy になる 13:17:55 まで、約77秒3台のままでした。

enabled

時刻      合計  InService  healthy
12:58:05   5     4          4
12:58:06   ← 新しいインスタンスを起動
12:58:11   5     5          4
12:59:22   5     5          5
13:00:44   ← 古いインスタンスを終了
13:00:45   5     4          4
13:00:45   ← 次の新しいインスタンスを起動
13:00:51   6     5          4

起動が先で、約2分38秒後に終了が始まりました。終了が始まったのは、healthy ターゲットが5台になった 12:59:22 より後です。4台の置き換えのどれも、同じ順序でした。

コンソールの「終了前に起動を管理する」には、インスタンスメンテナンスポリシーが設定されていないグループには、最小正常率 100%、最大正常率 110% が適用されると書かれています。有効時の指定なしのリフレッシュの Preferences も、MinHealthyPercentage 100、MaxHealthyPercentage 110 でした。

リフレッシュ全体を通しても、enabled のときの InService と healthy ターゲットは4台を下回りませんでした。代わりに、置き換え中は合計が最大6台(InService は最大5台)まで増えました。ASG の最大台数は8にしてあり、最大台数を希望台数と同じにした ASG は試していません。

まとめ

EC2 Auto Scaling のアカウント設定で「終了前に起動」を有効にすると、インスタンスを交換するメンテナンスで、代替インスタンスの起動に失敗して有効な台数が減る事故を回避しやすくなります。

今回は1回の測定でしたが、指定なしのインスタンスリフレッシュで、新しいインスタンスが healthy になってから古いインスタンスが終了される動作を確認できました。

多数の ASG が存在するアカウントで、本番環境の保護対策としては有効と考えられる設定です。ただし、一時的に EC2 の稼働台数が増えるため、コストが増えたり、メンテナンスの所要時間が長くなったりする可能性があります。オンデマンドキャパシティ予約を使用している場合や、ライセンスを厳密に管理している場合は、予約枠が不足したり、ライセンス数を超過したりする可能性にも留意してご利用ください。

この記事をシェアする

AWSのお困り事はクラスメソッドへ

関連記事