自動で EC2 Autoscaling の起動設定をAttachするスクリプトを php で作った

# 背景

インスタンスの更新を行うたびに、手動で起動設定を作り直していた。

1. 最新の EC2 から AMI を作る
2. AMI から 起動設定を作る
3. Autoscaling Group に Attach
4. 不要になった起動設定を削除
5. 不要になった AMI を削除

毎回この単純作業。
地味に時間がかかるのと、一つミスすると、スケールアウト時にちゃんと動かないとかトラブルになる。（開発環境でちょっとトラブルになりかけた）

ミスになりそうな単純作業は自動化しちゃえと。

# なぜ PHP で書いた?

10年ぐらい慣れ親しんだ言語なので！ それだけ。

# 前提

- php 7.0 以上がローカルで動くこと
- aws-cli インストール済み
- jq コマンドインストール済み
- 東京リージョンで使う前提

# そのソースコードを公開

[gist](https://gist.github.com/oz-urabe/208289a6de7f76ccf7c3709b5b83e760) に置いてます

```
$ git clone https://gist.github.com/208289a6de7f76ccf7c3709b5b83e760.git autoscaling-script
$ cd $_
# list の中身を各自の環境に合わせる
$ vim autoscaling-update.php
```

## ソースの中身

### `$list` について

`$list` は各ENV、各インスタンス、オートスケーリングの設定が記載された連想配列です。

```
$list = [ 
    'stage' => [
        'web' => [
            'namelike' => 'stage-web',
            'autoscaling_group' => 'stage-web-autoscaling',
            'launch_namelike' => 'stage-web-launch',
            'instance_type' => 't3.micro',
            'key_name' => 'stage',
            'security_groups' => 'sg-0dce82de47bea0926',
            'iam_instance_profile' => 'stage-web-role',
        ],  
        'admin-web' => [
            'namelike' => 'stage-admin-web',
            'autoscaling_group' => 'stage-admin-web-autoscaling',
            'launch_namelike' => 'stage-admin-web-launch',
            'instance_type' => 't3.micro',
            'key_name' => 'stage',
            'security_groups' => 'sg-0dce82de47bea0926',
            'iam_instance_profile' => 'stage-admin-web-role',
        ],  
        'pointback' => [

... snip ...

        ],  
    ],  
    'prod' => [
        'web' => [
            'namelike' => 'prod-web',
            'autoscaling_group' => 'prod-web-autoscaling',
            'launch_namelike' => 'prod-web-launch',
            'instance_type' => 'm5.large',
            'key_name' => 'prod',
            'security_groups' => 'sg-8faef0d139d0af',
            'iam_instance_profile' => 'prod-web-role',
        ],  
        'admin-web' => [

... snip ...

```

ENV は stage （開発）, prod (本番) 環境があり、
インスタンス種類は web(ユーザ画面), admin-web(管理画面), pointback(ポイントバック), batch(バッチ) が存在している想定です。

この連想配列は使われる方に合わせて自由にカスタマイズしてもらえればOKです。

### `$list` 内の個々の記述について

個々の記述では、どういう起動設定を作り、インスタンスタイプが何で、、、どの Autoscaling Group にAttachするのかが定義されています。

```
            'namelike' => 'prod-web',
            'autoscaling_group' => 'prod-web-autoscaling',
            'launch_namelike' => 'prod-web-launch',
            'instance_type' => 'm5.large',
            'key_name' => 'prod',
            'security_groups' => 'sg-8faef0d139d0af',
            'iam_instance_profile' => 'prod-web-role',
```

- namelike: instance名を記載します （ami の名前の一部としても使うので namelike というキーにしました)
- autoscaling_group: Autoscaling Group 名
- launch_namelike: 起動設定名のプレフィックスです。実行した日時にあわせて重複でエラーとならないように prod-web-launch-20200721190000 のような起動設定名が適用されます
- instance_type: インスタンスタイプです。 t3.nano, t3.micro, ... m5.xlarge など 東京リージョンで定義されているインスタンスタイプを指定できます
- key_name: SSHキーに何を使うかを指定します
- security_groups: Security Group の ID を指定します。複数の場合は、半角スペースをあけて記載します
- iam_instance_profile: IAM インスタンス Profile です

### 実行について

以下のように動かします。

```
$ ./autoscaling-update.php prod web // stage admin-web 環境の場合

$ ./autoscaling-update.php prod web // prod web 環境の場合
$ ./autoscaling-update.php prod all // prod 全環境の場合
```

実行すると以下のようなログが表示されます

```
$ ./autoscaling-update.php prod all                                                                                    ?[feature/add-attache-autoscaling-       + scripts]                                                                                                                                                                                                                            
[2020-07-21 20:22:22] 該当インスタンスいずれか一つ取得
[2020-07-21 20:22:22] execute command "aws ec2 describe-instances --region ap-northeast-1 \
 | jq -r '.Reservations[].Instances[] | select(.Tags[].Key == "aws:autoscaling:groupName") | select(.Tags[].Value == "prod-web-autoscaling") | select(.State.Name == "running") |.InstanceId'|head -1" 
[2020-07-21 20:22:23] command result .. i-02e087ffcfdc9cb4f
[2020-07-21 20:22:23] AMI 作成
[2020-07-21 20:22:23] execute command "aws ec2 create-image --region ap-northeast-1 --instance-id i-02e087ffcfdc9cb4f --no-reboot --name prod-web_20200721202223 | jq -r ".ImageId""
[2020-07-21 20:22:24] command result .. ami-04a9f007ba3509a30
[2020-07-21 20:22:24] AMI Tagging
[2020-07-21 20:22:24] execute command "aws ec2 create-tags --region ap-northeast-1 --resources ami-04a9f007ba3509a30 \
  --tags Key=Name,Value=prod-web_20200721202223 Key=Type,Value=autoscaling Key=Environment,Value=prod"
[2020-07-21 20:22:25] command result .. ami-04a9f007ba3509a30
[2020-07-21 20:22:25] AMI 作成完了待ち
[2020-07-21 20:22:25] execute command "aws ec2 wait image-available --region ap-northeast-1 --image-ids ami-04a9f007ba3509a30"
[2020-07-21 20:24:42] 起動設定 作成
[2020-07-21 20:24:42] execute command "aws autoscaling create-launch-configuration \
  --region ap-northeast-1 \
  --launch-configuration-name prod-web-launch-20200721202223 \
  --image-id ami-04a9f007ba3509a30 \
  --instance-type m5.large \
  --key-name hapi_lab \
  --security-groups sg-0a09da7b2899abf20 \
  --instance-monitoring Enabled=true \
  --iam-instance-profile prod-web-role
[2020-07-21 20:24:43] autoscaling group 更新
[2020-07-21 20:24:43] execute command "aws autoscaling update-auto-scaling-group --region ap-northeast-1 \
  --auto-scaling-group-name prod-web-autoscaling \
  --launch-configuration-name prod-web-launch-20200721202223"
[2020-07-21 20:24:44] execute command "aws autoscaling describe-launch-configurations --region ap-northeast-1 --output json"
[2020-07-21 20:24:46] prod-web-launch-202007091312 に関連する古い設定を削除します
[2020-07-21 20:24:46] execute command "aws autoscaling delete-launch-configuration --region ap-northeast-1 --launch-configuration-name prod-web-launch-202007091312"
[2020-07-21 20:24:47] prod-web-launch-202007091312 に関連する古い AMI の登録を解除します . amiId=ami-094d805c269cb018e
[2020-07-21 20:24:47] execute command "aws ec2 deregister-image --image-id ami-094d805c269cb018e"
[2020-07-21 20:24:48] 該当インスタンスいずれか一つ取得
[2020-07-21 20:24:48] execute command "aws ec2 describe-instances --region ap-northeast-1 \
 | jq -r '.Reservations[].Instances[] | select(.Tags[].Key == "aws:autoscaling:groupName") | select(.Tags[].Value == "prod-admin-web-autoscaling") | select(.State.Name == "running") |.InstanceId'|head -1" 
[2020-07-21 20:24:50] command result .. i-003be640ea8229484
[2020-07-21 20:24:50] AMI 作成
[2020-07-21 20:24:50] execute command "aws ec2 create-image --region ap-northeast-1 --instance-id i-003be640ea8229484 --no-reboot --name prod-admin-web_20200721202450 | jq -r ".ImageId""
[2020-07-21 20:24:51] command result .. ami-02751dec1db361b4c
[2020-07-21 20:24:51] AMI Tagging
[2020-07-21 20:24:51] execute command "aws ec2 create-tags --region ap-northeast-1 --resources ami-02751dec1db361b4c \
  --tags Key=Name,Value=prod-admin-web_20200721202450 Key=Type,Value=autoscaling Key=Environment,Value=prod"
[2020-07-21 20:24:52] command result .. ami-02751dec1db361b4c
[2020-07-21 20:24:52] AMI 作成完了待ち


... snip ...
```

## 課題

- 設定ファイルとスクリプトを一緒にしている. yaml とかに分離させたい
- userdata どうするのとか、スポットインスタンス使いたいとか、起動テンプレート使いたいとか、東京リージョン固定が嫌だとか、汎用的にはしていない