Lambdaを使ってAutoScalingを更新する

## はじめに
Amazon EC2 Auto Scalingで簡単にインスタンスを最新化できるようになりました。
<TABLE ALIGN=CENTER><TR><TD WIDTH=400px>
 <A HREF="https://dev.classmethod.jp/articles/update-amazon-ec2-auto-scaling-instance-update/" TARGET="_blank"><STRONG>[アップデート] Amazon EC2 Auto Scaling で Auto Scaling Group 内のインスタンスを最新化できるようになりました！ | Developers.IO</STRONG></A>
 <A HREF="http://b.hatena.ne.jp/entry/https://dev.classmethod.jp/articles/update-amazon-ec2-auto-scaling-instance-update/" TARGET="_blank">
 <IMG BORDER="0" SRC="http://b.hatena.ne.jp/entry/image/https://dev.classmethod.jp/articles/update-amazon-ec2-auto-scaling-instance-update/" BORDER="0" ALT="" /></a>
 <BR>
 [アップデート] Amazon EC2 Auto Scaling で Auto Scaling Group 内のインスタンスを最新化できるようになりました！ | Developers.IO... 
 </TD>
 <TD WIDTH=150px>
 <IMG STYLE="float:left;margin-right:.5em;" SRC="http://capture.heartrails.com/120x120/cool?https://dev.classmethod.jp/articles/update-amazon-ec2-auto-scaling-instance-update/" ALT="" WIDTH="120" HEIGHT="120" />
 </TD></TR>
</TABLE>

本機能をLambdaから実行することで、ビルド～デプロイを自動化してみました。
### フロー
1. CodeBuildからビルド資材をS3にアップロード
2. S3へのアップロードをトリガーにLambdaを起動
3. LambdaでAutoScalingの更新を実行
4. AutoScalingの更新でS3から最新のビルド資材を取得し、Webアプリケーションを起動
本投稿では、Lambdaを使ってAutoScalingを更新する部分をメインに記載します。

## 事前準備
デプロイ対象のWebアプリケーションを作成する。
ここではSpringBootで作成したWebアプリケーションをGitHubに登録しました。
[moria\-msn/spring\-boot\-hello\-world\-for\-aws](https://github.com/moria-msn/spring-boot-hello-world-for-aws)

## 1. CodeBuildからビルド資材をS3にアップロード
CodeBuildを実行するためにリポジトリ内にbuildspec.ymlを作成して、S3にビルド資材をアップロードするようにします。

```buildspec.yml
version: 0.2

phases:
  install:
    runtime-versions:
      java: corretto8
  build:
    commands:
      - echo Build started on `date`
      - mvn package
artifacts:
  files:
    - target/demo-0.0.1-SNAPSHOT.jar
```

次にS3にバケットを作成してから、CodeBuildでビルドプロジェクトを作成します。

## 2. S3へのアップロードをトリガーにLambdaを起動
S3に作成したバケットのイベントを作成します。
イベントには「すべてのオブジェクト作成イベント」を選択し、送信先にはLambda関数を選択します。
Lambda関数については、後述するLambda関数を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/364749/8b9ef3a9-2867-4a3c-a03d-a664bf66a0b3.png)

## 3. LambdaでAutoScalingの更新を実行
Lambdaで使用できる標準のAWS SDKでは、バージョンが古く、AutoScalingの更新機能を実行できません。
そのため、最新のAWS SDKをレイヤーとして追加する必要があります。
今回はランタイムに「Python 3.8」を使用したため、下記を参考にboto3の最新ライブラリをレイヤーに追加しました。
[Lambda Layers で最新の AWS SDK を使用する \- Qiita](https://qiita.com/hayao_k/items/b9750cc8fa69d0ce91b0)

レイヤーの追加が完了したら、lumbda_function.pyを下記の通り設定し、AutoScalingの更新を実行できるようにします。

```lumbda_function.py
import boto3

asg_client = boto3.client('autoscaling')

def lambda_handler(event, context):

    response = asg_client.start_instance_refresh(
        AutoScalingGroupName='[AutoScaling]',
        Strategy='Rolling',
        Preferences={
            'MinHealthyPercentage': 0,
            'InstanceWarmup': 300
        }
    )

    return("Success")
```

## 4. AutoScalingの更新でS3から最新のビルド資材を取得し、Webアプリケーションを起動
AutoScalingの起動設定でユーザデータを下記の通り設定することで、
S3から最新のビルド資材を取得し、Webアプリケーションを起動するようにします。

```ユーザデータ.txt
#!/bin/bash
sudo amazon-linux-extras enable corretto8
sudo yum install -y java-1.8.0-amazon-corretto
aws s3 cp s3://[バケット名]/ . --recursive
java -jar start-aws-code-build/target/demo-0.0.1-SNAPSHOT.jar
```

## 終わりに
上記設定により、CodeBuildを実行すると最新のWebアプリケーションをデプロイすることができました。
本機能を活用すれば、アプリケーションのデプロイ以外にも、下記のようにAutoScallingで使用するAMIの最新化も可能のようです。
[aws\-samples/ec2\-auto\-scaling\-instance\-refresh\-sample: Sample EC2 Auto Scaling Instance Refresh solution to update an Auto Scaling group when a new AMI is created by EC2 Image Builder](https://github.com/aws-samples/ec2-auto-scaling-instance-refresh-sample)