រំលងទៅមាតិកា

ការបម្រុងទុក ការស្តារចំពោះពេលវេលា និងលំហាត់ស្តារឡើងវិញ

បម្រុងទុក Quire ស្តារវាទៅចំណុចមួយក្នុងពេលវេលា ហើយបញ្ជាក់វាជាមួយលំហាត់ស្តារឡើងវិញ។

មើលជា Markdown

រចនាសម្ព័ន្ធស្ថិតនៅ docs/architecture/23-ops.md ផ្នែក 8។ នេះជា runbook សម្រាប់ផលិតផល Docker Compose។ វាត្រូវបានសរសេរដើម្បីឱ្យនរណាម្នាក់ធ្វើតាមដែលមិនបានសរសេរវា។ បើជំហានណាមួយមិនច្បាស់ នោះជាកំហុសក្នុងឯកសារនេះ។

អ្វីដែលត្រូវបានការពារ និងដោយរបៀបណា

ទ្រព្យសម្បត្តិ របៀប កន្លែង
មូលដ្ឋានទិន្នន័យ WAL ទុកក្នុងបណ្ណសារឥតឈប់ឈរ យ៉ាងច្រើនរៀងរាល់ 60 វិនាទី ចាប់ពីការចាប់ផ្តើមដំបូង volume pgwal
មូលដ្ឋានទិន្នន័យ ការបម្រុងទុកគោលជាមួយ pg_basebackup ប្រចាំថ្ងៃតាមលំនាំដើម (backup-scheduler) volume pgbackup
មូលដ្ឋានទិន្នន័យ ច្បាប់ចម្លងដែលបានឌិគ្រីបនៃការបម្រុងទុកគោល និង WAL រៀងរាល់ប្រាំនាទី (backup-offsite) ឃ្លាំងផ្សេងដែលអ្នកដាក់ឈ្មោះ
ឯកសារ volume files។ ចម្លងវាជាមួយឧបករណ៍បម្រុងទុកនៃម៉ាស៊ីនរបស់អ្នក ឬប្រើការផ្ទុកវត្ថុដែលមានកំណែ volume files
សំណង់ docker/.env ជាងគេ QUIRE_MASTER_KEY (និង QUIRE_MASTER_KEY_RETIRED ណាដែលនៅតែប្រើ) QUIRE_BACKUP_ENCRYPTION_KEY និង docker/secrets/audit-signing-key.pem រក្សាច្បាប់ចម្លងចេញពីម៉ាស៊ីននេះ
index ស្វែងរក cache rendition មិនបម្រុងទុក។ សង់ឡើងវិញ

គោលដៅ៖ ចំណុចស្តារក្នុង 60 វិនាទីនៃការដួល ហើយការស្តារក្នុង 60 នាទីសម្រាប់មូលដ្ឋានទិន្នន័យ 500 GB។

កំហុសពីរគឺធម្មតា។ មូលដ្ឋានទិន្នន័យដែលបានស្តារដោយគ្មានឯកសាររបស់វាបង្ហាញទំព័រខូច។ មូលដ្ឋានទិន្នន័យដែលបានស្តារ**ដោយគ្មាន QUIRE_MASTER_KEY**មិនអាចឌិគ្រីបលិខិតសម្គាល់ SSO webhook និងការរួមបញ្ចូលដែលវាកាន់បានទេ។ រហូតដល់ការបង្វិលសោ master បញ្ចប់ដោយគ្មានអ្វីដែលមិនដោះស្រាយ (key-rotation.md) នោះរួមបញ្ចូលសោដែលបានដក។ ទាំងពីរជាផ្នែកនៃការបម្រុងទុក។

ការយកការបម្រុងទុក

ការបម្រុងទុកគោលនៃពេញ kluster៖

docker compose -f docker/compose.yaml --profile backup run --rm backup

វារក្សាការបម្រុងទុកគោលថ្មីបំផុត QUIRE_BACKUP_KEEP (លំនាំដើម 5) ហើយកាត់ WAL ដែលចាស់បំផុតមិនត្រូវការទៀត ដូច្នេះបណ្ណសារមិនអាចធំឡើងឥតដែនកំណត់។ កំណត់កាលវិភាគប្រចាំថ្ងៃជាមួយ cron ឬ timer មួយ systemd លើម៉ាស៊ីន៖

15 2 * * * cd /srv/quire && docker compose -f docker/compose.yaml --profile backup run --rm backup >> /var/log/quire-backup.log 2>&1

ឬអនុញ្ញាតឱ្យស្តាខកំណត់កាលវិភាគវា៖ profile backup ដំណើរការ backup-scheduler ដែលយកការបម្រុងទុកគោលរៀងរាល់ QUIRE_BACKUP_INTERVAL_HOURS (លំនាំដើម 24) ហើយ backup-offsite ដែលបានពិពណ៌នាខាងក្រោម។

docker compose -f docker/compose.yaml --profile backup up -d

ច្បាប់ចម្លងឌិគ្រីបចេញពីម៉ាស៊ីន

volume ទាំងពីរស្ថិតលើម៉ាស៊ីនតែមួយជាមួយមូលដ្ឋានទិន្នន័យ ហើយការបម្រុងទុកលើម៉ាស៊ីនដែលបានដួលមិនមែនជាការបម្រុងទុកទេ។ backup-offsite ចម្លងការបម្រុងទុកគោលនីមួយៗ និង segment WAL ដែលបានទុកក្នុងបណ្ណសារនីមួយៗទៅឃ្លាំងផ្សែងតាមច្រកការផ្ទុក ដែលបានឌិគ្រីប ហើយរក្សាពួកវានៅទីនោះក្រោមការរក្សាទុក៖

  • ការឌិគ្រីប។ AES-256-GCM ជាមួយ QUIRE_BACKUP_ENCRYPTION_KEY (ឬឯកសារដែល QUIRE_BACKUP_ENCRYPTION_KEY_FILE ដាក់ឈ្មោះ)៖ 32 បៃ ពី openssl rand -hex 32។ ឯកសារនីមួយៗមាន nonce ផ្ទាល់ និង authentication tag ដូច្នេះច្បាប់ចម្លងអានមិនបានដោយគ្មានសោ ហើយការផ្លាស់ប្តូរណាមួយចំពោះវាត្រូវបានរកឃើញ។ រក្សាសោជាមួយ QUIRE_MASTER_KEY ឆ្ងាយពីម៉ាស៊ីននេះ ហើយឆ្ងាយពីឃ្លាំងបម្រុងទុក។ គ្មានសោគ្មានការស្តារទេ។
  • កន្លែង។ QUIRE_BACKUP_STORAGE_DRIVER ជា s3, azure ឬ local (ថាសឆ្ងាយដែលបានតោងនៅ QUIRE_BACKUP_STORAGE_ROOT)។ ការកំណត់ជាការកំណត់ឯកសារផ្ទុកដែលមានបូក QUIRE_BACKUP_ ខាងមុខ៖ QUIRE_BACKUP_S3_ENDPOINT, QUIRE_BACKUP_S3_BUCKET, QUIRE_BACKUP_S3_ACCESS_KEY_ID និងផ្សេងៗ។ ប្រើ bucket ខុសគ្នា ហើយល្អបំផុតគណនីខុសគ្នាពីឯកសារ ជាមួយលិខិតសម្គាល់ដែលអាចសរសេរបានប៉ុន្តែមិនអាចលុបបាន បើអ្នកផ្តល់អនុញ្ញាត។
  • ការរក្សាទុក។ ការបម្រុងទុកគោលថ្មីបំផុត QUIRE_BACKUP_OFFSITE_KEEP (លំនាំដើម QUIRE_BACKUP_KEEP ឬ 7) និង WAL ដែលចាស់បំផុតក្នុងចំណោមពួកវាត្រូវការ។ បញ្ជី និង segment ចាស់ៗត្រូវបានលុបចេញពីឃ្លាំង។
  • ពេល។ រៀងរាល់ QUIRE_BACKUP_SHIP_INTERVAL_SECONDS (លំនាំដើម 300)។ ការដឹកជញ្ជូនស្ថិតនិរន្តរ៍៖ អ្វីដែលបានផ្ទុករួចហើយត្រូវបានរំលង ហើយការបម្រុងទុកគោលរាប់ថាបានផ្ទុកតែនៅពេល manifest របស់វាត្រូវបានសរសេរ ចុងក្រោយ។

ពាក្យបញ្ជាដដែលដំណើរការដោយដៃ៖

docker compose -f docker/compose.yaml run --rm backup-offsite bun apps/worker/src/backups/main.ts ship
docker compose -f docker/compose.yaml run --rm backup-offsite bun apps/worker/src/backups/main.ts verify

ដើម្បីស្តារលើម៉ាស៊ីនថ្មី នាំបញ្ជីមួយត្រឡប់មុនសិន រួចធ្វើតាមជំហានខាងក្រោមជាមួយថតដែលបានទាញយកជំនួស volume pgbackup ហើយ wal-archive ដែលបានទាញយកជំនួស pgwal៖

bun apps/worker/src/backups/main.ts fetch base-20260924T021500Z /srv/restore

ការស្តារចំពោះពេលវេលា

ប្រើនេះបន្ទាប់ពីការបាត់បង់ទិន្នន័យ៖ ការនាំចូលខូច វគ្គសិក្សាដែលបានលុប ការផ្លាស់ប្តូរ contract ដែលអ្នកត្រូវលុប។ វាជំនួសមូលដ្ឋានទិន្នន័យផ្ទាល់ ដូច្នេះហាត់ប្រាណជាមួយលំហាត់ខាងក្រោមជាមុនសិន។

  1. ជ្រើសពេលគោលដៅ ជា UTC ទាន់មុនការខូច៖ 2026-09-24 09:30:00+00។ កំណត់ត្រាសវនកម្ម (/admin/audit) ជាទូទៅបង្ហាញពេលនោះ។
  2. ឈប់អ្វីៗដែលសរសេរ៖ docker compose -f docker/compose.yaml stop web content worker scheduler collab
  3. រក្សា kluster ដែលខូច រហូតដល់ការស្តារត្រូវបានផ្ទៀងផ្ទាត់៖
    docker compose -f docker/compose.yaml stop postgres
    docker run --rm -v quire_postgres18-data:/from -v quire_postgres-damaged:/to alpine cp -a /from/. /to/
  4. បើកការបម្រុងទុកគោលថ្មីបំផុតដែលចាស់ជាងពេលគោលដៅចូលក្នុង volume ទិន្នន័យ ហើយសុំការស្តារគោលដៅ៖
    docker run --rm -v quire_pgbackup:/backups:ro -v quire_postgres18-data:/var/lib/postgresql postgres:18-alpine sh -euc '
      base="$(ls -1d /backups/base-* | sort | tail -n 1)"   # or the one before the target
      rm -rf /var/lib/postgresql/18/docker && mkdir -p /var/lib/postgresql/18/docker
      tar -xzf "$base/base.tar.gz" -C /var/lib/postgresql/18/docker
      touch /var/lib/postgresql/18/docker/recovery.signal
      chown -R postgres:postgres /var/lib/postgresql/18/docker && chmod 700 /var/lib/postgresql/18/docker'
  5. ស្តារ៖ ចាប់ផ្តើម Postgres មួយដងជាមួយការកំណត់ស្តារ ពី override មួយ Compose ដូច្នេះឯកសារធម្មតាមិនប៉ះ៖
    # docker/compose.recover.yaml
    services:
      postgres:
        command: [postgres, -c, "restore_command=cp /var/lib/postgresql/wal-archive/%f %p",
                  -c, "recovery_target_time=2026-09-24 09:30:00+00",
                  -c, recovery_target_action=promote, -c, archive_mode=off,
                  -c, max_connections=200, -c, hba_file=/etc/postgresql/pg_hba.conf]
    override ជំនួសពាក្យបញ្ជាទាំងមូល ដូច្នេះវាបញ្ជូនការកំណត់ពីរដែលការស្តារពឹងផ្អែកលើ៖ max_connections មិនទាបជាងនៃ primary (បើអត់ការស្តារឈប់ជាមួយ “insufficient parameter settings”) និង pg_hba.conf ដែលបានតោង។
    docker compose -f docker/compose.yaml -f docker/compose.recover.yaml up -d postgres
    docker compose -f docker/compose.yaml logs -f postgres   # wait for "database system is ready"
  6. ពិនិត្យវា មុននឹងអនុញ្ញាតឱ្យអ្នកណាចូល៖ ខ្សែសវនកម្ម (docker compose -f docker/compose.yaml run --rm worker bun tooling/audit-verify/run.ts) ហើយថាទិន្នន័យដែលបានបាត់ត្រឡប់មកវិញ។
  7. ត្រឡប់ទៅធម្មតា៖ docker compose -f docker/compose.yaml up -d។ នេះចាប់ផ្តើមឡើងវិញ Postgres ជាមួយការទុកក្នុងបណ្ណសារបើក ហើយពេលវេលា WAL ថ្មីមួយចាប់ផ្តើម។ យកការបម្រុងទុកគោលថ្មីភ្លាមៗ។

ឈ្មោះគម្រោង quire ដាក់បូកខាងមុខ volume នីមួយៗ។ docker volume ls បង្ហាញឈ្មោះពិត។

លំហាត់ផ្ទៀងផ្ទាត់ដែលបានកំណត់កាលវិភាគ

backup-offsite ក៏ដំណើរការលំហាត់មួយរៀងរាល់ QUIRE_BACKUP_DRILL_INTERVAL_HOURS (លំនាំដើម 168 ប្រចាំសប្តាហ៍) ហើយម្តងទៀតនៅការឆ្លងកាត់បន្ទាប់បន្ទាប់ពីមួយបរាជ័យ។ វាទាញយកការបម្រុងទុកគោលចេញពីម៉ាស៊ីនថ្មីបំផុត និង segment WAL ទាំងអស់បន្ទាប់ពីវា ឌិគ្រីបនីមួយៗ (ដែលបញ្ជាក់ថាសោនៅតែបើកពួកវា ហើយគ្មានអ្វីបានកែ) ប្រៀបធៀបឯកសារនីមួយៗជាមួយ manifest របស់វា ពិនិត្យថាបណ្ណសារជាថតទិន្នន័យ Postgres ហើយពិនិត្យថាពីការបម្រុងទុកតទៅ WAL គ្មានគម្លាត។ របាយការណ៍ត្រូវបានសរសេរទៅឃ្លាំងជា reports/drill-<time>.json ហើយទៅកំណត់ត្រានៃសេវា។ លំហាត់ដែលបរាជ័យដាក់ឈ្មោះឯកសារ ឬ segment ដែលបាត់ដំបូង។

លំហាត់ស្តារឡើងវិញ

ការបម្រុងទុកដែលមិនដែលបានស្តារមិនមែនជាការបម្រុងទុកទេ។ លំហាត់ស្តារការបម្រុងទុកគោលពេញលេញថ្មីបំផុតដែលបានយកមុនពេលគោលដៅ បន្ថែមបណ្ណសារ WAL ចូល Postgres សាកល្បងដែលមិនចែករំលែកអ្វីជាមួយផ្ទាល់ ហើយបញ្ជាក់លទ្ធផល៖

docker/scripts/restore-drill.sh                                  # to ninety minutes ago
docker/scripts/restore-drill.sh --target "2026-09-24 09:30:00+00"

ពេលគោលដៅជា UTC តាមទម្រង់នោះពិត។ វាត្រូវការការបម្រុងទុកគោលចាស់ជាងវា ហើយ WAL ដែលបានទុកក្នុងបណ្ណសារលើសពីវា។ លើការដំឡើងថ្មី យកការបម្រុងទុកគោល ហើយរង់ចាំ segment ដែលបានទុកក្នុងបណ្ណសារបន្ទាប់ (យ៉ាងច្រើនមួយនាទីជាមួយការសរសេរ) មុននឹងជ្រើសពេលគោលដៅបន្ទាប់ពីការបម្រុងទុក។ លំហាត់ត្រូវការ Docker និង bash លើម៉ាស៊ីន គ្មានអ្វីផ្សេង។

ជំហាននីមួយៗបរាជ័យលំហាត់៖

  1. សមត្ថភាពស្តារ៖ kluster សាកល្បងបញ្ជូនឡើងវិញទៅពេលគោលដៅ ហើយបើក។
  2. ភាពពេញលេញ៖ ចំនួនជួររបស់តារាងនីមួយៗប្រឆាំងនឹងមូលដ្ឋានទិន្នន័យផ្ទាល់ (tooling/restore-drill)។ មូលដ្ឋានទិន្នន័យផ្ទាល់បានផ្លាស់ទីបន្ទាប់ពីពេលគោលដៅ ដូច្នេះតារាងមួយអាចខុសគ្នាដោយធំជាងនៃ 500 ជួរ និងមួយទាក់នៃទំហំរបស់វា ក្នុងទិសណាមួយ (ការសរសេរធ្វើឱ្យវា យឺត ការលុបធ្វើឱ្យការស្តារកាន់ច្រើន)។ ផ្នែកដែលបានបង្កើតបន្ទាប់ពីពេលគោលដៅមិនមែនជាតារាងដែលបានបាត់ទេ។ ពង្រីកការអនុញ្ញាតលើការដំឡើងដែលមមាញឹកជាងជាមួយ QUIRE_DRILL_MAX_BEHIND និង QUIRE_DRILL_MAX_DRIFT_RATIO។ តារាងដែលបាត់ ឬទទេបរាជ័យ។
  3. ភាពពេញលេញនៃទិន្នន័យ៖ ខ្សែ hash សវនកម្មផ្ទៀងផ្ទាត់លើច្បាប់ចម្លងដែលបានស្តារ។
  4. ភាពអាចប្រើបាន៖ តួនាទីកម្មវិធីអានតាមសុវត្ថិភាពជួរដេក។
  5. ពេលវេលា៖ ពីការចាប់ផ្តើមដល់សុខភាពល្អ ប្រឆាំងនឹង QUIRE_DRILL_RTO_SECONDS (លំនាំដើម 3600)។

វាមិនដែលសរសេរទៅមូលដ្ឋានទិន្នន័យផ្ទាល់ ឬ volume របស់វាទេ៖ volume បម្រុងទុក និង WAL ត្រូវបានតោងតែអាន ហើយ kluster សាកល្បងត្រូវបានយកចេញនៅចុងបញ្ចប់ ជោគជ័យ ឬបរាជ័យ។

កំណត់ QUIRE_DRILL_REPORT ទៅផ្លូវមួយដើម្បីឱ្យរបាយការណ៍ JSON ត្រូវបានសរសេរ ជោគជ័យ ឬបរាជ័យ ហើយដំណើរការវាតាមកាលវិភាគពីម៉ាស៊ីន Docker៖

30 3 1 * * cd /srv/quire && QUIRE_DRILL_REPORT=/var/log/quire-drill.json docker/scripts/restore-drill.sh >> /var/log/quire-drill.log 2>&1

ដំណើរការវាប្រចាំខែ ហើយមុនរាល់ការធ្វើឱ្យប្រសើរ។ លំហាត់ដែលបរាជ័យរារាំងការធ្វើឱ្យប្រសើរ។ មួយត្រីមាសមួយ ឱ្យនរណាម្នាក់ដែលមិនបានសរសេរ runbook នេះធ្វើការស្តារចំពោះពេលវេលាពិតលើម៉ាស៊ីនសម្រាប់បម្រុង ដោយប្រើតែឯកសារនេះ។

ឯកសារ

ឯកសារក្នុងស្រុកស្ថិតក្នុង volume files។ បម្រុងទុកវាជាមួយមូលដ្ឋានទិន្នន័យ ក្នុងពេលតែមួយ ហើយស្តារទាំងពីរជាមួយគ្នា៖

docker run --rm -v quire_files:/files:ro -v "$PWD":/out alpine tar -czf /out/files-$(date -u +%Y%m%d).tar.gz -C /files .

ជាមួយការផ្ទុកវត្ថុ បើក bucket versioning ហើយរក្សា 35 ថ្ងៃនៃកំណែដែលមិនមែនបច្ចុប្បន្ន។ ការស្តារចំពោះពេលវេលាសម្រាប់ឯកសារបន្ទាប់មកជារបស់ bucket ផ្ទាល់។

ការរុករក

វាយដើម្បីស្វែងរក…

↑↓ រុករក↵ ជ្រើសរើសEsc បិទ