EC2 AMIを自動で取得するスクリプトを検証してみた

## はじめに

EC2 AMIを取得するスクリプトを検証してみました。
**AMIの取得時にEC2を再起動しない且つディスクは削除終了にチェックを入れることです。**

chatGPTにAMI取得スクリプトを教えていただき動作検証した結果を記事にまとめています。

### 前提条件
2つのEC2のAMIを取得する
※EC2は作成後、削除するためEC2のインスタンスIDは隠しておりません。

**EC2の起動時刻がAMI取得後に変わらないことを確認する**

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2599002/83df605d-cd59-1a3d-dac1-c9b7147bbf69.png)

### AMI取得スクリプト
```
#!/bin/bash

# jqがインストールされているか確認
if ! command -v jq &> /dev/null; then
    echo "jqがインストールされていません。インストールしてください。"
    exit 1
fi

# 複数のインスタンスIDを指定
INSTANCE_IDS=("i-092d7b81160094de7" "i-00507569a3930cef8")

# 現在の日付を取得 (例: 20241110)
DATE=$(date +"%Y%m%d")

for INSTANCE_ID in "${INSTANCE_IDS[@]}"; do
    # インスタンスのNameタグを取得
    INSTANCE_NAME=$(aws ec2 describe-instances \
        --instance-ids "$INSTANCE_ID" \
        --query "Reservations[0].Instances[0].Tags[?Key=='Name'].Value" \
        --output text)

    # インスタンス名が取得できなければエラー
    if [ -z "$INSTANCE_NAME" ]; then
        echo "インスタンス $INSTANCE_ID のNameタグが見つかりません。スキップします。"
        continue
    fi

    # AMI名を作成 (例: インスタンス名-YYYYMMDD-test)
    AMI_NAME="${INSTANCE_NAME}-${DATE}-test"

    # インスタンスに紐づくブロックデバイスマッピングを取得し、DeleteOnTerminationを設定
    BLOCK_DEVICE_MAPPINGS=$(aws ec2 describe-instances \
        --instance-ids "$INSTANCE_ID" \
        --query "Reservations[0].Instances[0].BlockDeviceMappings" \
        --output json)

    # ブロックデバイスマッピングにDeleteOnTerminationを設定
    BLOCK_DEVICE_MAPPINGS_JSON=$(echo "$BLOCK_DEVICE_MAPPINGS" | jq -c '[.[] | {DeviceName: .DeviceName, Ebs: {DeleteOnTermination: true}}]')

    # AMIを作成 (再起動なし) + Nameタグを付与
    AMI_ID=$(aws ec2 create-image \
        --instance-id "$INSTANCE_ID" \
        --name "$AMI_NAME" \
        --no-reboot \
        --block-device-mappings "$BLOCK_DEVICE_MAPPINGS_JSON" \
        --tag-specifications "ResourceType=image,Tags=[{Key=Name,Value=$AMI_NAME}]" \
        --query "ImageId" \
        --output text)

    if [ -z "$AMI_ID" ]; then
        echo "AMIの作成に失敗しました。インスタンスID: $INSTANCE_ID"
        continue
    else
        echo "Created AMI for instance $INSTANCE_ID with AMI ID: $AMI_ID and name: $AMI_NAME"
    fi

    # AMIに関連するスナップショットを取得し、Nameタグを付与
    SNAPSHOT_IDS=$(aws ec2 describe-images \
        --image-ids "$AMI_ID" \
        --query "Images[0].BlockDeviceMappings[*].Ebs.SnapshotId" \
        --output text)

    for SNAPSHOT_ID in $SNAPSHOT_IDS; do
        aws ec2 create-tags \
            --resources "$SNAPSHOT_ID" \
            --tags Key=Name,Value="$AMI_NAME"

        if [ $? -eq 0 ]; then
            echo "Added Name tag to snapshot $SNAPSHOT_ID with Name: $AMI_NAME"
        else
            echo "Failed to add Name tag to snapshot $SNAPSHOT_ID"
        fi
    done
done
```
## 対応手順
sakuraエディタを開き、本記事に記載した上記のスクリプト貼り付けました。

UTF8を文字コードセットを指定して、改行コードLF(UNIX)を指定しました。
※上記の設定をしないとcloudshellでスクリプトを実行しようとしたら文字コードのエラーで怒られます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2599002/5484ccbe-c4e4-b904-aa31-624b0b7cd0f9.png)



cloudshellを起動しました。

```
[cloudshell-user@ip-10-130-46-88 ~]$ sh AMIget.sh
Created AMI for instance i-092d7b81160094de7 with AMI ID: ami-0a06d31f7f12dc21d and name: test-20241110-test
Added Name tag to snapshot snap-0e0aaeb59ee2485fa with Name: test-20241110-test
Added Name tag to snapshot snap-0ba6f95053ecc7845 with Name: test-20241110-test
Created AMI for instance i-00507569a3930cef8 with AMI ID: ami-07433c3736e775319 and name: test2-20241110-test
Added Name tag to snapshot snap-0fa3d5c0f38a92cc5 with Name: test2-20241110-test
```
**AMIを取得しました**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2599002/6aef41fa-7a4b-28cc-ab26-869056db5146.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2599002/e9cf4b44-d892-053f-aef2-5803362feea7.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2599002/785421d4-aa17-a53a-a8de-9c8b2c2bfac2.png)

**AMI取得した際にEC2は再起動されていないことを確認した。**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2599002/2db5dbf5-41d3-f075-2288-1ac3cd78e62a.png)

### 本記事のスクリプトで取得したAMIからEC2が問題なく起動できるか確認した
**取得したAMIからEC2を問題なく起動できてSSH接続までできました。**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2599002/1285fd3c-c53a-b26e-e34a-234d33825abd.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2599002/e2b8806c-457f-3933-e2ac-ceeffdd0f844.png)

**取得したAMIから復元したEC2からAMIが問題なく取得できました。**
```
[cloudshell-user@ip-10-130-46-88 ~]$ sh AMIget.sh
Created AMI for instance i-0d2fdc2e6a87e20ca with AMI ID: ami-0fe8859f8e5922229 and name: test3-20241110-test
Added Name tag to snapshot snap-031bc35b07d4addaf with Name: test3-20241110-test
Added Name tag to snapshot snap-0f546428647631583 with Name: test3-20241110-test
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2599002/02e34723-4ca0-2520-bf6b-d6ce6f4684e1.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2599002/6f21cb31-d88a-7da2-daaa-7e89a0ae7172.png)

元のEC2とスクリプトで取得したAMIから起動したEC2とディスク領域も同じのため、問題なし
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2599002/0b31cf72-53ec-d150-cf29-637e4c260eed.png)


## まとめ
AMI取得はスクリプトで取得した方が自動化出来て効率が良いです。
本記事のスクリプトで指定したEC2インスタンスIDからAMIを取得できるため、ぜひ参考にしてください