Русский
Русский
English
Статистика
Реклама

Backup

Чего ожидать от бета-версии Proxmox Backup Server

15.07.2020 12:10:08 | Автор: admin

10 июля 2020 года австрийская компания Proxmox Server Solutions GmbH представила публичную бета-версию нового решения по резервному копированию.

Мы уже рассказывали, как использовать штатные методы бэкапа в Proxmox VE и выполнять инкрементальный бэкап с помощью стороннего решения Veeam Backup & Replication. Теперь же, с появлением Proxmox Backup Server (PBS) процесс резервного копирования должен стать удобнее и проще.


Распространяется PBS на условиях лицензии GNU AGPL3, разработанной Фондом свободного программного обеспечения (Free Software Foundation). Это позволит без проблем использовать и модифицировать ПО под свои нужды.


Инсталляция PBS практически ничем не отличается от стандартного процесса установки Proxmox VE. Точно так же задаем FQDN, сетевые настройки и другие требуемые данные. После завершения инсталляции можно перезагрузить сервер и зайти в веб-интерфейс, используя ссылку вида:

https://<IP-address or hostname>:8007

Основное предназначение PBS выполнение резервного копирования виртуальных машин, контейнеров и физических хостов. Для выполнения этих операций предоставляется соответствующий RESTful API. Поддерживается три основных типа резервного копирования:

  • vm копирование виртуальной машины;
  • ct копирование контейнера;
  • host копирование хоста (реального или виртуальной машины).

Структурно бэкап виртуальной машины представляет собой набор архивов. Каждый дисковый накопитель и конфигурационный файл виртуальной машины упаковывается в отдельный архив. Такой подход позволяет ускорить процесс частичного восстановления (например, нужно вытащить только отдельную директорию из бэкапа), поскольку отпадает необходимость сканирования архива целиком.

Помимо привычного формата img для хранения объемных данных и образов виртуальных машин, появился формат pxar (Proxmox File Archive Format), предназначенный для хранения файлового архива. Он спроектирован таким образом, чтобы обеспечить высокую производительность для выполнения ресурсоемкого процесса дедупликации данных.

Если посмотреть на типичный набор файлов внутри снапшота, то вместе с файлом .pxar еще можно обнаружить файлы catalog.pcat1 и index.json. Первый хранит список всех файлов внутри бэкапа и предназначен для быстрого поиска нужных данных. Второй же, помимо списка, хранит размер и контрольную сумму каждого файла и предназначен для проверки консистентности.

Управляется сервер традиционно с помощью веб-интерфейса и/или утилит командной строки. Подробные описания команд CLI приведены в соответствующей документации. Веб-интерфейс лаконичен и знаком всем, кто хоть раз использовал Proxmox VE.


В PBS можно настроить задания синхронизации локальных и удаленных хранилищ данных, поддержку ZFS, шифрование AES-256 на стороне клиента и прочие полезные опции. Судя по дорожной карте, скоро появится возможность импорта существующих бэкапов, хоста с Proxmox VE или Proxmox Mail Gateway целиком.

Также с помощью PBS можно организовать бэкап любого хоста на базе Debian, установив клиентскую часть. Добавляем репозитории в /etc/apt/sources.list:

deb http://ftp.debian.org/debian buster main contribdeb http://ftp.debian.org/debian buster-updates main contrib# security updatesdeb http://security.debian.org/debian-security buster/updates main contrib

Обновляем список ПО:

apt-get update

Устанавливаем клиент:

apt-get install proxmox-backup-client

В дальнейшем появится поддержка и других дистрибутивов Linux.

Пощупать бета-версию PBS можно уже сейчас, готовый образ есть на официальном сайте. На форуме Proxmox также появилась соответствующая ветка обсуждений. Исходный код также доступен всем желающим.

Подводим итоги. Первая публичная бета-версия PBS уже сейчас демонстрирует набор весьма полезных возможностей и заслуживает самого пристального внимания. Надеемся, что будущий релиз нас не разочарует.
Подробнее..

Резервное копирование конфигурации ресурсов в Kubernetes

19.02.2021 12:19:30 | Автор: admin

Администраторы кластеров kubernetes сталкиваются с задачей сохранить конфигурацию ресурсов из пространства имен и перенести в другой кластер, или же сделать резервную копию нестабильной тестовой площадки. С этой задачей без проблем справляется бегло написанный в терминале односторчный скрипт с утилитой kubectl, но что если надоело каждый раз тратить пару минут времени на очередное написание скрипта. Так и появилась утилита kube-dump, по сути это утилита которая умеет только одно - дампить ресурсы кластера.

пример работы утилиты для сохранения всех ресурсов одного неймспейсапример работы утилиты для сохранения всех ресурсов одного неймспейса

При помощи данной утилиты вы можете сохранить ресурсы кластера в виде чистого yaml манифеста без лишних метаданных.

Ключевые особенности:

  • Сохранение выполняется только для тех ресурсов, к которым у вас есть доступ на чтение.

  • На вход можно передать перечень пространств имен, в противном случае будут использованы все доступные для вашего контекста.

  • К сохранению подлежат как ресурсы пространств имен, так и глобальные ресурсы кластера.

  • Использовать утилиту можно локально как обычный скрипт или запустить в контейнере или в кластере kubernetes к примеру как CronJob.

  • Может создавать архивы и ротировать их за собой.

  • Может фиксировать состояние в git репозитории и отправлять в удаленный репозиторий.

  • Вы можете указать конкретный перечень ресурсов кластера для выгрузки.

Конфигурацию для утилиты передаем с помощью аргументов командной строки или при помощью экспортированных переменных окружений или прочитанных из .env файла.

Начало работы

Необходимый минимум для запуска это наличие установленного kubectl и подключенного в него кластера, а также утилит jq и yq. Более подробно описано на странице документации по локальному запуску, а аргументы командной строки описаны здесь или же доступны по ключу --help.

Запустим утилиту для сохранения всех ресурсов кластера:

./kube-dump dump

Если вы не хотите разбираться с установкой зависимостей вы можете воспользоваться контейнером. Подробнее про работу с контейнером описано в этой статье.

Получим свежий образ и запустим утилиту для сохранения пространств имен dev и prod в смонтированную директорию /dump, где для доступа к кластеру мы пробрасываем в контейнер свой конфигурационный файл от kubectl.

docker pull woozymasta/kube-dump:latestdocker run --tty --interactive --rm \  --volume $HOME/.kube:/.kube \  --volume $HOME/dump:/dump \  woozymasta/kube-dump:latest \  dump-namespaces -n dev,prod -d /dump --kube-config /.kube/config

Установка CronJob в кластер

Рассмотрим более сложный пример когда контейнер будет запущен в кластере как CronJob который будет каждую ночь снимать дамп ресурсов и фиксировать правки в git репозитории с последующей отправкой в удаленный репозиторий. Пример подробно описан в статье.

В данном примере подразумевается что у вас есть доступ к управлению ролями кластера, потому что мы будем использовать для работы ServiceAccount и стандартную роль view. Если же вам не подходит глобальная роль view, вы можете создать свою роль для пространства имен или кластера, в помощь можете взять этот пример.

Создадим пространство имен где будет работать наш CronJob и ServiceAccount который будет использовать ClusterRoleBinding для роли view:

kubectl create ns kube-dumpkubectl -n kube-dump apply -f \  https://raw.githubusercontent.com/WoozyMasta/kube-dump/master/deploy/cluster-role-view.yaml

В качестве примера будем использовать авторизацию в GitLab по OAuth токену, по этому создадим секрет с адресом репозитория и токеном для авторизации:\

kubectl -n kube-dump create secret generic kube-dump \  --from-literal=GIT_REMOTE_URL=https://oauth2:$TOKEN@corp-gitlab.com/devops/cluster-bkp.git

Перед установкой настройте переменные окружения под ваши нужды, в примере по умолчанию установлен режим копирования пространств имен dev и prod с последующей фиксацией изменений в ветке my-cluster и отправкой в удаленный репозиторий.

Настроим CronJob в которм укажем периодичность запуска задания:

spec:  schedule: "0 1 * * *"

Или же установите пример как есть и после отредактируйте его:

kubectl -n kube-dump apply -f \  https://github.com/WoozyMasta/kube-dump/blob/master/deploy/cronjob-git-token.yamlkubectl -n kube-dump edit cronjobs.batch kube-dump

Планы по дальнейшему развитию

  • Реализовать отправку дампов в s3 совместимое хранилище;

  • Отправка уведомлений по электронной почте и через веб-хук;

  • Git-crypt для шифрования чувствительных данных;

  • Автодополнение в Bash/Zsh;

  • Поддержка OpenShift.

Также буду рад Вашим комментариям и предложениям с идеями и критикой.

Ссылки

Подробнее..

Из песочницы WAL-G бэкапы и восстановление СУБД PostgreSQL

14.06.2020 14:16:56 | Автор: admin
Уже давно известно, что делать бэкапы в SQL-дампы (используя pg_dump или pg_dumpall) не самая хорошая идея. Для резервного копирования СУБД PostgreSQL лучше использовать команду pg_basebackup, которая делает бинарную копию WAL-журналов. Но когда вы начнёте изучать весь процесс создания копии и восстановления, то поймёте что нужно написать как минимум пару трёхколёсных велосипедов, чтобы всё это работало и не вызывало у вас боль как сверху, так и снизу. Дабы облегчить страдания был разработан WAL-G.

WAL-G это инструмент, написанный на Golang для резервного копирования и восстановления PostgreSQL баз данных (а с недавнего времени и MySQL/MariaDB, MongoDB и FoundationDB). Он поддерживает работу с хранилищами Amazon S3 (и аналогами, например, Yandex Object Storage), а также Google Cloud Storage, Azure Storage, Swift Object Storage и просто с файловой системой. Вся настройка сводится к простым шагам, но из-за того что статьи о нём разрозненны по интернету нет полного how-to мануала, который бы включал все шаги от и до (на Хабре есть несколько постов, но многие моменты там упущены).

postgresql backup

Данная статья написана в первую очередь чтобы систематизировать свои знания. Я не являюсь DBA и где-то могу выражаться обывательско-разработческим языком, поэтому приветствуются любые исправления!

Отдельно отмечу что всё нижеприведенное актуально и проверено для PostgreSQL 12.3 на Ubuntu 18.04, все команды должны выполняться от привилегированного пользователя.

Установка


В момент написания данной статьи стабильная версия WAL-G v0.2.15 (март 2020). Её мы и будем использовать (но если вы захотите самостоятельно собрать его из master-ветки, то в репозитории на github есть все инструкции для этого). Для скачивания и установки нужно выполнить:

#!/bin/bashcurl -L "https://github.com/wal-g/wal-g/releases/download/v0.2.15/wal-g.linux-amd64.tar.gz" -o "wal-g.linux-amd64.tar.gz"tar -xzf wal-g.linux-amd64.tar.gzmv wal-g /usr/local/bin/

После этого нужно сконфигурировать вначале WAL-G, а потом сам PostgreSQL.

Настройка WAL-G


Для примера хранения бэкапов будет использоваться Amazon S3 (потому что он ближе к моим серверам и его использование обходится очень дёшево). Для работы с ним нужен s3-бакет и ключи доступа.

Во всех предыдущих статьях о WAL-G использовалось конфигурирование с помощью переменных окружения, но с этого релиза настройки можно расположить в .walg.json файле в домашней директории пользователя postgres. Для его создания выполним следующий bash-скрипт:

#!/bin/bashcat > /var/lib/postgresql/.walg.json << EOF{    "WALG_S3_PREFIX": "s3://your_bucket/path",    "AWS_ACCESS_KEY_ID": "key_id",    "AWS_SECRET_ACCESS_KEY": "secret_key",    "WALG_COMPRESSION_METHOD": "brotli",    "WALG_DELTA_MAX_STEPS": "5",    "PGDATA": "/var/lib/postgresql/12/main",    "PGHOST": "/var/run/postgresql/.s.PGSQL.5432"}EOF# обязательно меняем владельца файла:chown postgres: /var/lib/postgresql/.walg.json

Немного поясню по всем параметрам:

  • WALG_S3_PREFIX путь к вашему S3-бакету куда будут заливаться бэкапы (можно как в корень, так и в папку);
  • AWS_ACCESS_KEY_ID ключ доступа в S3 (в случае восстановления на тестовом сервере данные ключи должны иметь ReadOnly Policy! Об этом подробнее написано в разделе про восстановление);
  • AWS_SECRET_ACCESS_KEY секретный ключ в хранилище S3;
  • WALG_COMPRESSION_METHOD метод компрессии, лучше использовать Brotli (так как это золотая середина между итоговым размером и скоростью сжатия/разжатия);
  • WALG_DELTA_MAX_STEPS количество дельт до создания полного бэкапа (позволяют экономить время и размер загружаемых данных, но могут чуть замедлить процесс восстановления, поэтому не желательно использовать большие значения);
  • PGDATA путь к директории с данными вашей базы (можно узнать, выполнив команду pg_lsclusters);
  • PGHOST подключение к базе, при локальном бэкапе лучше делать через unix-socket как в этом примере.

Остальные параметры можно посмотреть в документации: https://github.com/wal-g/wal-g/blob/v0.2.15/PostgreSQL.md#configuration.

Настройка PostgreSQL


Чтобы архиватор внутри базы сам заливал WAL-журналы в облако и восстанавливался из них (в случае необходимости) нужно задать несколько параметров в конфигурационном файле /etc/postgresql/12/main/postgresql.conf. Только для начала вам нужно убедиться, что никакие из нижеприведенных настроек не заданы в какие-то другие значения, чтобы при перезагрузке конфигурации СУБД не упала. Добавить эти параметры можно с помощью:

#!/bin/bashecho "wal_level=replica" >> /etc/postgresql/12/main/postgresql.confecho "archive_mode=on" >> /etc/postgresql/12/main/postgresql.confecho "archive_command='/usr/local/bin/wal-g wal-push \"%p\" >> /var/log/postgresql/archive_command.log 2>&1' " >> /etc/postgresql/12/main/postgresql.confecho archive_timeout=60 >> /etc/postgresql/12/main/postgresql.confecho "restore_command='/usr/local/bin/wal-g wal-fetch \"%f\" \"%p\" >> /var/log/postgresql/restore_command.log 2>&1' " >> /etc/postgresql/12/main/postgresql.conf# перезагружаем конфиг через отправку SIGHUP сигнала всем процессам БДkillall -s HUP postgres

Описание устанавливаемых параметров:

  • wal_level сколько информации писать в WAL журналы, replica писать всё;
  • archive_mode включение загрузки WAL-журналов используя команду из параметра archive_command;
  • archive_command команда, для архивации завершённого WAL-журнала;
  • archive_timeout архивирование журналов производится только когда он завершён, но если ваш сервер мало изменяет/добавляет данных в БД, то имеет смысл выставить тут лимит в секундах, по истечению которого команда архивации будет вызвана принудительно (у меня интенсивная запись в базу каждую секунду, поэтому я отказался от установки этого параметра в продакшене);
  • restore_command команда восстановления WAL-журнала из бэкапа, будет использоваться в случае если в полном бэкапе (base backup) будет недоставать последних изменений в БД.

Подробнее обо всех этих параметрах можно прочитать в переводе официальной документации: https://postgrespro.ru/docs/postgresql/12/runtime-config-wal.

Настройка расписания резервного копирования


Как ни крути, но самым удобным способом для запуска является cron. Именно его мы и настроим для создания резервных копий. Начнём с команды создания полного бэкапа: в wal-g это аргумент запуска backup-push. Но для начала лучше выполнить эту команду вручную от пользователя postgres, чтобы убедиться что всё хорошо (и нет каких-то ошибок доступа):

#!/bin/bashsu - postgres -c '/usr/local/bin/wal-g backup-push /var/lib/postgresql/12/main'

В аргументах запуска указан путь к директории с данными напоминаю что его можно узнать, выполнив pg_lsclusters.

Если всё прошло без ошибок и данные загрузились в хранилище S3, то далее можно настроить периодический запуск в crontab:
#!/bin/bashecho "15 4 * * *    /usr/local/bin/wal-g backup-push /var/lib/postgresql/12/main >> /var/log/postgresql/walg_backup.log 2>&1" >> /var/spool/cron/crontabs/postgres# задаем владельца и выставляем правильные права файлуchown postgres: /var/spool/cron/crontabs/postgreschmod 600 /var/spool/cron/crontabs/postgres

В данном примере процесс бэкапа запускается каждый день в 4:15 утра.

Удаление старых резервных копий


Скорее всего вам не нужно хранить абсолютно все бэкапы с мезозойской эры, поэтому будет полезно периодически подчищать ваше хранилище (как полные бэкапы, так и WAL-журналы). Мы сделаем это всё также через cron задачу:

#!/bin/bashecho "30 6 * * *    /usr/local/bin/wal-g delete before FIND_FULL $(date -d '-10 days' '+%FT%TZ') --confirm >> /var/log/postgresql/walg_delete.log 2>&1" >> /var/spool/cron/crontabs/postgres# ещё раз задаем владельца и выставляем правильные права файлу (хоть это обычно это и не нужно повторно делать)chown postgres: /var/spool/cron/crontabs/postgreschmod 600 /var/spool/cron/crontabs/postgres

Cron будет выполнять эту задачу каждый день в 6:30 утра, удаляя всё (полные бэкапы, дельты и WALы) кроме копий за последние 10 дней, но оставит как минимум один бэкап до указанной даты, чтобы любая точка после даты попадала в PITR.

Восстановление из резервной копии


Ни для кого не секрет что залог здоровой базы в периодическом восстановлении и проверке целостности данных внутри. Как восстановиться с помощью WAL-G расскажу в этом разделе, а о проверках поговорим после.

Отдельно стоит отметить что для восстановления на тестовом окружении (всё то, что не production) нужно использовать Read Only аккаунт в S3, чтобы случайно не перезаписать бэкапы. В случае с WAL-G нужно задать пользователю S3 следующие права в Group Policy (Effect: Allow): s3:GetObject, s3:ListBucket, s3:GetBucketLocation. И, конечно, предварительно не забыть выставить archive_mode=off в файле настроек postgresql.conf, чтобы ваша тестовая база не захотела сбэкапиться по-тихому.

Восстановление производится лёгким движением руки с удалением всех данных PostgreSQL (в том числе пользователей), поэтому, пожалуйста, будьте предельно аккуратны когда будете запускать следующие команды.

#!/bin/bash# если есть балансировщик подключений (например, pgbouncer), то вначале отключаем его, чтобы он не нарыгал ошибок в логservice pgbouncer stop# если есть демон, который перезапускает упавшие процессы (например, monit), то останавливаем в нём процесс мониторинга базы (у меня это pgsql12)monit stop pgsql12# или останавливаем мониторинг полностьюservice monit stop# останавливаем саму базу данныхservice postgresql stop# удаляем все данные из текущей базы (!!!); лучше предварительно сделать их копию, если есть свободное место на дискеrm -rf /var/lib/postgresql/12/main# скачиваем резервную копию и разархивируем еёsu - postgres -c '/usr/local/bin/wal-g backup-fetch /var/lib/postgresql/12/main LATEST'# помещаем рядом с базой специальный файл-сигнал для восстановления (см. https://postgrespro.ru/docs/postgresql/12/runtime-config-wal#RUNTIME-CONFIG-WAL-ARCHIVE-RECOVERY ), он обязательно должен быть создан от пользователя postgressu - postgres -c 'touch /var/lib/postgresql/12/main/recovery.signal'# запускаем базу данных, чтобы она инициировала процесс восстановленияservice postgresql start

Для тех, кто хочет проверять процесс восстановления ниже подготовлен небольшой кусок bash-магии, чтобы в случае проблем в восстановлении скрипт упал с ненулевым exit code. В данном примере делается 120 проверок с таймаутом в 5 секунд (всего 10 минут на восстановление), чтобы узнать удалился ли сигнальный файл (это будет означать что восстановление прошло успешно):

#!/bin/bashCHECK_RECOVERY_SIGNAL_ITER=0while [ ${CHECK_RECOVERY_SIGNAL_ITER} -le 120 ]do    if [ ! -f "/var/lib/postgresql/12/main/recovery.signal" ]    then        echo "recovery.signal removed"        break    fi    sleep 5    ((CHECK_RECOVERY_SIGNAL_ITER+1))done# если после всех проверок файл всё равно существует, то падаем с ошибкойif [ -f "/var/lib/postgresql/12/main/recovery.signal" ]then    echo "recovery.signal still exists!"    exit 17fi

После успешного восстановления не забудьте запустить обратно все процессы (pgbouncer/monit и тд).

Проверка данных после восстановления


Обязательно нужно проверить целостность базы после восстановления, чтобы не возникло ситуации с побитой/кривой резервной копией. И лучше делать это с каждым созданным архивом, но где и как зависит только от вашей фантазии (можно поднимать отдельные сервера на почасовой оплате или запускать проверку в CI). Но как минимум необходимо проверять данные и индексы в базе.

Для проверки данных достаточно прогнать их через дамп, но лучше чтобы при создании базы у вас были включены контрольные суммы (data checksums):

#!/bin/bashif ! su - postgres -c 'pg_dumpall > /dev/null'then    echo 'pg_dumpall failed'    exit 125fi

Для проверки индексов существует модуль amcheck, sql-запрос к нему возьмём из тестов WAL-G и вокруг выстроим небольшую логику:

#!/bin/bash# добавляем sql-запрос для проверки в файл во временной директорииcat > /tmp/amcheck.sql << EOFCREATE EXTENSION IF NOT EXISTS amcheck;SELECT bt_index_check(c.oid), c.relname, c.relpagesFROM pg_index iJOIN pg_opclass op ON i.indclass[0] = op.oidJOIN pg_am am ON op.opcmethod = am.oidJOIN pg_class c ON i.indexrelid = c.oidJOIN pg_namespace n ON c.relnamespace = n.oidWHERE am.amname = 'btree'AND c.relpersistence != 't'AND i.indisready AND i.indisvalid;EOFchown postgres: /tmp/amcheck.sql# добавляем скрипт для запуска проверок всех доступных баз в кластере# (обратите внимание что переменные и запуск команд  экранированы)cat > /tmp/run_amcheck.sh << EOFfor DBNAME in \$(su - postgres -c 'psql -q -A -t -c "SELECT datname FROM pg_database WHERE datistemplate = false;" ')do    echo "Database: \${DBNAME}"    su - postgres -c "psql -f /tmp/amcheck.sql -v 'ON_ERROR_STOP=1' \${DBNAME}" && EXIT_STATUS=\$? || EXIT_STATUS=\$?    if [ "\${EXIT_STATUS}" -ne 0 ]    then        echo "amcheck failed on DB: \${DBNAME}"        exit 125    fidoneEOFchmod +x /tmp/run_amcheck.sh# запускаем скрипт/tmp/run_amcheck.sh > /tmp/amcheck.log# для проверки что всё прошло успешно можно проверить exit code или grepнуть ошибкуif grep 'amcheck failed' "/tmp/amcheck.log"then    echo 'amcheck failed: '    cat /tmp/amcheck.log    exit 125fi

Резюмируя


Выражаю благодарность Андрею Бородину за помощь в подготовке публикации и отдельное спасибо за его вклад в разработку WAL-G!

На этом данная заметка подошла к концу. Надеюсь что смог донести легкость настройки и огромный потенциал для применения этого инструмента у вас в компании. Я очень много слышал о WAL-G, но никак не хватало времени сесть и разобраться. А после того как внедрил его у себя из меня вышла эта статья.

Отдельно стоит заметить, что WAL-G также может работать со следующими СУБД:

Подробнее..

Перевод Какие возможности появились у утилиты rdiff-backup благодаря миграции на Python 3

22.09.2020 10:23:41 | Автор: admin
В процессе миграции на Python 3 разработчики утилиты rdiff-backup усовершенствовали её, добавив много новых фич.



В марте 2020 года вышел второй крупный релиз утилиты rdiff-backup. Второй за 11 лет. Во многом, это объясняется прекращением поддержки Python 2. Разработчики решили совместить приятное с полезным и доработали функционал утилиты.

Около 20 лет она верой и правдой служит Linux-сообществу помогает делать бэкапы на локальных и удалённых машинах, скажем так без лишней головной боли. Секрет прост: утилита позволяет делать бэкап только тех файлов, которые изменились с прошлого резервного копирования. Для более краткого обозначения этого процесса существует термин инкрементальное резервное копирование.

Второе рождение rdiff-backup пережила благодаря команде энтузиастов, которую возглавили Эрик Зольф и Патрик Дюфресне из IKUS Software, а также Отто Кекяляйнен из Seravo.


Новые фичи


Проект переехал в новый репозиторий и предлагает всем желающим стать контрибьюторами. Команда внесла в новый релиз все полезные доработки, которые появлялись в течение прошедших 11 лет. Среди них поддержка разрежённых файлов и баг-фиксы для жёстких ссылок.

Автоматизация на базе Travis CI


Другое важнейшее улучшение это конвейер CI/CD на базе распределённого веб-сервиса Travis CI. Теперь пользователи смогут запускать rdiff-backup в различных тестовых средах без риска сломать работающий проект. Конвейер CI/CD позволит выполнять автоматизированную сборку и доставку для всех основных платформ.

Простая установка с помощью yum и apt


Новая версия работает на большинстве ОС семейства Linux Fedora, Red Hat, Elementary, Debian и многих других. Разработчики постарались подготовить все необходимые открытые репозитории для лёгкого доступа к утилите. Установить rdiff-backup можно с помощью менеджера пакетов или пошаговой инструкции на GitHub-странице проекта.

Новый дом


Сайт проекта переехал с Savannah на GitHub Pages (rdiff-backup.net), разработчики обновили контент и дизайн сайта.

Как работать с rdiff-backup


Если вы познакомились с rdiff-backup только сейчас, вы удивитесь, насколько он прост в использовании. Разработчики позаботились о том, чтобы вы чувствовали себя комфортно: по их мнению, подобные утилиты не должны отвлекать своей сложностью от таких важных процессов, как подготовка бэкапа или планирование восстановления данных.

Бэкап


Чтобы запустить бэкап на локальном диске (например, USB), введите команду rdiff-backup, затем имя источника (откуда будете копировать файлы) и путь к каталогу, в который вы планируете сохранить их.

Например, чтобы сделать бэкап на локальном диске с именем my_backup_drive, введите:

$ rdiff-backup /home/tux/ /run/media/tux/my_backup_drive/

Для сохранения файлов во внешнем хранилище введите путь к удалённому серверу вместе со знаком ::

$ rdiff-backup /home/tux/ tux@example.com::/my_backup_drive/

Вероятно, ещё вам потребуются SSH ключи для доступа на сервер.

Восстановление файлов из бэкапа


Бэкапы делают потому, что иногда какие-то файлы имеют обыкновение, скажем так теряться. Утилита позволяет достаточно просто восстанавливать файлы из бэкапа. Но всё-таки по щелчку пальцем это сделать не получится.

Тут нам на помощь придут команды копирования cp для локального диска и scp для удалённого сервера.

Для локального диска нужно написать, например, такое:

$ cp _run_media/tux/my_backup_drive/Documents/example.txt \ ~/Documents

Для удалённого сервера:

$ scp tux@example.com::/my_backup_drive/Documents/example.txt \ ~/Documents

У команды rdiff-backup есть опции, которые позволяют настроить параметры копирования. Например, --restore-as-of даёт возможность указать, какую версию файла нужно восстановить.

Допустим, вы хотите восстановить файл в том состоянии, в котором он был 4 дня назад:

$ rdiff-backup --restore-as-of 4D \ /run/media/tux/foo.txt ~/foo_4D.txt

Или, может быть, вам нужна последняя версия:

$ rdiff-backup --restore-as-of now \ /run/media/tux/foo.txt ~/foo_4D.txt

Вы видите, что работать с rdiff-backup достаточно легко. У этой утилиты много настроек и возможностей. Например, вы можете исключать отдельные файлы из списка для бэкапа, делать резервное копирование с одного удалённого сервера на другой и так далее. С описанием всех её возможностей вы можете ознакомиться на странице с документацией.



На правах рекламы


Наши эпичные серверы используют only NVMe сетевое хранилище с тройной репликацией данных, надёжность на высоте! Вы можете использовать сервер не только для размещения своих проектов и любой информации, но и для хранения бэкапов важных данных с локальных машин или других серверов. К тому же, есть возможность делать резервные копии образа виртуального сервера в автоматическом или ручном режиме.

Подробнее..

Настраиваем Restic с systemd на Linux

31.01.2021 02:12:47 | Автор: admin

Restic хорошо известная программа для резервного копирования. Она достаточно проста, чтобы переноситься на любую ОС, и, вероятно, поэтому с ней не прилагается полноценный пример настройки на среднестатистической Linux-системе. Исправим это данным постом.


Поставим задачу следующим образом:


  1. Автоматический бэкап запускается ежедневно.
  2. Бэкап хранит только важные файлы и данные.
  3. Бэкап также включает в себя содержимое баз PostgreSQL, которое можно восстановить psql -f.

TL;DR поста

Пишем два юнита / таймера для systemd, запускаем restic под выделенным пользователем с CAP_DAC_READ_SEARCH, для PostgreSQL архивируем результат pg_dumpall.


Здесь предполагается, что бэкап производится на машине с Ubuntu Server 20.04 и выполняется на rest-server, работающий на 192.168.1.200. Тем не менее, конфигурация тривиально адаптируется к любому облачному провайдеру. Также предполагается, что репозиторий уже проинициализирован командой restic -r rest:http://192.168.1.200/your-repo/ init.


Бэкапим файлы/директории


Выполнять ПО с правами суперпользователя без особой надобности нежелательно, поэтому создадим для наших задач отдельного пользователя restic без группы и командной оболочки:


# useradd -m -N -s /usr/sbin/nologin restic

Нам понадобится следующий сервис systemd с параметром и таймер к нему:


/etc/systemd/system/restic@.service:


[Unit]# юнит активируется с параметром после @, то есть в#   systemctl start restic@your-repo.service# %I означает "your-repo"Description=Restic backup on %IAfter=syslog.targetAfter=network-online.target[Service]Type=oneshotUser=restic# читать список файлов к бэкапу будем из /etc/restic/your-repo.filesExecStart=/usr/local/bin/restic backup --files-from /etc/restic/%I.files# считаем репозиторий и пароль из /etc/restic/your-repo.envEnvironmentFile=/etc/restic/%I.env# выполняем restic с capability DAC_READ_SEARCH, дающей право# обходить права доступа ФС в Linux, это нужно для бэкапа# директорий, которые могут читать только другие пользователи# или суперпользовательAmbientCapabilities=CAP_DAC_READ_SEARCH[Install]WantedBy=multi-user.target

/etc/systemd/system/restic@.timer:


[Unit]# таймер, будучи запущенным с параметром после @# (restic@your-repo.timer), запустит restic@your-repo.serviceDescription=Run Restic at 12:00 AM[Timer]# запускаем restic ежедневно в 12 часов ночиOnCalendar=*-*-* 12:00:00[Install]WantedBy=timers.target

Адрес репозитория и пароль от него подаются на вход через файл с переменными среды в /etc/restic/your-repo.env. systemd читает их при старте юнита с правами root, поэтому имеет смысл задать разрешения директории /etc/restic/ соответствующим образом (т.е. 700 и владельцем установить root):


RESTIC_PASSWORD=your_repo_passwordRESTIC_REPOSITORY=rest:http://192.168.1.200/your-repo/

Нам также понадобится список файлов/директорий к бэкапу в /etc/restic/your-repo.files:


/var/lib/docker/etc/postgresql/etc/restic...

Бэкап PostgreSQL


Restic позволяет подачу данных для бэкапа через стандартный вход, так что мы можем скормить ему дамп, полученный pg_dumpall. Так как systemd запускает указанное директивой ExecStart вызовом execve(3), для использования перенаправления вывода и сжатия нам понадобится отдельный скрипт /usr/local/bin/pgdump.sh:


#!/usr/bin/env bashset -euo pipefail/usr/bin/sudo -u postgres pg_dumpall --clean \    | gzip --rsyncable \    | /usr/local/bin/restic backup --host $1 --stdin \        --stdin-filename postgres-$1.sql.gz

Сервис /etc/systemd/system/restic-pg@.service достаточно тривиален:


[Unit]Description=Restic PostgreSQL backup on %IAfter=syslog.targetAfter=network-online.targetAfter=postgresql.serviceRequires=postgresql.service[Service]Type=oneshotUser=resticExecStart=/usr/local/bin/pgdump.sh %IEnvironmentFile=/etc/restic/%I.env[Install]WantedBy=multi-user.target

Таймер /etc/systemd/system/restic-pg@.timer не отличается от виденного выше:


[Unit]Description=Run Restic on PostgreSQL at 12:00 AM[Timer]OnCalendar=*-*-* 0:00:00[Install]WantedBy=timers.target

Завершаем


Запустим таймеры и включим их автозагрузку:


# systemctl enable --now restic@your-repo.timer restic-pg@your-repo.timer

Проверим, работает ли построенная система:


# systemctl start restic@your-repo.service# systemctl start restic-pg@your-repo.service

Данный набор юнитов позволяет бэкапиться в неограниченное количество репозиториев, нужно лишь создать соответствующие /etc/restic/repo-name.{env,files}.


Ссылки


Подробнее..

Делаем откаты БД в msi. История про создание резервных копий и удаление БД в WixSharp

31.03.2021 14:23:38 | Автор: admin

При работе с базами данных (БД) в установщике, про который мы уже писали в прошлой статье (Пишем установщик на WixSharp. Плюшки, проблемы, возможности), в первую очередь, были реализованы проверка доступности СУБД по логину/паролю, добавление и обновление собственно БД (в нашем приложении их несколько) накатыванием миграций, a также добавление пользователей. Все это реализовано для двух СУБД Microsoft SqlServer и PostgreSql.
На первый взгляд этого достаточно, но иногда есть необходимость удалять БД и пользователей, а это влечет за собой создание резервных копий. Сразу выявили две необходимые задачи:

1.Удаление БД и пользователей при откате приложения в случае ошибки при первичной установке. При установке приложения, если возникает ошибка, происходил откат всех настроек, кроме БД. Добавленные БД и пользователи оставались. И, если при боевой эксплуатации, после серии тестирования эта ситуация непредвиденной ошибки маловероятна, то в процессе разработки и доработки установщика, ошибки возникают часто. Их, однозначно, нужно удалять.

2.Создание резервных копий (бэкапов) и удаление БД и пользователей при полном удалении приложения установщиком. Правильно ли оставлять БД после полного удаления приложения? Мы решили, что нет. Но бэкапы, конечно, сохранять нужно.

Из второго пункта возникла новая задача:

3.Создание бэкапов БД при обновлении приложения. Если мы сохраняем бэкапы при удалении, неплохо создавать их и перед обновлением, накатыванием миграций и прочими изменениями. Подстраховка еще никому не мешала. :)

Удаление БД и пользователей при откате приложения в случае ошибки при первичной установке

Если что-то пошло не так и при установке возникли ошибки, мы сразу же позаботились об удалении добавленных директорий и настроек, а также об очистке реестра. Но БД и пользователей также нужно удалять. В WixSharp для этого предусмотрен механизм роллбэка для CustomActions. Для существующего пользовательского действия нужно добавить еще один параметр - название пользовательского действия откатывающего изменения. Необходимо учесть, что данный механизм доступен только для deferred action (отложенных действий).

new ManagedAction(AddDatabaseAction, Return.check, When.After, Step.PreviousAction, Condition.NOT_Installed, DeleteAddedDatabasesAction)             {    UsesProperties = $@"{DATABASE_PROPERTIES}={database_properties}",    Execute = Execute.deferred,   ProgressText = $"Выполняется создание БД {databaseName}"              };

Тут сложностей не возникло и для каждого из СУБД было добавлено выполнение скрипта с удалением БД и пользователей, учитывая в скрипте, что в этот момент база может использоваться.

Создание бэкапов и удаление БД при полном удалении приложения установщиком

В данном случае, необходимо сохранять бэкапы БД, а затем, проводить удаление.

Пользовательское действие для создания бэкапа желательно выполнять до того, как начнут вноситься изменения установщиком, для этого предусмотрен тип immediate. В отличие от deferred, он выполняется сразу. Чтобы данное действие выполнялось только при удалении приложения, укажем условие Condition.BeingUninstalled:

new ManagedAction(BackupDatabaseAction, Return.check, When.After, Step.PreviousAction, Condition.BeingUninstalled){   Execute = Execute.immediate,   UsesProperties = DeleteAddedDatabases,   ProgressText = $"Выполняется скрипт по созданию резервных копий БД" }

Бэкапы решено было сохранять по пути, доступному текущему пользователю. Так как у нас несколько БД, группировку проводили по версии приложения. Название БД формировалось классически, с указанием имени и даты-времени создания.
\Users\{CurrentUser}\AppData\Local\{ApplicationName}\Backups\{VersionNumber}

Создаем этот путь:

Version installedVersion = session.LookupInstalledVersion();  string localUserPath = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData); string backupPath = Path.Combine(localUserPath, "ApplicationName", "Backups", installedVersion.ToString());  Directory.CreateDirectory(backupPath);

И если для Microsoft SqlServer создание бэкапов заключалось в выполнении банального sql-скрипта:

$" USE master" +                    $" BACKUP DATABASE [{databaseName}]" +                    $" TO DISK = N'{path}'" +                    $" WITH NOFORMAT, NOINIT, " +                    $" NAME = N'{backupName}', SKIP, NOREWIND, NOUNLOAD,  STATS = 10 ";

То для PostgreSql одним скриптом не обойтись. Бэкап можно создать запуском команды через командную строку. Понадобится выполнение следующих действий:

  • Запускать pg_dump.exe из соответствующей папки PostgreSql
    C:\Program Files\PostgreSQL\{Version}\bin
    Мы не знаем какая версия установлена у заказчика (обычно в документации мы указываем версию, не ниже которой требуется), какой путь был выбран. Поэтому основной путь с указанием версии получим из реестра:

const string KEY_MASK = @"SOFTWARE\PostgreSQL\Installations\";var currentVersion = Registry.LocalMachine.OpenSubKey(KEY_MASK)?.GetSubKeyNames()[0];if (currentVersion == null){  return ActionResult.Failure;}var keyName = $@"HKEY_LOCAL_MACHINE\{KEY_MASK}{currentVersion}";var postgresPath = (string)Registry.GetValue(keyName, "Base Directory", string.Empty);
  • Проверять, добавлены ли переменные среды для PostgreSql. И в случае необходимости добавить.
    C:\Program Files\PostgreSQL\12\bin
    C:\Program Files\PostgreSQL\12\lib

    Если они отсутствуют, запуск pg_dump будет невозможен.

string binEnv = $@"{postgresPath}\bin";string path = "PATH";var scope = EnvironmentVariableTarget.User;var currentEnvironmentVariable = Environment.GetEnvironmentVariable(name, scope);if (!currentEnvironmentVariable.ToUpper().Contains(binEnv.ToUpper())){  var newEnvironmentVariable = $@"{currentEnvironmentVariable};{binEnv}";  Environment.SetEnvironmentVariable(name, newEnvironmentVariable, scope);}
  • Сформировать аргументы создания бэкапа с помощью командной строки. Здесь необходимо указать параметры подключения, имя БД и путь сохранения бэкапа. Так как ранее нам не приходилось создавать бэкапы для PostgreSql, несложный поиск в интернете показывал примерно такое решение:

    pg_dump -h {host} -p {port} -U {username} {database_name} > {backuppath}

    Если в конфиг файле pg_hba не указано для local connections безусловное подключение trust, то будет требоваться введение пароля. В данном случае, требуется добавление файла .pgpass для текущего пользователя. Тогда, можно добавить в команду атрибут -w и пароль будет считываться оттуда. Так как вновь возникает ситуация, когда мы не знаем, как это организовано у заказчика, была найдена универсальная запись, с помощью которой можно передать все параметры в рамках одной команды:

    pg_dump --dbname=postgresql://{username}:{password}@{address}:{port}
    /{databaseName}-f {backupPath}

После того, как бэкапы созданы, можно удалить БД и пользователей. Здесь будет использоваться то же пользовательское действие DeleteAddedDatabasesAction, что и для отката из пункта 1. Оно будет отложенным и будет запускаться при условии деинсталляции Condition.BeingUninstalled:

new ManagedAction(DeleteAddedDatabasesAction, Return.check, When.After, Step.PreviousAction, Condition.BeingUninstalled){  Execute = Execute.deferred,  UsesProperties = $@"{DATABASE_PROPERTIES}={database_properties}",  ProgressText = $"Выполняется удаление БД {databaseName} и роли {role}" };

Операции с БД при обновлении приложения

При обновлении приложения последовательно происходит удаление, инициализация данных из реестра и установка новой версии. До внесения наших изменений все было хорошо, базы и пользователи оставались жить. Теперь нужно отличать чистое удаление от удаления при обновлении. Решили мы это добавлением новой переменной в реестр, которая инициализируется при обновлении (определяем сравнением версий), а также фиксацией пользовательского действия удаления.

Вывод

Для PostgreSql и Microsoft SqlServer в нашем установщике удалось наладить:

  • механизм удаления БД и пользователей;

  • создание резервных копий в случае полного удаления;

  • создание резервных копий в случае обновления приложения;

  • реализацию отката добавленных БД в случае неудачной первичной установки, либо ее отмене.

    Продолжаем пилить msi ;)

Подробнее..

Настройка continious бекапов PostgreSQL

20.07.2020 14:14:41 | Автор: admin

В данном мануале описывается процесс настройки постоянного (continuous) бекапирования для баз данных PostgreSQL.


В нашей фирме (business to business) под каждого клиента создается свой собственный сервер, на который устанавливается база данных PostgreSQL и наш софт. Таким образом, у нас не единый instance продакшена, а десятки с разными экземплярами базы. Процесс настройки бекапов является частью процесса установки продакшена, а само бекапирование начинается до выхода системы в продакшен и продолжается в течение всего жизненного цикла сотрудничества с клиентом. Спецификацию железа и базового software определяем мы, поэтому все инстансы, как правило, имеют одни и те же версии Linux и PostgreSQL. Изредка этот инвариант нарушается например, где-то по тем или иным причинам может стоять не Ubuntu, а Debian либо PostgreSQL более старой мажорной версии, чем у остальных. В последнем случае нужно быть особенно аккуратным при возникновении сбоя следует иметь ввиду, что восстановление базы должно осуществляться на ту же мажорную версию PostgreSQL, на которой был сделан бекап, так как описываемый подход требует бинарной совместимости файлов данных, которая гарантируется только при переходе между минорными версиями PostgreSQL. Как поступить, если этот инвариант нарушен, также описано в конце данной статьи.


Подразумевается, что у читающего может быть довольно мало знаний как в области бекапов PostgreSQL, так и в сфере работы с Linux (а в особенности с инструментами ее командной строки), поэтому tutorial написан как можно более подробно.


Базовая концепция Continuous Archiving and Point-in-Time Recovery


В этом разделе укажем основные идеи, лежащие в основе подхода Continuous Archiving and Point-in-Time Recovery. При необходимости подробные детали можно найти в документации PostgreSQL.


Пожалуй, как и все СУБД, PostgreSQL имеет файлы данных, в которых хранит текущее состояние базы данных. Однако, кроме этого PostgreSQL ведет и сохраняет логи изменений в базе данных. Эти логи представлены в виде так называемых write ahead logs (WAL) файлов, которые сохраняются в подпапке pg_wal директории с данными:




WAL-файлы используются PostgreSQL для защиты от сбоев. Упрощенно говоря, при коммите транзакции PostgreSQL убеждается, что именно изменения в соответствующем WAL-файле гарантированно сохранились на диск, но, вообще говоря, может не делать такую же проверку по отношению к файлам с данными, например, кешируя их изменения до определенного момента в оперативной памяти. Если после последнего гарантированного сохранения файлов данных на диск (checkpoint) произошел сбой и текущее состояние еще не было сохранено, то после восстановления работы PostgreSQL возьмет последний checkpoint файлов данных (назовем его base backup) и последовательно применит к нему изменения, сохраненные в WAL-файлах (replay log entries).


Вышеописанную модель также можно использовать и для бекапирования с последующим восстановлением (например) на другом сервере. Для этого, очевидно, требуется реализовать следующую схему:


  1. Сначала (один раз) снять бекап файлов данных (и отправить файлы в безопасное место на другой сервер)
  2. В процессе работы по мере появления WAL-файлов тоже их бекапить

Модель восстановления после сбоя, таким образом, тоже становится очевидной:


  1. На новом сервере PostgreSQL загрузить файлы данных из бекапа (упрощенно это соответствует их простому копированию в соответствующую рабочую папку данных)
  2. На новом сервере PostgreSQL загрузить WAL-файлы из бекапа (упрощенно это соответствует их простому копированию в соответствующую подпапку рабочей папки данных)

Стоит иметь ввиду следующие особенности рассматриваемой модели бекапов:


  • Бекапятся сразу все базы данных текущего PostgreSQL-сервера, т.е. нет возможности забекапить, например, только одну из них
  • Не обязательно накатывать на base backup все записи WAL-файлов, можно остановиться на каком-то временном моменте (point-in-time recovery). Эта фича позволяет восстановить базу и в том случае, если сбой произошел в виду программной ошибки (например, была удалена какая-то таблица посредством drop table и т.п.).

В следующих разделах описываются технические детали описанной схемы.
Для этой цели будут использоваться следующие наименования: целевой сервер текущий рабочий сервер, с которого делаем бекапы, сервер бекапов сервер на который отправляются бекапы, новый сервер сервер, на котором восстанавливается бекап целевого сервера после сбоя.


Оффтоп: несколько слов по безопасности


Ввиду особой ценности бекапов для бизнеса как с точки зрения восстановления после сбоев, так и с точки зрения возможных утечек информации нелишним будет пройтись по базовой безопасности Linux серверов. В целом, это не относится напрямую к рассматриваемой теме, поэтому, можно просто пробежаться глазами по этому разделу и, если у вас все устроено так же, спокойно пойти дальше. В случае если ваши решения по безопасности лучше описанных просьба отписаться в комментариях и рассказать о своем опыте. Если же вы считаете, что с безопасностью у вас хуже, то описанные ниже решения стоит, вероятно, как можно скорее применить и к вашим продакшенам. Рассматриваться будет Ubuntu 18.04, на других версиях Linux инструкция может отличаться.


  1. Ваша система имеет последние обновления
    sudo apt-get update && sudo apt-get upgrade
    
  2. Вы не работаете от пользователя 'root', вместо этого у вас создан персонифицированный (то есть, для каждого сотрудника, которому требуется доступ на сервер, свой) пользователь в группе sudo (в нашем случае, назовем его alex)
    sudo adduser alex# Вводим пароль и др. данные типа Full Name и т.п.sudo adduser alex sudo# Для проверки успешности создания пользователя можно зайти от него...sudo su - alex# ...и посмотреть список файлов в /root, куда имеют доступ только sudoerssudo ls -la /root# Если же ввести команду без sudo, то должна возникнуть ошибка авторизацииls -la /root
    
  3. При подключении по SSH вы не используете авторизацию по логину/паролю, применяя вместо этого доступ по ключу
    # ---Локальная машина сотрудника---# Считаем, что сотрудник на локальной машине сгенерировал пару приватный/публичный ключ,# например, так, если у сотрудника Linux:ssh-keygen -t rsa -b 4096# При этом парольную фразу при генерации ключа сотрудник не оставил пустой, а установил достаточно сложный пароль
    

    # ---Продакшен, пользователь alex---# Создадим файл публичного ключа и сохраним туда содержимое публичного ключа с локальной машины сотрудникаnano ~/alex.pub# Затем скопируем открытый ключ в authorized_keysmkdir -p ~/.sshtouch ~/.ssh/authorized_keyschmod 700 ~/.sshchmod 600 ~/.ssh/authorized_keyscat ~/alex.pub >> ~/.ssh/authorized_keysrm ~/alex.pub# Перезагрузим серверsudo reboot
    
  4. В конфиге ssh включена опция доступа по ключу, кроме этого порт доступа ssh изменен со стандартного на рандомный (макроподстановка [generatedPortNumber] в скрипте ниже) в диапазоне от 1024 до 57256 (т.к. часто сканеры портов для экономии ресурсов проверяют лишь стандартные порты)
    # Открыть файл настроек sshsudo nano /etc/ssh/sshd_config# Раскоментировать и поменять значения следующих ключей:PubkeyAuthentication yes# Если в файле присутствует ключ AuthenticationMethods, то в этом (и только в этом!) случае # поменять его значение или раскоментироватьAuthenticationMethods publickey# Поменять значение порта на [generatedPortNumber] и раскоментироватьPort [generatedPortNumber]# Перезагрузитьсяsudo reboot
    

    # --- После перезагрузки ---# Убедиться в успешности подключения по ssh на новый порт по ключу пользователя alex...
    
  5. Доступ root-а по ssh запрещен, доступ по паролю по ssh запрещен
    # Открыть файл настроек sshsudo nano /etc/ssh/sshd_config# Раскоментировать и поменять значения следующих ключей:PermitRootLogin noChallengeResponseAuthentication noPasswordAuthentication noUsePAM no# Перезагрузитьсяsudo reboot
    

Настройка сервера бекапов


Создание папок для бекапа


Поскольку у нас множество инсталляций, с которых будут собираться бекапы, структура папок будет следующей. Папка для хранения бекапов /var/lib/postgresql/backups. Под каждую инсталляцию в папке для хранения бекапов создается подпапка по имени клиента [clientName]. В каждой такой подпапке будут лежать 2 папки: base для базового бекапа и wal для continious archiving WAL-файлов с целевого сервера. Таким образом, при настройке бекапирования для клиента [clientName] выполняем следующие команды по созданию соответствующих директорий:


sudo mkdir -p /var/lib/postgresql/backups/[clientName]/basesudo mkdir -p /var/lib/postgresql/backups/[clientName]/wal

Разумеется, структура папок может быть и любой другой, которую вы находите более удобой для вас. Например, если хранить бекапы в home директориях соответствующих пользователей (см. ниже), то в следующем пункте можно сэкономить пару команд по раздаче прав на чтение и запись в эти папки.


Создание пользователя


В целях безопасности каждый продакшен (целевой сервер), с которого идут бекапы, будет иметь своего собственного пользователя на сервере бекапов. Это обычный пользователь с ограниченными правами (не sudoer), который должен иметь права на чтение и запись в свою папку для бекапа, но не иметь возможность ни читать, ни писать в папки чужих продакшенов. Таким образом, даже если данный целевой сервер будет скомпрометирован, это не приведет к утечке данных других продакшенов через сервер бекапов.
Подробнее процесс выглядит следующим образом. Допустим, мы настраиваем бекап для проекта с именем foo. Для настройки сервера бекапов изначально заходим на него от пользователя из sudo. Добавляем пользователя с ограниченными правами foobackup:


# Добавить нового пользователяsudo adduser foobackupAdding user `foobackup' ...Adding new group `foobackup' (1001) ...Adding new user `foobackup' (1001) with group `foobackup' ...Creating home directory `/home/foobackup' ...Copying files from `/etc/skel' ...Enter new UNIX password:Retype new UNIX password:passwd: password updated successfullyChanging the user information for foobackupEnter the new value, or press ENTER for the default        Full Name []: AlexGtG        Room Number []:        Work Phone []:        Home Phone []:        Other []:Is the information correct? [Y/n] Y

Выдача прав пользователю на папки бекапа


Разрешаем foobackup читать и писать в свою папку, но запрещаем это делать всем остальным:


# Владельцем папки foo назначается foobackupsudo chown -R foobackup: /var/lib/postgresql/backups/foo# Никто кроме владельца не имеет доступа к этой папкеsudo chmod -R 700 /var/lib/postgresql/backups/foo

Настройка публичных ключей


Для завершения настройки сервера бекапов нашему новому пользователю foobackup необходимо дать удаленный доступ, чтобы он имел возможность отсылать бекапы на сервер. Как и ранее, доступ будет осуществляться по ключам доступа и только по ним.


На целевом сервере бекапы делаются от имени пользователя postgres, соответственно генерируем (если этого не было сделано ранее) приватный и публичные ключи для него:


# Находясь на целевом сервере, в данном случае это сервер проекта foo,# заходим от имени postgressudo su - postgres# Генерируем новый приватный ключ (только если этого не было сделано ранее!)ssh-keygen -t rsa -b 4096Generating public/private rsa key pair.Enter file in which to save the key (/var/lib/postgresql/.ssh/id_rsa):/var/lib/postgresql/.ssh/id_rsa already exists.Overwrite (y/n)? yEnter passphrase (empty for no passphrase):Enter same passphrase again:Your identification has been saved in /var/lib/postgresql/.ssh/id_rsa.Your public key has been saved in /var/lib/postgresql/.ssh/id_rsa.pub.

Копируем содержимое публичного ключа из указанного при генерации системой места (Your public key has been saved in...), в нашем случае это /var/lib/postgresql/.ssh/id_rsa.pub:


# По-прежнему находясь на целевом сервере под пользователем postgres откроем файл публичного ключа и скопируем его содержимоеvi /var/lib/postgresql/.ssh/id_rsa.pub

Сохраняем публичный ключ на сервер бекапов для пользователя foobackup:


# На сервере бекапов:# Заходим от имени пользователя foobackupsudo su - foobackup#  В файл foobackup.pub cохранить содержимое открытого ключа, которое мы ранее скопировалиnano ~/foobackup.pub# Затем записать открытый ключ пользователя в authorized_keysmkdir -p ~/.sshtouch ~/.ssh/authorized_keyschmod 700 ~/.sshchmod 600 ~/.ssh/authorized_keyscat ~/foobackup.pub >> ~/.ssh/authorized_keysrm ~/foobackup.pub

Проверка работоспособности копирования


Теперь проверим, что мы все сделали правильно. В нашей схеме за копирование бекапов с целевого сервера на сервер бекапов будет отвечать scp утилита для копирования файлов на удаленный сервер с синтаксисом, аналогичным локальному аналогу cp. В принципе, можно использовать и другие средства доставки файлов, например, rsync и т.п.


# Находясь на целевом сервере (по-прежнему под пользователем postgres):# Заранее положим в папку /var/lib/postgresql/backups файл test.txt...# и скопируем его в соотв. папки сервера бекапов:scp /var/lib/postgresql/backups/test.txt foobackup@[backupServerIp]:/var/lib/postgresql/backups/foo/basescp /var/lib/postgresql/backups/test.txt foobackup@[backupServerIp]:/var/lib/postgresql/backups/foo/wal

После копирования заходим на сервер бекапов и убеждаемся, что файл действительно скопировался, например, так:


test -f /var/lib/postgresql/backups/foo/base/test.txt && echo 'exists in base' || echo 'not exists in base'test -f /var/lib/postgresql/backups/foo/wal/test.txt && echo 'exists in wal' || echo 'not exists in wal'

По окончании проверок файл test.txt следует удалить из соответствующих папок сервера бекапов.


Настройка целевого сервера


Конфигурация PostgreSQL


Архивирование без сжатия


В файле postgresql.conf (его расположение можно получить выполнив из psql команду "SHOW config_file;") сделать следующие изменения (с подстановкой [backupServerIp] = IP адрес сервера бекапов, [clientName] = foo):


#Раскоментировать и изменить строку с wal_level на следующее значение:wal_level = replica#Раскоментировать и изменить строку с archive_mode на следующую:archive_mode = on#Раскоментировать и изменить строку archive_command на следующее значение:archive_command = 'cat %p | ssh foobackup@[backupServerIp] "set -e; test ! -f /var/lib/postgresql/backups/[clientName]/wal/%f; cat > /var/lib/postgresql/backups/[clientName]/wal/%f.part; sync /var/lib/postgresql/backups/[clientName]/wal/%f.part;  mv /var/lib/postgresql/backups/[clientName]/wal/%f.part /var/lib/postgresql/backups/[clientName]/wal/%f"'      # command to use to archive a logfile segment#Раскоментировать и изменить строку archive_timeout на следующее значение:archive_timeout = 3600

В archive_command сначала проверяется не существует ли уже на сервере бекапов файл с таким именем. Это одно из требований документации PostgreSQL, которое направлено на защиту от разрушения integrity бекапа из-за администраторских ошибок когда, например, бекапирование с двух разных серверов по ошибке настроено на одну и ту же папку. Далее происходит копирование файла по сети (scp) с использованием достаточно стандартного подхода: сначала поток записывается во временный файл и затем, только если он полностью скопирован и сброшен на диск (sync), меняется его имя (mv) с временного (.part) на постоянное. Если после переименования файла случилась ошибка и метаданные о таком переименовании не были сброшены на диск, то скрипт вернется с ошибкой и PostgreSQL просто повторит отправку файла. Ошибка на любом шаге скрипта закончит весь скрипт с ненулевым кодом (set -e).


Каждый WAL-файл занимает 16Mb и его архивирование (в нашем случае "архивирование" это отправка на сервер бекапов) происходит только после того, как он заполнен. Таким образом, если данный клиент генерирует мало трафика БД, то бекап текущего WAL-файла может не происходить недетерменированно долго. Чтобы иметь возможность при сбое восстановить версию базы, например, не более часовой давности, необходимо в archive_timeout задать время форсированного архивирования (промежуток, через который даже неполный WAL-файл архивируется) в 1 час в секундах это 3600. Не следует устанавливать слишком малые значения, потому что даже неполные WAL-файлы занимают 16Mb таким образом, в заданный промежуток времени не менее 16Мб данных будет уходить на сервер бекапов. Например, при archive_timeout равном одному часу, в сутки на сервер бекапов будет уходить не менее 384Мб данных, в неделю это больше 2Gb.


Архивирование со сжатием


Учитывая возможные проблемы с разрастанием размера бекапов можно сразу делать сжатие и на сервер бекапов отправлять уже сжатые WAL-файлы (на своих продакшенах мы делаем именно так). В таком случае команда archive_command будет выглядеть так:


archive_command = 'gzip -c -9 %p | ssh foobackup@[backupServerIp] "set -e; test ! -f /var/lib/postgresql/backups/[clientName]/wal/%f.gz; cat > /var/lib/postgresql/backups/[clientName]/wal/%f.gz.part; gzip -t /var/lib/postgresql/backups/[clientName]/wal/%f.gz.part; sync /var/lib/postgresql/backups/[clientName]/wal/%f.gz.part;  mv /var/lib/postgresql/backups/[clientName]/wal/%f.gz.part /var/lib/postgresql/backups/[clientName]/wal/%f.gz"'       # command to use to archive a logfile segment

После сделанных в postgresql.conf изменений необходимо перезапустить PostgreSQL:


sudo service postgresql restart

Создание базового бекапа


Создание базового бекапа делается утилитой pg_basebackup, которая была установлена на целевом сервере вместе с PostgreSQL. Предполагается, что в PostgreSQL целевого сервера создан некий trusted пользователь с привилегиями, достаточными для осуществления бекапа всех баз данных на текущей инсталляции PostgreSQL (к примеру, это может быть администраторский аккаунт, используемый для обслуживания баз данных, или отдельный пользователь, специально созданный для создания базовых бекапов). Имя этого пользователя должно быть использовано в подстановке [trusted db user]. В процессе выполнения команды будет запрошен пароль этого пользователя. После создания бекапа сразу отправляем его на сервер бекапов.


#На целевом сервере:sudo -i -u postgrespg_basebackup --pgdata=/tmp/backups --format=tar --gzip --compress=9 --label=base_backup --host=127.0.0.1 --username=[trusted db user] --progress --verbose#При успехе в /tmp/backups будут созданы файлы base.tar.gz и pg_wal.tar.gz,#которые скопируем на сервер бекаповscp /tmp/backups/base.tar.gz /tmp/backups/pg_wal.tar.gz foobackup@[backupServerIp]:/var/lib/postgresql/backups/[clientName]/baseexit

Ключи --progress и --verbose не являются обязательными и используются для наглядности наблюдения процесса создания бекапа при наличии этих ключей PostgreSQL выдает некоторую дополнительную информацию в консоль в удобочитаемом виде.


Восстановление бекапа


Проверка работоспособности бекапирования


Перед тем, как выводить нашу инсталляцию foo в продакшен, необходимо убедиться в работоспособности настроенной системы бекапов. Проверка, очевидно, должна состоять из двух частей:


  1. Базовый бекап отправлен на сервер бекапов
  2. WAL-файлы отправляются на сервер бекапов

П.1 проверяется так: на сервере бекапов заходим в папку /var/lib/postgresql/backups/foo/base и убеждаемся, что она содержит файлы base.tar.gz и pg_wal.tar.gz:


image


Чтобы быстро без долгого времени наблюдения за системой проверить п.2, вернемся в пункт настройки PostgreSQL и поменяем таймаут архивирования (archive_timeout) на 60 секунд, затем рестартуем PostgreSQL. Теперь при наличии изменений в базе WAL-файлы будут архивироваться не реже, чем раз в минуту. Далее в течение некоторого времени (3-5 минут) будем любым (безопасным) образом генерировать изменения в базе например, мы делаем это просто через наш фронт, вручную создавая активность тестовыми пользователями.
Параллельно нужно наблюдать за папкой /var/lib/postgresql/backups/foo/wal сервера бекапов, где примерно раз в минуту будет появляться новый файл:


image


После проверки очень важно вернуть archive_timeout в продакшен значение (у нас в зависимости от клиента это минимум 1 час, т.е. 3600, максимум сутки, т.е. 86400).


Если видно, что файлы не отправляются на сервер бекапов, то исследование проблемы можно начать с анализа логов PostgreSQL, лежащих здесь /var/log/postgresql. Например, если пара приватный-публичный ключ была настроена неверно, то можно увидеть подобную запись в файле postgresql-10-main.log (название лог-файла зависит от устанавливаемой версии):


2019-09-02 15:48:52.503 UTC [12983] DETAIL:  The failed archive command was: scp pg_wal/00000001000000000000003B [fooBackup]@[serverBackupIp]:/var/lib/postgresql/backups/foo/wal/00000001000000000000003BHost key verification failed.lost connection

Восстановление из бекапа


Пусть у нас заранее подготовлен новый сервер, где установлен PostgreSQL той же мажорной версии, что и на целевом сервере. Также предположим, что с сервера бекапов мы предварительно скопировали папку бекапа /var/lib/postgresql/backups/foo на новый сервер по тому же пути.
Далее по шагам описана процедура развертывания этого бекапа на новом сервере.


Выясняем путь, по которому хранятся файлы данных:


#Находясь в psql:show data_directory;

В зависимости от версии PostgreSQL выдастся что-то подобное: /var/lib/postgresql/10/main


Удаляем все содержимое папки с данными:


#Останавливаем инстанс сервера, на который будем накатывать бекапsudo service postgresql stopsudo rm -rf /var/lib/postgresql/10/main/*

Останавливаем инстанс PostgreSQL на ЦЕЛЕВОМ сервере:


Если после сбоя доступ к целевом серверу сохранился, то останавливаем там инстанс PostgreSQL, чтобы потерять как можно меньшее количество новых данных, которые не войдут в бекап.


sudo service postgresql stop

Распаковываем файлы из бекапа в папку данных PostgreSQL:


Здесь и далее снова работаем с новым сервером.


sudo tar xvzf /var/lib/postgresql/backups/[clientName]/base/base.tar.gz -C /var/lib/postgresql/10/mainsudo tar xvzf /var/lib/postgresql/backups/[clientName]/base/pg_wal.tar.gz -C /var/lib/postgresql/10/main

Ожидается, что команда tar, запущенная от sudo, сохранит group и ownership распакованных файлов за пользователем postgres это важно, поскольку далее их будет использовать PostgreSQL, работающий именно от этого пользователя.


В папке с данными создаем конфиг восстановления:


Если сжатия на шаге архивирования WAL-файлов не было:


nano /var/lib/postgresql/10/main/recovery.conf#Добавить нужно единственную строку, заменив [clientName] на актуальное наименование инсталляции (в нашем примере [clientName] = foo)restore_command = 'cp /var/lib/postgresql/backups/[clientName]/wal/%f %p'#Выйти из nano c сохранением результатов и назначить права на файл пользователю postgressudo chown postgres:postgres /var/lib/postgresql/10/main/recovery.confsudo chmod 600 /var/lib/postgresql/10/main/recovery.conf#Назначить права на папку с бекапом WAL-файлов и ее содержимое (с подстановкой [clientName] = foo)sudo chown -R postgres:postgres /var/lib/postgresql/backups/[clientName]/walsudo chmod 700 /var/lib/postgresql/backups/[clientName]/walsudo chmod 600 /var/lib/postgresql/backups/[clientName]/wal/*

Если сжатие на шаге архивирования WAL-файлов было, то restore_command должен выглядеть следующим образом (все остальное не меняется):


restore_command = 'gunzip -c /var/lib/postgresql/backups/[clientName]/wal/%f.gz > %p'

Запускаем PostgreSQL:


sudo service postgresql start

Обнаружив в папке с данными конфиг восстановления, PostgreSQL входит в режим восстановления и начинает применять (replay) WAL-файлы из архива. После окончания восстановления recovery.conf будет переименован в recovery.done (поэтому очень важно на предыдущем шаге дать пользователю postgres права на изменение файла). После этого шага сервер PostgreSQL готов к работе. Если по внешним признакам видно, что база не восстановилась либо восстановилась только до уровня базового бекапа, то исследование проблемы можно начать с анализа логов PostgreSQL, лежащих здесь /var/log/postgresql. Например, если на предыдущем шаге не были даны права пользователю postgres на папку с бекапом WAL-файлов, то можно увидеть подобную запись в файле postgresql-10-main.log (название лог-файла зависит от устанавливаемой версии):


2019-09-04 11:52:14.532 CEST [27216] LOG:  starting archive recoverycp: cannot stat '/var/lib/postgresql/backups/foo/wal/0000000100000000000000A8': Permission denied

Перенос PostgreSQL базы данных между разными мажорными версиями


В этом параграфе, как и было обещано в начале статьи, рассмотрим случай, когда требуется перенести базу с одной мажорной версии на другую. Поскольку основным сценарием бекапирования для нас является подход, описанный выше, то здесь мы будем предполагать, что целевой сервер доступен и работоспособен то есть, перенос базы нужно осуществить не из-за сбоя, а по другим (организационным) причинам.


Будем использовать утилиту pg_dump или pg_dumpall. Обе они генерируют набор SQL-команд. Первая используется для создания бекапа конкретной базы данных, а вторая при бекапе всего кластера. В последнем случае, кроме баз данных кластера копируются еще и его глобальные объекты например, роли, что позволяет затем после развертывания бекапа не делать дополнительных действий в виде создания недостающих ролей, раздачи привилегий и т.п.


Создание дампа


На целевом сервере выполнить (желательно, чтобы на этот момент потребители его баз данных были остановлены и/или не проявляли активность по отношению к БД):


# Входим от имени пользователя postgres или от другого пользователя, являющегося админом текущего кластера PostgreSQLsudo -i -u postgres# Делаем дамп с опцией -с - при этой опции существующие при накатывании дампа объекты на целевом сервере будут удалены,#здесь foo.dump.gz - путь, по которому будет сохранен дамп.pg_dumpall -c | gzip -c > /tmp/backups/foo.dump.gz

Накатывание дампа


Будем считать, что на новый сервер по тому же пути (/tmp/backups/foo.dump.gz) скопирован сделанный на предыдущем шаге дамп.


Находясь на новом сервере:


# Входим от имени пользователя postgres, являющегося админом текущего кластера PostgreSQLsudo -i -u postgres#Накатим дамп на текущий кластер, выведем лог работы (включая ошибки) в файл /tmp/backups/foo.restore.outgunzip -c /tmp/backups/foo.dump.gz | psql -d postgres &> /tmp/backups/foo.restore.out

После окончания восстановления бекапа нужно просмотреть лог восстановления. По умолчанию psql работает с выключенным флагом ON_ERROR_STOP, поэтому при возникновении ошибок скрипт не прерывается, а продолжает работу. Ниже перечислены те ошибки, которые не являются проблемными, при появлении же в логе других ошибок следует считать восстановление базы не успешным.


#Если мы накатываем дамп на новый кластер, то целевой базы может не существовать, тогда появится ошибкаERROR:  database "foo" does not exist#Это не проблема, так как дамп содержит команду по созданию базы данных, однако, нужно убедиться, что далее по скрипту база создалась и подключение к ней успешно. Об этом говорит строка:You are now connected to database "foo" as user "postgres".#Дамп, созданный с ключом -c (clean) содержит команды пересоздания ролей: сначала производится попытка удалить роль, а затем создать ее заново.#Эта команда будет неуспешной для текущего пользователя, от которого работает psql, в данном случае это postgres, поэтому в логах встретится такая ошибка:ERROR:  current user cannot be dropped#Отметим, что даже если работать не от пользователя postgres, а, например, специально для целей накатывания бекапа создать нового пользователя, и работать от него, то все равно будет иметь место ошибка удаления роли postgres, так как эта роль требуется для работоспособности кластера.#Поскольку роль postgres не была удалена, то далее при попытке ее создания будет выдана ошибка:ERROR:  role "postgres" already exists#Внимание! Более никаких ошибок в логе восстановления базы данных встретиться не должно!

Включение сервисов


После окончания накатывания дампа нужно:


  1. Настроить бекапирование нового сервера
  2. Переключить соответствующие сервисы на новый адрес базы данных и включить их для пользователя

После этого перенос можно считать завершенным.

Подробнее..
Категории: Postgresql , Backup

Путеводитель по резервному копированию баз данных

25.08.2020 10:05:02 | Автор: admin
О, никакое убежище не выдержит попадания метеорита. Но ведь у вас, как и у каждого, есть резерв, так что можете не беспокоиться.

Станислав Лем, Звёздные дневники Ийона Тихого

Резервным копированием называется сохранение копии данных где-то вне основного места их хранения.



Главное назначение резервного копирования восстановление данных после их потери. В связи с этим нередко приходится слышать, что при наличии реплики базы данных с неё всегда можно восстановить данные, и резервное копирование не нужно. На самом деле резервное копирование позволяет решить как минимум три задачи, которые не могут быть решены при помощи реплики, да и реплику без резервной копии не инициализировать.

Во-первых, резервная копия позволяет восстановить данные после логической ошибки. Например, бухгалтер удалил группу проводок или администратор БД уничтожил табличное пространство. Обе операции абсолютно легитимны с точки зрения базы данных, и процесс репликации воспроизведёт их в базе-реплике.

Во-вторых, современные СУБД весьма надёжные программные комплексы, однако изредка всё же происходит повреждение внутренних структур базы данных, после которого доступ к данным пропадает. Что особенно обидно, такое нарушение происходит обычно при высокой нагрузке или при установке какого-нибудь обновления. Но как высокая нагрузка, так и регулярные обновления говорят о том, что база данных отнюдь не тестовая, и данные, хранящиеся в ней, ценны.

Наконец, третья задача, решение которой требует наличия резервной копии, это клонирование базы, например, для целей тестирования.

Резервное копирование баз данных так или иначе базируется на одном из двух принципов:

  • Выборка данных с последующим сохранением в произвольном формате;
  • Снимок состояния файлов БД и сохранение журналов.

Давайте рассмотрим эти принципы и реализующие их инструменты подробнее.

Выгрузка данных


В наборе утилит, прилагающихся к любой СУБД, обязательно есть инструменты для выгрузки и загрузки данных. Данные сохраняются либо в текстовом формате, либо в двоичном формате, специфичном для конкретной СУБД. В таблице ниже приведён список таких инструментов:

Двоичный формат Текстовый формат
Oracle DataPump Export/DataPump Import
Export/Import
SQL*Plus/SQL*Loader
PostgreSQL pg_dump, pg_dumpall/pg_restore pg_dump, pg_dumpall/psql
Microsoft SQL Server bcp bcp
DB2 unload/load unload/load
MySQL mysqldump, mysqlpump/mysql, mysqlimport
MongoDB mongodump/mongorestore mongoexport/mongoimport
Cassandra nodetool snapshot/sstableloader cqlsh

Текстовый формат хорош тем, что его можно редактировать или даже создавать внешними программами, а двоичный в свою очередь хорош тем, что позволяет быстрее выгружать и загружать данные за счёт экономии ресурсов на преобразовании форматов.

Несмотря на простоту и очевидность идеи выгрузки данных, для резервирования нагруженных промышленных баз такой метод применяют редко. Вот причины, по которым выгрузка не подходит для полноценного резервного копирования:

  • процесс выгрузки создаёт значительную нагрузку на систему-источник;
  • выгрузка занимает много времени к моменту окончания выгрузки она станет уже неактуальной;
  • сделать согласованную выгрузку всей базы данных при высокой нагрузке практически невозможно, поскольку СУБД вынуждена хранить снимок своего состояния на момент начала выгрузки. Чем больше транзакций совершено с момента начала выгрузки, тем больше объём снимка (неактуальных копий данных в PostgreSQL, пространства undo в Oracle, tempdb в Microsoft SQL Server ит.п.);
  • выгрузка сохраняет логическую структуру данных, но не сохраняет их физическую структуру параметры физического хранения таблиц, индексы идр.

Тем не менее, у выгрузки есть и достоинства:

  • высокая избирательность: можно выгрузить отдельные таблицы, отдельные поля и даже отдельные строки;
  • выгруженные данные можно загрузить в базу данных другой версии, а если выгрузка сделана в текстовом формате, то и в другую базу данных.

Таким образом, выгрузка используется в основном для таких задач как резервирование небольших таблиц (например, справочников) или распространение наборов данных с очередным релизом приложения.

Самым же распространённым методом резервного копирования баз данных является копирование файлов базы.

Холодное сохранение файлов БД


Очевидная идея остановить базу данных и скопировать все её файлы. Такая резервная копия называется холодной. Способ крайне надёжный и простой, но у него есть два очевидных недостатка:

  • из холодной резервной копии можно восстановить только то состояние базы данных, которое было в момент останова; транзакции, сделанные после рестарта базы, в холодную резервную копию не попадут;
  • далеко не у каждой базы данных есть технологическое окно, когда базу можно остановить.

Если же холодное резервное копирование вас устраивает, нужно помнить что

  • холодная копия иногда должна включать в себя и журналы. Методы определения журналов, которые должны попасть в холодную копию, индивидуальны для каждой СУБД. Например, в Oracle необходимо скопировать так называемые online redo, то есть фиксированное количество журнальных файлов в специальном каталоге, причём даже тогда, когда база остановлена корректно. В PostgreSQL нужно сохранить все журналы начиная с журнала, содержащего последнюю контрольную точку, информация о которой содержится в управляющем файле.
  • каталог базы данных может содержать достаточно большие файлы временных табличных пространств, которые не обязательно включать в резервную копию. Кстати, это замечание верно и для горячего резервного копирования.

Горячее сохранение файлов


Большинство резервных копий современных баз данных выполняется путём копирования файлов базы данных без остановки базы. Здесь видны несколько проблем:

  • В момент начала копирования содержимое базы данных может не совпадать с содержимым файлов, т.к. часть информации находится в кеше и ещё не записана на диск.
  • Во время копирования содержимое базы может меняться. Если используются изменяемые структуры данных, то меняется содержимое файлов, а при использовании неизменяемых структур меняется набор файлов: новые файлы появляются, а старые удаляются.
  • Поскольку запись данных в базу и чтение файлов БД никак не синхронизированы, программа резервного копирования может прочитать некорректную страницу, в которой половина будет от старой версии страницы, а другая половина от новой.

Для того, чтобы резервная копия получилась согласованной, у каждой СУБД существует команда, которая сообщает, что начат процесс резервного копирования. Синтаксически эта команда может выглядеть по-разному:

  • в Oracle это отдельная команда ALTER DATABASE/TABLESPACE BEGIN BACKUP;
  • в PostgreSQL функция pg_start_backup();
  • в Microsoft SQL Server и DB2 подготовка к резервному копированию выполняется неявно в процессе выполнения команды BACKUP DATABASE;
  • в MySQL Enterprise, Cassandra и MongoDB подготовка неявно выполняется внешней утилитой mysqlbackup, OpsCenter и Ops Manager соответственно.

Несмотря на синтаксические различия, процесс подготовки к резервному копированию выглядит одинаково.

Вот как выглядит подготовка к резервному копированию в СУБД с изменяемыми дисковыми структурами, т.е. во всех традиционных дисковых реляционных системах:

  1. Запоминается момент начала резервного копирования; резервная копия должна будет содержать журналы базы данных начиная с этого момента.
  2. Выполняется контрольная точка, то есть все изменения, которые произошли в страницах данных до запомненного момента, сбрасываются на диск. Это гарантирует, что журналы до момента начала резервного копирования при восстановлении не потребуются.
  3. Включается особый режим журналирования: если страница данных изменилась в первый раз после загрузки с диска, то вместо того, чтобы записывать в журнал изменения страницы, база запишет туда страницу целиком. При выполнении подготовительной процедуры все страницы вытесняются на диск, и поэтому при первом изменении блок всегда будет записан в журнал целиком. Но если в процессе резервного копирования страница снова будет вытеснена на диск, то следующее её изменение также приведёт к появлению в журнале полной копии страницы. Это гарантирует, что если вдруг при копировании файла с данными страница получится некорректной, применение журнала сделает его корректной вновь.
  4. Блокируется изменение заголовков файлов данных, то есть той его части, изменения которой не отражаются в журналах. Это гарантирует, что заголовок будет скопирован корректно, а потом к файлу данных корректно будут применены журналы.

После того, как все перечисленные выше процедуры выполнены, можно копировать файлы данных средствами операционной системы cp, rsync и другими. Включение режима резервного копирования снижает производительность базы данных: во-первых, увеличивается объём журналов, а во-вторых, если вдруг в режиме резервного копирования произойдёт сбой, восстановление будет более продолжительным, т.к. заголовки файлов данных не обновляются. Чем быстрее резервное копирование закончится, тем лучше для базы данных, поэтому здесь уместно применение таких средств как снимок (snapshot) файловой системы или разрыв зеркала (BCV) в дисковом массиве. Одни СУБД (Oracle, PostgreSQL) оставляют администратору возможность самостоятельно выбрать способ копирования, другие (Microsoft SQL Server) предоставляют интерфейс для интеграции собственных утилит резервного копирования с механизмами файловых систем или СХД.

По окончании резервного копирования нужно перевести базу данных обратно в обычное состояние. В Oracle это делается командой ALTER DATABASE/TABLESPACE END BACKUP, в PostgreSQL вызовом функции pg_stop_backup(), а в других базах внутренними подпрограммами соответствующих команд или внешних сервисов.

Вот как выглядит времення диаграмма процесса резервного копирования:



  • Подготовка к резервному копированию (begin backup) занимает время, иногда значительное. Даже если используются зеркальные тома или файловые системы с возможностью изготовления снимков, процесс резервного копирования не будет мгновенным.
  • Вместе с файлами данных необходимо сохранить журналы начиная с момента начала подготовки к резервному копированию и заканчивая моментом возврата базы в нормальное состояние.
  • Восстановиться из этой резервной копии можно на момент возврата базы в нормальное состояние. Восстановление на более ранний момент невозможно.

С базами данных, использующими неизменяемые структуры данных (снимки памяти, LSM-деревья) ситуация проще. Подготовка к резервному копированию состоит из следующих шагов:

  1. Данные из памяти сбрасываются на диск.
  2. Фиксируется список файлов, попадающих в резервную копию. До тех пор, пока процесс резервного копирования не закончится, базе запрещено удалять эти файлы, даже если они становятся не нужны.

По сигналу об окончании резервного копирования база с неизменяемыми структурами снова может удалять ненужные файлы.

Восстановление на точку


Резервная копия позволяет восстановить состояние базы данных на момент, когда завершилась команда возврата из режима резервного копирования. Однако авария, после которой потребуется восстановление, может произойти в любой момент. Задача восстановления состояния БД на произвольный момент называется восстановлением на точку (point-in-time recovery).

Чтобы обеспечить такую возможность, следует сохранять журналы БД начиная с момента окончания резервного копирования, а в процессе восстановления продолжить применять журналы к восстановленной копии. После того, как БД восстановлена из резервной копии на момент окончания копирования, состояние базы (файлов и кэшированных страниц) гарантированно корректно, поэтому особый режим журналирования не нужен. Применяя журналы до нужного момента, можно получить состояние базы данных на любую точку во времени.

Если скорость восстановления резервной копии ограничена лишь пропускной способностью диска, то скорость применения журналов обычно ограничена производительностью процессора. Если в основной базе данных изменения происходят параллельно, то при восстановлении все изменения выполняются последовательно в порядке чтения из журнала. Таким образом время восстановления линейно зависит от того, насколько далеко точка восстановления отстоит от точки окончания резервного копирования. Из-за этого приходится довольно часто делать полные резервные копии минимум раз в неделю для баз с небольшой транзакционной нагрузкой и до ежедневного копирования высоконагруженных баз.

Инкрементальное резервное копирование


Чтобы ускорить восстановление на точку, хотелось бы иметь возможность выполнять резервное копирование как можно чаще, но при этом не занимать лишнего места на дисках и не нагружать базу задачами резервного копирования.

Решение задачи инкрементальное резервное копирование, то есть копирование только тех страниц данных, которые изменились с момента предыдущего резервного копирования.
Инкрементальное резервное копирование имеет смысл только для СУБД, использующих изменяемые структуры данных.

Инкремент может отсчитываться как от полной резервной копии (кумулятивная копия), так и от любой предыдущей копии (дифференциальная копия).



К сожалению, единой терминологии не существует, и разные производители используют разные термины:

Дифференциальная Кумулятивная
Oracle Differential Cumulative
PostgresPro Incremental
Microsoft SQL Server Differential
IBM DB2 Delta Incremental

При наличии инкрементальных копий процесс восстановления на точку выглядит следующим образом:

  • восстанавливается последняя полная резервная копия, сделанная до момента восстановления;
  • поверх полной копии восстанавливаются инкрементальные копии;
  • накатываются журналы с точки начала резервного копирования до точки восстановления.

Наличие кумулятивной копии ускоряет процесс восстановления. Так, например, для восстановления состояния базы на точку между T3 и T4 необходимо восстановить две инкрементальных копии, а для восстановления на точку после T4 только одну.
Очевидно, что объём одной кумулятивной копии меньше, чем объём нескольких дифференциальных копий, потому что некоторые страницы изменились по несколько раз, и каждая инкрементальная копия содержит свою версию страницы.

Есть три способа создания инкрементальной копии:

  1. создание полной копии и вычисление разницы с предыдущей полной копией;
  2. разбор журналов, создание списка изменённых страниц и резервирование страниц, включённых в список;
  3. запрос изменённых страниц в базе данных.

Первый способ экономит дисковое пространство, но не решает задачу снижения нагрузки на базу данных. Более того, если у нас есть полная резервная копия, то превращать её в инкрементальную бессмысленно, т.к. восстановление полной копии быстрее, чем восстановление предыдущей полной копии и инкремента. Задачу экономии дискового пространства при таком подходе лучше переложить на специальные компоненты со встроенными механизмами дедупликации. Это могут быть как специальные СХД (EMC DataDomain, HPE StorageWorks VLS, вся линейка NetApp), так и программные продукты (ZFS, Veritas NetBackup PureFile, Windows Server Data Deduplication).

Второй и третий способ отличаются механизмом определения списка изменённых страниц. Разбор журналов более ресурсоёмкий, плюс для его реализации необходимо знать структуру журнальных файлов. Спросить у самой базы, какие именно страницы изменились, проще всего, но для этого ядро СУБД должно иметь функциональность отслеживания изменённых блоков (block change tracking).

Впервые функциональность инкрементального резервного копирования была создана в ПО Oracle Recovery Manager (RMAN), появившемся в релизе Oracle8i. Oracle сразу реализовал отслеживание изменённых блоков, поэтому необходимости в разборе журналов нет.

PostgreSQL не отслеживает изменённые блоки, поэтому утилита pg_probackup, разработанная российской компанией Postgres Professional, определяет изменённые страница путём анализа журнала. Однако компания поставляет и СУБД PostgresPro, которая включает расширение ptrack, отслеживающее изменение страниц. При использовании pg_probackup с СУБД PostgresPro утилита запрашивает изменённые страницы на у самой базы точно так же, как и RMAN.

Microsoft SQL Server так же, как и Oracle, отслеживает изменённые страницы, но команда BACKUP позволяет делать только полные и кумулятивные резервные копии.

В DB2 есть возможность отслеживания измененных страниц, но по умолчанию она выключена. После включения DB2 позволит делать полные, дифференциальные и кумулятивные резервные копии.

Важное отличие описанных в этом разделе средств (кроме pg_probackup) от файловых средств резервного копирования в том, что они запрашивают образы страниц у базы данных, а не читают данные с диска самостоятельно. Недостаток такого подхода небольшая дополнительная нагрузка на базу. Однако этот недостаток с лихвой компенсируется тем, что прочитанная страница всегда корректна, поэтому нет необходимости во включении на время резервного копирования особого режима журналирования.

Ещё раз обратите внимание, что наличие инкрементальных копий не отменяет требований к наличию журналов для восстановления на произвольную точку во времени. Поэтому в промышленных базах данных журналы постоянно переписываются на внешний носитель, а резервные копии, полные и/или инкрементальные, создаются по расписанию.

Наилучшей на сегодня реализацией идеи инкрементального резервного копирования является программно-аппаратный комплекс (в терминологии Oracle engineered system) Zero Data Loss Recovery Appliance специализированное решение Oracle для резервного копирования собственной БД. Комплекс представляет собой кластер серверов с большим объёмом дисков, на которые установлена модифицированная версия ПО Recovery Manager и может работать как с другими программно-аппаратными комплексами Oracle (Database Appliance, Exadata, SPARC Supercluster), так и с базами Oracle на традиционной инфраструктуре. В отличие от обычного RMAN, в ZDLRA реализована концепция вечного инкремента (incremental forever). Система единственный раз создаёт полную копию базы данных, а потом делает только инкрементальные копии. Дополнительные модули RMAN позволяют объединять копии, создавая новые полные копии из инкрементальных.

К чести российских разработчиков нужно заметить, что и pg_probackup умеет объединять инкрементальные копии.



В отличие от многих похожих вопросов, вопрос какой метод резервного копирования лучше имеет однозначный ответ лучше всего родная для используемой СУБД утилита, обеспечивающая возможность инкрементального копирования.

Для администратора БД гораздо более важными являются вопросы выбора стратегии резервного копирования и интеграция средств резервирования баз данных в корпоративную инфраструктуру. Но эти вопросы выходят за рамки данной статьи.
Подробнее..

Этюд по PITR в PostgreSQL штатными средствами

28.10.2020 20:04:59 | Автор: admin
В короткой заметке описан cценарий Point In Time Recovery с использованием средств из стандартной поставки PostgreSQL версии 11.
Для создания базовой резервной копии используется штатная утилита pg_basebackeup.
Для потоковой архивации файлов WAL используется штатная утилита pg_receivewal

Общий сценарий довольно подробно описан в документации Непрерывное архивирование и восстановление на момент времени (Point-in-Time Recovery, PITR), однако довольно общими фразами. Поэтому при попытке реализовать на практике возникли некоторые, хотя и вполне преодолимые шероховатости.

Посмотрел по поиску на Хабре, вроде не нашел статей о PITR штатными средствами. Так, что может быть кому то пригодится, в качестве шаблона-рыбы.

Конфигурация для тестирования самая простая, один сервер RedHat Linux, один сервис PostgreSQL(pgdata=/postgres/pgdata, waldir=/postgres/waldir), pg_receivewal запускается от имени postgres, заполнение тестовыми данными не уточняется и оставлено на личноe усмотрение.

Порядок действий по пунктам


1. Создать папки хранения и добавить скрипты

Создать папки.
mkdir -p /postgres/wal_arcchown postgres:postgres /postgres/wal_arcmkdir -p /postgres/backupchown postgres:postgres /postgres/backupsmkdir -p /postgres/scriptschown postgres:postgres /postgres/scripts

Cкрипты в папке /postgres/scripts
pg_receivewal.sh
#!/bin/bash# pg_receivewal.sh# /postgres/scripts/pg_receivewal --no-loop --synchronous --slot=slot_receivewal --directory=/postgres/wal_arc --verbose --host=localhost > /postgres/scripts/pg_receivewal.log 2>&1

rename.sh
#!/bin/bash# rename.sh# /postgres/scripts/for f in /postgres/wal_arc/*.partial;do  mv -- "$f" "${f%.partial}"doneexit 0

2. Запустить непрерывное архивирование WAL-файлов

Настроить файл .pgpass, для запуска pg_receivewal без пароля:
vi ~/.pgpass    localhost:5432:*:postgres:postgreschmod 0600 ~/.pgpass

Настроить сервис для запуска pg_receivewal.Пользователь root.
pg_receivewal.service
########################################################### /etc/systemd/system/# pg_receivewal.service[Unit]Description=Receiving for WAL stream[Service]Type=simpleWorkingDirectory=/postgres/scriptsUser=postgresGroup=postgresExecStart=/postgres/scripts/pg_receivewal.sh[Install]WantedBy=multi-user.target

Запускаем сервис.Пользователь root
systemctl daemon-reloadsystemctl start pg_receivewal.service

Проверяем.Пользователь root.
systemctl status pg_receivewal.service

В случае успешного старта получаем ответ
 pg_receivewal.service - Receiving for WAL stream   Loaded: loaded (/etc/systemd/system/pg_receivewal.service; disabled; vendor preset: disabled)   Active: active (running) since...

3. Заполнение тестовыми данными

Любым способом, на усмотрение читателя.

4. Создание базовой резервной копии.

Все стандартно и тривиально:
pg_basebackup  -D /postgres/backups/ --format=tar -Xs --progress --verbose

Получаем ответ о успешном выполнении:
pg_basebackup: initiating base backup, waiting for checkpoint to completepg_basebackup: checkpoint completedpg_basebackup: base backup completed

5. Имитируем катастрофу БД

Остановить сервер PostgreSQL любым способом.
Удалить папки файлов данных и WAL:
rm -rf /postgres/pgdatarm -rf /postgres/waldir

6. Восстановление БД

Создать папки файлов данных и WAL:
mkdir /postgres/pgdatachown postgres:postgres /postgres/pgdatachmod 750 /postgres/pgdata mkdir /postgres/waldirchown postgres:postgres /postgres/waldirchmod 750 /postgres/waldir

Восстановить файлы данных из базовой резервной копии:
cd /postgres/backups cp base.tar /postgres/pgdata cd /postgres/pgdata tar -xvf base.tar rm base.tar rm -r pg_wal ln -s /postgres/waldir pg_wal

В папке /postgres/wal_arc имеется неполный файл WAL(с расширением partial), нужно его переименовать, на случай если точка восстановления окажется в незаполненном файле WAL. Переименовать файл вручную или скриптом rename.sh:
/postgres/scripts/rename.sh

Для восстановления на заданную точку во времени необходимо подготовить файл recovery.conf:
restore_command = 'cp /postgres/wal_arc/%f  %p'recovery_target_time = '*****'recovery_target_action=promote

recovery_target_time задается требуемая временная точка восстановления в формате timestamp.

Запустить сервис PostgreSQL любым доступным способом.

Файл recovery.conf переименован в recovery.done ?
cd /postgres/pgdatals -la recovery.done

Если файл переименован-восстановление прошло успешно.

Дополнительно полезно убедиться, что лог файл содержит следующие строки:
starting point-in-time recovery to ...database system is ready to accept connections 


В случае успешного восстановления перезапускаем потоковую архивацию файлов WAL:
pg_receivewal --create-slot --slot=slot_receivewal --verbose
Пользователь root
systemctl start pg_receivewal.service


Итог:


В самом простом сценарии, База Данных восстановлена на требуемую точку во времени.
Подробнее..
Категории: Postgresql , Backup , Recovery

Этюд по PITR штатными средствами PostgreSQL

28.10.2020 22:13:41 | Автор: admin
В короткой заметке описан cценарий Point In Time Recovery с использованием средств из стандартной поставки PostgreSQL версии 11.
Для создания базовой резервной копии используется штатная утилита pg_basebackeup.
Для потоковой архивации файлов WAL используется штатная утилита pg_receivewal

Общий сценарий довольно подробно описан в документации Непрерывное архивирование и восстановление на момент времени (Point-in-Time Recovery, PITR), однако довольно общими фразами. Поэтому при попытке реализовать на практике возникли некоторые, хотя и вполне преодолимые шероховатости.

Посмотрел по поиску на Хабре, вроде не нашел статей о PITR штатными средствами. Так, что может быть кому то пригодится, в качестве шаблона-рыбы.

Конфигурация для тестирования самая простая, один сервер RedHat Linux, один сервис PostgreSQL(pgdata=/postgres/pgdata, waldir=/postgres/waldir), pg_receivewal запускается от имени postgres, заполнение тестовыми данными не уточняется и оставлено на личноe усмотрение.

Порядок действий по пунктам


1. Создать папки хранения и добавить скрипты

Создать папки.
mkdir -p /postgres/wal_arcchown postgres:postgres /postgres/wal_arcmkdir -p /postgres/backupchown postgres:postgres /postgres/backupsmkdir -p /postgres/scriptschown postgres:postgres /postgres/scripts

Cкрипты в папке /postgres/scripts
pg_receivewal.sh
#!/bin/bash# pg_receivewal.sh# /postgres/scripts/pg_receivewal --no-loop --synchronous --slot=slot_receivewal --directory=/postgres/wal_arc --verbose --host=localhost > /postgres/scripts/pg_receivewal.log 2>&1

rename.sh
#!/bin/bash# rename.sh# /postgres/scripts/for f in /postgres/wal_arc/*.partial;do  mv -- "$f" "${f%.partial}"doneexit 0

2. Запустить непрерывное архивирование WAL-файлов

Настроить файл .pgpass, для запуска pg_receivewal без пароля:
vi ~/.pgpass    localhost:5432:*:postgres:postgreschmod 0600 ~/.pgpass

Настроить сервис для запуска pg_receivewal.Пользователь root.
pg_receivewal.service
########################################################### /etc/systemd/system/# pg_receivewal.service[Unit]Description=Receiving for WAL stream[Service]Type=simpleWorkingDirectory=/postgres/scriptsUser=postgresGroup=postgresExecStart=/postgres/scripts/pg_receivewal.sh[Install]WantedBy=multi-user.target

Запускаем сервис.Пользователь root
systemctl daemon-reloadsystemctl start pg_receivewal.service

Проверяем.Пользователь root.
systemctl status pg_receivewal.service

В случае успешного старта получаем ответ
 pg_receivewal.service - Receiving for WAL stream   Loaded: loaded (/etc/systemd/system/pg_receivewal.service; disabled; vendor preset: disabled)   Active: active (running) since...

3. Заполнение тестовыми данными

Любым способом, на усмотрение читателя.

4. Создание базовой резервной копии.

Все стандартно и тривиально:
pg_basebackup  -D /postgres/backups/ --format=tar -Xs --progress --verbose

Получаем ответ о успешном выполнении:
pg_basebackup: initiating base backup, waiting for checkpoint to completepg_basebackup: checkpoint completedpg_basebackup: base backup completed

5. Имитируем катастрофу БД

Остановить сервер PostgreSQL любым способом.
Удалить папки файлов данных и WAL:
rm -rf /postgres/pgdatarm -rf /postgres/waldir

6. Восстановление БД

Создать папки файлов данных и WAL:
mkdir /postgres/pgdatachown postgres:postgres /postgres/pgdatachmod 750 /postgres/pgdata mkdir /postgres/waldirchown postgres:postgres /postgres/waldirchmod 750 /postgres/waldir

Восстановить файлы данных из базовой резервной копии:
cd /postgres/backups cp base.tar /postgres/pgdata cd /postgres/pgdata tar -xvf base.tar rm base.tar rm -r pg_wal ln -s /postgres/waldir pg_wal

В папке /postgres/wal_arc имеется неполный файл WAL(с расширением partial), нужно его переименовать, на случай если точка восстановления окажется в незаполненном файле WAL. Переименовать файл вручную или скриптом rename.sh:
/postgres/scripts/rename.sh

Для восстановления на заданную точку во времени необходимо подготовить файл recovery.conf:
restore_command = 'cp /postgres/wal_arc/%f  %p'recovery_target_time = '*****'recovery_target_action=promote

recovery_target_time задается требуемая временная точка восстановления в формате timestamp.

Запустить сервис PostgreSQL любым доступным способом.

Файл recovery.conf переименован в recovery.done ?
cd /postgres/pgdatals -la recovery.done

Если файл переименован-восстановление прошло успешно.

Дополнительно полезно убедиться, что лог файл содержит следующие строки:
starting point-in-time recovery to ...database system is ready to accept connections 


В случае успешного восстановления перезапускаем потоковую архивацию файлов WAL:
pg_receivewal --create-slot --slot=slot_receivewal --verbose
Пользователь root
systemctl start pg_receivewal.service


Итог:


В самом простом сценарии, База Данных восстановлена на требуемую точку во времени.
Подробнее..
Категории: Postgresql , Backup , Recovery

MS SQL Server BACKUP на стероидах

08.10.2020 22:10:01 | Автор: admin

Подождите! Подождите! Правда, это не очередная статья про типы бэкапов SQL Server. Я даже не буду рассказывать про отличия моделей восстановления и как бороться с разросшимся "логом".

Возможно (только возможно), после прочтения этого поста, вы сможете сделать так, чтобы бэкап, который снимается у вас стандартными средствами, завтра ночью снялся, ну, в 1.5 раза быстрее. И только за счёт того, что вы используете чуть-чуть больше параметров BACKUP DATABASE.

Если для вас содержимое поста было очевидным - извините. Я прочитал всё, до чего добрался гугл по фразе "habr sql server backup", и ни в одной статье не нашёл упоминания о том, что на время бэкапа можно каким-то образом повлиять с помощью параметров.

Было бы, конечно, круто, оказаться самым умным и выложить эксклюзивный контент, но это, к сожалению, не так. Есть и англоязычные, и русскоязычные статьи/посты (всегда путаюсь как их правильно называть), посвящённые этой теме. Вот часть из тех, что попались мне: раз, два, три (на sql.ru).

Итак, для начала приложу несколько урезанный синтаксис BACKUP из MSDN (кстати, там выше я писал про BACKUP DATABASE, но всё это применимо и к бэкапу журнала транзакций, и к дифференциальному бэкапу, но, возможно, с менее явным эффектом):

BACKUP DATABASE { database_name | @database_name_var }  TO <backup_device> [ ,...n ]  <...>  [ WITH { <...>           | <general_WITH_options> [ ,...n ] } ][;]<general_WITH_options> [ ,...n ]::=<...>--Media Set Options <...> | BLOCKSIZE = { blocksize | @blocksize_variable }--Data Transfer Options   BUFFERCOUNT = { buffercount | @buffercount_variable } | MAXTRANSFERSIZE = { maxtransfersize | @maxtransfersize_variable }<...>

<...> - значит, что там что-то было, но я это убрал, потому что сейчас это к теме не относится.

Как вы обычно снимаете бэкап? Как "учат" снимать бэкап в миллиардах статей? Вообще, если нужно будет разово снять бэкап какой-то не очень большой базы, я автоматически напишу что-то вроде вот такого:

BACKUP DATABASE smthTO DISK = 'D:\Backup\smth.bak'WITH STATS = 10, CHECKSUM, COMPRESSION, COPY_ONLY;--ладно, CHECKSUM я написал только чтобы казаться умнее

И, в общем-то, тут перечислено, наверное 75-90% всех параметров, которые обычно упоминаются в статьях о бэкапах. Ну там INIT, SKIP ещё. А вы ходили в MSDN? Вы видели, что там опций на полтора экрана? Я вот тоже видел...

Наверное, вы уже поняли, что дальше речь пойдёт о трёх параметрах, которые остались в первом блоке кода - BLOCKSIZE, BUFFERCOUNT и MAXTRANSFERSIZE. Вот их описания из MSDN:

BLOCKSIZE={blocksize|@blocksize_variable} указывает размер физического блока в байтах.Поддерживаются размеры 512, 1024, 2048, 4096, 8192, 16384, 32768 и 65536байт (64КБ).Значение по умолчанию равно 65536 для ленточных устройств и 512 для других устройств.Обычно в этом параметре нет необходимости, так как инструкция BACKUP автоматически выбирает размер блока, соответствующий устройству.Явная установка размера блока переопределяет автоматический выбор размера блока.

BUFFERCOUNT={buffercount|@buffercount_variable} определяет общее число буферов ввода-вывода, которые будут использоваться для операции резервного копирования.Можно указать любое целое положительное значение, однако большое число буферов может вызвать ошибку нехватки памяти из-за чрезмерного виртуального адресного пространства в процессе Sqlservr.exe.

Общий объем пространства, используемого буферами, определяется по следующей формуле:BUFFERCOUNT * MAXTRANSFERSIZE.

MAXTRANSFERSIZE={maxtransfersize|@maxtransfersize_variable} указывает наибольший объем пакета данных в байтах для обмена данными междуSQLServerи носителем резервного набора.Поддерживаются значения, кратные 65536 байтам (64КБ), вплоть до 4194304 байт (4МБ).

Клянусь - я читал это раньше, но мне и в голову не приходило, какое влияние на производительность они могут оказывать. Более того, видимо, нужно сделать своеобразный "каминг-аут" и признать, что даже сейчас я не до конца понимаю, что именно они делают. Наверное, надо побольше почитать про буферизированный ввод-вывод и работу с жёстким диском. Когда-нибудь я это сделаю, а сейчас могу просто написать скрипт, который проверит как эти значения влияют на скорость, с которой снимается бэкап.

Сделал небольшую базу, размером около 10 ГБ, положил её на SSD, а каталог для бэкапов положил на HDD.

Создаю временную таблицу для хранения результатов (у меня она не временная, чтобы можно было поковырять результаты подробнее, но вы уж сами решайте):

DROP TABLE IF EXISTS ##bt_results; CREATE TABLE ##bt_results (    id              int IDENTITY (1, 1) PRIMARY KEY,    start_date      datetime NOT NULL,    finish_date     datetime NOT NULL,    backup_size     bigint NOT NULL,    compressed_size bigint,    block_size      int,    buffer_count    int,    transfer_size   int);

Принцип работы скрипта простой - вложенные циклы, каждый из которых меняет значение одного параметра, подсовываю в команду BACKUP эти параметры, сохраняю последнюю запись с историей из msdb.dbo.backupset, удаляю файл бэкапа и следующая итерация. Поскольку данные о выполнении бэкапа берутся из backupset, точность несколько теряется (там нет долей секунд), но это мы переживём.

Сначала нужно разрешить использование xp_cmdshell, чтобы удалять бэкапы (потом не забудьте отключить, если он вам не нужен):

EXEC sp_configure 'show advanced options', 1;  EXEC sp_configure 'xp_cmdshell', 1;RECONFIGURE;EXEC sp_configure 'show advanced options', 0;  GO

Ну и, собственно:

DECLARE @tmplt AS nvarchar(max) = N'BACKUP DATABASE [bt]TO DISK = ''D:\SQLServer\backup\bt.bak''WITH     COMPRESSION,    BLOCKSIZE = {bs},    BUFFERCOUNT = {bc},    MAXTRANSFERSIZE = {ts}';DECLARE @sql AS nvarchar(max);/* BLOCKSIZE values */DECLARE @bs     int = 4096,         @max_bs int = 65536;/* BUFFERCOUNT values */DECLARE @bc     int = 7,        @min_bc int = 7,        @max_bc int = 800;/* MAXTRANSFERSIZE values */DECLARE @ts     int = 524288,   --512KB, default = 1024KB        @min_ts int = 524288,        @max_ts int = 4194304;  --4MBSELECT TOP 1     @bs = COALESCE (block_size, 4096),     @bc = COALESCE (buffer_count, 7),     @ts = COALESCE (transfer_size, 524288)FROM ##bt_resultsORDER BY id DESC;WHILE (@bs <= @max_bs)BEGIN    WHILE (@bc <= @max_bc)    BEGIN               WHILE (@ts <= @max_ts)        BEGIN            SET @sql = REPLACE (REPLACE (REPLACE(@tmplt, N'{bs}', CAST(@bs AS nvarchar(50))), N'{bc}', CAST (@bc AS nvarchar(50))), N'{ts}', CAST (@ts AS nvarchar(50)));            EXEC (@sql);            INSERT INTO ##bt_results (start_date, finish_date, backup_size, compressed_size, block_size, buffer_count, transfer_size)            SELECT TOP 1 backup_start_date, backup_finish_date, backup_size, compressed_backup_size,  @bs, @bc, @ts             FROM msdb.dbo.backupset            ORDER BY backup_set_id DESC;            EXEC xp_cmdshell 'del "D:\SQLServer\backup\bt.bak"', no_output;            SET @ts += @ts;        END                SET @bc += @bc;        SET @ts = @min_ts;        WAITFOR DELAY '00:00:05';    END    SET @bs += @bs;    SET @bc = @min_bc;    SET @ts = @min_ts;END

Если вдруг вам нужны пояснения по тому, что здесь происходит - пишите в комментарии, или личку. Пока расскажу только про параметры, которые подсовываю в BACKUP DATABASE.

Для BLOCKSIZE у нас "закрытый" список значений, причём у меня не выполнялся бэкап с BLOCKSIZE < 4КБ. MAXTRANSFERSIZE любое число кратное 64КБ - от 64КБ до 4МБ. По-умолчанию на моей системе 1024КБ, я взял 512 - 1024 - 2048 - 4096.

Сложнее было с BUFFERCOUNT - он может быть любым положительным числом, а вот по ссылке написано как он рассчитывается в BACKUP DATABASE и чем опасны большие значения. Там же написано как получить информацию о том, с каким BUFFERCOUNT реально снимается бэкап - у меня это 7. Уменьшать его смысла не было, а верхняя граница была обнаружена опытным путём - при BUFFERCOUNT = 896 и MAXTRANSFERSIZE = 4194304 бэкап упал с ошибкой (о которой написано по ссылке выше):

Msg 3013, Level 16, State 1, Line 7 BACKUP DATABASE is terminating abnormally.

Msg 701, Level 17, State 123, Line 7 There is insufficient system memory in resource pool 'default' to run this query.

Для сравнения, сначала покажу результаты выполнения бэкапа без указания параметров вообще:

BACKUP DATABASE [bt]TO DISK = 'D:\SQLServer\backup\bt.bak'WITH COMPRESSION;

Ну, бэкап и бэкап:

Processed 1070072 pages for database 'bt', file 'bt' on file 1.

Processed 2 pages for database 'bt', file 'bt_log' on file 1.

BACKUP DATABASE successfully processed 1070074 pages in 53.171 seconds (157.227 MB/sec).

Сам скрипт, тестирующий параметры, отработал за пару часов, все замеры в гугл таблице. А вот выборка результатов, имеющих три лучших времени выполнения (я пытался сделать красивый график, но, увы, придётся обойтись табличкой).

SELECT TOP 7 WITH TIES     compressed_size,     block_size,     buffer_count,     transfer_size,    DATEDIFF(SECOND, start_date, finish_date) AS backup_time_secFROM ##bt_resultsORDER BY backup_time_sec ASC;

Т.е. только за счёт управления стандартными параметрами BACKUP был получен выигрыш во времени снятия бэкапа в 2 раза: 26 секунд, против 53 в начале. А неплохо ведь, да? Но нужно посмотреть что там с восстановлением. А вдруг теперь восстанавливаться будет в 4 раза дольше?

Для начала замерим, сколько происходит восстановление бэкапа с настройками по умолчанию:

RESTORE DATABASE [bt]FROM DISK = 'D:\SQLServer\backup\bt.bak'WITH REPLACE, RECOVERY;

Ну это вы и сами знаете, пути там, replace-не replace, recovery-не recovery. И у меня выполняется это так:

Processed 1070072 pages for database 'bt', file 'bt' on file 1.

Processed 2 pages for database 'bt', file 'bt_log' on file 1.

RESTORE DATABASE successfully processed 1070074 pages in 40.752 seconds (205.141 MB/sec).

А теперь попробую восстановить бэкапы, снятые с изменёнными BLOCKSIZE, BUFFERCOUNT и MAXTRANSFERSIZE.

BLOCKSIZE = 16384, BUFFERCOUNT = 224, MAXTRANSFERSIZE = 4194304

RESTORE DATABASE successfully processed 1070074 pages in 32.283 seconds (258.958 MB/sec).

BLOCKSIZE = 4096, BUFFERCOUNT = 448, MAXTRANSFERSIZE = 4194304

RESTORE DATABASE successfully processed 1070074 pages in 32.682 seconds (255.796 MB/sec).

BLOCKSIZE = 16384, BUFFERCOUNT = 448, MAXTRANSFERSIZE = 2097152

RESTORE DATABASE successfully processed 1070074 pages in 32.091 seconds (260.507 MB/sec).

BLOCKSIZE = 4096, BUFFERCOUNT = 56, MAXTRANSFERSIZE = 4194304

RESTORE DATABASE successfully processed 1070074 pages in 32.401 seconds (258.015 MB/sec).

Инструкция RESTORE DATABASE при восстановлении не меняется, в ней не указываются эти параметры, SQL Server сам их определяет по бэкапу. И видно, что даже при восстановлении может быть выигрыш - практически на 20% быстрее (честно говоря, не много времени уделил восстановлению, протыкал несколько самых "быстрых" бэкапов и убедился, что ухудшения нет).

На всякий случай уточню - здесь описаны не какие-то оптимальные для всех параметры. Оптимальные параметры для себя вы можете получить только тестированием. Я получил такие результаты, вы получите другие. Но вы видите, что свои бэкапы можно "потюнить" и они реально могут формироваться и разворачиваться быстрее.

Ещё настоятельно рекомендую, прочитать-таки документацию целиком, потому что именно для вашей системы могут быть нюансы.


Раз уж начал писать про бэкапы, хочу сразу написать ещё об одной "оптимизации", которая встречается чаще, чем "тюнинг" параметров (её же, насколько я понимаю, использует как минимум часть утилит для резервного копирования, возможно, вместе с параметрами, описанными ранее), но на Хабре она тоже пока не была описана.

Если посмотреть на вторую строчку в документации, сразу под BACKUP DATABASE, там мы видим:

TO <backup_device> [ ,...n ]

Как вы думаете, что будет, если указать несколько backup_device'ов? Синтаксис ведь позволяет. А будет очень интересная вещь - бэкап просто "размажется" по нескольким девайсам. Т.е. каждый "девайс" по-отдельности будет бесполезен, потеряли один, потеряли весь бэкап. Но как такое размазывание скажется на скорости резервного копирования?

Попробуем сделать бэкап на два "девайса", которые лежат рядышком в одной папке:

BACKUP DATABASE [bt]TO     DISK = 'D:\SQLServer\backup\bt1.bak',    DISK = 'D:\SQLServer\backup\bt2.bak'   WITH COMPRESSION;

Батюшки-светы, да что ж это делается-то?

Processed 1070072 pages for database 'bt', file 'bt' on file 1.

Processed 2 pages for database 'bt', file 'btlog' on file 1.

BACKUP DATABASE successfully processed 1070074 pages in 40.092 seconds (208.519 MB/sec).

Бэкап сделался на 25% быстрее просто на ровном месте? А если ещё пару устройств добавить?

BACKUP DATABASE [bt]TO     DISK = 'D:\SQLServer\backup\bt1.bak',    DISK = 'D:\SQLServer\backup\bt2.bak',    DISK = 'D:\SQLServer\backup\bt3.bak',    DISK = 'D:\SQLServer\backup\bt4.bak'WITH COMPRESSION;

BACKUP DATABASE successfully processed 1070074 pages in 34.234 seconds (244.200 MB/sec).

Итого, выигрыш около 35% времени снятия бэкапа только за счёт того, что бэкап пишется сразу в 4 файла на одном диске. Проверял большее количество - на моём ноуте выигрыш отсутствует, оптимально - 4 устройства. Для вас - не знаю, нужно проверять. Ну и, кстати, если у вас эти устройства - это реально разные диски, поздравляю, выигрыш должен быть ещё значительнее.

Теперь поговорим как это счастье восстановить. Для этого придётся менять команду восстановления и перечислять все девайсы:

RESTORE DATABASE [bt]FROM     DISK = 'D:\SQLServer\backup\bt1.bak',    DISK = 'D:\SQLServer\backup\bt2.bak',    DISK = 'D:\SQLServer\backup\bt3.bak',    DISK = 'D:\SQLServer\backup\bt4.bak'WITH REPLACE, RECOVERY;

RESTORE DATABASE successfully processed 1070074 pages in 38.027 seconds (219.842 MB/sec).

Чуть-чуть быстрее, но где-то рядом, не существенно. В общем, бэкап снимается быстрее, а восстанавливается так же - успех? Как по мне - вполне себе успех. Это важно, поэтому повторюсь - если вы теряете хотя бы один из этих файлов - теряете весь бэкап.

Если посмотреть в журнале информацию о бэкапе, выводимую с помощью Trace Flag 3213 и 3605, то можно обратить внимание, что при бэкапе в несколько устройств, увеличивается, как минимум количество BUFFERCOUNT. Наверное, можно попробовать подобрать более оптимальные параметры и для BUFFERCOUNT, BLOCKSIZE, MAXTRANSFERSIZE, но у меня сходу не получилось, а проводить такое тестирование ещё раз, но для разного количества файлов я поленился. Да и диски жалко. Если вы хотите организовать такое тестирование у себя, скрипт переделать не сложно.


В конце поговорим о цене. Если бэкап снимается параллельно с работой пользователей - нужно очень ответственно подойти к тестированию, поскольку если бэкап снимается быстрее - диски напрягаются сильнее, нагрузка на процессор возрастает (надо же это всё ещё и сжимать налету), соответственно, снижается общая отзывчивость системы.

Шутки-шутками, но прекрасно понимаю, что никаких откровений не сделал. То, что написано выше - это просто демонстрация того, как можно подобрать оптимальные параметры для снятия бэкапов.

Помните, что всё, что вы делаете - вы делаете на свой страх и риск. Проверяйте свои резервные копии и не забывайте про DBCC CHECKDB.

Подробнее..

Eще один бэкап больше, чем скрипт, проще, чем система

28.07.2020 10:08:24 | Автор: admin
Систем резервного копирования множество, но что делать, если обслуживаемые сервера разбросаны по разным регионам и клиентам и нужно обходиться средствами операционной системы?



Добрый день, Habr!
Меня зовут Наталья. Я тимлид группы администраторов приложений в НПО Криста. Мы Ops для группы проектов нашей компании. У нас довольно своеобразная ситуация: мы устанавливаем и сопровождаем наше ПО как на серверах нашей компании, так и на серверах, расположенных у клиентов. При этом бэкапить сервер целиком нет необходимости. Важны лишь существенные данные: СУБД и отдельные каталоги файловой системы. Конечно, клиенты имеют (или не имеют) свои регламенты резервного копирования и часто предоставляют некое внешнее хранилище для складывания туда резервных копий. В этом случае после создания бэкапа мы обеспечиваем отправку во внешнее хранилище.

Какое-то время для целей бэкапа мы обходились bash-скриптом, но по мере разрастания вариантов настроек пропорционально росла и запутанность этого скрипта, и в один прекрасный момент мы пришли к необходимости его разрушить до основанья, а затем.....

Готовые решения не подошли по разным причинам: из-за необходимости децентрализации бэкапов, обязательности хранения бэкапов локально у клиента, сложности настройки, импортозамещения, ограничения доступа.

Нам показалось, что проще написать что-то своё. При этом хотелось получить что-то такое, чего хватит для нашей ситуации на следующие N лет, но с возможностью потенциального расширения области применения.

Условия задачи были следующие:
1. базовый инстанс бэкапа автономен, работает локально
2. хранение резервных копий и логов всегда в пределах сети клиента
3. инстанс состоит из модулей такой своеобразный конструктор
4. необходима совместимость с используемыми дистрибутивами Linux, включая устаревшие, желательна потенциальная кроссплатформенность
5. для работы с инстансом достаточно доступа по ssh, открытие дополнительных портов необязательно
6. максимальная простота настройки и эксплуатации
7. возможно (но не обязательно) существование отдельного инстанса, позволяющего централизованно просмотреть состояние бэкапов с разных серверов

То, что у нас получилось, можно посмотреть здесь: github.com/javister/krista-backup
ПО написано на python3; работает на Debian, Ubuntu, CentOS, AstraLinux 1.6.
Документация выложена в каталоге docs репозитария.

Основные понятия, которыми оперирует система:
action действие, реализующее одну атомарную операцию (бэкап БД, бэкап каталога, перенос из каталога А в каталог Б и т. д.). Существующие actions лежат в каталоге core/actions
task задание, набор actions, описывающий одну логическую задачу бэкапа
schedule расписание, набор task с опциональным указанием времени выполнения задачи

Конфигурация бэкапа хранится в yaml-файле; общая структура конфига:
общие настройки
раздел actions: описание действий, используемых на этом сервере
раздел schedule: описание всех заданий (наборов действий) и расписание их запуска по крону, если такой запуск требуется
Пример конфига можно посмотреть здесь: github.com/javister/krista-backup/blob/master/KristaBackup/config.yaml.example

Что умеет приложение на текущий момент:
поддерживаются основные для нас операции: бэкап PostgreSQL, бэкап каталога файловой системы через tar; операции с внешним хранилищем; rsync между каталогами; ротация бэкапов (удаление старых копий)
вызов внешнего скрипта
выполнение вручную отдельного задания
/opt/KristaBackup/KristaBackup.py run make_full_dump

можно добавить (или убрать) в кронтабе отдельное задание или все расписание
/opt/KristaBackup/KristaBackup.py enable all

генерация триггер-файла по результатам бэкапа. Эта функция полезна в связке с Zabbix для мониторинга бэкапов
может работать в фоне в режиме webapi или web
/opt/KristaBackup/KristaBackup.py web start [--api]


Разница между режимами: в webapi нет собственно веб-интерфейса, но приложение отвечает на запросы другого инстанса. Для режима web нужно установить flask и несколько дополнительных пакетов, а это не везде приемлемо, например в сертифицированной AstraLinux SE.

Через веб-интерфейс можно посмотреть состояние и логи бэкапов подключенных серверов: веб-инстанс запрашивает данные с бэкап-инстансов через API. Доступ к web требует авторизации, доступ к webapi нет.



Логи некорректно прошедших бэкапов размечаются цветом: warning желтым, error красным.





Если администратору не нужна шпаргалка по параметрам и серверные ОС однородны, можно скомпилировать файл и распространять уже готовый пакет.

Распространяем мы эту утилиту в основном через Ansible, выкатывая сначала на часть наименее важных серверов, а после тестирования на все остальные.

В итоге мы получили компактную автономную утилиту копирования, поддающуюся автоматизации и пригодную для эксплуатации даже малоопытными администраторами. Нам удобно может, пригодится и вам?
Подробнее..

Итоги конкурса Acronis True Image 2021 и еще немного о защите

28.08.2020 16:14:16 | Автор: admin
Вот и пришло время подвести итоги конкурса, который мы объявили 21 августа в посте, посвященном анонсу Acronis True Image 2021. Под катом имена победителей, а также еще немного информации о продукте и о потребностях в защите для персональных пользователей.

image

Прошлый пост, в котором мы рассказали о новшествах Acronis True Image 2021, вызвал достаточно большой отклик. Однако в комментариях были не только истории о реальных факапах с потерей данных, но также ряд вопросов, которые, судя по всему, волнуют многих. Поэтому сегодня мы ответим на основные из них и перейдем к чествованию победителей конкурса эпических фейлов.

Свой путь к российским пользователям


Сразу несколько хабровчан отметили, что ATI нельзя купить на глобальном сайте, если вы из России. И это чистая правда, потому что разработкой и локализацией Acronis True Image в России занимается ООО Акронис Инфозащита. Это российская компания, которая адаптирует технологии защиты данных и поддерживает продукт для российских пользователей. Версия Acronis True Image 2021 для российского рынка будет доступна осенью

image

С антивирусом?


В состав Acronis True Image входит антивирусная защита, но это не отдельный продукт, а встроенный в решение движок, который дополняет систему защиты данных. Возможность перехвата вирусов, шифровальщиков и других видов вредоносного ПО помогает не допустить незаметной порчи данных и удаления резервных копий, а также помогает автоматически восстановить оригинальные файлы в случае их повреждения.

Внедрение дополнительной защиты в продукт стало результатом реализации концепции SAPAS, включающей в себя 5 векторов киберзащиты безопасность, доступность, приватность, аутентичность и защищенность данных (SAPAS Safety, Accessibility, Privacy, Authenticity, Security). Таким образом удается дополнительно обезопасить информацию пользователей от порчи или утраты.

image

Однако никто не заставляет пользователей обязательно работать с этой возможностью. Вы можете отключить ее в настройках целиком или оставить лишь самую необходимую часть функций, полагаясь при этом на любую другую систему защиты от вредоносного ПО.\

Победители!


Что же, с формальностями мы разобрались. И теперь, та-да-ам! Пришло время наградить наших победителей. В комментариях своими историями поделились 8 человек:

  • s37 рассказал о том, как важно наличие бэкапа для систем видеонаблюдения, и как можно упустить подозреваемого в краже, если не сохранить вовремя данные с дисков в надежное место
  • shin_g поведал трогательную историю о потере игровых сейвов в далеком 2004 году. Наличие бэкапа, но не регулярного привело недавно к потере xls-таблицы c домашним бюджетом и историей покупок за несколько лет, а также библиотеки iTunes, в которой уже были отмечены в избранное более половины из ~10000 треков.
  • wmgeek рассказал о том, как злой шифровальщик прятался в установщике взломанного ПО Acronis. В результате были зашифрованы документы пользователя, и он стал загружать только лицензионное ПО.
  • CaptainFlint отметил, что важно не только иметь бэкапы, но и хранить их достаточно долгое время. Он бэкапил почтовую базу в Backblaze, но после крэша компьютера узнал, что часть диска была испорчена раньше, чем упала вся система. Но время хранения старых версий в базовом тарифе сервиса составляло всего один месяц, и часть писем оказалась безвозвратно утеряна. Буду апгрейдить тариф до годового срока хранения.
  • sukhe рассказал студенческую историю с отключением электричества в аудитории рубильником.
  • wyp4ik признался, что факапов с данными было много, но больше всего ему запомнилась атака трояна-шифровальщик Dharma на большую контору, состоящую из микропредприятийю. В итоге было зашифровано 5 сетевых папок разных микропредприятий и для некоторых сотрудников были потеряны файлы за 5 лет работы некоторых сотрудников. При этом для тех ПК, на которых стоял Acronis, все кончилось благополучно.
  • drWhy поделился опытом сложностей организации ручного резервного копирования в офисных условиях
  • ByashaCat рассказал об атаке почтового шифровальщика, а также об отсутствии денег у подростка на нормальный антивирус и вредоносное ПО в торрентах

Мы обещали наградить троих лучших, но нам, увы, не удалось выбрать их из 8 претендентов. Поэтому общим собранием было принято решение наградить всех! Так что стучитесь в личку, дорогие победители! Мы пришлем вам ключ от продукта.
Подробнее..

Как восстановить Sentry после не удачного обновления

22.07.2020 22:18:15 | Автор: admin
Всем привет. Я хочу рассказать о том, как проходило восстановление Sentry после неудачного обновления.

Что же такое Sentry?

Это система полного отслеживания ошибок с открытым исходным кодом, которая поддерживает широкий спектр серверных, браузерных, настольных и родных мобильных языков и сред, включая PHP, Node. js, Python, Ruby, C #, Java, Go, React, Angular, Vue, JavaScript и другие.

Немного о том как просто и не принуждённо всё поломалось.

Жили мы на версии 9.0.0 и пришло время обновиться. Пощупав web интерфейс 10.0.0 принял решение обновиться на неё. Это была самая большая ошибка!

Обновление прошло в штатном режиме. Сначала переход на 9.1.2 затем на 10.0.0 (иначе нельзя). Далее обнаружил что не запускается worker. Причиной этому добавление новых приложений и зависимостей.

Попытки собрать приложения и засунуть их в k8s не увенчались успехом.

Было принято решение откатиться назад. Но тут меня ждало разочарование. После миграции на 10 версию, часть данных переезжает в clickhouse и удаляется из Postgres.

После 3 часов работ и привлечения DBA эксперта данные были восстановлены до рабочего состояния.

Как?

Сделали рядом инстанс PG, закинули туда схему от версии 9.0.0 и начали потабличное восстановление. Конечно без ошибок и напильника тут не обошлось.

На этом история не заканчивается. Пришло время всё же обновиться, на версию 9.1.2.

Собрал образ, запускаю:

sentry upgrade

и видим вот такое чудесное сообщение:

 ! I'm not trusting myself; either fix this yourself by fiddling ! with the south_migrationhistory table, or pass --delete-ghost-migrations ! to South to have it delete ALL of these records (this may not be good).Exception in thread Thread-1 (most likely raised during interpreter shutdown)

После долгих поисков, проб и ошибок было найдено решение.

Необходимо восстановить схему данных текущей версии.

Для этого клонируем репозиторий:

git clone https://github.com/getsentry/onpremise.git

Переходим в ветку 9.1.2, так как ветки 9.0.0 уже нет.

cd onpremise && git checkout tags/9.1.2

Далее правим образ в Dockerfile:

#cat Dockerfile ARG SENTRY_IMAGEFROM ${SENTRY_IMAGE:-sentry:9.0.0}-onbuild
Затем правим compose file

docker-compose.yml
# NOTE: This docker-compose.yml is meant to be just an example of how# you could accomplish this on your own. It is not intended to work in# all use-cases and must be adapted to fit your needs. This is merely# a guideline.# See docs.getsentry.com/on-premise/server/ for full# instructionsversion: '3.4'x-defaults: &defaults  restart: unless-stopped  build:    context: .  depends_on:    - redis   # - postgres    - memcached    - smtp  env_file: .env  environment:    SENTRY_MEMCACHED_HOST: memcached    SENTRY_REDIS_HOST: redis    SENTRY_POSTGRES_HOST: 'sentry.cl.ats'    SENTRY_DB_USER: 'sentryDB'    SENTRY_DB_NAME: 'sentry_user'    SENTRY_DB_PASSWORD: 'sentry_passwd'    SENTRY_POSTGRES_PORT: 5432    SENTRY_EMAIL_HOST: smtp  volumes:    - sentry-data:/var/lib/sentry/filesservices:  smtp:    restart: unless-stopped    image: tianon/exim4  memcached:    restart: unless-stopped    image: memcached:1.5-alpine  redis:    restart: unless-stopped    image: redis:3.2-alpine  #postgres:  #  restart: unless-stopped  #  image: postgres:9.5  #  environment:  #    POSTGRES_HOST_AUTH_METHOD: 'trust'  #  volumes:  #    - sentry-postgres:/var/lib/postgresql/data  web:    <<: *defaults    ports:      - '9000:9000'  cron:    <<: *defaults    command: run cron  worker:    <<: *defaults    command: run workervolumes:    sentry-data:      external: true    #sentry-postgres:    #  external: true


Немного пояснений. Так как у меня есть отдельный инстанс базы данных, то создание через compose пропускаю, так же ненужен volume sentry-postgres.

После данных манипуляций запускаем сборку:

./install.sh 

В процессе может выскочить ошибка о которой я упомянул выше. Не обращаем внимания и после того как процесс закончится запускаем следующую команду:

docker-compose run --rm web sentry django migrate --delete-ghost-migrations

Примерный вывод
Creating network "onpremise_default" with the default driverCreating onpremise_memcached_1 ... doneCreating onpremise_smtp_1      ... doneCreating onpremise_redis_1     ... done21:30:26 [INFO] sentry.plugins.github: apps-not-configuredRunning migrations for sentry:- Nothing to migrate. - Loading initial data for sentry.Installed 0 object(s) from 0 fixture(s)Running migrations for nodestore:- Nothing to migrate. - Loading initial data for nodestore.Installed 0 object(s) from 0 fixture(s)Running migrations for search:- Nothing to migrate. - Loading initial data for search.Installed 0 object(s) from 0 fixture(s)Running migrations for social_auth:- Nothing to migrate. - Loading initial data for social_auth.Installed 0 object(s) from 0 fixture(s)Running migrations for tagstore:- Nothing to migrate. - Loading initial data for tagstore.Installed 0 object(s) from 0 fixture(s)Running migrations for jira_ac:- Nothing to migrate. - Loading initial data for jira_ac.Installed 0 object(s) from 0 fixture(s)Running migrations for hipchat_ac:- Nothing to migrate. - Loading initial data for hipchat_ac.Installed 0 object(s) from 0 fixture(s)


Далее можно запускать upgrade.

docker-compose run --rm web sentry upgrade

Stdout
Starting onpremise_smtp_1      ... doneStarting onpremise_memcached_1 ... doneStarting onpremise_redis_1     ... done21:30:48 [INFO] sentry.plugins.github: apps-not-configuredSyncing...Creating tables ...Installing custom SQL ...Installing indexes ...Installed 0 object(s) from 0 fixture(s)Synced: > django.contrib.admin > django.contrib.auth > django.contrib.contenttypes > django.contrib.messages > django.contrib.sessions > django.contrib.sites > django.contrib.staticfiles > crispy_forms > debug_toolbar > raven.contrib.django.raven_compat > rest_framework > sentry.plugins.sentry_interface_types > sentry.plugins.sentry_mail > sentry.plugins.sentry_urls > sentry.plugins.sentry_useragents > sentry.plugins.sentry_webhooks > sudo > south > sentry_plugins.slackNot synced (use migrations): - sentry - sentry.nodestore - sentry.search - social_auth - sentry.tagstore - sentry_plugins.jira_ac - sentry_plugins.hipchat_ac(use ./manage.py migrate to migrate these)Running migrations for sentry:- Nothing to migrate. - Loading initial data for sentry.Installed 0 object(s) from 0 fixture(s)Running migrations for nodestore:- Nothing to migrate. - Loading initial data for nodestore.Installed 0 object(s) from 0 fixture(s)Running migrations for search:- Nothing to migrate. - Loading initial data for search.Installed 0 object(s) from 0 fixture(s)Running migrations for social_auth:- Nothing to migrate. - Loading initial data for social_auth.Installed 0 object(s) from 0 fixture(s)Running migrations for tagstore:- Nothing to migrate. - Loading initial data for tagstore.Installed 0 object(s) from 0 fixture(s)Running migrations for jira_ac:- Nothing to migrate. - Loading initial data for jira_ac.Installed 0 object(s) from 0 fixture(s)Running migrations for hipchat_ac:- Nothing to migrate. - Loading initial data for hipchat_ac.Installed 0 object(s) from 0 fixture(s)Creating missing DSNsCorrecting Group.num_comments counter


И так, схема восстановлена. Можно обновиться на 9.1.2.

Для этого в Dockerfile меняем версию на 9.1.2:

ARG SENTRY_IMAGEFROM ${SENTRY_IMAGE:-sentry:9.1.2}-onbuild
И запускаем install.sh

./install.sh

Если всё сделано верно, то процесс завершится без ошибок. Вывод должен быть приметно такой:

Stdout
# ./install.sh Checking minimum requirements...Creating volumes for persistent storage...Created sentry-data..env already exists, skipped creation.Building and tagging Docker images...smtp uses an image, skippingmemcached uses an image, skippingredis uses an image, skippingBuilding webStep 1/2 : ARG SENTRY_IMAGEStep 2/2 : FROM ${SENTRY_IMAGE:-sentry:9.1.2}-onbuild# Executing 4 build triggers ---> Running in 6c97f9fcaf63DEPRECATION: Python 2.7 will reach the end of its life on January 1st, 2020. Please upgrade your Python as Python 2.7 won't be maintained after that date. A future version of pip will drop support for Python 2.7. More details about Python 2 support in pip, can be found at https://pip.pypa.io/en/latest/development/release-process/#python-2-supportRemoving intermediate container 6c97f9fcaf63 ---> Running in 9e0f65ee3af6Removing intermediate container 9e0f65ee3af6 ---> Running in 09754c44319cRemoving intermediate container 09754c44319c ---> a12fa31c2675Successfully built a12fa31c2675Successfully tagged onpremise_web:latestBuilding cronStep 1/2 : ARG SENTRY_IMAGEStep 2/2 : FROM ${SENTRY_IMAGE:-sentry:9.1.2}-onbuild# Executing 4 build triggers ---> Using cache ---> Using cache ---> Using cache ---> Using cache ---> a12fa31c2675Successfully built a12fa31c2675Successfully tagged onpremise_cron:latestBuilding workerStep 1/2 : ARG SENTRY_IMAGEStep 2/2 : FROM ${SENTRY_IMAGE:-sentry:9.1.2}-onbuild# Executing 4 build triggers ---> Using cache ---> Using cache ---> Using cache ---> Using cache ---> a12fa31c2675Successfully built a12fa31c2675Successfully tagged onpremise_worker:latestDocker images built.Generating secret key...Secret key written to .envSetting up database...Starting onpremise_smtp_1      ... doneStarting onpremise_redis_1     ... doneStarting onpremise_memcached_1 ... done21:35:07 [WARNING] sentry.utils.geo: settings.GEOIP_PATH_MMDB not configured.21:35:10 [INFO] sentry.plugins.github: apps-not-configuredSyncing...Creating tables ...Installing custom SQL ...Installing indexes ...Installed 0 object(s) from 0 fixture(s)Migrating...Running migrations for sentry: - Migrating forwards to 0472_auto__add_field_sentryapp_author. > sentry:0424_auto__add_field_integration_status > sentry:0425_auto__add_index_pullrequest_organization_id_merge_commit_sha > sentry:0425_remove_invalid_github_idps > sentry:0426_auto__add_sentryappinstallation__add_sentryapp__add_field_user_is_sent > sentry:0427_auto__add_eventattachment__add_unique_eventattachment_project_id_event > sentry:0428_auto__add_index_eventattachment_project_id_date_added > sentry:0429_auto__add_integrationexternalproject__add_unique_integrationexternalpr > sentry:0430_auto__add_field_organizationintegration_status > sentry:0431_auto__add_field_externalissue_metadata > sentry:0432_auto__add_field_relay_is_internal > sentry:0432_auto__add_index_userreport_date_added__add_index_eventattachment_date_ > sentry:0433_auto__add_field_relay_is_internal__add_field_userip_country_code__add_ > sentry:0434_auto__add_discoversavedqueryproject__add_unique_discoversavedqueryproj > sentry:0435_auto__add_field_discoversavedquery_created_by > sentry:0436_rename_projectdsymfile_to_projectdebugfile > sentry:0437_auto__add_field_sentryapp_status > sentry:0438_auto__add_index_sentryapp_status__chg_field_sentryapp_proxy_user__chg_ > sentry:0439_auto__chg_field_sentryapp_owner > sentry:0440_auto__del_unique_projectdebugfile_project_debug_id__add_index_projectd > sentry:0441_auto__add_field_projectdebugfile_data > sentry:0442_auto__add_projectcficachefile__add_unique_projectcficachefile_project_ > sentry:0443_auto__add_field_organizationmember_token_expires_at > sentry:0443_auto__del_dsymapp__del_unique_dsymapp_project_platform_app_id__del_ver > sentry:0444_auto__add_sentryappavatar__add_field_sentryapp_redirect_url__add_field > sentry:0445_auto__add_promptsactivity__add_unique_promptsactivity_user_feature_org > sentry:0446_auto__add_index_promptsactivity_project_id > sentry:0447_auto__del_field_promptsactivity_organization__add_field_promptsactivit > sentry:0448_auto__add_field_sentryapp_is_alertable > sentry:0449_auto__chg_field_release_owner > sentry:0450_auto__del_grouphashtombstone__del_unique_grouphashtombstone_project_ha > sentry:0451_auto__del_field_projectbookmark_project_id__add_field_projectbookmark_ > sentry:0452_auto__add_field_sentryapp_events > sentry:0452_auto__del_field_releaseenvironment_organization_id__del_field_releasee > sentry:0453_auto__add_index_releasefile_release_name > sentry:0454_resolve_duplicate_0452 > sentry:0455_auto__add_field_groupenvironment_first_seen > sentry:0456_auto__add_dashboard__add_unique_dashboard_organization_title__add_widg > sentry:0457_auto__add_field_savedsearch_is_global__chg_field_savedsearch_project__ > sentry:0457_auto__add_monitorcheckin__add_monitor__add_index_monitor_type_next_che > sentry:0458_global_searches_data_migrationSaved Searchs: 100% |########################################################################################################################################################################| Time: 0:00:07 > sentry:0459_global_searches_unique_constraint > sentry:0460_auto__add_field_servicehook_organization_id > sentry:0461_event_attachment_indexes > sentry:0462_auto__add_servicehookproject > sentry:0462_releaseenvironment_project_id > sentry:0463_backfill_service_hook_project > sentry:0464_auto__add_sentryappcomponent__add_field_sentryapp_schema > sentry:0464_groupenvironment_foreignkeys > sentry:0465_sync > sentry:0466_auto__add_platformexternalissue__add_unique_platformexternalissue_grou > sentry:0467_backfill_integration_status > sentry:0468_auto__add_field_projectdebugfile_code_id__add_index_projectdebugfile_p > sentry:0468_recent_search > sentry:0469_fix_state > sentry:0470_org_saved_search > sentry:0471_global_saved_search_types > sentry:0472_auto__add_field_sentryapp_authorThe following content types are stale and need to be deleted:    sentry | dsymobject    sentry | dsymapp    sentry | useridentity    sentry | dsymsymbol    sentry | dsymsdk    sentry | globaldsymfile    sentry | versiondsymfile    sentry | projectdsymfile    sentry | grouphashtombstone    sentry | minidumpfile    sentry | dsymbundleAny objects related to these content types by a foreign key will alsobe deleted. Are you sure you want to delete these content types?If you're unsure, answer 'no'.    Type 'yes' to continue, or 'no' to cancel: yesRunning migrations for sentry.nodestore:- Nothing to migrate.Running migrations for sentry.search:- Nothing to migrate.Running migrations for social_auth:- Nothing to migrate.Running migrations for sentry.tagstore:- Nothing to migrate.Running migrations for sentry_plugins.hipchat_ac:- Nothing to migrate.Running migrations for sentry_plugins.jira_ac:- Nothing to migrate.Synced: > django.contrib.admin > django.contrib.auth > django.contrib.contenttypes > django.contrib.messages > django.contrib.sessions > django.contrib.sites > django.contrib.staticfiles > crispy_forms > debug_toolbar > rest_framework > sentry.plugins.sentry_interface_types > sentry.plugins.sentry_mail > sentry.plugins.sentry_urls > sentry.plugins.sentry_useragents > sentry.plugins.sentry_webhooks > sudo > southMigrated: - sentry - sentry.nodestore - sentry.search - social_auth - sentry.tagstore - sentry_plugins.hipchat_ac - sentry_plugins.jira_acCreating missing DSNsCorrecting Group.num_comments counterCleaning up...----------------You're all done! Run the following command get Sentry running:  docker-compose up -d


Всё, версия 9.1.2 установлена.

Выводы.

Это всем известные прописные истины. Не спешите, делайте резервные копии и проверяйте всё несколько раз.

Благодарю за внимание!
Подробнее..

Как восстановить Sentry после неудачного обновления

23.07.2020 00:16:58 | Автор: admin
Всем привет. Я хочу рассказать о том, как проходило восстановление Sentry после неудачного обновления.

Что же такое Sentry?

Это система полного отслеживания ошибок с открытым исходным кодом, которая поддерживает широкий спектр серверных, браузерных, настольных и родных мобильных языков и сред, включая PHP, Node. js, Python, Ruby, C #, Java, Go, React, Angular, Vue, JavaScript и другие.

Немного о том, как просто и непринуждённо всё поломалось.

Жили мы на версии 9.0.0 и пришло время обновиться. Пощупав web интерфейс 10.0.0, принял решение обновиться на неё. Это была самая большая ошибка!

Обновление прошло в штатном режиме. Сначала переход на 9.1.2 затем, на 10.0.0 (иначе нельзя). Далее обнаружил, что не запускается worker. Причиной этому добавление новых приложений и зависимостей.

Попытки собрать приложения и засунуть их в k8s не увенчались успехом.

Было принято решение откатиться назад. Но тут меня ждало разочарование. После миграции на 10 версию, часть данных переезжает в clickhouse и удаляется из Postgres.

После 3 часов работ и привлечения DBA эксперта данные были восстановлены до рабочего состояния.

Как?

Сделали рядом инстанс PG, закинули туда схему от версии 9.0.0 и начали потабличное восстановление. Конечно, без ошибок и напильника тут не обошлось.

На этом история не заканчивается. Пришло время всё же обновиться на версию 9.1.2.

Собрал образ, запускаю:

sentry upgrade

и видим вот такое чудесное сообщение:

 ! I'm not trusting myself; either fix this yourself by fiddling ! with the south_migrationhistory table, or pass --delete-ghost-migrations ! to South to have it delete ALL of these records (this may not be good).Exception in thread Thread-1 (most likely raised during interpreter shutdown)

После долгих поисков, проб и ошибок было найдено решение.

Необходимо восстановить схему данных текущей версии.

Для этого клонируем репозиторий:

git clone https://github.com/getsentry/onpremise.git

Переходим в ветку 9.1.2, так как ветки 9.0.0 уже нет.

cd onpremise && git checkout tags/9.1.2

Далее правим образ в Dockerfile:

#cat Dockerfile ARG SENTRY_IMAGEFROM ${SENTRY_IMAGE:-sentry:9.0.0}-onbuild
Затем правим compose file

docker-compose.yml
# NOTE: This docker-compose.yml is meant to be just an example of how# you could accomplish this on your own. It is not intended to work in# all use-cases and must be adapted to fit your needs. This is merely# a guideline.# See docs.getsentry.com/on-premise/server/ for full# instructionsversion: '3.4'x-defaults: &defaults  restart: unless-stopped  build:    context: .  depends_on:    - redis   # - postgres    - memcached    - smtp  env_file: .env  environment:    SENTRY_MEMCACHED_HOST: memcached    SENTRY_REDIS_HOST: redis    SENTRY_POSTGRES_HOST: 'sentry.cl.ats'    SENTRY_DB_USER: 'sentryDB'    SENTRY_DB_NAME: 'sentry_user'    SENTRY_DB_PASSWORD: 'sentry_passwd'    SENTRY_POSTGRES_PORT: 5432    SENTRY_EMAIL_HOST: smtp  volumes:    - sentry-data:/var/lib/sentry/filesservices:  smtp:    restart: unless-stopped    image: tianon/exim4  memcached:    restart: unless-stopped    image: memcached:1.5-alpine  redis:    restart: unless-stopped    image: redis:3.2-alpine  #postgres:  #  restart: unless-stopped  #  image: postgres:9.5  #  environment:  #    POSTGRES_HOST_AUTH_METHOD: 'trust'  #  volumes:  #    - sentry-postgres:/var/lib/postgresql/data  web:    <<: *defaults    ports:      - '9000:9000'  cron:    <<: *defaults    command: run cron  worker:    <<: *defaults    command: run workervolumes:    sentry-data:      external: true    #sentry-postgres:    #  external: true


Немного пояснений. Так как у меня есть отдельный инстанс базы данных, то создание через compose пропускаю, также не нужен volume sentry-postgres.

После данных манипуляций запускаем сборку:

./install.sh 

В процессе может выскочить ошибка, о которой я упомянул выше. Не обращаем внимания и после того, как процесс закончится, запускаем следующую команду:

docker-compose run --rm web sentry django migrate --delete-ghost-migrations

Примерный вывод
Creating network "onpremise_default" with the default driverCreating onpremise_memcached_1 ... doneCreating onpremise_smtp_1      ... doneCreating onpremise_redis_1     ... done21:30:26 [INFO] sentry.plugins.github: apps-not-configuredRunning migrations for sentry:- Nothing to migrate. - Loading initial data for sentry.Installed 0 object(s) from 0 fixture(s)Running migrations for nodestore:- Nothing to migrate. - Loading initial data for nodestore.Installed 0 object(s) from 0 fixture(s)Running migrations for search:- Nothing to migrate. - Loading initial data for search.Installed 0 object(s) from 0 fixture(s)Running migrations for social_auth:- Nothing to migrate. - Loading initial data for social_auth.Installed 0 object(s) from 0 fixture(s)Running migrations for tagstore:- Nothing to migrate. - Loading initial data for tagstore.Installed 0 object(s) from 0 fixture(s)Running migrations for jira_ac:- Nothing to migrate. - Loading initial data for jira_ac.Installed 0 object(s) from 0 fixture(s)Running migrations for hipchat_ac:- Nothing to migrate. - Loading initial data for hipchat_ac.Installed 0 object(s) from 0 fixture(s)


Далее можно запускать upgrade.

docker-compose run --rm web sentry upgrade

Stdout
Starting onpremise_smtp_1      ... doneStarting onpremise_memcached_1 ... doneStarting onpremise_redis_1     ... done21:30:48 [INFO] sentry.plugins.github: apps-not-configuredSyncing...Creating tables ...Installing custom SQL ...Installing indexes ...Installed 0 object(s) from 0 fixture(s)Synced: > django.contrib.admin > django.contrib.auth > django.contrib.contenttypes > django.contrib.messages > django.contrib.sessions > django.contrib.sites > django.contrib.staticfiles > crispy_forms > debug_toolbar > raven.contrib.django.raven_compat > rest_framework > sentry.plugins.sentry_interface_types > sentry.plugins.sentry_mail > sentry.plugins.sentry_urls > sentry.plugins.sentry_useragents > sentry.plugins.sentry_webhooks > sudo > south > sentry_plugins.slackNot synced (use migrations): - sentry - sentry.nodestore - sentry.search - social_auth - sentry.tagstore - sentry_plugins.jira_ac - sentry_plugins.hipchat_ac(use ./manage.py migrate to migrate these)Running migrations for sentry:- Nothing to migrate. - Loading initial data for sentry.Installed 0 object(s) from 0 fixture(s)Running migrations for nodestore:- Nothing to migrate. - Loading initial data for nodestore.Installed 0 object(s) from 0 fixture(s)Running migrations for search:- Nothing to migrate. - Loading initial data for search.Installed 0 object(s) from 0 fixture(s)Running migrations for social_auth:- Nothing to migrate. - Loading initial data for social_auth.Installed 0 object(s) from 0 fixture(s)Running migrations for tagstore:- Nothing to migrate. - Loading initial data for tagstore.Installed 0 object(s) from 0 fixture(s)Running migrations for jira_ac:- Nothing to migrate. - Loading initial data for jira_ac.Installed 0 object(s) from 0 fixture(s)Running migrations for hipchat_ac:- Nothing to migrate. - Loading initial data for hipchat_ac.Installed 0 object(s) from 0 fixture(s)Creating missing DSNsCorrecting Group.num_comments counter


Итак, схема восстановлена. Можно обновиться на 9.1.2.

Для этого в Dockerfile меняем версию на 9.1.2:

ARG SENTRY_IMAGEFROM ${SENTRY_IMAGE:-sentry:9.1.2}-onbuild
И запускаем install.sh

./install.sh

Если всё сделано верно, то процесс завершится без ошибок. Вывод должен быть примерно такой:

Stdout
# ./install.sh Checking minimum requirements...Creating volumes for persistent storage...Created sentry-data..env already exists, skipped creation.Building and tagging Docker images...smtp uses an image, skippingmemcached uses an image, skippingredis uses an image, skippingBuilding webStep 1/2 : ARG SENTRY_IMAGEStep 2/2 : FROM ${SENTRY_IMAGE:-sentry:9.1.2}-onbuild# Executing 4 build triggers ---> Running in 6c97f9fcaf63DEPRECATION: Python 2.7 will reach the end of its life on January 1st, 2020. Please upgrade your Python as Python 2.7 won't be maintained after that date. A future version of pip will drop support for Python 2.7. More details about Python 2 support in pip, can be found at https://pip.pypa.io/en/latest/development/release-process/#python-2-supportRemoving intermediate container 6c97f9fcaf63 ---> Running in 9e0f65ee3af6Removing intermediate container 9e0f65ee3af6 ---> Running in 09754c44319cRemoving intermediate container 09754c44319c ---> a12fa31c2675Successfully built a12fa31c2675Successfully tagged onpremise_web:latestBuilding cronStep 1/2 : ARG SENTRY_IMAGEStep 2/2 : FROM ${SENTRY_IMAGE:-sentry:9.1.2}-onbuild# Executing 4 build triggers ---> Using cache ---> Using cache ---> Using cache ---> Using cache ---> a12fa31c2675Successfully built a12fa31c2675Successfully tagged onpremise_cron:latestBuilding workerStep 1/2 : ARG SENTRY_IMAGEStep 2/2 : FROM ${SENTRY_IMAGE:-sentry:9.1.2}-onbuild# Executing 4 build triggers ---> Using cache ---> Using cache ---> Using cache ---> Using cache ---> a12fa31c2675Successfully built a12fa31c2675Successfully tagged onpremise_worker:latestDocker images built.Generating secret key...Secret key written to .envSetting up database...Starting onpremise_smtp_1      ... doneStarting onpremise_redis_1     ... doneStarting onpremise_memcached_1 ... done21:35:07 [WARNING] sentry.utils.geo: settings.GEOIP_PATH_MMDB not configured.21:35:10 [INFO] sentry.plugins.github: apps-not-configuredSyncing...Creating tables ...Installing custom SQL ...Installing indexes ...Installed 0 object(s) from 0 fixture(s)Migrating...Running migrations for sentry: - Migrating forwards to 0472_auto__add_field_sentryapp_author. > sentry:0424_auto__add_field_integration_status > sentry:0425_auto__add_index_pullrequest_organization_id_merge_commit_sha > sentry:0425_remove_invalid_github_idps > sentry:0426_auto__add_sentryappinstallation__add_sentryapp__add_field_user_is_sent > sentry:0427_auto__add_eventattachment__add_unique_eventattachment_project_id_event > sentry:0428_auto__add_index_eventattachment_project_id_date_added > sentry:0429_auto__add_integrationexternalproject__add_unique_integrationexternalpr > sentry:0430_auto__add_field_organizationintegration_status > sentry:0431_auto__add_field_externalissue_metadata > sentry:0432_auto__add_field_relay_is_internal > sentry:0432_auto__add_index_userreport_date_added__add_index_eventattachment_date_ > sentry:0433_auto__add_field_relay_is_internal__add_field_userip_country_code__add_ > sentry:0434_auto__add_discoversavedqueryproject__add_unique_discoversavedqueryproj > sentry:0435_auto__add_field_discoversavedquery_created_by > sentry:0436_rename_projectdsymfile_to_projectdebugfile > sentry:0437_auto__add_field_sentryapp_status > sentry:0438_auto__add_index_sentryapp_status__chg_field_sentryapp_proxy_user__chg_ > sentry:0439_auto__chg_field_sentryapp_owner > sentry:0440_auto__del_unique_projectdebugfile_project_debug_id__add_index_projectd > sentry:0441_auto__add_field_projectdebugfile_data > sentry:0442_auto__add_projectcficachefile__add_unique_projectcficachefile_project_ > sentry:0443_auto__add_field_organizationmember_token_expires_at > sentry:0443_auto__del_dsymapp__del_unique_dsymapp_project_platform_app_id__del_ver > sentry:0444_auto__add_sentryappavatar__add_field_sentryapp_redirect_url__add_field > sentry:0445_auto__add_promptsactivity__add_unique_promptsactivity_user_feature_org > sentry:0446_auto__add_index_promptsactivity_project_id > sentry:0447_auto__del_field_promptsactivity_organization__add_field_promptsactivit > sentry:0448_auto__add_field_sentryapp_is_alertable > sentry:0449_auto__chg_field_release_owner > sentry:0450_auto__del_grouphashtombstone__del_unique_grouphashtombstone_project_ha > sentry:0451_auto__del_field_projectbookmark_project_id__add_field_projectbookmark_ > sentry:0452_auto__add_field_sentryapp_events > sentry:0452_auto__del_field_releaseenvironment_organization_id__del_field_releasee > sentry:0453_auto__add_index_releasefile_release_name > sentry:0454_resolve_duplicate_0452 > sentry:0455_auto__add_field_groupenvironment_first_seen > sentry:0456_auto__add_dashboard__add_unique_dashboard_organization_title__add_widg > sentry:0457_auto__add_field_savedsearch_is_global__chg_field_savedsearch_project__ > sentry:0457_auto__add_monitorcheckin__add_monitor__add_index_monitor_type_next_che > sentry:0458_global_searches_data_migrationSaved Searchs: 100% |########################################################################################################################################################################| Time: 0:00:07 > sentry:0459_global_searches_unique_constraint > sentry:0460_auto__add_field_servicehook_organization_id > sentry:0461_event_attachment_indexes > sentry:0462_auto__add_servicehookproject > sentry:0462_releaseenvironment_project_id > sentry:0463_backfill_service_hook_project > sentry:0464_auto__add_sentryappcomponent__add_field_sentryapp_schema > sentry:0464_groupenvironment_foreignkeys > sentry:0465_sync > sentry:0466_auto__add_platformexternalissue__add_unique_platformexternalissue_grou > sentry:0467_backfill_integration_status > sentry:0468_auto__add_field_projectdebugfile_code_id__add_index_projectdebugfile_p > sentry:0468_recent_search > sentry:0469_fix_state > sentry:0470_org_saved_search > sentry:0471_global_saved_search_types > sentry:0472_auto__add_field_sentryapp_authorThe following content types are stale and need to be deleted:    sentry | dsymobject    sentry | dsymapp    sentry | useridentity    sentry | dsymsymbol    sentry | dsymsdk    sentry | globaldsymfile    sentry | versiondsymfile    sentry | projectdsymfile    sentry | grouphashtombstone    sentry | minidumpfile    sentry | dsymbundleAny objects related to these content types by a foreign key will alsobe deleted. Are you sure you want to delete these content types?If you're unsure, answer 'no'.    Type 'yes' to continue, or 'no' to cancel: yesRunning migrations for sentry.nodestore:- Nothing to migrate.Running migrations for sentry.search:- Nothing to migrate.Running migrations for social_auth:- Nothing to migrate.Running migrations for sentry.tagstore:- Nothing to migrate.Running migrations for sentry_plugins.hipchat_ac:- Nothing to migrate.Running migrations for sentry_plugins.jira_ac:- Nothing to migrate.Synced: > django.contrib.admin > django.contrib.auth > django.contrib.contenttypes > django.contrib.messages > django.contrib.sessions > django.contrib.sites > django.contrib.staticfiles > crispy_forms > debug_toolbar > rest_framework > sentry.plugins.sentry_interface_types > sentry.plugins.sentry_mail > sentry.plugins.sentry_urls > sentry.plugins.sentry_useragents > sentry.plugins.sentry_webhooks > sudo > southMigrated: - sentry - sentry.nodestore - sentry.search - social_auth - sentry.tagstore - sentry_plugins.hipchat_ac - sentry_plugins.jira_acCreating missing DSNsCorrecting Group.num_comments counterCleaning up...----------------You're all done! Run the following command get Sentry running:  docker-compose up -d


Всё, версия 9.1.2 установлена.

Выводы.

Это всем известные прописные истины. Не спешите, делайте резервные копии и проверяйте всё несколько раз.

Благодарю за внимание!
Подробнее..

Из песочницы Миграция Jira Service Desk из облака на сервер

15.11.2020 18:09:06 | Автор: admin
Не буду спорить, что использование SaaS-ов, и в частности Jira Service Desk Cloud, удобно и облегчает работу системным администраторам. В целях безопасности или более гибкого управления сервисом, которое не предоставляет облако, может потребоваться перенос сервиса из облака на сервер организации.

Процесс миграции Jira Service Desk(JSD) можно условно разделить на три этапа:

  1. Подготовка резервной копии(бэкапа).
  2. Подготовка сервера. Установка программного обеспечения. Настройка.
  3. Развертывание бэкапа из облака на сервере.

К подготовке сервера можно отнести установку операционной системы на сервер, установку программного обеспечения, настройку. Сервер может быть как физическим, так и виртуальным. В моем случае будет использоваться CentOS 7, а программное обеспечение будет автоматически устанавливаться простым скриптом. Установка CentOS 7 описана не будет. Будем считать, что ОС уже установлена.

Технические требования к серверу можно посмотреть по ссылке.


1) Подготовка резервной копии.

Сделаем бэкап нашего облачного JSD.

Заходим в системные настройки облачного JSD, вкладка Управление резервным копированием.

image

Сделаем резервную копию сервера.

Выбираем полную миграцию сервера и загружаем резервную копию. На резервное копирование есть ограничение в 48 часов. То есть, после создания бэкапа, следующий можно будет сделать только через 2 дня.

2) Подготовка сервера. Установка программного обеспечения. Настройка.

Скрипт можно скачать тут любым удобным для вас способом.

Запускаем терминал или подключаемся к серверу по SSH.

Добавим права на выполнение скрипту командой:

sudo chmod +x soft_install_c7.sh

Запускаем скрипт командой:

sudo bash soft_install_c7.sh

image

Начнется обновление и затем установка программного обеспечения.

Кроме установки ПО скрипт создаст базу данных(БД) в Postgre Sql

При создании БД скрипт может ругнуться на доступ. Ничего страшного, база будет создана.

image

После завершения исполнения скрипта можно зайти в консоль Postgre Sql и убедится в этом.

image

В процессе исполнение скрипта необходимо будет ввести e-mail и пароль для настройки pgAdmin 4 и ответить на несколько вопросов.

image

Бинарный файл для установки JSD скачается и запустится автоматически. Необходимо будет ответить на несколько вопросов.

image

Порты для работы JSD можно оставить по умолчанию или выбрать другие.

Правила брандмауэра для корректной работы Apache, pgAdmin 4 и JSD добавятся автоматически. По умолчанию скрипт откроет порты 80, 8080 и 5432.

Добавить порт по своему усмотрению можно командой:

sudo firewall-cmd --zone=public add-port=порт/tcp permanent

Удалить порт можно командой:

sudo firewall-cmd --zone=public --remove-port=порт/tcp --permanent

Посмотреть все правила брандмауэра можно командой:

sudo firewall-cmd list-all или sudo iptables -L -n -v line-numbers

Для перезагрузки брандмауэра используйте команду:

sudo firewall-cmd --reload

image

Исполнение скрипта завершится сообщением DONE!

В завершении подготовки сервера можно подключить pgAdmin 4 к серверу Postgre Sql через адрес локальной петли 127.0.0.1, или как вам больше нравится. Измените настройки в pg_hba.conf на актуальные для вашей конфигурации, если это необходимо.

image

Логин и пароль для базы можно посмотреть в скрипте:

База: jsd_db
Пользователи:
Логин:jira Пароль:123
Логин:postgres Пароль:postgres

Можете изменить на свои значения перед запуском скрипта или после, непосредственно в Postgre Sql.

Не забудьте отключить SSL, если вы его не используете. Если pgAdmin 4 не будет соединяться с сервером, попробуйте перезагрузить службу.

sudo service postgresql-11 restart 

Информацию по базам данных вы можете найти в документации Atlassian.

3) Развертывание бэкапа из облака на сервере.

В браузере переходим по ip-адресу сервера с указанием порта. По умолчанию порт 8080. У меня это выглядит так 192.168.1.25:8080

Вы должны увидеть следующее.

image

Я выбираю пункт выполнить настройку самостоятельно и на следующей странице указываю настройки для базы данных. После подключение начнется создание базы данных это займет некоторое время.

image

После создания базы данных на следующей странице будет предложено импортировать данные или согласится с настройками и нажать далее.

image

Выбираем импортировать данные.

В полях открывшейся страницы указываем наименование бэкапа, лицензию(если необходимо) и настройки почты.

image

Можно сгенерировать триальную лицензию на месяц на сайте Atlassian. Для этого нужно будет зарегистрироваться на сайте. При генерации лицензии необходимо выбрать jira service desk (server).

Перед восстановлением JSD из бэкапа разместите бэкап на сервере в каталоге /var/atlassian/application-data/jira/import

Если указанные данные корректны, вы должны увидеть прогресс импорта данных.
Импорт займет некоторое время.

image

Вас приветствует страница входа, если все прошло хорошо. Осталось ввести логин и пароль.

image

По умолчанию логин sysadmin, пароль sysadmin.

После первого логина вы можете увидеть сообщения об обновлении, также необходимо будет выбрать язык и сделать настройки аккаунта(если необходимо). Чтобы были доступны проекты и задачи восстановленные из бэкапа, необходимо дать права учетной записи по умолчанию, либо поменять пароли учетным записям, которые были перенесены в бэкапе.

На этом перенос JSD из облака на сервер закончен.

Еще почитать о миграции можно тут.

Спасибо за внимание, всего хорошего и удачи!
Подробнее..

Как использовать объектное S3-хранилище Mail.ru Cloud Solutions для хранения бэкапов Veeam

07.12.2020 18:15:24 | Автор: admin
LogiMap ASRS Unit by Vidom

Veeam Backup & Replication коммерческая платформа для резервного копирования и управления данными облачной, виртуальной и физической среды. Она поддерживает разные сценарии хранения данных, в том числе использование S3-совместимых объектных хранилищ для хранения бэкапов, об одном из которых они сами недавно писали: про подключение к хранилищу MinIo.

Между тем, есть смысл использовать S3 в виде готового облачного сервиса, когда вы не хотите сами заниматься вопросами обслуживания и масштабирования хранилища. Сервис-провайдер даёт дополнительные функциональности (надёжность, безопасность и так далее) по стоимости ниже, чем большинство собственных инсталляций, за счёт массовости предоставления услуги.

Я покажу подключение Veeam к облачному объектному S3-хранилищу на примере Mail.ru Cloud Storage. Потому что я из этой команды :) Так что буду рад обратной связи по этому сценарию и самому сервису в комментариях.

Выбор в сторону объектного хранилища S3 в качестве хранилища бэкапов был вполне очевидным, так как:

  1. Стандарт де-факто.
  2. Многие производители уже реализовали в своих системах резервного копирования поддержку S3.
  3. Надежность.
  4. Низкая стоимость.

Тестовый стенд


Тестовый стенд:

  1. Виртуальная машина с Windows (установлена Windows-Server-2019Std-ru.202006) для установки Veeam.
  2. Виртуальная машина с Ubuntu 20.04 в качестве инстанса для бэкапа.
  3. Настроенный доступ и бакет в хранилище MCS S3.

Установку Veeam опустим, она хорошо описана в официальной документации. Я использовал для установки версию Veeam Backup & Replication Community Edition, с выписанной пробной лицензией на месяц. Community Edition не поддерживает создание Scale-Out Backup Repository.

Далее перейдем к настройке.

Подключение Object Storage


  1. Нажмите на Backup Repositories, далее правой кнопкой мыши вызовите Add Backup Repository:


  2. Выберите Object Storage:


  3. Выберите S3 Compatible:


  4. Введите имя хранилища и нажмите Next:


  5. В качестве Service point введите hb.bizmrg.com, регион default. Напротив Credentials нажмите Add:


  6. Введите свой Access Key ID и Secret Access Key для доступа к S3 MCS, нажмите OK:


  7. Выберите бакет и нажмите Browse напротив Folder для выбора папки, где в бакете будут храниться бэкапы:


  8. Выберите существующую папку или создайте новую и нажмите ОК:


  9. Если необходимо установить лимит места, которое могут занимать бэкапы, поставьте галочку Limit object storage consumption и установите лимит. Галочку immutable не ставьте, MCS S3 пока не поддерживает эту функцию. Нажмите Next:


  10. Создание объектного стораджа завершено:



Подключение Scale Out Backup Repository (SOBR)


Логика работы Veeam такова, что использовать напрямую объектное хранилище S3 нельзя, необходимо собрать расширяемое хранилище, состоящее из локального репозитория бэкапов и хранилища S3, куда будут переноситься бэкапы из локального хранилища, в соответствии с настроенной политикой переноса. Обратите внимание, что SOBR-хранилище недоступно в Community-версии приложения, необходима лицензия.

  1. Выберите в левой колонке Scale-Out Repositories и нажмите в поле справа правую кнопку мыши. Выберите Add scale-out backup repository:


  2. Введите имя репозитория и нажмите Next:


  3. Нажмите Add и добавьте локальное хранилище:


  4. Выберите политику размещения бэкапов либо хранение полных и инкрементальных бэкапов вместе, либо разнесение их по хранилищам. Нажмите Next:


  5. Поставьте галочку Extend scale-out backup repository capacity with object storage и добавьте созданное ранее объектное хранилище. Ниже настраивается политика работы как видно на скриншоте, у нас настроено сразу же переносить вновь созданные бэкапы в S3, а также переносить уже существующие бэкапы старше 7 дней. Нажмите Apply:


  6. SOBR-хранилище успешно создано:



Настройка бэкапа Linux-сервера


Настроим бэкап тестового сервера Linux. Для бэкапа Veeam должен установить свой агент на Linux-сервер.

  1. Добавим данные сервера Linux, который мы хотим бекапить. Нажмите в нижнем левом углу экрана на Home, в верхнем левом углу на Backup Job и выберите Linux computer:


  2. Выберите Server и Managed by backup server. Настраивать задания можно как централизованно, так и на серверах, которые мы хотим бэкапить, в настройках Veeam-агента. В данном случае настроим управление со стороны сервера Veeam:


  3. Выберите название нового задания и нажмите Next:


  4. Нажмите на Add и выберите Individual computer:


  5. Введите имя или IP-адрес Linux-сервера, который будем бэкапить, напротив Credentials нажмите Add. В выпадающем меню выберите тип авторизации по паролю или по ключу. В нашем случае по ключу:


  6. Введите имя пользователя, выберите на диске предварительно сохраненный файл с приватным ключом к серверу. Приватный ключ формируется при заказе инстанса в панели управления MCS. Установите галочку Elevate account privileges automatically, нажмите OK:


  7. Выберите, что бэкапить в данном случае весь сервер. Нажмите Next:


  8. Выберите хранилище, куда будут помещены бэкапы. В нашем случае настроенное ранее Scale-Out Backup Repository. Нажмите Next:


  9. Настройте расписание запуска и нажмите Apply:


  10. Если необходим немедленный запуск задания, установите галочку Run the job when I click Finish. Нажмите Finish:



После окончания настройки Veeam сразу запустит проверку наличия агента на сервере, который мы добавили и установит его при необходимости. После этого начнется первый бэкап.

Прогресс бэкапа можно увидеть, если нажать на Last 24 Hours/Running и выбрать созданное нами бэкап-задание Ubuntu1:



После окончания бэкапа в web-интерфейсе S3 MCS можно увидеть, что Veeam создал папку с бэкапом сервера:



На этом настройка закончена, удачи!

В нашем телеграм-канале новости об этом и других сервисах на облачной платформе Mail.ru Cloud Solutions.

Еще про использование S3-хранилища:

Подробнее..

Категории

Последние комментарии

  • Имя: Макс
    24.08.2022 | 11:28
    Я разраб в IT компании, работаю на арбитражную команду. Мы работаем с приламы и сайтами, при работе замечаются постоянные баны и лаги. Пацаны посоветовали сервис по анализу исходного кода,https://app Подробнее..
  • Имя: 9055410337
    20.08.2022 | 17:41
    поможем пишите в телеграм Подробнее..
  • Имя: sabbat
    17.08.2022 | 20:42
    Охренеть.. это просто шикарная статья, феноменально круто. Большое спасибо за разбор! Надеюсь как-нибудь с тобой связаться для обсуждений чего-либо) Подробнее..
  • Имя: Мария
    09.08.2022 | 14:44
    Добрый день. Если обладаете такой информацией, то подскажите, пожалуйста, где можно найти много-много материала по Yggdrasil и его уязвимостях для написания диплома? Благодарю. Подробнее..
© 2006-2024, personeltest.ru