0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

EC2インスタンスを別リージョンにコピーするスクリプト

Posted at

はじめに

AWSのEC2インスタンスを別リージョンに移設する必要があったため、対象EC2インスタンスID.ソースリージョン、ターゲットリージョンを指定して、AMIを作成し、別リージョンにコピーするスクリプトを作成しました。

前提

  • AWS CLIがインストールされていること
  • AWS ConfigureでIAM認証情報が設定されていること

スクリプトの概要

このスクリプトは以下の機能を提供します:

  1. 指定されたEC2インスタンスからAMIを作成
  2. AMI作成を待って、作成したAMIを別リージョンにコピー

スクリプト

スクリプトファイル内容
#!/bin/bash

set -e

# ヘルプメッセージの表示
show_help() {
    cat << EOF
EC2インスタンスを別リージョンにコピーするスクリプト

使用方法:
    $(basename $0) [オプション]

オプション:
    --instance-id     コピー元のEC2インスタンスID(必須)
    --source-region   コピー元のAWSリージョン(必須)
    --target-region   コピー先のAWSリージョン(必須)
    --ami-name        AMIの名前(オプション)
    --help           このヘルプメッセージを表示

例:
    # AMI名を指定する場合
    $(basename $0) --instance-id i-1234567890abcdef0 --source-region ap-northeast-1 --target-region us-west-2 --ami-name "custom-ami-name"
    
    # AMI名を指定しない場合(EC2のNameタグから自動生成)
    $(basename $0) --instance-id i-1234567890abcdef0 --source-region ap-northeast-1 --target-region us-west-2
EOF
    exit 1
}

# エラーメッセージを表示して終了
error_exit() {
    echo "エラー: $1" >&2
    exit 1
}

# 引数のパース
while [[ $# -gt 0 ]]; do
    case $1 in
        --help)
            show_help
            ;;
        --instance-id)
            INSTANCE_ID="$2"
            shift 2
            ;;
        --source-region)
            SOURCE_REGION="$2"
            shift 2
            ;;
        --target-region)
            TARGET_REGION="$2"
            shift 2
            ;;
        --ami-name)
            CUSTOM_AMI_NAME="$2"
            shift 2
            ;;
        *)
            error_exit "不明な引数: $1"
            ;;
    esac
done

# 必須パラメータのチェック
[[ -z "$INSTANCE_ID" ]] && error_exit "instance-idは必須です"
[[ -z "$SOURCE_REGION" ]] && error_exit "source-regionは必須です"
[[ -z "$TARGET_REGION" ]] && error_exit "target-regionは必須です"

# インスタンスIDの形式チェック
[[ ! "$INSTANCE_ID" =~ ^i-[a-f0-9]{8,}$ ]] && error_exit "無効なインスタンスID形式です: $INSTANCE_ID"

# AWS CLIの存在確認
command -v aws >/dev/null 2>&1 || error_exit "AWS CLIがインストールされていません"

echo "パラメータの確認:"
echo "インスタンスID: $INSTANCE_ID"
echo "ソースリージョン: $SOURCE_REGION"
echo "ターゲットリージョン: $TARGET_REGION"

# EC2インスタンスの存在確認とNameタグの取得
echo "EC2インスタンスの情報を取得中..."
INSTANCE_INFO=$(aws ec2 describe-instances \
    --instance-ids "$INSTANCE_ID" \
    --region "$SOURCE_REGION" \
    --query 'Reservations[0].Instances[0]' \
    --output json 2>/dev/null) || error_exit "インスタンスの取得に失敗しました"

# AMI名の設定
if [[ -n "$CUSTOM_AMI_NAME" ]]; then
    AMI_NAME="$CUSTOM_AMI_NAME"
else
    # Nameタグの取得
    INSTANCE_NAME=$(echo "$INSTANCE_INFO" | jq -r '.Tags[] | select(.Key=="Name") | .Value' 2>/dev/null)
    if [[ -z "$INSTANCE_NAME" ]]; then
        error_exit "指定されたEC2インスタンス($INSTANCE_ID)にNameタグが設定されていません。--ami-nameオプションでAMI名を指定してください。"
    fi
    AMI_NAME="${INSTANCE_NAME}_AMI"
fi
echo "AMI名: $AMI_NAME"

# AMIの作成
echo "AMIを作成中..."
AMI_ID=$(aws ec2 create-image \
    --instance-id "$INSTANCE_ID" \
    --name "$AMI_NAME" \
    --description "Created from $INSTANCE_ID" \
    --region "$SOURCE_REGION" \
    --no-reboot \
    --output text) || error_exit "AMIの作成に失敗しました"

echo "AMI ID: $AMI_ID"

# AMI状態の待機処理
wait_for_image() {
    local image_id=$1
    local region=$2
    local retries=6
    local attempt=1

    while [ $attempt -le $retries ]; do
        echo "AMI状態確認: 試行 $attempt/$retries"
        if aws ec2 wait image-available --image-ids "$image_id" --region "$region"; then
            return 0
        fi
        attempt=$((attempt + 1))
        if [ $attempt -le $retries ]; then
            echo "リトライします..."
        fi
    done
    return 1
}

# AMI作成完了を待機
echo "AMIの作成完了を待機中..."
if ! wait_for_image "$AMI_ID" "$SOURCE_REGION"; then
    error_exit "AMIの作成待機中にエラーが発生しました(6回試行後)"
fi

echo "AMIの作成が完了しました"

# AMIを別リージョンにコピー
echo "AMIを $TARGET_REGION にコピー中..."
COPIED_AMI_ID=$(aws ec2 copy-image \
    --source-image-id "$AMI_ID" \
    --source-region "$SOURCE_REGION" \
    --region "$TARGET_REGION" \
    --name "$AMI_NAME" \
    --output text) || error_exit "AMIのコピーに失敗しました"

echo "コピーされたAMI ID: $COPIED_AMI_ID"

# AMIコピーの完了を待機
echo "AMIのコピー完了を待機中..."
if ! wait_for_image "$COPIED_AMI_ID" "$TARGET_REGION"; then
    error_exit "AMIのコピー待機中にエラーが発生しました(6回試行後)"
fi

echo "処理が正常に完了しました"
echo "ソースAMI ID (${SOURCE_REGION}): ${AMI_ID}"
echo "コピー先AMI ID (${TARGET_REGION}): ${COPIED_AMI_ID}"

使用方法

./copy-ec2.sh [オプション]

オプション:
    --instance-id     コピー元のEC2インスタンスID(必須)
    --source-region   コピー元のAWSリージョン(必須)
    --target-region   コピー先のAWSリージョン(必須)
    --ami-name        AMIの名前(オプション)
    --help           このヘルプメッセージを表示

実行例

# AMI名を指定する場合
./copy-ec2.sh --instance-id i-1234567890abcdef0 --source-region ap-northeast-1 --target-region us-west-2 --ami-name "custom-ami-name"

# AMI名を指定しない場合(EC2のNameタグから自動生成)
./copy-ec2.sh --instance-id i-1234567890abcdef0 --source-region ap-northeast-1 --target-region us-west-2

スクリプトの主要な機能

1. パラメータの検証

# 必須パラメータのチェック
[[ -z "$INSTANCE_ID" ]] && error_exit "instance-idは必須です"
[[ -z "$SOURCE_REGION" ]] && error_exit "source-regionは必須です"
[[ -z "$TARGET_REGION" ]] && error_exit "target-regionは必須です"

# インスタンスIDの形式チェック
[[ ! "$INSTANCE_ID" =~ ^i-[a-f0-9]{8,}$ ]] && error_exit "無効なインスタンスID形式です: $INSTANCE_ID"

2. AMI名の設定

AMI名は以下の優先順位で決定されます:

  1. --ami-nameオプションで指定された値
  2. EC2インスタンスのNameタグの値 + "_AMI"
if [[ -n "$CUSTOM_AMI_NAME" ]]; then
    AMI_NAME="$CUSTOM_AMI_NAME"
else
    INSTANCE_NAME=$(echo "$INSTANCE_INFO" | jq -r '.Tags[] | select(.Key=="Name") | .Value' 2>/dev/null)
    if [[ -z "$INSTANCE_NAME" ]]; then
        error_exit "指定されたEC2インスタンス($INSTANCE_ID)にNameタグが設定されていません。--ami-nameオプションでAMI名を指定してください。"
    fi
    AMI_NAME="${INSTANCE_NAME}_AMI"
fi

3. AMIの作成とコピー

AMIの作成とコピーは以下の手順で行われます:

  1. ソースリージョンでAMIを作成
  2. AMIの作成完了を待機
  3. ターゲットリージョンにAMIをコピー
  4. コピーの完了を待機
# AMIの作成
AMI_ID=$(aws ec2 create-image \
    --instance-id "$INSTANCE_ID" \
    --name "$AMI_NAME" \
    --description "Created from $INSTANCE_ID" \
    --region "$SOURCE_REGION" \
    --no-reboot \
    --output text)

# AMIを別リージョンにコピー
COPIED_AMI_ID=$(aws ec2 copy-image \
    --source-image-id "$AMI_ID" \
    --source-region "$SOURCE_REGION" \
    --region "$TARGET_REGION" \
    --name "$AMI_NAME" \
    --output text)

まとめ

AMI作成やコピーに時間がかかるため、GUIで作業すると待機時間がかかるため、スクリプトで自動化することで、放置している間に作業が完了するため、便利かなと思い、作成しました。

参考文献

0
0
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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?