AWS CLIを組み合わせて不要なEBSスナップショットを特定したい!

Adways Advent Calendar 2019 3日目の記事です。

http://blog.engineer.adways.net/entry/advent_calendar_2019


 

こんにちは。奥村です。
本日は、EBSのスナップショットを削除するために作成したBashスクリプトを紹介します。
aws cliを使って、AutoScaling Groupで使われていないスナップショットを特定するスクリプトです。

本題

ふとAWSマネジメントコンソールのEBSスナップショットを見ると、何のために作られたか分からないEBSスナップショットが存在することありませんか?
私はありました。
「分からないから消しちゃおう」とはいかないのが現実。
AutoScalingを行っていると、Launch config(起動設定)でAMIを指定しますね。そしてAMIはEBSスナップショットから作成される。

つまり、EBSスナップショットが無くなると、オートスケーリングできなくなりますね。
もしかしたらそもそも消せないかもしれません

なので、事前に利用状態かの判断を簡単にするためにスクリプトを作成しました。

今回紹介するのは

  • ホストゾーンをpecoで選択し登録されているレコードの中でAliasレコードを表示するスクリプト
  • ALBのARNを引数にして、対象のALBで利用しているLaunch configを表示するスクリプト
  • Launch configの一覧、AMI一覧を結合して表示するスクリプト

です。

「Route53 -> ALB -> AutoScaling」という環境向けのスクリプトですが、同じパターンを採用していることが多いのではないかと思います。

環境

必要なコマンドラインツールと実行検証を行った環境を記載します。

  • Bash
    • 4.3.4
  • jq
    • 1.5.1
  • peco
    • v0.5.1
  • aws cli
    • 1.16.131

上記コマンドが使える前提で進めていきます。

Bashスクリプト

ホストゾーンをpecoで選択し登録されているレコードの中でAliasレコードを表示するスクリプト

「get_from_domain_to_alb.sh」という名前にしています。

#!/bin/bash
hosted_zone_id=$(aws route53 list-hosted-zones | jq -r '.HostedZones[] | [.Name, .Id]|@tsv' | peco | awk '{print $2}' | awk -F'/' '{print $3}')

hostzone_alias_records=$(aws route53 list-resource-record-sets --hosted-zone-id "${hosted_zone_id}" | jq -r '.ResourceRecordSets[] | select(has("AliasTarget")) | [.Name, .AliasTarget.DNSName]|@tsv')
alb_dns_name=$(echo "$hostzone_alias_records" | awk '{print $2}' | sed -r 's/^dualstack.(.*)\./\1/')

alias_record_alb_dns=$(paste <(echo "$hostzone_alias_records") <(echo "$alb_dns_name") | sort -k 3 )

alb=$(aws elbv2 describe-load-balancers | jq -r '.LoadBalancers[] | [.DNSName, .LoadBalancerName, .LoadBalancerArn]|@tsv' | sort -k 1)

join -a 1 -a 2 -1 3 -2 1 -o 1.{1,2} 2.{2,3} -e none <(echo "${alias_record_alb_dns}") <(echo "${alb}")

を実行すると

./get_from_domain_to_alb.sh
<ドメイン> <Aliasレコードの宛先> <ALBの名前> <ALBのARN>
<ドメイン> <Aliasレコードの宛先> <ALBの名前> <ALBのARN>
.
.
.

という形式で表示されます。

これで、ドメインからALBのARNまでの関係を知ることができました。
次のスクリプトで、ALBのARNを引数として使います。

ALBのARNを引数にして、対象のALBで利用しているLaunch configを表示するスクリプト

「get_from_alb_to_launchconfig.sh」という名前にしています。

#!/bin/bash

if [[ -z "$1" ]];then
  echo "need $0 <alb_arn>"
  exit 1
fi

alb_arn=$1
target_groups=$(aws elbv2 describe-target-groups --load-balancer-arn "${alb_arn}" | jq -r --arg alb_arn "${alb_arn}" '.TargetGroups[]| [$alb_arn, .TargetGroupName, .TargetGroupArn]|@tsv'| sort -k 3)
target_group_array=($(echo "${target_groups}" | awk '{ print $3}' | tr '\n' ' ' | sed 's/\s*$//'))

target_group_autoscaling=$(for target_group_arn in "${target_group_array[@]}"
do
  aws autoscaling describe-auto-scaling-groups | jq -r --arg arn "${target_group_arn}" '.AutoScalingGroups[] | select(.TargetGroupARNs | contains([$arn])) | [$arn, .AutoScalingGroupName, .LaunchConfigurationName]|@tsv'
done | grep -v ^$ | sort -k 1)

join -a 1 -a 2 -1 3 -2 1 -o 1.{1,2} 2.{2,3} -e none <(echo "${target_groups}") <(echo "${target_group_autoscaling}")

を実行すると

./get_from_alb_to_launchconfig.sh <ALBのARN>
<ALBのARN> <ターゲットグループ名> <オートスケーリンググループ名> <Launch Config名>
<ALBのARN> <ターゲットグループ名> <オートスケーリンググループ名> <Launch Config名>

という形式で表示されます。

対象のLaunch configがなければ(オートスケーリングじゃなければ)対象の列には「none」と表示されます。

Launch configの一覧、AMI一覧を結合して表示するスクリプト

「get_from_launchconfig_to_ebs.sh」という名前にしています。

#!/bin/bash
launch_response=$(aws autoscaling describe-launch-configurations)
launch_config=$(echo "${launch_response}" | jq -r '.LaunchConfigurations[]| [.LaunchConfigurationName, .ImageId]|@tsv' | sort -k 2)
ami_response=$(aws ec2 describe-images --owners self)
ami=$(echo "${ami_response}" | jq -r '.Images[]| [.ImageId, .Name, .BlockDeviceMappings[0].Ebs.SnapshotId]|@tsv' | sort )
join -a 1 -a 2 -1 2 -2 1 -o 1.{1,2} 2.{2,3} -e none <(echo "${launch_config}") <(echo "${ami}") | sort | tac | uniq

を実行すると

<Launch Config名> <AMI名> <スナップショットID>
<Launch Config名> <AMI名> <スナップショットID>
.
.
.

という形式で表示されます。
スナップショットだけ存在し、Launch Config, AMIと紐づかない行は、「none」と表示されます。
Launch Configと紐づかないスナップショットの特定もできましたね!

本来行いたかったのは、このスクリプトですね!

これで使っていないEBSスナップショットを特定することができました!
後は削除するだけです!

まとめ

年越し前にEBSやEBSスナップショットが削除(掃除)できて良かったです!
実際の削除を行う時は自己責任でお願いします...
当スクリプトでお掃除を行いましたが、現在は Pakcer + CloudFormationで AMI作成 -> 最新のLaunch Config作成 -> ターゲットグループに適用を行っています。
そもそも手作業が発生しない運用を目指すのが良いと思います。

最後までご覧いただきありがとうございました。


 

次はまっちゃんの記事です。

http://blog.engineer.adways.net/entry/advent_calendar_2019/04