Backup and Recovery Strategies

Linuxバックアップとリカバリ戦略 完全ガイド

目次

  1. はじめに
  2. バックアップの基礎概念
  3. バックアップレベルの分類
  4. tar によるバックアップ
  5. rsync によるバックアップ
  6. dd によるバックアップ
  7. LVMスナップショットによるバックアップ
  8. borgbackup による高度なバックアップ
  9. restic によるバックアップ
  10. データベースバックアップ
  11. エンタープライズバックアップツール概要
  12. 災害復旧計画
  13. バックアップの検証とテスト
  14. バックアップスケジューリング
  15. バックアップ監視
  16. バックアップツール比較表
  17. トラブルシューティング
  18. ベストプラクティス
  19. 参考資料

1. はじめに

バックアップとリカバリは、システム管理における最も重要な責務の一つである。ハードウェア障害、ソフトウェアバグ、ヒューマンエラー、ランサムウェア攻撃など、データ損失のリスクは常に存在する。適切なバックアップ戦略を策定し、定期的にリカバリテストを実施することが、ビジネス継続性の確保に不可欠である。

本ドキュメントでは、Linuxシステムにおけるバックアップとリカバリの概念、ツール、戦略、そして実践的な手順を包括的に解説する。


2. バックアップの基礎概念

2.1 バックアップの種類

┌─────────────────────────────────────────────────────────┐
│                  バックアップの種類                        │
│                                                          │
│  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐     │
│  │  フルバック  │  │  増分バック  │  │  差分バック  │     │
│  │   アップ    │  │   アップ    │  │   アップ    │     │
│  │             │  │             │  │             │     │
│  │ 全データの  │  │ 前回バック  │  │ 前回フル   │     │
│  │ 完全コピー  │  │ アップ以降  │  │ バックアップ│     │
│  │             │  │ の変更分    │  │ 以降の変更分│     │
│  └─────────────┘  └─────────────┘  └─────────────┘     │
└─────────────────────────────────────────────────────────┘

フルバックアップ

# 全データの完全なコピー
# メリット: リストアが最も簡単で高速
# デメリット: 最も多くのストレージと時間が必要

# 例: tar による完全バックアップ
$ sudo tar czf /backup/full-backup-$(date +%Y%m%d).tar.gz /home /etc /var/www

増分バックアップ (Incremental)

# 前回のバックアップ(フルまたは増分)以降の変更分のみ
# メリット: バックアップ時間とストレージが最小
# デメリット: リストアには全ての増分が必要

# 日別スケジュール例:
# 日曜: フルバックアップ
# 月曜: 月曜の変更分(日曜フル以降)
# 火曜: 火曜の変更分(月曜増分以降)
# 水曜: 水曜の変更分(火曜増分以降)
# ... 以降同様

差分バックアップ (Differential)

# 前回のフルバックアップ以降の全変更分
# メリット: リストアにはフル+最新差分のみ必要
# デメリット: 増分より多くのストレージが必要

# 日別スケジュール例:
# 日曜: フルバックアップ
# 月曜: 日曜以降の変更分
# 火曜: 日曜以降の変更分(月曜分を含む)
# 水曜: 日曜以降の変更分(月・火曜分を含む)
# ... 差分は日々増大する

バックアップ種類の比較表:

項目フル増分差分
バックアップ時間最長最短中間
ストレージ使用量最大最小中間
リストア時間最短最長中間
リストアの複雑さ
必要なバックアップセットフル1つフル + 全増分フル + 最新差分

2.2 3-2-1 バックアップルール

┌────────────────────────────────────────────────────┐
│               3-2-1 バックアップルール              │
│                                                     │
│  3 → データのコピーを最低3つ保持                    │
│      (オリジナル + 2つのバックアップ)               │
│                                                     │
│  2 → 2種類以上の異なるメディアに保存                │
│      (例: ローカルディスク + テープ/クラウド)       │
│                                                     │
│  1 → 1つはオフサイト(遠隔地)に保管                  │
│      (例: 別データセンター、クラウドストレージ)     │
│                                                     │
│  拡張: 3-2-1-1-0 ルール                            │
│  1 → 1つはオフライン(エアギャップ)に保管           │
│  0 → リストアテストでエラー0を確認                  │
└────────────────────────────────────────────────────┘

2.3 RPO と RTO

用語定義
RPO (Recovery Point Objective)許容できる最大のデータ損失量(時間)RPO=1時間 → 最大1時間分のデータ損失を許容
RTO (Recovery Time Objective)サービス復旧までの最大許容時間RTO=4時間 → 4時間以内にサービスを復旧
# RPO/RTOに基づくバックアップ戦略
# RPO=24時間 → 日次バックアップで十分
# RPO=1時間  → 1時間ごとのバックアップまたはレプリケーション
# RPO=0      → リアルタイムレプリケーション(DRBD, データベースレプリケーション)

3. バックアップレベルの分類

3.1 ファイルシステムレベル

# ファイル単位でのバックアップ
# ツール: tar, rsync, borgbackup, restic

# メリット:
# - 個別ファイルの選択的リストアが可能
# - 異なるファイルシステム間でのリストアが可能
# - 増分バックアップが効率的

# デメリット:
# - 特殊ファイル(デバイスファイル等)の扱いに注意が必要
# - ファイルシステムのメタデータ(ACL, xattr等)の保存に注意

3.2 ブロックレベル

# ディスク/パーティション全体のバックアップ
# ツール: dd, partclone, Clonezilla

# メリット:
# - ファイルシステムに依存しない
# - ベアメタルリカバリが可能
# - ブートセクタを含む完全なコピー

# デメリット:
# - 個別ファイルのリストアが困難
# - 空き領域もバックアップされる(圧縮で軽減可能)
# - 異なるサイズのディスクへのリストアが困難

3.3 アプリケーションレベル

# アプリケーション固有のバックアップ
# ツール: mysqldump, pg_dump, mongodump

# メリット:
# - データの一貫性が保証される
# - 柔軟なリストア(特定テーブル、データベースの選択)
# - 異なるバージョン間でのマイグレーションが可能

# デメリット:
# - アプリケーション固有の知識が必要
# - 大規模データベースではバックアップに時間がかかる

4. tar によるバックアップ

4.1 基本操作

# アーカイブの作成
$ sudo tar cf /backup/home.tar /home
$ sudo tar cf /backup/etc.tar /etc

# アーカイブの内容一覧
$ tar tf /backup/home.tar | head -20

# アーカイブの展開
$ tar xf /backup/home.tar -C /restore/

# 特定ファイルの展開
$ tar xf /backup/home.tar home/user1/.bashrc -C /restore/

# 詳細出力付きでアーカイブを作成
$ sudo tar cvf /backup/home.tar /home 2>&1 | tee /backup/home.log

4.2 圧縮オプション

# gzip圧縮(.tar.gz / .tgz)- 最も一般的
$ sudo tar czf /backup/home.tar.gz /home

# bzip2圧縮(.tar.bz2)- より高い圧縮率
$ sudo tar cjf /backup/home.tar.bz2 /home

# xz圧縮(.tar.xz)- 最高の圧縮率(時間はかかる)
$ sudo tar cJf /backup/home.tar.xz /home

# zstd圧縮(.tar.zst)- 高速かつ高圧縮率
$ sudo tar --zstd -cf /backup/home.tar.zst /home

# 圧縮形式の比較(100GB のデータの場合の目安)
# gzip:  圧縮率 ~60%, 速度: 高速
# bzip2: 圧縮率 ~55%, 速度: 中速
# xz:    圧縮率 ~50%, 速度: 低速
# zstd:  圧縮率 ~57%, 速度: 最高速

圧縮形式比較表:

形式拡張子圧縮率圧縮速度展開速度推奨用途
gzip.tar.gz高速高速汎用
bzip2.tar.bz2低速中速アーカイブ保存
xz.tar.xz最高最低速中速長期アーカイブ
zstd.tar.zst最高速最高速日次バックアップ

4.3 増分バックアップ

# GNU tar の増分バックアップ(--listed-incremental)
# スナップショットファイルを使用して変更を追跡

# レベル0(フルバックアップ)
$ sudo tar --listed-incremental=/backup/snapshot.snar \
    -czf /backup/full-$(date +%Y%m%d).tar.gz /home
# snapshot.snar ファイルが新規作成される

# レベル1(増分バックアップ)- 前回のバックアップ以降の変更
$ sudo cp /backup/snapshot.snar /backup/snapshot.snar.bak
$ sudo tar --listed-incremental=/backup/snapshot.snar \
    -czf /backup/incr-$(date +%Y%m%d).tar.gz /home

# リストア(フル → 増分の順に展開)
$ sudo tar --listed-incremental=/dev/null \
    -xzf /backup/full-20240115.tar.gz -C /restore/
$ sudo tar --listed-incremental=/dev/null \
    -xzf /backup/incr-20240116.tar.gz -C /restore/
$ sudo tar --listed-incremental=/dev/null \
    -xzf /backup/incr-20240117.tar.gz -C /restore/

# 除外パターンの使用
$ sudo tar czf /backup/home.tar.gz \
    --exclude='*.tmp' \
    --exclude='*.cache' \
    --exclude='.local/share/Trash' \
    --exclude='node_modules' \
    /home

# 除外リストファイルを使用
$ cat /backup/exclude-list.txt
*.tmp
*.cache
*.swp
.local/share/Trash
node_modules
__pycache__

$ sudo tar czf /backup/home.tar.gz \
    --exclude-from=/backup/exclude-list.txt /home

4.4 実践的なtar バックアップスクリプト

#!/bin/bash
# /usr/local/bin/tar-backup.sh
# tar を使用した日次バックアップスクリプト

BACKUP_DIR="/backup/tar"
SOURCE_DIRS="/home /etc /var/www /var/lib/mysql"
DATE=$(date +%Y%m%d)
DOW=$(date +%u)  # 1=月曜 ... 7=日曜
SNAPSHOT="${BACKUP_DIR}/snapshot.snar"
LOG_FILE="${BACKUP_DIR}/backup-${DATE}.log"
RETENTION_DAYS=30

mkdir -p "${BACKUP_DIR}"

exec > >(tee -a "${LOG_FILE}") 2>&1
echo "=== Backup started at $(date) ==="

if [ "${DOW}" -eq 7 ]; then
    # 日曜日: フルバックアップ
    echo "Performing FULL backup..."
    rm -f "${SNAPSHOT}"
    BACKUP_FILE="${BACKUP_DIR}/full-${DATE}.tar.gz"
else
    # 月〜土: 増分バックアップ
    echo "Performing INCREMENTAL backup..."
    cp "${SNAPSHOT}" "${SNAPSHOT}.bak" 2>/dev/null
    BACKUP_FILE="${BACKUP_DIR}/incr-${DATE}.tar.gz"
fi

tar --listed-incremental="${SNAPSHOT}" \
    --exclude-from=/backup/exclude-list.txt \
    -czf "${BACKUP_FILE}" ${SOURCE_DIRS}

RESULT=$?

if [ ${RESULT} -eq 0 ]; then
    SIZE=$(du -sh "${BACKUP_FILE}" | awk '{print $1}')
    echo "Backup completed successfully: ${BACKUP_FILE} (${SIZE})"
else
    echo "ERROR: Backup failed with exit code ${RESULT}"
    # アラート送信
    echo "Backup failed on $(hostname)" | mail -s "Backup FAILED" admin@example.com
fi

# 古いバックアップの削除
find "${BACKUP_DIR}" -name "*.tar.gz" -mtime +${RETENTION_DAYS} -delete
find "${BACKUP_DIR}" -name "*.log" -mtime +${RETENTION_DAYS} -delete

echo "=== Backup finished at $(date) ==="

5. rsync によるバックアップ

5.1 基本操作

# ローカルディレクトリの同期
$ rsync -av /home/ /backup/home/

# 主要オプション
# -a (--archive): -rlptgoD と同等(再帰的、リンク、パーミッション、タイムスタンプ等を保持)
# -v (--verbose): 詳細出力
# -z (--compress): 転送時に圧縮
# -h (--human-readable): 人間が読みやすい形式
# -P (--progress --partial): 進捗表示と部分転送の継続
# --delete: コピー元にないファイルをコピー先から削除

# パーミッション、ACL、xattr を含む完全同期
$ rsync -aAXv --delete /home/ /backup/home/

# 進捗表示付き
$ rsync -avhP /home/ /backup/home/
sending incremental file list
user1/Documents/report.pdf
        1,234,567 100%  45.67MB/s    0:00:00 (xfr#1, to-chk=256/1024)

5.2 リモート同期

# SSHを使用したリモートバックアップ
$ rsync -avz -e ssh /home/ user@backup-server:/backup/home/

# SSH ポートの指定
$ rsync -avz -e "ssh -p 2222" /home/ user@backup-server:/backup/home/

# SSH鍵認証を使用(自動バックアップ向け)
$ rsync -avz -e "ssh -i /root/.ssh/backup_key -o StrictHostKeyChecking=no" \
    /home/ user@backup-server:/backup/home/

# 帯域制限付き(1Mbps)
$ rsync -avz --bwlimit=1000 /home/ user@backup-server:/backup/home/

# rsync デーモンを使用(rsync プロトコル)
$ rsync -avz /home/ backup-server::backup-module/home/

5.3 除外パターン

# コマンドラインで除外
$ rsync -av \
    --exclude='*.tmp' \
    --exclude='*.cache' \
    --exclude='.git/' \
    --exclude='node_modules/' \
    /home/ /backup/home/

# 除外ファイルを使用
$ cat /etc/rsync-exclude.conf
*.tmp
*.swp
*.cache
.Trash/
.local/share/Trash/
node_modules/
__pycache__/
.git/
*.log

$ rsync -av --exclude-from=/etc/rsync-exclude.conf /home/ /backup/home/

# 包含と除外の組み合わせ
$ rsync -av \
    --include='*.conf' \
    --include='*/' \
    --exclude='*' \
    /etc/ /backup/etc-conf-only/

5.4 増分バックアップ戦略(ハードリンク使用)

# rsync + ハードリンクによる増分バックアップ
# 変更のないファイルはハードリンクで参照し、ストレージを節約

#!/bin/bash
# /usr/local/bin/rsync-backup.sh

BACKUP_BASE="/backup/rsync"
SOURCE="/home/"
DATE=$(date +%Y-%m-%d_%H%M)
LATEST="${BACKUP_BASE}/latest"
DEST="${BACKUP_BASE}/${DATE}"

mkdir -p "${DEST}"

rsync -aAXv --delete \
    --link-dest="${LATEST}" \
    --exclude-from=/etc/rsync-exclude.conf \
    "${SOURCE}" "${DEST}/"

# 最新バックアップへのシンボリックリンクを更新
rm -f "${LATEST}"
ln -s "${DEST}" "${LATEST}"

echo "Backup completed: ${DEST}"

# 結果の確認
$ ls -la /backup/rsync/
drwxr-xr-x 3 root root 4096 Jan 15 02:00 2024-01-15_0200
drwxr-xr-x 3 root root 4096 Jan 16 02:00 2024-01-16_0200
drwxr-xr-x 3 root root 4096 Jan 17 02:00 2024-01-17_0200
lrwxrwxrwx 1 root root   30 Jan 17 02:00 latest -> 2024-01-17_0200

# 各バックアップディレクトリは完全なスナップショットに見えるが、
# 変更のないファイルはハードリンクのため追加ストレージを消費しない
$ du -sh /backup/rsync/2024-01-15_0200   # フル: 50GB
$ du -sh /backup/rsync/2024-01-16_0200   # 増分: 2GB (実際のディスク使用量)
$ du -sh /backup/rsync/2024-01-17_0200   # 増分: 1.5GB

6. dd によるバックアップ

# ディスク全体のブロックレベルバックアップ
$ sudo dd if=/dev/sda of=/backup/sda.img bs=64K status=progress
107374182400 bytes (107 GB, 100 GiB) copied, 1200 s, 89.5 MB/s

# パーティション単位のバックアップ
$ sudo dd if=/dev/sda1 of=/backup/sda1.img bs=64K status=progress

# 圧縮付きバックアップ
$ sudo dd if=/dev/sda bs=64K status=progress | gzip -c > /backup/sda.img.gz
$ sudo dd if=/dev/sda bs=64K status=progress | zstd -T0 > /backup/sda.img.zst

# リストア
$ sudo dd if=/backup/sda.img of=/dev/sda bs=64K status=progress

# 圧縮バックアップからのリストア
$ zcat /backup/sda.img.gz | sudo dd of=/dev/sda bs=64K status=progress
$ zstd -d /backup/sda.img.zst --stdout | sudo dd of=/dev/sda bs=64K status=progress

# MBR のバックアップ(最初の512バイト)
$ sudo dd if=/dev/sda of=/backup/sda-mbr.img bs=512 count=1

# ディスク複製(同サイズのディスク間)
$ sudo dd if=/dev/sda of=/dev/sdb bs=64K status=progress conv=noerror,sync

# dd の注意点
# - 空き領域もコピーされるため非効率
# - conv=noerror,sync: エラー時にスキップして継続
# - 必ず正しいデバイスを指定すること(dd = "disk destroyer" の異名)

7. LVMスナップショットによるバックアップ

# LVM構成の確認
$ sudo lvs
  LV      VG     Attr       LSize   Pool Origin Data%  Meta%
  root    centos -wi-a----- 100.00g
  home    centos -wi-a----- 200.00g

# スナップショットの作成
$ sudo lvcreate -L 20G -s -n home-snapshot /dev/centos/home
  Logical volume "home-snapshot" created.

# スナップショットの確認
$ sudo lvs
  LV            VG     Attr       LSize   Pool Origin Data%  Meta%
  root          centos -wi-a----- 100.00g
  home          centos -wi-a----- 200.00g
  home-snapshot centos swi-a-s---  20.00g      home    0.01

# スナップショットをマウントしてバックアップ
$ sudo mkdir /mnt/snapshot
$ sudo mount -o ro /dev/centos/home-snapshot /mnt/snapshot

# スナップショットからバックアップを取得
$ sudo tar czf /backup/home-$(date +%Y%m%d).tar.gz -C /mnt/snapshot .

# または rsync で同期
$ sudo rsync -aAXv /mnt/snapshot/ /backup/home-snapshot/

# スナップショットのアンマウントと削除
$ sudo umount /mnt/snapshot
$ sudo lvremove /dev/centos/home-snapshot
Do you really want to remove active logical volume centos/home-snapshot? [y/n]: y
  Logical volume "home-snapshot" successfully removed.

LVMスナップショットバックアップスクリプト

#!/bin/bash
# /usr/local/bin/lvm-snapshot-backup.sh
# LVMスナップショットを使用した一貫性のあるバックアップ

VG="centos"
LV="home"
SNAP_SIZE="20G"
SNAP_NAME="${LV}-snap"
MOUNT_POINT="/mnt/backup-snapshot"
BACKUP_DIR="/backup/lvm"
DATE=$(date +%Y%m%d)

echo "Creating LVM snapshot..."
lvcreate -L ${SNAP_SIZE} -s -n ${SNAP_NAME} /dev/${VG}/${LV} || {
    echo "ERROR: Failed to create snapshot"
    exit 1
}

echo "Mounting snapshot..."
mkdir -p ${MOUNT_POINT}
mount -o ro /dev/${VG}/${SNAP_NAME} ${MOUNT_POINT} || {
    echo "ERROR: Failed to mount snapshot"
    lvremove -f /dev/${VG}/${SNAP_NAME}
    exit 1
}

echo "Creating backup..."
tar czf ${BACKUP_DIR}/${LV}-${DATE}.tar.gz -C ${MOUNT_POINT} .
RESULT=$?

echo "Cleaning up..."
umount ${MOUNT_POINT}
lvremove -f /dev/${VG}/${SNAP_NAME}

if [ ${RESULT} -eq 0 ]; then
    echo "Backup completed successfully"
else
    echo "ERROR: Backup failed"
    exit 1
fi

8. borgbackup による高度なバックアップ

borgbackup(Borg)は、重複排除、圧縮、暗号化をサポートする高度なバックアップツールである。

8.1 インストールと初期設定

# インストール
$ sudo dnf install borgbackup          # RHEL/CentOS (EPEL)
$ sudo apt install borgbackup          # Ubuntu/Debian
$ pip install borgbackup               # pip

# ローカルリポジトリの初期化(暗号化あり)
$ borg init --encryption=repokey /backup/borg-repo
Enter new passphrase:
Enter same passphrase again:
Do you want your passphrase to be displayed for verification? [yN]: y
Your passphrase (between quotes): "my-secure-passphrase"

# リモートリポジトリの初期化
$ borg init --encryption=repokey ssh://user@backup-server/backup/borg-repo

# 暗号化モードの選択
# repokey: 暗号化キーをリポジトリに保存(推奨)
# keyfile: 暗号化キーをローカルに保存
# repokey-blake2: blake2ハッシュを使用(高速)
# none: 暗号化なし

# 暗号化キーのエクスポート(重要!必ずバックアップすること)
$ borg key export /backup/borg-repo /safe-location/borg-key-backup

8.2 バックアップの作成

# 基本的なバックアップ
$ borg create /backup/borg-repo::home-{now:%Y-%m-%d_%H%M} /home
Enter passphrase for key /backup/borg-repo:

# 圧縮付きバックアップ
$ borg create --compression lz4 \
    /backup/borg-repo::home-{now:%Y-%m-%d_%H%M} /home

# 圧縮アルゴリズムの選択
# lz4:  最高速(推奨デフォルト)
# zstd: 高速かつ高圧縮率
# zlib: 中程度の速度と圧縮率
# lzma: 最高の圧縮率(低速)

# 除外パターン付きバックアップ
$ borg create --compression zstd \
    --exclude '*.tmp' \
    --exclude '*.cache' \
    --exclude 'sh:**/.git' \
    --exclude 'sh:**/node_modules' \
    --stats --progress \
    /backup/borg-repo::system-{now:%Y-%m-%d_%H%M} \
    /home /etc /var/www

# 出力例:
# Archive name: system-2024-01-15_0200
# Archive fingerprint: a1b2c3d4e5...
# Time (start): Mon, 2024-01-15 02:00:01
# Time (end):   Mon, 2024-01-15 02:05:30
# Duration: 5 minutes 29 seconds
# Number of files: 125,432
#                        Original size    Compressed size    Deduplicated size
# This archive:               50.00 GB          35.00 GB           2.50 GB
# All archives:              250.00 GB         175.00 GB          48.00 GB

# リモートリポジトリへのバックアップ
$ borg create ssh://user@backup-server/backup/borg-repo::home-{now:%Y-%m-%d} /home

8.3 リストとリストア

# アーカイブ一覧の表示
$ borg list /backup/borg-repo
home-2024-01-15_0200    Mon, 2024-01-15 02:00:01 [a1b2c3d4...]
home-2024-01-16_0200    Tue, 2024-01-16 02:00:01 [e5f6g7h8...]
home-2024-01-17_0200    Wed, 2024-01-17 02:00:01 [i9j0k1l2...]

# アーカイブ内のファイル一覧
$ borg list /backup/borg-repo::home-2024-01-15_0200 | head -20
drwxr-xr-x root   root          0 Mon, 2024-01-15 01:30:00 home
drwx------ user1  user1         0 Mon, 2024-01-15 01:30:00 home/user1
-rw-r--r-- user1  user1       220 Mon, 2024-01-15 01:30:00 home/user1/.bashrc

# アーカイブの詳細情報
$ borg info /backup/borg-repo::home-2024-01-15_0200

# 完全リストア
$ cd /restore
$ borg extract /backup/borg-repo::home-2024-01-15_0200

# 特定ファイル/ディレクトリのリストア
$ borg extract /backup/borg-repo::home-2024-01-15_0200 home/user1/Documents

# 特定パターンにマッチするファイルのリストア
$ borg extract --pattern '+ home/user1/*.conf' \
    --pattern '- *' \
    /backup/borg-repo::home-2024-01-15_0200

# ドライランモード(リストアせずに確認)
$ borg extract --dry-run --list /backup/borg-repo::home-2024-01-15_0200

# FUSE マウント(バックアップをファイルシステムとしてマウント)
$ mkdir /mnt/borg
$ borg mount /backup/borg-repo::home-2024-01-15_0200 /mnt/borg
$ ls /mnt/borg/home/user1/
$ cp /mnt/borg/home/user1/important-file.txt /home/user1/
$ borg umount /mnt/borg

8.4 プルーニング(古いバックアップの削除)

# プルーニングポリシーの適用
$ borg prune --keep-daily=7 \
    --keep-weekly=4 \
    --keep-monthly=12 \
    --keep-yearly=3 \
    --list --stats \
    /backup/borg-repo

# プルーニングポリシーの説明:
# --keep-daily=7:   過去7日間の日次バックアップを保持
# --keep-weekly=4:  過去4週間の週次バックアップを保持
# --keep-monthly=12: 過去12ヶ月の月次バックアップを保持
# --keep-yearly=3:  過去3年間の年次バックアップを保持

# 特定のプレフィックスに対してプルーニング
$ borg prune --prefix "home-" \
    --keep-daily=7 --keep-weekly=4 \
    /backup/borg-repo

# プルーニング後のリポジトリコンパクト化
$ borg compact /backup/borg-repo

# リポジトリの整合性チェック
$ borg check /backup/borg-repo
$ borg check --verify-data /backup/borg-repo    # データの完全性も検証(時間がかかる)

8.5 borgbackup 自動バックアップスクリプト

#!/bin/bash
# /usr/local/bin/borg-backup.sh
# borgbackup を使用した自動バックアップスクリプト

export BORG_REPO="/backup/borg-repo"
export BORG_PASSPHRASE="your-secure-passphrase"
# または: export BORG_PASSCOMMAND="cat /root/.borg-passphrase"

BACKUP_NAME="system-{now:%Y-%m-%d_%H%M}"
LOG_FILE="/var/log/borg-backup.log"

exec > >(tee -a "${LOG_FILE}") 2>&1
echo "=== Borg Backup started at $(date) ==="

# バックアップの作成
borg create \
    --verbose --stats --show-rc \
    --compression zstd \
    --exclude-caches \
    --exclude '*.tmp' \
    --exclude '*.cache' \
    --exclude '/home/*/.local/share/Trash' \
    --exclude '/var/tmp/*' \
    --exclude '/var/cache/*' \
    ::${BACKUP_NAME} \
    /home \
    /etc \
    /var/www \
    /var/lib/mysql

backup_exit=$?

# プルーニング
borg prune \
    --list --stats --show-rc \
    --keep-daily=7 \
    --keep-weekly=4 \
    --keep-monthly=12 \
    --keep-yearly=3

prune_exit=$?

# コンパクト化
borg compact
compact_exit=$?

# 結果の評価
global_exit=$(( backup_exit > prune_exit ? backup_exit : prune_exit ))
global_exit=$(( global_exit > compact_exit ? global_exit : compact_exit ))

if [ ${global_exit} -eq 0 ]; then
    echo "Backup, prune, and compact completed successfully"
elif [ ${global_exit} -eq 1 ]; then
    echo "Backup, prune, and/or compact finished with warnings"
else
    echo "Backup, prune, and/or compact finished with errors"
    echo "Borg backup FAILED on $(hostname)" | \
        mail -s "Borg Backup FAILED" admin@example.com
fi

echo "=== Borg Backup finished at $(date) ==="
exit ${global_exit}

9. restic によるバックアップ

resticは、高速で安全なバックアップツールで、多数のバックエンドストレージに対応する。

# インストール
$ sudo dnf install restic              # RHEL (EPEL)
$ sudo apt install restic              # Ubuntu/Debian

# ローカルリポジトリの初期化
$ restic init --repo /backup/restic-repo
enter password for new repository:
enter password again:
created restic repository xxxxxxxx at /backup/restic-repo

# S3バックエンドの初期化
$ export AWS_ACCESS_KEY_ID="your-access-key"
$ export AWS_SECRET_ACCESS_KEY="your-secret-key"
$ restic init --repo s3:s3.amazonaws.com/bucket-name/restic

# バックアップの作成
$ restic -r /backup/restic-repo backup /home /etc /var/www
enter password for repository:
repository xxxxxxxx opened successfully
Files:        12,345 new,    50 changed,  100,000 unmodified
Added to the repo: 2.5 GiB
processed 112,395 files, 50.00 GiB in 3:25

# 除外パターン付き
$ restic -r /backup/restic-repo backup \
    --exclude='*.tmp' \
    --exclude-file=/etc/restic-exclude.conf \
    /home

# スナップショット一覧
$ restic -r /backup/restic-repo snapshots
ID        Time                 Host        Tags        Paths
────────────────────────────────────────────────────────────────
a1b2c3d4  2024-01-15 02:00:01  server1                 /home,/etc,...
e5f6g7h8  2024-01-16 02:00:01  server1                 /home,/etc,...
i9j0k1l2  2024-01-17 02:00:01  server1                 /home,/etc,...

# リストア
$ restic -r /backup/restic-repo restore latest --target /restore/
$ restic -r /backup/restic-repo restore a1b2c3d4 --target /restore/

# 特定ファイルのリストア
$ restic -r /backup/restic-repo restore latest \
    --include "/home/user1/Documents" --target /restore/

# プルーニング
$ restic -r /backup/restic-repo forget \
    --keep-daily 7 --keep-weekly 4 --keep-monthly 12 \
    --prune

# マウント(FUSE)
$ mkdir /mnt/restic
$ restic -r /backup/restic-repo mount /mnt/restic
$ ls /mnt/restic/snapshots/

10. データベースバックアップ

10.1 MySQL/MariaDB (mysqldump)

# 全データベースのバックアップ
$ mysqldump --all-databases --single-transaction --routines --triggers \
    -u root -p > /backup/mysql/all-databases-$(date +%Y%m%d).sql

# 特定データベースのバックアップ
$ mysqldump --single-transaction --routines --triggers \
    -u root -p mydb > /backup/mysql/mydb-$(date +%Y%m%d).sql

# 圧縮付きバックアップ
$ mysqldump --all-databases --single-transaction \
    -u root -p | gzip > /backup/mysql/all-databases-$(date +%Y%m%d).sql.gz

# テーブル単位のバックアップ
$ mysqldump -u root -p mydb users orders > /backup/mysql/mydb-tables.sql

# スキーマのみ(データなし)
$ mysqldump --no-data -u root -p mydb > /backup/mysql/mydb-schema.sql

# データのみ(スキーマなし)
$ mysqldump --no-create-info -u root -p mydb > /backup/mysql/mydb-data.sql

# リストア
$ mysql -u root -p < /backup/mysql/all-databases-20240115.sql
$ mysql -u root -p mydb < /backup/mysql/mydb-20240115.sql
$ zcat /backup/mysql/all-databases-20240115.sql.gz | mysql -u root -p

# mysqlpump(並列バックアップ、MySQL 5.7+)
$ mysqlpump --all-databases --default-parallelism=4 \
    -u root -p > /backup/mysql/all-databases-pump.sql

# xtrabackup(ホットバックアップ、大規模DB向け)
$ sudo xtrabackup --backup --target-dir=/backup/mysql/xtrabackup/ \
    --user=root --password=xxxx

# xtrabackup リストア
$ sudo xtrabackup --prepare --target-dir=/backup/mysql/xtrabackup/
$ sudo systemctl stop mysqld
$ sudo xtrabackup --copy-back --target-dir=/backup/mysql/xtrabackup/
$ sudo chown -R mysql:mysql /var/lib/mysql
$ sudo systemctl start mysqld

10.2 PostgreSQL (pg_dump)

# 単一データベースのバックアップ
$ pg_dump -U postgres mydb > /backup/pgsql/mydb-$(date +%Y%m%d).sql

# カスタム形式(圧縮+柔軟なリストア)
$ pg_dump -U postgres -Fc mydb > /backup/pgsql/mydb-$(date +%Y%m%d).dump

# ディレクトリ形式(並列バックアップ対応)
$ pg_dump -U postgres -Fd -j 4 mydb -f /backup/pgsql/mydb-dir/

# 全データベースのバックアップ
$ pg_dumpall -U postgres > /backup/pgsql/all-databases-$(date +%Y%m%d).sql

# 特定テーブルのバックアップ
$ pg_dump -U postgres -t users -t orders mydb > /backup/pgsql/mydb-tables.sql

# スキーマのみ
$ pg_dump -U postgres -s mydb > /backup/pgsql/mydb-schema.sql

# リストア(SQL形式)
$ psql -U postgres mydb < /backup/pgsql/mydb-20240115.sql

# リストア(カスタム形式)
$ pg_restore -U postgres -d mydb /backup/pgsql/mydb-20240115.dump

# リストア(ディレクトリ形式、並列リストア)
$ pg_restore -U postgres -d mydb -j 4 /backup/pgsql/mydb-dir/

# 特定テーブルのリストア
$ pg_restore -U postgres -d mydb -t users /backup/pgsql/mydb-20240115.dump

# WAL アーカイブによる継続的バックアップ(PITR対応)
# postgresql.conf
archive_mode = on
archive_command = 'cp %p /backup/pgsql/wal/%f'

# ベースバックアップの取得
$ pg_basebackup -U postgres -D /backup/pgsql/basebackup/ \
    -Ft -z -P --checkpoint=fast

11. エンタープライズバックアップツール概要

11.1 Amanda

# Amanda (Advanced Maryland Automatic Network Disk Archiver)
# 特徴: テープ/ディスクベースのネットワークバックアップ

# インストール
$ sudo dnf install amanda-server amanda-client    # RHEL
$ sudo apt install amanda-server amanda-client     # Ubuntu

# アーキテクチャ:
# Amanda Server → Amanda Client (各ホスト)
# - amandad: クライアントデーモン
# - amdump: バックアップ実行
# - amrecover: 対話的リストア

# 設定ファイル: /etc/amanda/<config-name>/
# amanda.conf: サーバ設定
# disklist: バックアップ対象

11.2 Bacula

# Bacula - エンタープライズ級のバックアップシステム
# コンポーネント:
# - Director: バックアップジョブの管理
# - Storage Daemon: ストレージメディアの管理
# - File Daemon: クライアント側でファイルを提供
# - Catalog: バックアップメタデータのデータベース
# - Console: 管理インターフェース

# インストール
$ sudo dnf install bacula-director bacula-storage bacula-client bacula-console

# 設定ファイル:
# /etc/bacula/bacula-dir.conf    (Director)
# /etc/bacula/bacula-sd.conf     (Storage Daemon)
# /etc/bacula/bacula-fd.conf     (File Daemon)
# /etc/bacula/bconsole.conf      (Console)

12. 災害復旧計画

12.1 ベアメタルリカバリ

# ベアメタルリカバリの手順
# 1. レスキューメディアからブート
# 2. ネットワーク設定
# 3. ディスクパーティショニング
# 4. バックアップからのリストア
# 5. ブートローダーの再インストール

# ReaR (Relax-and-Recover) を使用したベアメタルリカバリ
$ sudo dnf install rear    # RHEL
$ sudo apt install rear     # Ubuntu

# ReaR 設定
$ cat /etc/rear/local.conf
OUTPUT=ISO
OUTPUT_URL=nfs://backup-server/backup/rear/
BACKUP=NETFS
BACKUP_URL=nfs://backup-server/backup/rear/
BACKUP_PROG_EXCLUDE=('/tmp/*' '/var/crash/*')
NETFS_KEEP_OLD_BACKUP_COPY=yes

# レスキューISO + バックアップの作成
$ sudo rear mkbackup
Relax-and-Recover 2.7 / 2022-07-13
Running rear mkbackup (PID 12345 date 2024-01-15 02:00:00)
...
Wrote ISO image: /var/lib/rear/output/rear-server1.iso (1.2 GiB)
Making backup (using backup method NETFS)
Creating tar archive '/tmp/rear.xxxx/outputfs/server1/backup.tar.gz'
...
Exiting rear mkbackup with zero exit code.

# リカバリ手順:
# 1. rear-server1.iso からブート
# 2. "Recover" を選択
# 3. rear recover コマンドを実行
# 4. 再起動

12.2 DRサイト構成

# DR (Disaster Recovery) サイト構成パターン

# 1. Cold Site: 基本インフラのみ(RPO: 数日〜数週間)
# - バックアップメディアからリストア
# - 復旧時間が最も長い

# 2. Warm Site: インフラ + 定期的なデータ同期(RPO: 数時間〜1日)
# rsync による定期同期
$ rsync -avz --delete /data/ dr-site:/data/

# 3. Hot Site: リアルタイムレプリケーション(RPO: 数秒〜数分)
# DRBD によるブロックレベルレプリケーション
# データベースレプリケーション
# ストレージレプリケーション

13. バックアップの検証とテスト

# 1. tar アーカイブの整合性チェック
$ tar tzf /backup/home.tar.gz > /dev/null
$ echo $?    # 0 = OK

# 詳細な検証
$ tar --compare -f /backup/home.tar.gz -C /home
# 差分がある場合にのみ出力される

# 2. borg の整合性チェック
$ borg check /backup/borg-repo
$ borg check --verify-data /backup/borg-repo

# 3. restic の整合性チェック
$ restic -r /backup/restic-repo check
$ restic -r /backup/restic-repo check --read-data

# 4. リストアテスト(最も重要)
# 定期的にバックアップからリストアし、データの完全性を確認
$ mkdir /tmp/restore-test
$ borg extract /backup/borg-repo::latest --target /tmp/restore-test

# ファイル数とサイズの比較
$ find /home -type f | wc -l
$ find /tmp/restore-test/home -type f | wc -l

# チェックサムの比較
$ find /home -type f -exec md5sum {} \; | sort > /tmp/original.md5
$ find /tmp/restore-test/home -type f -exec md5sum {} \; | sort > /tmp/restored.md5
$ diff /tmp/original.md5 /tmp/restored.md5

# 5. バックアップ検証スクリプト
#!/bin/bash
# /usr/local/bin/verify-backup.sh
REPO="/backup/borg-repo"
export BORG_PASSPHRASE="your-passphrase"

echo "Checking repository integrity..."
borg check "${REPO}" 2>&1
CHECK_RESULT=$?

echo "Getting latest archive info..."
LATEST=$(borg list --last 1 --format '{archive}' "${REPO}")
borg info "${REPO}::${LATEST}"

echo "Performing restore test..."
RESTORE_DIR=$(mktemp -d)
borg extract "${REPO}::${LATEST}" --target "${RESTORE_DIR}" home/user1/.bashrc
RESTORE_RESULT=$?

if [ ${CHECK_RESULT} -eq 0 ] && [ ${RESTORE_RESULT} -eq 0 ]; then
    echo "PASS: Backup verification successful"
else
    echo "FAIL: Backup verification failed"
    echo "Backup verification FAILED" | mail -s "Backup Verify FAILED" admin@example.com
fi

rm -rf "${RESTORE_DIR}"

14. バックアップスケジューリング

# cron によるスケジューリング
$ sudo crontab -e

# 日次フルバックアップ(毎日2:00)
0 2 * * * /usr/local/bin/borg-backup.sh >> /var/log/backup-cron.log 2>&1

# 週次フルバックアップ(日曜2:00)+ 日次増分
0 2 * * 0 /usr/local/bin/full-backup.sh >> /var/log/backup-cron.log 2>&1
0 2 * * 1-6 /usr/local/bin/incr-backup.sh >> /var/log/backup-cron.log 2>&1

# データベースバックアップ(毎日3:00)
0 3 * * * /usr/local/bin/db-backup.sh >> /var/log/db-backup.log 2>&1

# バックアップ検証(週1回、土曜4:00)
0 4 * * 6 /usr/local/bin/verify-backup.sh >> /var/log/backup-verify.log 2>&1

# systemd timer によるスケジューリング(推奨)
$ cat /etc/systemd/system/borg-backup.service
[Unit]
Description=Borg Backup Service
After=network-online.target

[Service]
Type=oneshot
ExecStart=/usr/local/bin/borg-backup.sh
Nice=19
IOSchedulingClass=best-effort
IOSchedulingPriority=7

$ cat /etc/systemd/system/borg-backup.timer
[Unit]
Description=Daily Borg Backup Timer

[Timer]
OnCalendar=*-*-* 02:00:00
RandomizedDelaySec=1800
Persistent=true

[Install]
WantedBy=timers.target

# timer の有効化
$ sudo systemctl enable --now borg-backup.timer

# timer の確認
$ systemctl list-timers --all | grep borg
Mon 2024-01-15 02:00:00 JST  23h left  Sun 2024-01-14 02:15:30  borg-backup.timer  borg-backup.service

15. バックアップ監視

# バックアップ監視の要素
# 1. バックアップの成功/失敗
# 2. バックアップサイズの推移
# 3. バックアップ所要時間
# 4. リポジトリの空き容量
# 5. 最終バックアップからの経過時間

# 監視スクリプト例
#!/bin/bash
# /usr/local/bin/backup-monitor.sh

BORG_REPO="/backup/borg-repo"
export BORG_PASSPHRASE="your-passphrase"
ALERT_EMAIL="admin@example.com"
MAX_AGE_HOURS=26  # 最終バックアップからの最大許容時間

# 最終バックアップの時刻を確認
LAST_BACKUP=$(borg list --last 1 --format '{time}' "${BORG_REPO}")
LAST_EPOCH=$(date -d "${LAST_BACKUP}" +%s)
NOW_EPOCH=$(date +%s)
AGE_HOURS=$(( (NOW_EPOCH - LAST_EPOCH) / 3600 ))

if [ ${AGE_HOURS} -gt ${MAX_AGE_HOURS} ]; then
    echo "ALERT: Last backup is ${AGE_HOURS} hours old (max: ${MAX_AGE_HOURS})" | \
        mail -s "Backup Age ALERT on $(hostname)" ${ALERT_EMAIL}
fi

# ディスク使用量の確認
DISK_USAGE=$(df -h /backup | awk 'NR==2{print $5}' | tr -d '%')
if [ ${DISK_USAGE} -gt 85 ]; then
    echo "WARNING: Backup disk is ${DISK_USAGE}% full" | \
        mail -s "Backup Disk Space WARNING" ${ALERT_EMAIL}
fi

# バックアップサイズのレポート
borg info "${BORG_REPO}" --last 5 --json | \
    python3 -c "
import json, sys
data = json.load(sys.stdin)
for archive in data.get('archives', []):
    name = archive['name']
    size = archive['stats']['deduplicated_size'] / (1024**3)
    print(f'{name}: {size:.2f} GB (deduplicated)')
"

16. バックアップツール比較表

ツール種類重複排除暗号化リモート増分圧縮用途
tarアーカイブなしなしなしありありシンプルなバックアップ
rsync同期なしSSHありあり転送時ファイル同期、ミラーリング
ddブロックなしなしなしなしパイプディスクイメージ
borgbackupバックアップありありSSHありあり推奨:汎用バックアップ
resticバックアップありあり多数ありありクラウドバックアップ
Amandaエンタープライズなしありありありあり大規模環境
Baculaエンタープライズなしありありありあり大規模環境

17. トラブルシューティング

よくある問題と解決策

# 1. バックアップ先の容量不足
$ df -h /backup
# 対策: 古いバックアップの削除、圧縮率の向上、ストレージ追加

# 2. rsync がタイムアウトする
$ rsync -avz --timeout=300 --contimeout=60 /home/ remote:/backup/home/
# 対策: タイムアウト値の調整、--partial オプションで再開可能に

# 3. borg リポジトリのロック
$ borg break-lock /backup/borg-repo
# 対策: 他のborgプロセスが実行中でないことを確認

# 4. パーミッションエラー
$ sudo rsync -aAXv --numeric-ids /home/ /backup/home/
# 対策: root権限で実行、--numeric-ids でUID/GIDを数値で保持

# 5. 大量のファイルによるメモリ不足
# borgの場合: --chunker-params を調整
# rsyncの場合: ディレクトリ単位で分割

# 6. ネットワークバックアップの遅延
$ rsync -avz --compress-level=9 --bwlimit=10000 /data/ remote:/backup/
# 対策: 圧縮レベルの調整、帯域制限の設定

18. ベストプラクティス

運用上のベストプラクティス

  1. 3-2-1ルールを遵守する: 最低3つのコピー、2種類のメディア、1つはオフサイト。

  2. 定期的にリストアテストを実施する: バックアップはリストアできなければ意味がない。月次でリストアテストを実施する。

  3. バックアップを監視する: バックアップジョブの成功/失敗、サイズの推移、経過時間を監視し、異常を検知する。

  4. 暗号化を使用する: 特にオフサイトバックアップやクラウドストレージへのバックアップでは暗号化を必須とする。

  5. バックアップキーを安全に保管する: 暗号化キーを紛失するとバックアップを復元できない。キーは別の安全な場所に保管する。

  6. RPO/RTOに基づいて戦略を策定する: ビジネス要件に合わせたバックアップ頻度とリカバリ手順を定める。

  7. バックアップの自動化: 手動バックアップに依存しない。cron/systemd timerで自動化する。

  8. ドキュメントを整備する: バックアップ手順、リカバリ手順、連絡先を文書化し、最新の状態に保つ。

セキュリティのベストプラクティス

# 1. バックアップファイルのアクセス制御
$ chmod 600 /backup/*.tar.gz
$ chown root:root /backup/*.tar.gz

# 2. バックアップ転送の暗号化(SSH)
$ rsync -avz -e "ssh -o StrictHostKeyChecking=yes" /data/ remote:/backup/

# 3. バックアップリポジトリの暗号化
$ borg init --encryption=repokey-blake2 /backup/borg-repo

# 4. イミュータブルバックアップ(改ざん防止)
# S3 Object Lock を使用
# または borgmatic の --append-only モード

# 5. バックアップアカウントの権限を最小限にする
# バックアップ専用のSSHキーを使用
# forced command でコマンドを制限

19. 参考資料

公式ドキュメント

関連ツール

ツールURL説明
borgbackupborgbackup.readthedocs.io重複排除バックアップ
resticrestic.netクラウド対応バックアップ
borgmatictorsion.org/borgmaticborgのラッパー
duplicityduplicity.gitlab.io暗号化バックアップ
ReaRrelax-and-recover.orgベアメタルリカバリ

ドキュメント情報:

  • 作成日: 2024年1月
  • 対象: Linux バックアップとリカバリ戦略
  • バージョン: 1.0
  • 著者: AI Generated Technical Documentation