LoginSignup
23
23

More than 5 years have passed since last update.

EC2インスタンスを毎日自動バックアップする処理をAWS SDK for PHP 2で作成する

Last updated at Posted at 2015-05-08
  • インスタンスのバックアップ(AMI)を自動で1日1回作りたい。
  • 任意の時間にcrontabで1回実行しよう。
  • 保存期間を3日間~7日間、または任意の日数保存しておきたい。
  • 古いAMIは自動で削除したい。AMIとスナップショットを両方消す必要がある。タグAutoCreatedに作成日を付けて取得しよう。
  • バックアップしたいEC2インスタンスにタグDailyBackupを付けて制御したい。

いきなりプログラムをコピペする

create_image.php
<?php

// Include the SDK using the Composer autoloader
require 'vendor/autoload.php';

use Aws\Ec2\Ec2Client;

$today = date('Y-m-d H:i:s');
echo "---BEGIN--- Create Image {$today}\n";

# バックアップの保存日数
$delete_date = date('Y-m-d', strtotime('- 3 day'));
define('DELETE_DATE', $delete_date);

# ap-northeast-1    アジアパシフィック(東京)
# ap-southeast-1    アジアパシフィック (シンガポール)
# ap-southeast-2    アジアパシフィック(シドニー)
# eu-central-1      欧州 (フランクフルト)
# eu-west-1         欧州 (アイルランド)
# sa-east-1         南米(サンパウロ)
# us-east-1         US East (N. Virginia)
# us-west-1         米国西部(北カリフォルニア)
# us-west-2         米国西部(オレゴン)
# 処理実行するリージョン
# eu-central-1      欧州 (フランクフルト) ここは有効領域でないので外すこと
$regions = [
    'ap-northeast-1',
    'ap-southeast-1',
    'ap-southeast-2',
    'eu-west-1',
    'sa-east-1',
    'us-east-1',
    'us-west-1',
    'us-west-2',
];

# 各リージョン毎にバックアップ
$return = array_map('backup', $regions);
# 各リージョン毎に保存期間の過ぎたAMIとSnapshotを消す
$return = array_map('delete_images', $regions);

function backup($region)
{
    echo "---$region BIGIN--- Auto Backup\n";

    # クライアント作成
    $ec2client = Ec2Client::factory(['region' => $region]);

    # 対象instance_ids取得
    $target_instances = $ec2client->describeInstances(
        [
            'Filters' => [
                [
                    'Name' => 'tag:DailyBackup',
                    'Values' => ['true'],
                ],
            ],
        ]
    );

    $target_ids = $target_instances->getPath('Reservations/*/Instances/0/InstanceId');

    # id無いなら処理終了
    if (empty($target_ids))
    {
        echo "---$region FINISH--- Target insetances is empty. Not back up anything.\n";

        return;
    }

    # AMIをinstance_ids分作る。
    foreach ($target_ids as $id)
    {
        $result = create_image($ec2client, $id);
        $image_id = $result['ImageId'];

        # Imageが作成されるまで少し待つ。sleep無いと、タグが付かない事があった
        sleep(1);
        $result = add_tag($ec2client, $image_id, 'AutoCreated', date('Y-m-d'));

        $image_info = $ec2client->describeImages(
            [
                'ImageIds' => [$image_id],
            ]
        );
        $snapshot_id = $image_info->getPath('Images/0/BlockDeviceMappings/0/Ebs/SnapshotId');
        $result = add_tag($ec2client, $snapshot_id, 'AutoCreated', date('Y-m-d'));
        echo "instance_id: $id AMI: $image_id Snapshot_id: $snapshot_id \n";
    }
    echo "---$region FINISH--- Auto Backup\n";
}

function create_image($ec2client, $instance_id)
{
    $result = $ec2client->createImage(
        [
            'InstanceId' => $instance_id,
            'Name' => $instance_id . '_autobackup_' . date('Y-m-d-H-i-s'),
            'Description' => 'autobackup create' . date('Y-m-d-H-i-s'),
            'NoReboot' => true,
        ]
    );

    return $result;
}

function add_tag($ec2client, $resource_id, $key, $value)
{
    $result = $ec2client->createTags(
        [
            'Resources' => [$resource_id],
            'Tags' => [
                [
                    'Key' => $key,
                    'Value' => $value,
                ],
            ],
        ]
    );

    return $result;
}

function delete_images($region)
{
    echo "---$region BIGIN--- Delete AMI and SnapShot\n";

    # クライアント作成
    $ec2client = Ec2Client::factory(['region' => $region]);

    # 削除対象のIDを取得する
    list($image_ids, $snapshot_ids) = get_delete_image_ids($ec2client);

    # IDが無いなら処理終了
    if (empty($image_ids))
    {
        echo "---$region FINISH--- Image ids is empty. Not delete anything\n";

        return;
    }

    # AMIを削除する
    $result = deregister_images($ec2client, $image_ids);

    # SnapShotを削除する
    $result = delete_snapshot($ec2client, $snapshot_ids);

    echo "---$region FINISH--- Delete AMI and SnapShot\n";
}

function get_delete_image_ids($ec2client)
{
    $result = $ec2client->describeImages([
        'Filters' => [
            [
                'Name' => 'tag:AutoCreated',
                'Values' => [DELETE_DATE],
            ],
        ],
    ]);

    # image_idを取得するついでにSnapshot_idも取得できるので取得する
    $image_ids = $result->getPath('Images/*/ImageId');
    $snapshot_ids = $result->getPath('Images/*/BlockDeviceMappings/0/Ebs/SnapshotId');

    return [$image_ids, $snapshot_ids];
}

function deregister_images($ec2client, $image_ids)
{
    foreach ($image_ids as $id)
    {
        $result = $ec2client->deregisterImage(
            [
                'ImageId' => $id,
            ]
        );
        echo 'deregister Image: ', $id, "\n";
    }

    return $result;
}

function delete_snapshot($ec2client, $snapshot_ids)
{
    foreach ($snapshot_ids as $id)
    {
        $result = $ec2client->deleteSnapshot(
            [
                'SnapshotId' => $id,
            ]
        );
        echo 'delete snapshot:  ', $id, "\n";
    }

    return $result;
}

echo "---END--- Create Image \n";

実行

  • タグDailyBackup:trueのインスタンスがバックアップされる
  • タグAutoCreated:YY-mm-ddとついていて、3日前のAMIと対応するSnapShotが削除される。
$ php create_image.php
---BEGIN--- Create Image 2015-04-30 16:00:11
---sa-east-1 BIGIN--- Auto Backup
---sa-east-1 FINISH--- Target insetances is empty. Not back up anything.
---us-east-1 BIGIN--- Auto Backup
instance_id: i-e74019b7 AMI: ami-82e5eaea Snapshot_id: snap-c03c2559
instance_id: i-ac737157 AMI: ami-66e4eb0e Snapshot_id: snap-183e2781
---us-east-1 FINISH--- Auto Backup
---sa-east-1 BIGIN--- Delete AMI and SnapShot
---sa-east-1 FINISH--- Image ids is empty. Not delete anything
---us-east-1 BIGIN--- Delete AMI and SnapShot
---us-east-1 FINISH--- Image ids is empty. Not delete anything
---END--- Create Image

Crontabで1日一回 自動実行させる

crontab
SHELL=/bin/bash
# root PATHを設定
PATH=/usr/local/bin:/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/sbin:/opt/aws/bin:/home/ec2-user/bin:/opt/aws/bin
# mailを送信したくない時
MAILTO=""
AWS=/home/ec2-user/aws-php

# 時間はJSTかUSTかシステムに合わせる。今回はJST。 ログはmessageに吐き出す。
# EC2インスタンスを業務時間だけ自動起動する処理
27 8 * * 1-5 php $AWS/ec2_start.php  2>&1 | logger -t AWS_SDK_AUTO -p local0.info
# EC2インスタンスを毎日自動バックアップする処理
21 8 * * * php $AWS/create_image.php  2>&1 | logger -t AWS_SDK_AUTO -p local0.info

関連するページ

EC2インスタンスを業務時間だけ自動起動する処理をAWS SDK for PHP 2で作成する
自動起動処理するEC2インスタンス自身をオートスケールで1時間だけ起動する

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