Անցնել բովանդակությանը

Պահուստավորում, ժամանակակետի վերականգնում և վերականգնման փորձ

Պահուստավորեք Quire-ը, վերականգնեք այն նշված պահի վիճակով և ապացուցեք վերականգնման փորձի հաջողությունը։

Դիտել որպես Markdown

Դիզայնը նկարագրված է docs/architecture/23-ops.md փաստաթղթի 8-րդ բաժնում։ Սա Docker Compose արտադրանքի գործառնական ուղեցույցն է։ Այն գրված է այնպես, որ կարողանա հետևել նաև այն անձը, ով այն չի գրել․ եթե որևէ քայլ անհասկանալի է, դա այս փաստաթղթի թերությունն է։

Ինչն է պաշտպանված և ինչպես

Տվյալ Ինչպես Որտեղ
Տվյալների բազա WAL-ն արխիվացվում է շարունակաբար՝ առավելագույնը յուրաքանչյուր 60 վայրկյանը մեկ՝ առաջին մեկնարկից ի վեր pgwal ծավալ
Տվյալների բազա pg_basebackup-ով հիմնական պահուստային պատճեններ, լռելյայն՝ ամեն օր (backup-scheduler) pgbackup ծավալ
Տվյալների բազա Հիմնական պատճենների և WAL-ի կոդավորված պատճեններ ամեն հինգ րոպեն մեկ (backup-offsite) Ձեր նշած առանձին պահոց
Ֆայլեր files ծավալը։ Պատճենեք այն հոսթի պահուստավորման գործիքով կամ օգտագործեք տարբերակվող օբյեկտների պահեստ files ծավալ
Գաղտնի արժեքներ docker/.env, հատկապես QUIRE_MASTER_KEY-ը (և դեռ օգտագործվող QUIRE_MASTER_KEY_RETIRED բանալիները), QUIRE_BACKUP_ENCRYPTION_KEY-ը և docker/secrets/audit-signing-key.pem-ը Պատճենը պահեք այս հոսթից դուրս
Որոնման ինդեքսներ, քեշեր, տարբերակված ֆայլեր Չեն պահուստավորվում․ վերակառուցվում են

Նպատակներն են՝ խափանումից հետո վերականգնման կետը լինի 60 վայրկյանի սահմանում, իսկ 500 GB տվյալների բազայի վերականգնումը՝ 60 րոպեի ընթացքում։

Երկու սխալ հաճախ են պատահում։ Առանց ֆայլերի վերականգնված տվյալների բազան ցուցադրում է խափանված էջեր։ Առանց QUIRE_MASTER_KEY վերականգնված բազան չի կարող բացել իր SSO-ի, վեբհուքների ու ինտեգրումների հավատարմագրերը․ մինչև գլխավոր բանալու պտտումն ավարտվի առանց չլուծված արժեքների (key-rotation.md), դրանք ներառում են նաև հին բանալիները։ Երկուսն էլ պահուստավորման մաս են։

Պահուստային պատճենների ստեղծում

Ամբողջ կլաստերի հիմնական պահուստային պատճենը․

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

Այն պահում է ամենանոր QUIRE_BACKUP_KEEP հիմնական պատճենները (լռելյայն՝ 5) և մաքրում է ամենահինին այլևս անհրաժեշտություն չունեցող WAL-ը, որպեսզի արխիվը անսահման չաճի։ Հոսթի cron-ով կամ systemd ժմչփով նախատեսեք ամենօրյա գործարկում․

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

Կամ թողեք, որ կլաստերն ինքը պլանավորի․ backup պրոֆիլը գործարկում է backup-scheduler-ը, որը հիմնական պատճեն է ստեղծում յուրաքանչյուր QUIRE_BACKUP_INTERVAL_HOURS ժամում (լռելյայն՝ 24), և հաջորդ բաժնում նկարագրված backup-offsite-ը։

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

Հոսթից դուրս կոդավորված պատճեններ

Երկու ծավալն էլ տվյալների բազայի հետ նույն հոսթում են, իսկ խափանված մեքենայի վրա պահված պատճենը պահուստային պատճեն չէ։ backup-offsite-ը պահեստի դարպասով կոդավորված պատճենում է յուրաքանչյուր հիմնական պահուստային պատճենն ու WAL-ի յուրաքանչյուր արխիվացված հատվածը առանձին պահոցում և այնտեղ պահում ըստ պահպանման կանոնների․

  • Կոդավորում։ AES-256-GCM՝ QUIRE_BACKUP_ENCRYPTION_KEY-ով (կամ QUIRE_BACKUP_ENCRYPTION_KEY_FILE-ում նշված ֆայլով)․ 32 բայթ՝ ստացված openssl rand -hex 32 հրամանով։ Յուրաքանչյուր ֆայլ ունի իր nonce-ն ու վավերացման պիտակը, ուստի առանց բանալու պատճենն ընթեռնելի չէ, իսկ ցանկացած փոփոխություն հայտնաբերվում է։ Բանալին պահեք 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-ը․ ավելի հին հավաքածուներն ու հատվածները ջնջվում են պահոցից։
  • Երբ։ Ամեն QUIRE_BACKUP_SHIP_INTERVAL_SECONDS վայրկյանը մեկ (լռելյայն՝ 300)։ Փոխանցումն իդեմպոտենտ է․ պահվածը բաց է թողնվում, իսկ հիմնական պատճենը պահված է համարվում միայն այն բանից հետո, երբ որպես վերջին գործողություն գրվում է դրա մանիֆեստը։

Նույն հրամանը կարելի է ձեռքով գործարկել․

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

Նոր հոսթում վերականգնելու համար նախ հետ բերեք հավաքածուն, ապա հետևեք ստորև քայլերին՝ pgbackup ծավալի փոխարեն օգտագործելով ներբեռնված թղթապանակը, իսկ ներբեռնված wal-archive-ը՝ pgwal-ի փոխարեն․

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

Վերականգնում նշված ժամանակակետին

Օգտագործեք տվյալների կորստից հետո՝ սխալ ներմուծման, ջնջված դասընթացի կամ հետարկելու անհրաժեշտություն ունեցող կրճատման միգրացիայի դեպքում։ Այն փոխարինում է գործող տվյալների բազան, ուստի նախ փորձարկեք ստորև նշված եղանակով։

  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. Պահեք վնասված կլաստերը, մինչև վերականգնման ստուգումը․
    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. Նպատակային պահից հին նորագույն հիմնական պատճենը բացեք տվյալների ծավալի մեջ և խնդրեք որոշակի ժամանակի վերականգնում․
    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-ը մեկ անգամ գործարկեք վերականգնման կարգավորումներով՝ 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]
    Լրացուցիչ ֆայլը փոխարինում է ամբողջ հրամանը, ուստի կրկնում է վերականգնման համար անհրաժեշտ երկու կարգավորումները․ max_connections-ը չպետք է ցածր լինի հիմնական սերվերի արժեքից (հակառակ դեպքում վերականգնումն ընդհատվում է «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 անունը յուրաքանչյուր ծավալի նախածանցն է․ ճշգրիտ անունները ցուցադրում է docker volume ls հրամանը։

Պլանավորված ստուգման փորձ

backup-offsite-ը նաև փորձ է անցկացնում յուրաքանչյուր QUIRE_BACKUP_DRILL_INTERVAL_HOURS ժամում (լռելյայն՝ 168, շաբաթը մեկ), իսկ ձախողումից հետո՝ հաջորդ անցման ժամանակ։ Այն վերցնում է հոսթից դուրս եղած նորագույն հիմնական պատճենն ու դրանից հետո եղած բոլոր WAL հատվածները, ապակոդավորում յուրաքանչյուրը (ապացուցելով, որ բանալին դեռ բացում է դրանք, և ոչինչ չի փոփոխվել), յուրաքանչյուր ֆայլը համեմատում իր մանիֆեստի հետ, ստուգում՝ արխիվը Postgres-ի տվյալների թղթապանակ է, և հաստատում, որ պահուստավորումից սկսվող WAL-ում բաց չկա։ Հաշվետվությունը գրվում է պահոցում՝ reports/drill-<time>.json անունով և ծառայության մատյանում․ անհաջող փորձը նշում է ֆայլը կամ առաջին բացակայող հատվածը։

Վերականգնման փորձ

Երբեք չվերականգնված պահուստային պատճենը ստուգված չէ։ Փորձը թիրախային պահից առաջ արված ամենանոր ամբողջական հիմնական պատճենն ու 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։ Նոր տեղադրման դեպքում հիմնական պատճեն ստեղծեք և սպասեք հաջորդ արխիվացված հատվածին (գրառումներ լինելու դեպքում՝ առավելագույնը մեկ րոպե), ապա ընտրեք պահուստավորումից հետո ընկած նպատակային պահ։ Փորձը հոսթի վրա պահանջում է միայն Docker և bash, ուրիշ ոչինչ։

Հետևյալ քայլերից յուրաքանչյուրի ձախողումը ձախողում է փորձը․

  1. Վերականգնելիություն․ ժամանակավոր կլաստերը վերարտադրում է տվյալները մինչև նպատակային պահը և բացվում։
  2. Ամբողջականություն․ յուրաքանչյուր աղյուսակի տողերի քանակի համեմատում գործող բազայի հետ (tooling/restore-drill)։ Գործող բազան նպատակային պահից առաջ է անցել, ուստի աղյուսակի տողերի քանակը կարող է երկու ուղղությամբ տարբերվել 500 տողից և իր չափի տասներորդից ավելի արժեքով (գրառումները վերականգնումը հետ են թողնում, ջնջումները՝ վերականգնված տարբերակում ավելի շատ տվյալ պահում)․ նպատակային պահից հետո ստեղծված բաժանմունքը կորած աղյուսակ չէ։ Ավելի ակտիվ տեղադրման դեպքում թույլատրելի շեղումը մեծացրեք QUIRE_DRILL_MAX_BEHIND և QUIRE_DRILL_MAX_DRIFT_RATIO կարգավորումներով։ Բացակայող կամ դատարկված աղյուսակը ձախողում է առաջացնում։
  3. Ամբողջականություն․ վերականգնված պատճենում ստուգվում է աուդիտի hash շղթան։
  4. Օգտագործելիություն․ հավելվածի դերը տվյալները կարդում է տողի մակարդակով անվտանգության ներքո։
  5. Ժամանակ․ մեկնարկից մինչև հաջող արդյունքը համեմատվում է QUIRE_DRILL_RTO_SECONDS-ի հետ (լռելյայն՝ 3600)։

Փորձը երբեք չի գրում գործող տվյալների բազայում կամ դրա ծավալներում․ պահուստային պատճենի և WAL-ի ծավալները կցվում են միայն կարդալու իրավունքով, իսկ ժամանակավոր կլաստերը հեռացվում է վերջում՝ հաջողության կամ ձախողման դեպքում։

Սահմանեք 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

Գործարկեք ամեն ամիս և յուրաքանչյուր արդիականացումից առաջ։ Անհաջող փորձը արգելափակում է արդիականացումը։ Յուրաքանչյուր եռամսյակ թող որևէ մեկը, ով չի գրել այս ուղեցույցը, պահուստային հոսթում կատարի իրական ժամանակակետի վերականգնում՝ օգտագործելով միայն այս փաստաթուղթը։

Ֆայլեր

Տեղային ֆայլերը 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-ի տարբերակավորումը և 35 օր պահեք չընթացիկ տարբերակները․ այդ դեպքում ֆայլերի ժամանակակետի վերականգնումը կատարվում է հենց bucket-ի սեփական մեխանիզմով։

Նավիգացիա

Մուտքագրեք՝ որոնելու համար…

↑↓ նավարկել↵ ընտրելEsc փակել