さくらのクラウドのディスクの自動バックアップを自作してみる


概要

さくらのクラウドには自動バックアップという機能がありますので、まずはこちらの利用を検討するのがよいと思われます。
以下の希望がある場合は、本処理が参考になる可能性があります。

  • 実行時間を指定したい
  • 週次以外のスケジュールを指定したい

手法

usacloudという CLIクライアントを利用して、対象となるディスクを特定し、アーカイブを作成後、保存世代数を超える過去分を削除するスクリプトを作成します。
この処理を、cron で好きな時間帯に実行することで、お手製の自動バックアップとする形です。
今回は自前のサーバなどを用意しなくてもすむように、GitHub Actions を使用して、指定した時間帯で usacloud のコンテナを作成し、スクリプトを実行するようにしています。


注意事項

  • スクリプトはあくまでもサンプルなので、エラー処理等は一切入れていません。必要に応じて修正ください。
  • 全ゾーンを対象に、 myautobackup タグが付いたディスクをすべてバックアップ対象としています。
  • アーカイブ名は myautobackup-年月日-コピー元ディスクID とし、 myautobackup タグを付与しています。
  • 保存世代数は ROTATE で指定しています。
  • アーカイブ作成コマンドには --no-wait をつけることで、作成完了まで待たずに次の処理にすすむようにしてあります。ただし、それでも数十秒程度は時間がかかるものと思われます。

基本的な流れ

  1. GitHub のリポジトリを プライベート で作成してください。

    • パブリックで作成して公開してしまうと、ログが見えることになるので危険です。
  2. 該当リポジトリ内の Settings で、Secrets内の Actions に以下 Actions secrets を設定してください。

    Name
    SAKURACLOUD_ACCESS_TOKEN
    SAKURACLOUD_ACCESS_TOKEN_SECRET
    
  3. 以下ファイルを配置してください。

    backup.sh
    #!/bin/bash
    
    TODAY=`TZ='Asia/Tokyo' date "+%Y%m%d"`
    TARGET_TAG="myautobackup"
    NAME="myautobackup-${TODAY}"
    TAGS="myautobackup"
    ROTATE=2
    
    for Zone in tk1a tk1b is1a is1b
    do
    	echo "---- List Target Disks of $Zone ----"
    	DiskIds=`usacloud disk ls --tags $TARGET_TAG --zone $Zone --query="reverse | .[].ID" --query-driver=jq | xargs`
    
    	for DiskId in $DiskIds
    	do
    		echo "---- Create Archive $DiskId ----"
    		usacloud archive create --source-disk-id $DiskId --name "${NAME}-${DiskId}" --tags $TAGS -y --zone $Zone -q --no-wait
    
    		# sort by CreatedAt or Name
    		ArchiveIds=`usacloud archive ls --scope user --tags $TAGS --zone $Zone --output-type json --query "map(select( .SourceDiskID==$DiskId )) | sort_by(.CreatedAt) | reverse | .[${ROTATE}:]|.[].ID" --query-driver=jq | xargs`
    		for Id in $ArchiveIds
    		do
    			echo "---- Delete Archive $Id ----"
    			usacloud archive delete -y $Id --zone $Zone
    		done
    	done
    done
    
    echo "---- Archives ----"
    usacloud archive ls --scope user --tags $TAGS --zone all	
    
    .github/workflows/backup.yml
    name: Backup
    
    on:
    #  push:
    #    branches:
    #      - main
      schedule:
        - cron:  '20 0 * * *'
    
    jobs:
      node-docker:
        runs-on: ubuntu-latest
        container: #起動するコンテナイメージを指定
          image: ghcr.io/sacloud/usacloud #指定のdockerイメージを使用
    
        env:
          SAKURACLOUD_ACCESS_TOKEN: ${{ secrets.SAKURACLOUD_ACCESS_TOKEN }}
          SAKURACLOUD_ACCESS_TOKEN_SECRET: ${{ secrets.SAKURACLOUD_ACCESS_TOKEN_SECRET }}
          SAKURACLOUD_ZONE: "is1a"
        steps: #dockerコンテナ内でステップを実行
          - name: Log usacloud version
            run: |
              usacloud -v #バージョンの確認
              cat /etc/os-release #Linuxバージョンの確認
              apk add --update --no-cache tzdata
          - uses: actions/checkout@v2 #次ステップでファイル読み込むのでクローンが必要
          - name: Run a script
            run: sh ./backup.sh
    
  4. backup.yml にあるとおり、日本時間の毎日 9:20頃に実行されるようになっていますので、必要に応じて実行時間を変更してください。

    schedule:
    	- cron:  '20 0 * * *'
    
    • 上記指定だと実際には 11時過ぎに実行されたりしました。負荷の少なそうな時間帯を探すか、おとなしく自前の実行環境を用意した方がいいかもしれません。
    • 実行時間については公式の情報も参照ください。
    ノート: scheduleイベントは、GitHub Actionsのワークフローの実行による高負荷の間、遅延させられることがあります。 
    高負荷の時間帯には、毎時の開始時点が含まれます。 
    遅延の可能性を減らすために、Ⅰ時間の中の別の時間帯に実行されるようワークフローをスケジューリングしてください。
    
  5. backup.sh にあるとおり、保存世代数は 2 になっていますので、必要に応じて変更してください。

    ROTATE=2
    

サンプルログ

実行時のログを確認すると、以下のように見えます。
このときは 2つのディスクが対象になっていて、うち 1つはすでに 2つのアーカイブがあったため、作成後に古い 1つが削除されています。

Run sh ./backup.sh
---- List Target Disks of tk1a ----
---- List Target Disks of tk1b ----
---- Create Archive ***********5 ----
***********8
---- Delete Archive ***********2 ----
---- Create Archive ***********4 ----
***********9
---- List Target Disks of is1a ----
---- List Target Disks of is1b ----
---- Archives ----
+------+--------------+-----------------------------------+----------------+-------+-------------+
| Zone |      ID      |               Name                |      Tags      | Scope | Description |
+------+--------------+-----------------------------------+----------------+-------+-------------+
| tk1b | ***********4 | myautobackup-20220327-********... | [myautobackup] | user  | -           |
| tk1b | ***********0 | myautobackup-20220327-********... | [myautobackup] | user  | -           |
| tk1b | ***********8 | myautobackup-20220328-********... | [myautobackup] | user  | -           |
| tk1b | ***********9 | myautobackup-20220328-********... | [myautobackup] | user  | -           |
+------+--------------+-----------------------------------+----------------+-------+-------------+

最後に

さくらのクラウドを利用している時点でなんらかサーバはあるわけなので、その中で cron で設定すればいいわけですが、やはりサービス利用のサーバとは役割上わけたいところですし、とはいえこのためだけに管理サーバを別途用意するのにお金をかけるのも・・・という場合には、こういった方法もお手軽でおもしろいかなと思います。
サーバの作成も Terraform で実行している場合は、そのコードとまとめて管理することもできて、ちょうどよいかもしれません。
参考になれば幸いです。
どうぞよいさくらのクラウドライフを!