Данила (Dayfing)
Жарияланымдарға оралу
2 508 сөз13 мин

restic арқылы 3-2-1 сақтық көшірме және қалпына келтіру жаттығуы

Қалпына келтіруге жарайтын сақтық көшірме сіздің қатысуыңызсыз кесте бойынша іске қосылады, бір көшірмесін бұзылған сервер жоя алмайтын сыртқы орында сақтайды, дерекқорларды келісілген күйде түсіреді және жақында уақыты өлшеніп, қалпына келтіру арқылы тексерілген. restic үшін бұл object lock немесе append-only сервермен қорғалған S3-үйлесімді қоймадағы шифрланған репозиторийді, әр іске қосу алдындағы дерекқор дамптарын, ақаулар туралы ескертетін systemd таймерін және тұрақты қалпына келтіру жаттығуларын білдіреді. Бұл нұсқаулық осы схеманы Linux сервері үшін құрады, ал дәл сол бөліктер әзірлеуші компьютеріне де жарайды.

Құралдарды таңдамас бұрын RPO мен RTO анықтаңыз

Recovery point objective (RPO) қанша деректі жоғалтуға дайын екеніңізді уақыт бірлігімен көрсетеді. Recovery time objective (RTO) қалпына келтіру кезінде сервис қанша уақыт тұрып қала алатынын көрсетеді. Сервис иесі екі сұраққа да қарапайым сөзбен жауап береді: «біз ең көбі бір күндік тапсырыстарды жоғалта аламыз» және «дүкен төрт сағат ішінде қайта істеуі керек».

Кесте бойынша жасалатын сақтық көшірмеде ең нашар жағдайдағы шығын шамамен іске қосулар арасындағы аралыққа және бір іске қосудың сыртқы қоймаға жету уақытына тең. Сағат 02:00-де басталып, жүктеуді 02:40-та аяқтайтын түнгі тапсырма ең нашар жағдайда шамамен 24 сағат 40 минуттық RPO береді. Егер дерекқор үшін бұл тым көп болса, оның көшірмесін жиірек жасаңыз немесе WAL мұрағаттауын қосыңыз.

RTO негізінен деректерді тасымалдау және қайта құру уақытымен анықталады. Тасымалдау секундтары мегабитпен берілген деректер көлемін Мбит/с арқылы берілген арна жылдамдығына бөлгенге тең. 200 ГБ қалпына келтіру 1 600 000 мегабит болады, сондықтан 100 Мбит/с жылдамдықта ол дерекқорды қалпына келтіруге дейін-ақ 16 000 секунд, яғни шамамен 4,4 сағат алады. Егер бұл RTO-дан асып кетсе, бір ғана қашықтағы бакет мақсатқа жеткізбейді, сізге жергілікті көшірме немесе резервтік жүйе керек.

3-2-1 ережесі және оның 3-2-1-1-0 кеңейтімі

3-2-1 ережесі деректердің екі түрлі қойма түріндегі үш көшірмесін білдіреді, олардың бірі сыртқы орында тұрады. VPS-те бірінші көшірме жұмыс дискісінде, екіншісі бөлек қоймадағы жергілікті дамп не репозиторий, ал үшіншісі басқа провайдердегі немесе басқа аккаунттағы бакетте жатады. Сол дискідегі екінші бөлім біріншімен бірге істен шығады, сондықтан жергілікті көшірмені басқа құрылғыда (оны таңдауға NVMe SSD таңдау нұсқаулығы көмектеседі) немесе басқа хостта ұстаңыз.

Сақтық көшірме жүйелерін шығарушылар 3-2-1-1-0 кеңейтімін танымал етті. Қосымша бірлік офлайн немесе өзгермейтін көшірмені білдіреді: сервердегі root құқығы және оның бұлттық тіркелгі деректері бар шабуылдаушы да оны жоя алмауы керек. Нөл тұтастықты тексеру мен қалпына келтіру сынақтарында қате жоқ екенін білдіреді. Көп схема дәл осы соңғы цифрды өткізіп жібереді, бірақ қалған төртеуінің шынайы екенін тек сол көрсетеді.

Нені сақтау керек және нені шығарып тастау керек

Жария көзден тез қайта жасауға болмайтын нәрсені сақтаңыз: /etc, /srv немесе /var/www ішіндегі қолданба коды мен жүктелген файлдар, SSH және GPG кілттері бар үй каталогтары, crontab, TLS материалдары, дерекқор дамптары және apt-mark showmanual шығаратын орнатылған пакеттер тізімі. Әзірлеуші компьютерінде push жасалмаған жұмыс, stash, dotfiles, кілттер мен құжаттар құнды.

Үлкен немесе қайта жасалатын деректерді шығарып тастаңыз: кэштер, node_modules, виртуалды орталар, құрастыру нәтижелері, контейнер бейнелері, модель салмақтары және swap. /var/lib/postgresql сияқты жұмыс істеп тұрған дерекқор каталогтарын да шығарып тастаңыз, өйткені істеп тұрған серверден алынған көшірме жарамды сақтық көшірме емес. restic шығару файлдарында / таңбасынан басталатын үлгі абсолюттік жолға сәйкес келеді, ал node_modules сияқты жай атау кез келген тереңдікте сәйкес келеді:

/var/lib/postgresql
/var/lib/docker
/var/cache
/var/tmp
/swapfile
/home/*/.cache
node_modules
.venv
__pycache__
*.tmp

--exclude-caches қосымша түрде стандартты CACHEDIR.TAG файлы бар каталогтарды өткізіп жібереді, ал --one-file-system restic-тің басқа тіркелген файлдық жүйелерге өтуіне жол бермейді.

restic негіздері: репозиторий, шифрлау және құпиясөз

restic дедупликацияланған снапшоттарды жергілікті дискідегі, SFTP арқылы қолжетімді, өзінің REST серверіндегі немесе объектілік қоймадағы репозиторийде сақтайды және тек жаңа бөліктерді жүктейді. Шифрлауды өшіру мүмкін емес: restic дизайн құжаттамасына сәйкес барлық деректер санауыш режиміндегі AES-256 арқылы шифрланады және Poly1305-AES арқылы аутентификацияланады, ал кілтті scrypt арқылы күшейтілген құпиясөз қорғайды.

Интерактивті командалар мен кестелік тапсырмалар бірдей мәндерді қолдануы үшін баптауларды тек root оқи алатын орта файлында сақтаңыз. Репозиторий құжаттамасы URL пішімдерін келтіреді, мысалы S3-үйлесімді сервистер үшін s3:https://server:port/bucket.

# /etc/restic/restic.env, mode 600
RESTIC_REPOSITORY=s3:https://s3.example.com/web1-backups
RESTIC_PASSWORD_FILE=/etc/restic/password
RESTIC_CACHE_DIR=/var/cache/restic
AWS_ACCESS_KEY_ID=replace-me
AWS_SECRET_ACCESS_KEY=replace-me
HEARTBEAT_URL=https://monitor.example.net/ping/web1-backup
ALERT_WEBHOOK_URL=https://chat.example.net/hooks/backups
install -d -m 700 /etc/restic
(umask 077; openssl rand -base64 32 > /etc/restic/password)
set -a; . /etc/restic/restic.env; set +a
restic init
restic key add    # қалпына келтіруге арналған офлайн көшірме үшін екінші құпиясөз
restic backup --one-file-system --exclude-caches \
  --exclude-file=/etc/restic/excludes.txt /etc /root /home /srv /var/www
restic snapshots

Құжаттама мұны тура айтады: құпиясөзді жоғалту деректерді қайтарымсыз жоғалтуды білдіреді. Құпиясөзді, репозиторий URL-ін және бакеттің тіркелгі деректерін құпиясөз менеджерінде және мөрленген офлайн көшірмеде сақтаңыз, бірақ ешқашан тек қорғалатын серверде ғана ұстамаңыз. Құпия деректер менеджерін қолдансаңыз, RESTIC_PASSWORD_COMMAND файлды оқудың орнына құпиясөзді шығара алады.

forget және prune арқылы сақтау, check арқылы тұтастық

restic forget сақтау саясатын снапшоттардың әр тобына қолданады (әдепкі бойынша хост пен жолдар бойынша топтастырылады), ал prune ешбір снапшот сілтемейтін деректерді жояды. --prune жалаушасы екі қадамды да орындайды:

restic forget --prune --keep-daily 14 --keep-weekly 8 --keep-monthly 12 --keep-yearly 3
restic check --read-data-subset=10%

Бұл саясат снапшоты бар соңғы 14 күннің әрқайсысы үшін ең жаңа снапшотты, одан кейін 8 апта бойы аптасына біреуден, 12 ай бойы айына біреуден және 3 жыл бойы жылына біреуден сақтайды. Саясатты өзгерткенде --dry-run қосып, алдын ала қараңыз. forget құжаттамасында prune кезінде репозиторий құлыпталатыны айтылған, сондықтан оны сақтық көшірмелерден бөлек уақытқа қойыңыз және көшірме командасына --retry-lock беріңіз.

restic check құрылым мен метадеректерді тексереді. --read-data әр pack-ті жүктеп алады, бұл уақыт пен шығыс трафикті қажет етеді, ал --read-data-subset бір бөлігін оқиды: 10% әр іске қосуда кездейсоқ ішкі жиынды таңдайды, ал 3/12 тұрақты он екіден бір бөлікті оқиды, бұл репозиторийге қызмет көрсету нұсқаулығында сипатталған. Сәтті тексеру репозиторийдің келісімділігін дәлелдейді, бірақ сервисті қалпына келтіре алатыныңызды дәлелдемейді.

Шифрлаушы вирус өшіре алмайтын сыртқы репозиторий

root құқығы бар шабуылдаушы /etc/restic/restic.env файлын оқи алады. Егер бұл тіркелгі деректері объектілерді жоюға рұқсат етсе, сыртқы көшірмені де жоюға болады. Тіркелгі деректерін бір бакетпен шектеңіз, әкімшілік кілттерді серверден тыс ұстаңыз және Linux VPS қорғау нұсқаулығындағы ең аз артықшылық қағидаларын қолданыңыз. Содан кейін екі қорғаудың бірін таңдаңыз.

append-only режиміндегі REST сервер

restic жобасының rest-server құралында --append-only режимі бар, ол жаңа сақтық көшірмелерді қабылдайды, бірақ барларын жоюға немесе өзгертуге тыйым салады. restic құжаттамасы мұндай репозиторийлер үшін forget пен prune командаларын бөлек, жақсы қорғалған машинадан іске қосуды және --keep-weekly сияқты ережелердің орнына --keep-within қолдануды ұсынады, өйткені бұзылған клиент нағыз снапшоттардың орнын алатын, уақыт белгілері әдейі таңдалған жалған снапшоттар қоса алады.

S3-үйлесімді қоймадағы object lock

S3 Object Lock объект нұсқаларын write-once-read-many үлгісімен сақтайды. Ол нұсқалауды қажет етеді, ал compliance режимінде ешкім, соның ішінде аккаунттың root пайдаланушысы да, құлыпталған нұсқаны сақтау мерзімі біткенге дейін жоя алмайды. 0.13 нұсқасынан бастап restic мұндай бакеттер талап ететін жүктеу бақылау сомаларын жібереді, сондықтан ол бакеттің әдепкі сақтау саясатымен жұмыс істейді (басқа провайдерлер үшін --endpoint-url қосыңыз):

aws s3api create-bucket --bucket web1-backups --object-lock-enabled-for-bucket
aws s3api put-object-lock-configuration --bucket web1-backups \
  --object-lock-configuration '{"ObjectLockEnabled":"Enabled","Rule":{"DefaultRetention":{"Mode":"COMPLIANCE","Days":30}}}'

restic мұндай бакеттегі файлды жойғанда, S3 жою маркерін қосады, ал құлыпталған нұсқа сақталып қалады. Шабуылдан кейін бакетті бұрынғы күйінде көшіріңіз, мысалы rclone copy --s3-version-at "2026-09-20" offsite:web1-backups /srv/recovered-repo командасымен, содан соң сол көшірмеден қалпына келтіріңіз. prune жойған деректер сақтау мерзімі аяқталғанша орын алып тұрады, сондықтан ескі нұсқаларды осы мерзімнен ерте емес өмірлік цикл ережесімен жойыңыз. Бүкіл циклді өз провайдеріңізде тексеріңіз, өйткені S3-үйлесімді іске асырулар әртүрлі.

PostgreSQL-дің келісілген сақтық көшірмелері

PostgreSQL құжаттамасы файлдық жүйе деңгейіндегі сақтық көшірмелер туралы нақты айтады: деректер каталогының жарамды көшірмесі үшін сервер тоқтатылуы керек, ал қосылуларға тыйым салу жеткіліксіз, өйткені tar сияқты құралдар атомарлық снапшот жасамайды, ал сервер деректерді жадта буферлейді. Барлық деректер файлдары мен WAL бар томның атомарлық снапшоты жұмыс істейді, себебі PostgreSQL апаттан кейінгідей WAL-ды қайта ойнатады.

Көп сервер үшін логикалық дамптар ең қарапайым әрі дұрыс таңдау болып қала береді. pg_dump дерекқор қолданыста тұрғанда келісілген экспорт жасайды және басқа пайдаланушыларды бұғаттамайды. directory пішімі дамп жасауды да, қалпына келтіруді де параллель орындауға мүмкіндік береді. Рөлдер дампқа кірмейді, сондықтан жаһандық объектілерді бөлек шығарыңыз. Бұл скрипт әр сақтық көшірме алдында іске қосылып, соңғы дамптарды жергілікті дискіде сақтайды:

#!/usr/bin/env bash
# /usr/local/sbin/pg-dump-for-backup
set -euo pipefail
out=/var/backups/postgresql
install -d -m 700 -o postgres -g postgres "$out"
runuser -u postgres -- pg_dumpall --globals-only --file="$out/globals.sql"
runuser -u postgres -- psql -Atc \
  "SELECT datname FROM pg_database WHERE datallowconn AND NOT datistemplate" |
while read -r db; do
  rm -rf "$out/$db.new"
  runuser -u postgres -- pg_dump --format=directory --jobs=2 --file="$out/$db.new" "$db"
  rm -rf "$out/$db"
  mv "$out/$db.new" "$out/$db"
done

Үлкен кластерді логикалық қалпына келтіру RTO-ға сыймаса немесе point-in-time recovery керек болса, pg_basebackup қолданыңыз. Ол бүкіл кластерді репликация протоколы арқылы бос каталогқа көшіреді, REPLICATION атрибуты бар рөлді және pg_hba.conf жазбасын талап етеді, сондай-ақ көшірмені іске қосуға қажет WAL-ды жібереді. pg_verifybackup нәтижені манифест бойынша тексереді:

sudo -u postgres pg_basebackup --pgdata=/var/backups/pg-base --wal-method=stream --checkpoint=fast
sudo -u postgres pg_verifybackup /var/backups/pg-base

pg_restore индекстерді олардың анықтамалары бойынша қайта құрады. Дерекқорда үлкен векторлық индекстер болса, мысалы pgvector гибридті іздеу нұсқаулығындағы HNSW индекстері, бұл қайта құру қалпына келтіру уақытының басым бөлігін алуы мүмкін.

systemd сервисі мен таймері арқылы кесте

oneshot түріндегі сервис алдымен дампты, содан кейін сақтық көшірмені іске қосады. Дамп сәтсіз аяқталса, сақтық көшірме басталмайды және юнит failed күйіне өтеді. Юниттерді /etc/systemd/system/ ішінде сақтаңыз:

# restic-backup.service
[Unit]
Description=restic backup to the off-site repository
Wants=network-online.target
After=network-online.target postgresql.service
OnFailure=backup-alert@%n.service

[Service]
Type=oneshot
EnvironmentFile=/etc/restic/restic.env
CacheDirectory=restic
Nice=10
IOSchedulingClass=idle
ExecStartPre=/usr/local/sbin/pg-dump-for-backup
ExecStart=/usr/local/bin/restic backup --retry-lock 30m \
    --one-file-system --exclude-caches \
    --exclude-file=/etc/restic/excludes.txt --tag scheduled \
    /etc /root /home /srv /var/www /var/backups/postgresql
ExecStartPost=-/usr/bin/curl -fsS --max-time 10 --retry 3 ${HEARTBEAT_URL}
# restic-backup.timer
[Unit]
Description=Nightly restic backup

[Timer]
OnCalendar=*-*-* 02:15:00
RandomizedDelaySec=30m
Persistent=true

[Install]
WantedBy=timers.target

Таймерді systemctl enable --now restic-backup.timer командасымен қосып, systemctl list-timers арқылы тексеріңіз. systemd.timer құжаттамасына сәйкес, Persistent=true машина өшіп тұрғанда өткізіп алған іске қосуды кейін орындайды, ал RandomizedDelaySec= бір бакетке жазатын хосттарды уақыт бойынша таратады. oneshot сервистерінде әдепкі бойынша іске қосу тайм-ауты жоқ. Linux ноутбугында дәл сол жұп үй каталогы үшін пайдаланушы юниттері ретінде жұмыс істейді.

Сол тақырыптамасы бар апталық restic-maintenance.service тазалау мен тексерулерді орындайды:

ExecStart=/usr/local/bin/restic forget --prune --retry-lock 2h \
    --keep-daily 14 --keep-weekly 8 --keep-monthly 12 --keep-yearly 3
ExecStart=/usr/local/bin/restic check --read-data-subset=10%%

Пайыз белгісін сол күйінде жазу үшін %% қолданыңыз, өйткені юнит файлдарында % спецификаторды бастайды.

Ақаулар мониторингі және ескертулер

Екі тәуелсіз сигнал қолданыңыз, әйтпесе үнсіз ақау инцидент кезінде ғана білінеді. Бірінші сигналды OnFailure= береді. restic-тің шығу кодтары нақты: 1 команданың сәтсіздігін, 3 кейбір бастапқы файлдардың оқылмағанын, 10 репозиторийдің жоқтығын, 11 құлыптаудың сәтсіз болғанын, ал 12 құпиясөздің қате екенін білдіреді. systemd кез келген нөлдік емес кодты ақау деп санайды, бұл 3 үшін де дұрыс: снапшот бар, бірақ онда олқылықтар бар.

# [email protected]
[Unit]
Description=Alert for failed %i

[Service]
Type=oneshot
EnvironmentFile=/etc/restic/restic.env
ExecStart=/usr/bin/curl -fsS --max-time 10 --retry 3 \
    --data-urlencode "text=%H: %i failed, see journalctl -u %i" \
    ${ALERT_WEBHOOK_URL}

Бір шаблон барлық тапсырмаларға қызмет етеді, ал systemd оған MONITOR_EXIT_STATUS сияқты айнымалыларды береді. Тізбекті systemctl start [email protected] командасымен тексеріңіз.

Екінші сигнал dead man's switch ретінде жұмыс істейді: ExecStartPost= сәтті аяқталғаннан кейін ғана heartbeat URL-ге сұрау жібереді, ал мониторинг жүйесі сұрау, мысалы, 26 сағат ішінде келмесе, дабыл қағады. Осылайша өшірілген таймер немесе сөндірілген хост анықталады. Сырттан бақылау үшін күн сайын басқа машинадан restic snapshots --latest 1 --json --no-lock іске қосып, ең жаңа снапшот RPO-дан ескі болса, ескерту жіберіңіз.

Уақыты өлшенетін қалпына келтіру жаттығуын өткізіңіз

Жаттығу болжамдарды нақты сандарға айналдырады. Оны алғашқы баптаудан кейін, ірі өзгерістерден кейін және кемінде тоқсанына бір рет жұмыс хостында емес, таза виртуалды машинада өткізіңіз әрі нақты инцидент кезінде инженерде болатын нәрселерді ғана қолданыңыз: құпиясөз менеджеріндегі жазба және runbook.

  1. Шартты инцидент басталған сәтте секундомерді іске қосыңыз.
  2. Тіркелгі деректерін алып, restic орнатыңыз және снапшоттар тізімін шығарыңыз. Ең жаңа снапшоттың жасы сіздің нақты RPO көрсеткішіңіз болады.
  3. Файлдар мен дамптарды, содан кейін дерекқорды қалпына келтіріп, әр қадамның уақытын өлшеңіз.
  4. Қолданбаның staging көшірмесін іске қосып, бір нақты сценарийден өтіңіз.
  5. Кезеңдердің ұзақтығы мен мәселелерді жазып, runbook-ты жаңартыңыз.
set -a; . ./restic.env; set +a
restic snapshots --latest 3
time restic restore latest --target /restore --verify
sudo -u postgres psql -f /restore/var/backups/postgresql/globals.sql
sudo -u postgres createdb app
time sudo -u postgres pg_restore --jobs=4 --dbname=app /restore/var/backups/postgresql/app
sudo -u postgres psql -d app -c "SELECT max(created_at) FROM orders;"

--verify қалпына келтірілген файлдарды қайта оқып, снапшотпен салыстырады. Соңғы сұрау қалпына келтіру кезінде іс жүзінде қанша дерек жоғалғанын көрсетеді. Рөлдер бұрыннан бар екені туралы қателер күтілетін жағдай. Сондай-ақ ең жиі кездесетін нақты сұрау, яғни бір файлды --include /etc/nginx/nginx.conf арқылы қалпына келтіруді де жаттықтырыңыз.

Жалпы уақытты RTO-мен салыстырыңыз. Жиі кездесетін тосын жағдайлар: жетіспейтін тіркелгі деректері, тек істен шыққан серверде ғана болған құпиясөз, индекстердің баяу қайта құрылуы және TLS кілттері немесе сақталатын жолдардан тыс .env сияқты ұмытылған файлдар.

restic, BorgBackup немесе файлдық жүйе снапшоттары

Көп схема бұл тәсілдерді біріктіреді: жылдам жергілікті кері қайтару үшін ZFS, Btrfs немесе LVM снапшоты, оған қоса сыртқы орындағы файлдық сақтық көшірмелер. BorgBackup 1.4 қазіргі тұрақты тармақ болып табылады.

Қасиет restic BorgBackup 1.4 Файлдық жүйе снапшоттары
Сақтау орны Жергілікті, SFTP, REST сервер, S3-үйлесімді және басқа бұлттық қоймалар Жергілікті немесе SSH арқылы, серверде Borg болғаны жақсы Сол пул; сыртқы көшірме үшін zfs send сияқты репликация керек
Шифрлау Әрқашан қосулы Репозиторий құрылғанда таңдалады, міндетті емес Қоймаға байланысты
Бұзылған клиент rest-server --append-only, бакеттің object lock қорғауы borg serve --append-only Тек бөлек басқарылатын жүйеге репликацияланғанда қорғалған
Дерекқор келісімділігі Дамптар керек Дамптар керек Деректер мен WAL бір атомарлық снапшотта болса, crash-consistent
Қалпына келтіру Бір файлдан бүкіл ағашқа дейін, FUSE арқылы тіркеу Бір файлдан бүкіл ағашқа дейін, FUSE арқылы тіркеу Бүкіл томды кері қайтару немесе тіркелген снапшоттан көшіру
Клиенттер Linux, macOS, Windows, BSD Linux, macOS, BSD; Windows тек эксперименттік WSL немесе Cygwin арқылы Файлдық жүйеге байланысты

Сол пулдағы снапшот сәтсіз деплойдан қорғайды, бірақ пулдың істен шығуынан немесе хосттың бұзылуынан қорғамайды, сондықтан ол өз бетінше 3-2-1 мағынасындағы көшірме емес.

Тексеру тізімі

  • RPO мен RTO жазылған және сервис иесімен келісілген.
  • Үш көшірме бар, біреуі сыртқы орында, біреуі өзгермейтін немесе append-only.
  • Құпиясөз, репозиторий URL-і және тіркелгі деректері құпиясөз менеджерінде және офлайн сақталған.
  • Жұмыс істеп тұрған дерекқор каталогтары шығарылған, ал дамптар қосылған.
  • PostgreSQL жаһандық объектілері бар pg_dump немесе тексерілген pg_basebackup арқылы қамтылған.
  • Таймер Persistent=true қолданады, ал OnFailure= өңдеушісі сынақта кемінде бір рет іске қосылған.
  • Heartbeat сәтті іске қосу болмаса, ал сыртқы тексеру снапшоттар ескірсе, дабыл қағады.
  • forget --prune және check --read-data-subset апта сайын орындалады.
  • Сервердің тіркелгі деректері құлыпталған нұсқаларды жоя алмайды.
  • Уақыты өлшенген қалпына келтіру жаттығуы осы тоқсанда өтті, ал runbook оның қорытындыларын көрсетеді.

Басқа жарияланымдар