DB のバックアップと復元確認を追加(ステップ10) #14
+4
-2
@@ -144,11 +144,13 @@ TVer(`https://tver.jp/`)で公開中の動画情報を取得し、選んだ
|
|||||||
- 本番の`/healthz`はHTTP `200`、新着バラエティは98件だった。4分の本編`ep5hcgopp2`は登録から20秒以内に完了し、92,340,468バイトの1080p H.264/AAC MP4をNASへ保存した。所有者はUID `1024`・GID `100`、`.incoming`は空で、`/library`とHTTP Range `206`も確認した [実機] 2026-10-04 確認
|
- 本番の`/healthz`はHTTP `200`、新着バラエティは98件だった。4分の本編`ep5hcgopp2`は登録から20秒以内に完了し、92,340,468バイトの1080p H.264/AAC MP4をNASへ保存した。所有者はUID `1024`・GID `100`、`.incoming`は空で、`/library`とHTTP Range `206`も確認した [実機] 2026-10-04 確認
|
||||||
- NASは番組フォルダ内に所有者UID `0`の`@eaDir`を作る。ライブラリ一覧はDBから作るため、アプリへの影響はない [実機] 2026-10-04 確認
|
- NASは番組フォルダ内に所有者UID `0`の`@eaDir`を作る。ライブラリ一覧はDBから作るため、アプリへの影響はない [実機] 2026-10-04 確認
|
||||||
- `callNewerDetail/drama`は毎回100件を返し、応答に続きや総件数を示す項目はなかった。`result.contents`は`type=newer`で、`content`は`id`・`version`・`title`のみ。`page=2`・`offset=100`・`limit=200`を付けても先頭・末尾IDが同じ100件となり、パラメータは無視された。100件を超えて取得する手段は見つからなかったが、非公開APIのため不可能とは断定しない。新着一覧は直近100件までとなる一方、登録番組の自動確認は番組ごとの`callSeriesSeasons`→`callSeasonEpisodes`を使うため、新着から外れた回も取りこぼさない [実機] 2026-10-04 確認
|
- `callNewerDetail/drama`は毎回100件を返し、応答に続きや総件数を示す項目はなかった。`result.contents`は`type=newer`で、`content`は`id`・`version`・`title`のみ。`page=2`・`offset=100`・`limit=200`を付けても先頭・末尾IDが同じ100件となり、パラメータは無視された。100件を超えて取得する手段は見つからなかったが、非公開APIのため不可能とは断定しない。新着一覧は直近100件までとなる一方、登録番組の自動確認は番組ごとの`callSeriesSeasons`→`callSeasonEpisodes`を使うため、新着から外れた回も取りこぼさない [実機] 2026-10-04 確認
|
||||||
- dockage上の使い捨て`postgres:17`コンテナへマイグレーション001〜003を適用してテスト用の行を投入し、`backup-db.sh`と`restore-test.sh`を実行した。gzip圧縮・権限600のダンプ作成、同じ`STAMP`での2回目が`ln`の失敗で非0終了して既存ダンプを保持すること、主要4表の行数一致、一時DBの削除、ログに`psql`の標準出力が残らないことを確認した。NASの`tver-postgres`とDSMタスクスケジューラでの実行は未確認 [実機] 2026-10-04 確認
|
- dockage上の使い捨て`postgres:17`コンテナへマイグレーション001〜003を適用してテスト用の行を投入し、`backup-db.sh`と`restore-test.sh`を実行した。gzip圧縮・権限600のダンプ作成、同じ`STAMP`での2回目が`ln`の失敗で非0終了して既存ダンプを保持すること、主要4表の行数一致、一時DBの削除、ログに`psql`の標準出力が残らないことを確認した [実機] 2026-10-04 確認
|
||||||
|
- NASの`/volume1/docker/tver-db/`へスクリプトを配置し、DSMタスクスケジューラのrootタスクから実行して、`/volume1/backups/tver/`へ`tver_20261004_182838.sql.gz`(2,286バイト)と`tver_20261004_183256.sql.gz`(2,289バイト)を作成した。ダンプはroot所有・権限600で、バックアップディレクトリはroot所有・`drwxr-xr-x`だった。`restore-test.sh`を`sudo`で実行し、`download_jobs` 1件・`subscriptions` 1件・`known_episodes` 1件・`schema_migrations` 3件の一致、ログへの結果記録、一時DBの削除を確認した。一般ユーザーではroot所有のログへ書き込めず失敗する [実機] 2026-10-04 確認
|
||||||
|
- DSMのACLで全員書き込み可だった`/volume1/docker`配下について、`/volume1/docker/tver-db`を`chmod 755`、`backup-db.sh`と`restore-test.sh`を`chmod 700`にしてACLが外れたことを確認した。変更後も本番アプリの`/queue`と`/subscriptions`はHTTP `200`でDBを読み取れた。PostgreSQLコンテナ再起動後の動作は未確認 [実機] 2026-10-04 確認
|
||||||
|
|
||||||
## 課題
|
## 課題
|
||||||
|
|
||||||
- DSMの日次バックアップタスクを登録し、本物の`tver-postgres`でバックアップ作成と`restore-test.sh`による一時DBへの復元を1回確認する [要確認]
|
- 登録済みのDSM日次バックアップタスクが翌日以降に自動実行され、新しいダンプを作ることを確認する [要確認]
|
||||||
- DRM・地域制限の実例探しはTVerへの大量アクセスになるため行わず、運用中に観測する。workerは失敗時の`error_message`をDBへ保存し、既知の文言に一致しない失敗は`unknown`にする。実例が出た時点で分類を見直す
|
- DRM・地域制限の実例探しはTVerへの大量アクセスになるため行わず、運用中に観測する。workerは失敗時の`error_message`をDBへ保存し、既知の文言に一致しない失敗は`unknown`にする。実例が出た時点で分類を見直す
|
||||||
|
|
||||||
## 確かめ方
|
## 確かめ方
|
||||||
|
|||||||
+27
-13
@@ -56,13 +56,18 @@ tags:
|
|||||||
/volume1/docker/tver-db/pgdata/
|
/volume1/docker/tver-db/pgdata/
|
||||||
```
|
```
|
||||||
|
|
||||||
2. [[../deploy/nas/tver-db/compose.yaml|NAS用compose.yaml]]、`.env.example`、`backup-db.sh`、`restore-test.sh`を`/volume1/docker/tver-db/`に配置し、スクリプトを所有者だけが実行できるようにする。
|
2. [[../deploy/nas/tver-db/compose.yaml|NAS用compose.yaml]]、`.env.example`、`backup-db.sh`、`restore-test.sh`を`/volume1/docker/tver-db/`に配置する。ディレクトリはroot以外がファイルを削除・置換できないようにし、スクリプトはrootだけが実行できるようにする。
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
chmod 755 /volume1/docker/tver-db
|
||||||
chmod 700 /volume1/docker/tver-db/backup-db.sh
|
chmod 700 /volume1/docker/tver-db/backup-db.sh
|
||||||
chmod 700 /volume1/docker/tver-db/restore-test.sh
|
chmod 700 /volume1/docker/tver-db/restore-test.sh
|
||||||
|
ls -ld /volume1/docker/tver-db
|
||||||
|
ls -l /volume1/docker/tver-db/backup-db.sh /volume1/docker/tver-db/restore-test.sh
|
||||||
```
|
```
|
||||||
|
|
||||||
|
DSMのACLが付いている場合、`chmod`後の`ls`でパーミッション表示の末尾から`+`が外れ、ディレクトリが`drwxr-xr-x`、スクリプトが`-rwx------`になったことを確認する。`/volume1/docker`では全員書き込み可のACLが確認されたため、スクリプトだけでなく配置ディレクトリにも`chmod 755`を適用する。
|
||||||
|
|
||||||
3. `.env.example`を`.env`へコピーし、`POSTGRES_PASSWORD`に十分長いランダムな値を設定する。値には、URLへの埋め込みで追加のエスケープが不要な16進文字列を使える。
|
3. `.env.example`を`.env`へコピーし、`POSTGRES_PASSWORD`に十分長いランダムな値を設定する。値には、URLへの埋め込みで追加のエスケープが不要な16進文字列を使える。
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
@@ -257,37 +262,46 @@ DSMの「コントロール パネル」→「タスク スケジューラ」で
|
|||||||
|
|
||||||
`DOCKER`、`CONTAINER`、`BACKUP_DIR`、`KEEP_DAYS`、`DB_USER`、`DB_NAME`は環境変数で上書きできる。通常運用では既定値を使う。
|
`DOCKER`、`CONTAINER`、`BACKUP_DIR`、`KEEP_DAYS`、`DB_USER`、`DB_NAME`は環境変数で上書きできる。通常運用では既定値を使う。
|
||||||
|
|
||||||
> [!todo] NAS実機で確認する
|
> [!success] NASで手動実行を確認済み
|
||||||
> DSMタスクの登録、1回の手動実行、日次実行の履歴、14日より古い世代の削除は未確認である。[要確認]
|
> DSMタスクスケジューラへrootの日次タスクを登録し、手動実行で2つのgzipダンプを作成した。復元確認も成功している。翌日以降の日次自動実行は未確認である。[実機] 2026-10-04 確認
|
||||||
|
|
||||||
|
> [!todo] 日次自動実行を確認する
|
||||||
|
> 翌日以降にDSMタスクの実行履歴と新しいダンプを確認する。[要確認]
|
||||||
|
|
||||||
### 5.2 手動でバックアップを確認する
|
### 5.2 手動でバックアップを確認する
|
||||||
|
|
||||||
NASへSSH接続し、初回は手動で実行する。
|
NASへSSH接続し、初回は手動で実行する。
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
bash /volume1/docker/tver-db/backup-db.sh
|
sudo bash /volume1/docker/tver-db/backup-db.sh
|
||||||
LATEST=$(find /volume1/backups/tver -name 'tver_*.sql.gz' -type f -print | sort | tail -n 1)
|
LATEST=$(sudo find /volume1/backups/tver -name 'tver_*.sql.gz' -type f -print | sort | tail -n 1)
|
||||||
test -n "$LATEST"
|
test -n "$LATEST"
|
||||||
test -s "$LATEST"
|
sudo test -s "$LATEST"
|
||||||
gzip -t "$LATEST"
|
sudo gzip -t "$LATEST"
|
||||||
ls -lh "$LATEST"
|
sudo ls -lh "$LATEST"
|
||||||
```
|
```
|
||||||
|
|
||||||
スクリプトが`OK:`、保存先、バイト数を表示し、`gzip -t`が成功することを確認する。`pg_dump`の失敗や空のダンプでは非0で終了し、完成ファイルを残さない。同じ秒の完成ファイルが既にある場合も非0で終了し、既存ファイルを上書きしない。同時実行時は同一ディレクトリ内のハードリンク作成に成功した一方だけが完成ファイルを公開する。
|
スクリプトが`OK:`、保存先、バイト数を表示し、`gzip -t`が成功することを確認する。`pg_dump`の失敗や空のダンプでは非0で終了し、完成ファイルを残さない。同じ秒の完成ファイルが既にある場合も非0で終了し、既存ファイルを上書きしない。同時実行時は同一ディレクトリ内のハードリンク作成に成功した一方だけが完成ファイルを公開する。
|
||||||
|
|
||||||
|
> [!success] NASでのバックアップ結果
|
||||||
|
> DSMタスクスケジューラから実行し、`tver_20261004_182838.sql.gz`(2,286バイト)と`tver_20261004_183256.sql.gz`(2,289バイト)を`/volume1/backups/tver/`へ作成した。ダンプはroot所有・権限600で、バックアップディレクトリはroot所有・`drwxr-xr-x`だった。[実機] 2026-10-04 確認
|
||||||
|
|
||||||
### 5.3 別DBへの復元を確認する
|
### 5.3 別DBへの復元を確認する
|
||||||
|
|
||||||
最新ダンプを本番DBへ戻す前に、同じコンテナ内の一時DB`tver_restore_test`へ復元する。
|
最新ダンプを本番DBへ戻す前に、同じコンテナ内の一時DB`tver_restore_test`へ復元する。
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
bash /volume1/docker/tver-db/restore-test.sh
|
sudo bash /volume1/docker/tver-db/restore-test.sh
|
||||||
tail -n 100 /volume1/backups/tver/restore-test.log
|
sudo tail -n 100 /volume1/backups/tver/restore-test.log
|
||||||
```
|
```
|
||||||
|
|
||||||
`download_jobs`、`subscriptions`、`known_episodes`、`schema_migrations`の行数が本番DBと一致し、最後に「復元確認に成功」と表示されることを確認する。復元SQLの通常出力は抑制され、ログには開始、各表の結果、成功または失敗が残る。SQLエラーは標準エラーとしてログに残る。一時DBは成功・失敗のどちらでもEXIT trapで削除される。本番DBに対しては行数取得の`SELECT`だけを実行する。
|
`restore-test.sh`はrootで実行する。バックアップディレクトリとログがroot所有のため、一般ユーザーでは`restore-test.log`への書き込みに失敗する。`download_jobs`、`subscriptions`、`known_episodes`、`schema_migrations`の行数が本番DBと一致し、最後に「復元確認に成功」と表示されることを確認する。復元SQLの通常出力は抑制され、ログには開始、各表の結果、成功または失敗が残る。SQLエラーは標準エラーとしてログに残る。一時DBは成功・失敗のどちらでもEXIT trapで削除される。本番DBに対しては行数取得の`SELECT`だけを実行する。
|
||||||
|
|
||||||
> [!todo] 復元確認を実行する
|
> [!success] NASでの復元確認結果
|
||||||
> 本物のNASと`tver-postgres`では未実行である。手動バックアップ後に`restore-test.sh`を1回実行し、ログと一時DBの削除を確認する。[要確認]
|
> 一般ユーザー`kazu634`での実行は`restore-test.log`へ書き込めず、`touch: Permission denied`で終了した。`sudo`で実行すると、`download_jobs` 1件、`subscriptions` 1件、`known_episodes` 1件、`schema_migrations` 3件が本番DBと一時DBで一致し、「復元確認に成功」と表示された。同じ結果がログに残り、一時DBも削除された。[実機] 2026-10-04 確認
|
||||||
|
|
||||||
|
> [!note] 配置ディレクトリの権限変更後の状態
|
||||||
|
> `/volume1/docker/tver-db`を`chmod 755`にした後も、本番アプリの`/queue`と`/subscriptions`はHTTP `200`を返し、DBを読み取れた。PostgreSQLコンテナを再起動した後の動作は未確認である。[要確認]
|
||||||
|
|
||||||
### 5.4 障害時に本番DBへ復元する
|
### 5.4 障害時に本番DBへ復元する
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user