AMIバックアップ操作をAWSCLIで行う

# 目的（やりたいこと）
- AMI取得をCLI行いたい

メンテナンスなどでマシン（EC2）のイメージバックアップ（AMI）を行う。GUIでも実施可能だが煩雑。GUIも頻繁にアップデートされるため、コマンドで実施。

# 前提条件
- Cloudshellを利用

# 手順

<br>

## インスタンスID取得
EC2のタグ「Name」に対して、「target-grp-machine01」と設定しているマシンのインスタンスIDを確認する（このマシンがバックアップ取得対象インスタンス）。タグNameでなくとも、なにかしらタグとValueを入れていれば検索できる。

EC2_NAME変数にtarget-grp-machine01を代入。
```sh
export EC2_NAME=target-grp-machine01
```

この名前から、Nameタグを検索し、インスタンスIDを表示してINSTANCE_ID変数に代入。
```sh
export INSTANCE_ID=`aws ec2 describe-instances --filter "Name=tag:Name,Values=${EC2_NAME}" --query "Reservations[].Instances[].[InstanceId]" --output text | column -t`
```

インスタンスIDが代入されたことを確認する。
```sh
echo ${INSTANCE_ID}
```

<br>

## インスタンス停止
オンラインバックアップすると、瞬断したりする。このため、完全な静止点をとる意味でもコールドバックアップを行う。マシンを以下コマンドでシャットダウンする。「--region ap-northeast-1」は東京リージョン。ご自身のリージョンに任意修正。


```sh
aws ec2 stop-instances --instance-ids "${INSTANCE_ID} --region ap-northeast-1
```

## インスタンス状態確認
インスタンスが停止したかどうかを確認する。停止するとStopped表記になる。
※Nameタグを検索し、インスタンスの状態を表示するため、ご自身のタグ名に修正。

```sh
aws ec2 describe-instances --filter "Name=tag:Name,Values=${EC2_NAME}" --query 'Reservations[].Instances[].{Name:Tags[?Key==`Name`].Value|[0],InstanceId:InstanceId,state:State.Name}' --output text | column -t
```

## AMI名確定
AMI名を決めておく。
CloudShellは時刻がUTCのため、バックアップ日時がUTCだと困るので、JSTで現在の日次を取得。

```sh
export BACKUP_DATE=`TZ=JST-9 date +"%Y%m%d%I%M"`
```

日時の代入確認。
```sh
echo ${BACKUP_DATE}
```

現在日時と同じことを確認。
```sh
TZ=JST-9 date
```


AMI名を代入。ここではAMI名を「ami-target-grp-machine01_JSTの現在日時」としている。

```sh
export AMI_NAME=ami-target-grp-machine01_"${BACKUP_DATE}"
```

代入の確認。
```sh
echo ${AMI_NAME}
```

## AMI作成
以下コマンドで実際にバックアップを行う。
「--region ap-northeast-1」は東京リージョンだが、実際のインスタンスを配置しているリージョンに合わせて変更。

```sh
aws ec2 create-image \
 --instance-id ${INSTANCE_ID} \
 --name ${AMI_NAME} \
 --region ap-northeast-1 \
 --tag-specifications \
 "ResourceType=image,Tags=[{Key=Name,Value='${AMI_NAME}'}]" \
 "ResourceType=snapshot,Tags=[{Key=Name,Value='${AMI_NAME}'}]"
```

## AMI確認
AMIのバックアップ状態を確認する。
「--owners AWSアカウントID」は自身のAWSアカウントIDを入力。

```sh
aws ec2 describe-images \
 --region ap-northeast-1 \
 --owners AWSアカウントID \
 --filters "Name=tag:Name,Values='${AMI_NAME}'" \
 --query 'Images[].{Id1:Tags[?Key==`Name`].Value|[0],Id2:ImageId,id3:CreationDate,Id4:State}' \
 --output text | column -t
```

## スナップショット確認
AMIによるバックアップは、インスタンスの各EBSスナップショットをとっていることが実態とのこと。ということで、タグに指定したAMI名から、スナップショットの状況を確認する。これが完了するとAMI取得が完了する。「AMI確認」のコマンドと本コマンドを交互に叩いて、バックアップ状況を確認していく。

```sh
aws ec2 describe-snapshots \
  --owner-ids AWSアカウントID \
  --filters "Name=tag:Name,Values='${AMI_NAME}'" \
  --query 'Snapshots[].{Id1:Tags[?Key==`Name`].Value|[0],Id2:SnapshotId,Id3:StartTime,Id4:State,Id5:Progress}' \
  --output text | column -t
```

## インスタンス起動
念のため環境変数を確認。値があればOK。

```sh
echo ${EC2_NAME}
echo ${INSTANCE_ID}
```

インスタンスを起動する。

```sh
aws ec2 start-instances --instance-ids ${INSTANCE_ID} --region ap-northeast-1
```

インスタンス状態確認コマンドで確認。runningになれば起動OK。Nameタグで取得しているため、任意修正。


```sh
aws ec2 describe-instances --filter "Name=tag:Name,Values=${EC2_NAME}" --query 'Reservations[].Instances[].{Name:Tags[?Key==`Name`].Value|[0],InstanceId:InstanceId,state:State.Name}' --output text | column -t
```


# 参考

AWS コマンドでEC2のAMIを作成/削除するサンプル

https://itsakura.com/aws-command

<br>
AMIの作成時にイメージとスナップショットにタグを付けるAWS CLI

https://cloud5.jp/ami-and-sanpshot-tag/

<br>
AWS CLIでAMI・スナップショット一覧を取得する

https://blog.serverworks.co.jp/get-ami-snapshot-list

<br>
AWS CLIの--queryでよく使う、ダッシュ(-)とかをエスケープしたり変数展開する方法まとめ

https://qiita.com/qtatsunishiura/items/fdd5e7f251299a90cd8c

<br>
AWS CLIからEC2の起動と停止を行う

https://itsakura.com/aws-cli-ec2-start

<br>
dateコマンドでタイムゾーンを指定する

https://salumarine.com/set-timezone-for-date-command/