Percona Server и Percona XtraBackup в docker-контейнере

Jul 31, 2017 10:00 · 856 words · 5 minute read percona docker backup

Со стремительным ростом популярности docker-контейнеров уже никого не удивить, например, запуском Percona Server в docker’е. Однако на просторах Интернета не так уж много подробных инструкций о том, как делать резервные копии (и восстанавливаться из них), если ваш MySQL-сервер запущен в docker-контейнере.

Давайте разберемся с запуском Percona Server в docker’е и рассмотрим вариант создания бекапов с помощью утилиты Percona XtraBackup!

Итак, нам понадобятся два docker-контейнера — один непосредственно для MySQL-сервера, второй — для создания резервных копий. В качестве MySQL-сервера будем использовать Percona Server 5.7, контейнеры будем собирать самостоятельно — это несложно.

Создадим каталог, в котором будет находиться все необходимое для основного контейнера (назовем его percona):

mkdir /percona

В данном каталоге у нас будут находится инструкции по сборке контейнера (Dockerfile), конфигурационный файл для MySQL-сервера (my.cnf), файл docker-compose.yml для запуска контейнера (не люблю вводить длиннющие команды вида docker run ...) и файл с переменными окружения, которые будут использоваться при запуске контейнера (.env).

Давайте рассмотрим содержимое данных файлов, Dockerfile выглядит так:

FROM percona:5.7
 
RUN chown -R mysql:mysql /var/lib/mysql/
 
ADD my.cnf /etc/mysql/conf.d/my.cnf
 
CMD ["mysqld"]
 
EXPOSE 3306

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

[client]
socket                                      = /var/run/mysqld/mysqld.sock
 
[mysqld]
socket                                      = /var/run/mysqld/mysqld.sock
pid-file                                    = /var/run/mysqld/mysqld.pid
user                                        = mysql
basedir                                     = /usr
datadir                                     = /var/lib/mysql
tmpdir                                      = /var/lib/mysql-tmp
sql-mode                                    = "STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION"
sysdate-is-now                              = 0
transaction-isolation                       = REPEATABLE-READ
default-storage-engine                      = InnoDB
event-scheduler                             = OFF
performance_schema                          = 0
collation-server                            = utf8_general_ci
character-set-server                        = utf8
 
### Percona specific general options
expand_fast_index_creation                  = OFF
userstat                                    = OFF
thread_statistics                           = OFF
 
### Connectivity options
port                                        = 3306
max_user_connections                        = 400
secure-auth                                 = ON
back_log                                    = 2048
skip-name-resolve                           = 0
max_connect_errors                          = 1000000
read_only                                   = OFF
bind-address                                = ::
max_allowed_packet                          = 16777216
wait_timeout                                = 14400
max_connections                             = 500
thread_cache_size                           = 64
net_write_timeout                           = 60
net_read_timeout                            = 30
safe-user-create                            = 1
interactive_timeout                         = 14400
 
### General caches
key_buffer_size                             = 16777216
query_cache_size                            = 0
tmp_table_size                              = 16777216
max_heap_table_size                         = 16777216
table_open_cache                            = 8192
query_cache_type                            = 0
 
### InnoDB options
innodb_buffer_pool_size                     = 512M
innodb_open_files                           = 1024
innodb_flush_method                         = O_DIRECT
innodb_log_file_size                        = 64M
innodb_read_io_threads                      = 4
innodb_file_format                          = Barracuda
innodb_old_blocks_time                      = 1000
innodb_autoinc_lock_mode                    = 2
innodb_io_capacity                          = 200
innodb_log_buffer_size                      = 8M
innodb_stats_on_metadata                    = OFF
innodb_thread_concurrency                   = 0
innodb_support_xa                           = ON
innodb_buffer_pool_instances                = 1
innodb_concurrency_tickets                  = 10000
innodb_write_io_threads                     = 4
innodb                                      = force
innodb_file_per_table                       = ON
innodb_flush_log_at_trx_commit              = 2
 
### Logging options
general_log_file                            = /var/log/mysql/mysql_general.log
log-error                                   = /var/log/mysql/mysql_error.log
slow_query_log_file                         = /var/log/mysql/mysql_slow.log
log-warnings                                = 1
log-queries-not-using-indexes               = ON
long_query_time                             = 2
log-slow-admin-statements                   = 1
log-slow-slave-statements                   = 1
general-log                                 = OFF
slow-query-log                              = ON
 
### Percona specific logging options
log_slow_rate_type                          = session
slow_query_log_use_global_control           = log_slow_filter,log_slow_rate_limit,log_slow_verbosity,long_query_time,min_examined_row_limit
log_slow_sp_statements                      = ON
log_slow_filter                             = ''
log_slow_verbosity                          = microtime,query_plan
log_slow_rate_limit                         = 1
slow_query_log_always_write_time            = 10
 
[mysqld_safe]
log-error                                   = /var/log/mysql/mysql_error.log

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

### Data Path for all storage systems.
DATA_SAVE_PATH=/srv
### Percona ############################################################################################################
PERCONA_DATABASE=test_db
PERCONA_USER=testuser
PERCONA_PASSWORD=testpassword
PERCONA_PORT=3306
PERCONA_ROOT_PASSWORD=rootpassword

И, наконец, docker-compose.yml содержит такие строки:

version: '2'
services:
### Percona Container ########################################
    percona:
        container_name: percona
        image: my-percona-test:latest
        environment:
            - MYSQL_DATABASE=${PERCONA_DATABASE}
            - MYSQL_USER=${PERCONA_USER}
            - MYSQL_PASSWORD=${PERCONA_PASSWORD}
            - MYSQL_ROOT_PASSWORD=${PERCONA_ROOT_PASSWORD}
        volumes:
            - ${DATA_SAVE_PATH}/percona:/var/lib/mysql
        ports:
            - "${PERCONA_PORT}:3306"

Для сборки образа, находясь в каталоге /percona, запускаем команду:

docker build -t my-percona-test:latest .

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

docker-compose up -d

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

mkdir /xtrabackup

В данном каталоге у нас будут находиться инструкции по сборке контейнера (Dockerfile) и два скрипта — один для создания бекапа (make_backup.sh), второй для восстановления данных (make_backup.sh).

Содержимое Dockerfile следующее:

FROM percona:5.7
 
RUN apt-get update && \
    apt-get install -y --no-install-suggests pigz percona-xtrabackup-24 && \
    rm -rf /var/lib/apt/lists/*
 
RUN mkdir -p /backups
 
ADD make_backup.sh /make_backup.sh
ADD restore_backup.sh /restore_backup.sh
 
VOLUME ["/backups"]

Содержимое скрипта создания бекапа:


BACKUP="/usr/bin/innobackupex"
workdir="/backups/"
OPTIONS="--host=percona --port=3306 --user=root --password=rootpassword"
dump="mysql.tar"

# при распаковке использовать ключ -i, например tar -ixvf backup.tar
$BACKUP $OPTIONS --stream=tar ./ | pigz -p 5 > ${workdir}${dump}.gz

Скрипт для восстановления данных из резервной копии выглядит так:

backupdir="/backups/"
archive="mysql.tar.gz"
mysqldir="/var/lib/mysql/"
 
cd $mysqldir && rm -rf *
cd $backupdir && tar -ixvf $archive -C $mysqldir
cd $mysqldir && innobackupex --apply-log --ibbackup=xtrabackup ./
chown -R 999:999 $mysqldir

Собираем контейнер (находясь в каталоге с Dokerfile) командой:

docker build -t my-xtrabackup:latest .

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

docker run -it --net=docker_default --link percona:percona --name=xtrabackup -v /srv/percona:/var/lib/mysql -v /srv/backups:/backups --rm my-xtrabackup:latest sh -c 'exec /make_backup.sh'

Даная команда запускает контейнер из собранного нами образа (my-xtrabackup:latest), присваивает ему имя xtrabackup, назначает ему такую же локальную сеть, как и в запущенного ранее контейнера с Percona Server, связывает контейнеры с помощью опции --link, пробрасывает внутрь контейнера каталоги /srv/percona и /srv/backups с хост-машины (в одном находятся БД, второй используется для хранения бекапов) и выполняет скрипт make_backup.sh. После после выполнения скрипта (когда бекап будет создан) контейнер будет удален, благодаря использованию опции --rm.

Чтобы восстановить данные из резервной копии, следует использовать такую команду (контейнер с Percona Server должен быть выключен во избежание возможных конфликтов):

docker run -it --name=xtrabackup -v /srv/percona:/var/lib/mysql -v /srv/backups:/backups --rm my-xtrabackup:latest sh -c 'exec /restore_backup.sh'

Данная команда очень похожа на предыдущую, разница лишь в выполняемом скрипте и в отсутствии параметров --net=docker_default --link percona:percona — они нам не нужны, так как контейнер с MySQL-сервером выключен.

tweet Share