18
15

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

AWS-CLIによるAMI作成と削除自動化(JSON取得によるRedmineチケット駆動)

Last updated at Posted at 2016-09-11

はじめに

本記事では、AWS-CLIによるAMI作成方法と削除方法について記述します。
また、JenkinsとRedmineを使用したAMI作成・削除の自動化の実現例も合わせて記述します。

実現イメージ

チケット起票(Redmine)→チケット内容取得(Jenkins)→取得内容に合わせてAWS-CLI実行(Jenkins)→起票
チケット更新(Jenkins,Redmine)※

※AWS-CLI実行結果を起票されたチケットに対して更新します。(AMIIDやチケットステータスを更新)

AMI作成

コマンド

AMI作成
aws ec2 create-image --instance-id EC2インスタンスID --name "任意のAMI名" --reboot

説明

--instanceid:AMIの元となるEC2インスタンスIDを指定してください。インスタンスIDはAWSコンソールまたはAWS-CLIだとdescribe-instancesで参照できます。
--name:作成するAMIの名前を指定します。文字の範囲ですが、ASCIIコードまでしか対応されていなかった気がします。曖昧ですみません…
--reboot/--no reboot:AMI作成時にインスタンスを再起動するかを指定します。--no rebootでインスタンスが稼働中にAMIを作成することができます。ただし、公式ドキュメントには以下のように記載されています。可能な限り--rebootを指定して、インスタンスとAMIが同じ状態であることを担保したほうが良いと思います。

[No reboot] を選択した場合、Amazon では作成されたイメージのファイルシステムの整合性を保証できません。

AMI削除

コマンド

AMI削除
aws ec2 deregister-image --image-id 削除したいAMIID
SnapShot削除
aws ec2 delete-snapshot --snapshot-id AMIに紐づくSnapShotIDを指定

説明

--image-id:削除したいAMIIDを指定します。
SnapShot削除:AMIに紐づくSnapShotを削除しない限り、課金されます。

実装例

Jenkins側(シェルの実行)

#!/bin/bash

#JSON形式でチケット情報を取得(終了チケットを含めて取得)
JSON=$(curl -v -H "Content-Type: application/json" -X GET --data-binary "@issue.json" -H "X-Redmine-API-Key: RedmineAPIキーをここに指定" http://RedmineURLをここに指定/issues.json?status_id=%2a)

#チケットID取得
TicketId=$(echo ${JSON} | jq '.issues[].id')
#チケットステータス取得
TicketStatus=$(echo ${JSON} | jq '.issues[].status | .id')
#チケット進捗率取得
TicketDoneRatio=$(echo ${JSON} | jq '.issues[].done_ratio')
#インスタンスID取得
InstanceId=$(echo ${JSON} | jq '.issues[].description' | sed -e 's/\\r\\n/,/g' | awk -F, '{print $1}' | awk -F: '{print $2}')
#AMI名取得
AmiName=$(echo ${JSON} | jq '.issues[].subject' | sed -e 's/[\" ,]//g')

#取得した値を配列化
TICKET_ID=(`echo ${TicketId}`)
TICKET_STATUS=(`echo ${TicketStatus}`)
TICKET_DONE_RATIO=(`echo ${TicketDoneRatio}`)
INSTANCE_ID=(`echo ${InstanceId}`)
AMI_NAME=(`echo ${AmiName}`)


COUNT=0
for rec in ${TICKET_ID[@]}
do
    #チケットステータスが新規のチケットを対象とする
	if [ ${TICKET_STATUS[$COUNT]} -eq "1" ]; then
    #チケットステータスが新規のみAMI作成
    	#AMI作成
    	RET=$(aws ec2 create-image --instance-id ${INSTANCE_ID[$COUNT]} --name "${AMI_NAME[$COUNT]}" --reboot)
        
        #作成したAMIIDを取得
    	AmiId=$(echo ${RET} | python -m json.tool | grep "ImageId" | awk -F: '{print $2}' | sed -e 's/[\" ,]//g')
        
        #AMIの元となるインスタンスのタグ情報取得
        NameTag=$(aws ec2 describe-instances --instance-ids ${INSTANCE_ID[$COUNT]} | jq '.Reservations[].Instances[] | .Tags[] | select(.Key=="Name").Value')
        ApplicationTag=$(aws ec2 describe-instances --instance-ids ${INSTANCE_ID[$COUNT]} | jq '.Reservations[].Instances[] | .Tags[] | select(.Key=="Application").Value')
        CostcenterTag=$(aws ec2 describe-instances --instance-ids ${INSTANCE_ID[$COUNT]} | jq '.Reservations[].Instances[] | .Tags[] | select(.Key=="Costcenter").Value')
        OwnerTag=$(aws ec2 describe-instances --instance-ids ${INSTANCE_ID[$COUNT]} | jq '.Reservations[].Instances[] | .Tags[] | select(.Key=="Owner").Value')
        
        
        #作成したAMIにタグを付与
        aws ec2 create-tags --resources ${AmiId} --tags Key=Name,Value=${NameTag}
        aws ec2 create-tags --resources ${AmiId} --tags Key=Application,Value=${ApplicationTag}
        aws ec2 create-tags --resources ${AmiId} --tags Key=Costcenter,Value=${CostcenterTag}
        aws ec2 create-tags --resources ${AmiId} --tags Key=Owner,Value=${OwnerTag}
        #チケットIDをタグに追加
        aws ec2 create-tags --resources ${AmiId} --tags Key=TicketId,Value=${TICKET_ID[$COUNT]}
        
        #作成したAMIIDをチケットの履歴に追加
        curl -v -H "Content-Type: application/json" -H "X-Redmine-API-Key: RedmineAPIキーをここに指定" -X PUT -d '{"issue":{"notes":"AmiId:'$AmiId'"}}' http://RedmineURLをここに指定/issues/${TICKET_ID[$COUNT]}.json
        
    	#チケットステータスを"進行中"に更新
        curl --include http://RedmineURLをここに指定/issues/${TICKET_ID[$COUNT]}.xml -X PUT -d '<issue><status_id>2</status_id></issue>' -H "Content-Type: text/xml" -H "X-Redmine-API-Key: RedmineAPIキーをここに指定"

    #チケットステータスが進行中かつ進捗率が0%のチケットを対象とする        
    elif [ ${TICKET_STATUS[$COUNT]} -eq "5" ] && [ ${TICKET_DONE_RATIO[$COUNT]} -eq 0 ]; then
        #チケットステータスが"終了"かつ進捗率が"0%"の場合、AMI削除
        
        #AMI情報取得
        AmiList=$(aws ec2 describe-tags --filters "Name=resource-type,Values=image" "Name=key,Values=TicketId" "Name=value,Values=${TICKET_ID[$COUNT]}")
        
        #AMIID取得
        DeleteAmiId=$(echo ${AmiList} | jq '.Tags[].ResourceId' | sed -e 's/[\" ,]//g')
        
		#SnapShot情報取得
        SnapShotId=$(aws ec2 describe-images --image-ids $DeleteAmiId | jq '.Images[].BlockDeviceMappings[].Ebs | .SnapshotId' | sed -e 's/[\" ,]//g')
        #取得した値を配列化
		SNAPSHOT_ID=(`echo ${SnapShotId}`)

        #AMI削除
		aws ec2 deregister-image --image-id $DeleteAmiId
        
        #スナップショット削除
        #INT=0
        for item in ${SNAPSHOT_ID[@]}
        do
        	aws ec2 delete-snapshot --snapshot-id ${SNAPSHOT_ID[$INT]}
            INT=`expr $INT + 1`
        done
        
        
        #進捗率を"100%"に更新
        curl --include http://RedmineURLをここに指定/issues/${TICKET_ID[$COUNT]}.xml -X PUT -d '<issue><done_ratio>100</done_ratio></issue>' -H "Content-Type: text/xml" -H "X-Redmine-API-Key: RedmineAPIキーをここに指定"
        
        #削除した旨をチケットの履歴に追加
        curl --include http://RedmineURLをここに指定/issues/${TICKET_ID[$COUNT]}.xml -X PUT -d "<issue><notes>deleted the AMI.</notes></issue>" -H "Content-Type: text/xml" -H "X-Redmine-API-Key: RedmineAPIキーをここに指定"
    fi
    
    COUNT=`expr $COUNT + 1`
done

Redmine側

###チケット記述ルール(チケットテンプレートを活用)
題名:作成したいAMI名を入力
説明:
InstanceId:i-XXXXXXXX(作成したいAMIの元となるEC2インスタンスIDを入力)
Description:開発環境のAMIです。(AMIの情報を入力※入力内容は自由です)

18
15
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
18
15

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?