💽

自宅サーバにUSB-HDDつなげてNAS化したので、AWS S3へ自動バックアップを検討して実践してみた

2023/01/04に公開

概要

久しぶりに自宅サーバの立ち上げをした。
もともとはラズパイ4でマイクラサーバを立ち上げていたけど、スペック不足だったことと、dockerを使いたかったのでArmじゃなくてIntelアーキテクチャのサーバが欲しかったので、立ち上げに至る。
せっかくなので、HDDをUSBで接続してNAS化。

NAS化したからには、そこに保存したデータは絶対になくさないような運用をしたい。
というわけで、定期的にAWS S3へバックアップすることにした。
S3へは差分バックアップで、必要なファイルだけ更新する。
また、バージョニングを有効にして、一定期間は削除したファイルも参照できるようにしたい。
そして、バックアップ後一定期間が経ったファイルはコストの安い保管設定に移行する。

バックアップのルールを考える

  1. USBハードディスクにあるファイルは、そのままS3へ保存する
    • 圧縮等はしない。今回保存したいのは、写真や音楽ファイルファイルで、圧縮の効果が薄い
    • (圧縮が必要になったら考える・・・)
    • オブジェクト単位で更新判断されるので、ファイルを一つにまとめたりもしない
  2. s3ではバージョニングを有効にする
    • 過去のバージョンは、半年保存後削除する
    • そもそもNASに置くファイルは度々更新するものではないので、それほど嵩張らない想定
  3. aws cliで、s3へ差分バックアップをする
    • ローカルに存在するファイルをs3へsyncで一気にバックアップ
    • ローカルで削除したファイルは、s3でも削除する
      • バージョニングを有効にしているので、削除したファイルも数ヶ月は救出可能
  4. 朝、毎日バックアップ処理を実行する
    • まず、サーバ内のバックアップが必要なデータを、USB-HDDに保管する
    • USB-HDDの内容は、全てバックアップ対象とする
    • 明け方にバックアップ処理を実行
    • ログの取得と、実行結果の通知をする(今回は未実装)

余談)S3のストレージクラスについて

S3に保存するにあたって、S3のストレージクラスについて調べたら、S3 Glacier Instant RetrievalIntelligent-Tieringというクラスが実装されたことを知った。
こちらの記事でそれぞれの特徴がわかる。
【AWS】S3のストレージクラスについてまとめる
こちらはストレージクラスを選択するときに必要な情報が詳しい。
S3ストレージクラスの選択に迷った時に見るフローチャートを作ってみた(2022年8月版)

今回保管するファイルはバックアップなので、まさにGlacier Instant Retrieval向き!
S3標準は0.025USD/GB、1ゾーン IAで0.011USD/GBのところ、Instant Retrievalは驚異の0.005USD/GB
旧GlacierことGlacier Flexible Retrievalの0.0045USD/GBと10%しか変わらない。素晴らしい。
しかも取り出しはミリ秒単位でできるということで、旧Glacierを選択する理由がなくなった印象。(AWS的には、旧Glacierは運用考えると微妙になってきたのかな)
特徴は上記記事に詳しいが、取り出しのためのコストがGBあたり0.03USDかかるのがポイント。今回はバックアップなので問題にならない。

  • ちなみに、ライフサイクル設定で標準から低頻度アクセスへの移行は30日以上経っていないとできないけど、Instant Retrievalには1日でも移行可能。

また、保管してしばらく経ったら、アクセスの可能性は低くなると想定。つまり、HDDが壊れる1回だけになるはず。S3 Glacier Deep Archiveに移行する。
最小保存期間が180日になるので、半年に一回の更新もないことを想定。

Intelligent-Tieringもいいかもと思った。自動で標準→低頻度アクセス(IA)→Glacier Instant Retrievalへストレージクラスを変更してくれる。
S3 Intelligent-Tiering のしくみ
ただ、Objectのサイズが128KBより大きなものに対してはアクセスの有無を判定するために、モニタリングコストというものがかかる($0.0025 per 1000 OBJ)
バックアップはストレージクラスを安い方へ移動することしかないはずなので、Intelligent-Tieringはコスト面で不適かなーということで見送り。

やること

  1. 保存先のS3バケットの作成
  2. S3バケットへのライフサイクルの設定
  3. S3保存だけできるIAMユーザーを作成し、アクセスキー・シークレットキーを用意
  4. サーバにバックアップのバッチを作成

バケットを作成

今回は作成済みだったので割愛。

ライフサイクルの設定

IAMを作成、キーを取得

運用を考慮して、ユーザーをグループに所属させ、グループにアクセスポリシーを設定する。

  • 対象のバケットを操作できる権限を持ったポリシーを作成
  • ローカルサーバからバックアップをするグループを作成
    • このグループに所属するユーザーは、ローカルのサーバ内からS3へバックアップする人たちということがわかるようにする。
    • 名前の例:backup_to_s3_from_local_server
  • 今回のサーバからバックアップをするためのユーザーを作成
    • どのサーバからバックアップする人なのかが分かる名前にする。
    • 名前の例:backup_to_s3_from_local_server_raspi

ローカルサーバの設定

AWS CLIの準備はこちらが参考になる。
AWS CLI のみで S3 にファイルをアップロードする方法

  • 今回は、プロファイル名をつけました:s3backup

AWS CLIでS3を操作する方法は、こちらがわかりやすい。
AWS CLIでS3操作(ls,mb,rb,cp,mv,rm,sync)

バッチを作成

やることは以下。

  1. 特定のフォルダをtarして、バックアップ対象のUSBHDDフォルダに保存するバッチ
  2. USBHDDフォルダをまるごとs3へ保存するバッチ

バックアップするファイルを纏める処理

マイクラサーバのデータをまとめる例。
バッチの実行ログは、バッチの置いてあるディレクトリにlogディレクトリを作成して保存する

#!/bin/bash -xvue

# バッチのログ保存処理
cur_dir="$(dirname $0)"
filename="$(basename $0)"
mkdir -p ${cur_dir}/log
exec 2> ${cur_dir}/log/${filename}.$(date +%Y%m%d_%H%M%S)

# マイクラデータをバックアップする。ディレクトリの準備
backup_dir="/mnt/usbhdd/backup/minecraft/auto_backup"
mkdir -p ${backup_dir}

target_dir="${HOME}/minecraft"
cd ${target_dir}

# 対象フォルダにあるファイル・ディレクトリを1つずつ固めて、バックアップ対象ディレクトリへ保管
while read filename; do
        tar zcf ${backup_dir}/${filename}.tgz ${filename}
done < <(ls -1)

exit 0

USB-HDDをS3へバックアップするバッチ

こちらはシンプルに、対象ディレクトリをsyncで一気にコピー。
自動的に、差分ファイルだけを、マルチパートで高速にアップロードしてくれる。
手元のサーバからだと、50MB/sくらい出ていました。

#!/bin/bash -xveu

# バッチのログ保存処理
cur_dir="$(dirname $0)"
filename="$(basename $0)"
mkdir -p ${cur_dir}/log
exec 2> ${cur_dir}/log/${filename}.$(date +%Y%m%d_%H%M%S)

# バックアップ処理
backup_dir="/mnt/usbhdd"
target_s3dir="s3://backetname/backup/usbhdd"

aws --profile=s3backup s3 sync ${backup_dir} ${target_s3dir} --delete --storage-class GLACIER_IR

exit 0

syncのオプションとしては、--deleteで、ローカルで削除されたファイルはサーバ側でも削除するように指定。
ただし、バージョニングを有効にしているので、削除後半年は復活可能。
また、アップロード時点でGlacier Instant Retrievalを指定するための--storage-class GLACIER_IR。ライフサイクルでも3日後に移行するようにしているが、最初からこれにしておく。
Amazon S3 Glacier はデータをアーカイブするのに最適 – S3 Glacier Instant Retrieval ストレージクラスのご紹介

cronへ登録

crontab -eして、上記バッチを登録する。
実行してみて、logフォルダのログを確認する。

まとめ

久しぶりにサーバを建てるのも楽しかったけど、S3とbashも触れて良かった。
運用面で処理通知とかまだできていないので、それを実装するのが次のテーマかなー

追記

USB-HDDが/devのどこにいるかは、lsblkを使うとわかりやすい

 $ lsblk
NAME        MAJ:MIN RM   SIZE RO TYPE MOUNTPOINT
sda           8:0    0   1.8T  0 disk
└─sda1        8:1    0   1.8T  0 part
mmcblk0     179:0    0 119.1G  0 disk
├─mmcblk0p1 179:1    0   256M  0 part /boot
└─mmcblk0p2 179:2    0 118.8G  0 part /

Linuxで自動でマウントする場合は、/etc/fstabに追記する。
blkidコマンドで、UUIDを確認しておく。
以下のような感じ。

UUID="{blkidで調べたUUID}" /mnt/usbhdd auto defaults 0 0
GitHubで編集を提案

Discussion