Amazon Web Services è un gigante della tecnologia, soprattutto quando si tratta di aprire la strada ai servizi di cloud computing top di gamma. I suoi prodotti di servizi completamente gestiti (Amazon RDS) sono unici nel loro genere. Ma poi di nuovo, mentre può essere una piattaforma perfetta per alcune organizzazioni, può essere una sfida uscirne se non lo è. Ci sono sempre preoccupazioni di rimanere bloccati in una situazione di blocco del fornitore.
Alcuni aspetti da tenere a mente durante la migrazione da RDS a una piattaforma on-premise sono i vincoli di budget, la sicurezza e l'autonomia dei dati. Questo perché i dati sono la tua risorsa più preziosa e mantenendo il controllo ovunque risiedano, è sempre fondamentale che l'organizzazione e l'azienda rimangano sempre competitive. Nessuna organizzazione può permettersi di avere il cloud lock-in, eppure molte aziende si trovano esattamente in quella situazione e iniziano a cercare soluzioni alternative esistenti che possano essere utilizzate in locale.
Questo blog ti spiegherà come migrare da Amazon RDS verso un server in loco. Il nostro database di destinazione sul server locale si trova su un server Linux RHEL/CentOS, ma la procedura applicabile si applica ad altre versioni di Linux, purché i pacchetti siano installati correttamente.
Ci sono alcune soluzioni esistenti di terze parti che offrono la migrazione dei dati ma non è applicabile per una piattaforma on-premise. Inoltre, non è gratuito e migrare utilizzando gratuitamente con soluzioni open source è sempre favorevole e vantaggioso. Sebbene esistano anche dubbi e preoccupazioni poiché la garanzia e il supporto non sono vincolati alle tecnologie open source, ma ti mostreremo qui come ottenere ciò in una procedura semplice.
Poiché Amazon RDS supporta la compatibilità con MySQL e MariaDB. Ci concentreremo su di loro per questo blog.
Migrazione da Amazon RDS per MySQL o MariaDB
Un approccio tipico alla migrazione dei dati da Amazon RDS a un server in loco consiste nell'eseguire un backup utilizzando una copia logica. Questo può essere fatto utilizzando soluzioni di utilità di backup compatibili per funzionare con Amazon RDS, che è un servizio completamente gestito. I servizi di database completamente gestiti non offrono accessi SSH, quindi la copia fisica dei backup non è un'opzione.
Utilizzo di mysqldump
L'uso di mysqldump deve essere installato nel nodo del database di destinazione situato in locale. Deve essere preparato come una replica del nodo AWS RDS in modo che tutte le transazioni successive vengano replicate nel nodo. Per fare ciò, segui i passaggi seguenti.
Host sorgente AWS RDS :database-1.xxxxxxx.us-east-2.rds.amazonaws.com
Host server in loco :192.168.10.226 (testnode26)
Prima di avviare il dump, assicurati che le ore di conservazione del binlog siano impostate. Per impostarlo, puoi eseguire la procedura di esempio chiamata di seguito nella tua istanza Amazon RDS,
mysql> call mysql.rds_set_configuration('binlog retention hours', 24);
Query OK, 2 rows affected (0.23 sec)
mysql> CALL mysql.rds_show_configuration;
+------------------------+-------+------------------------------------------------------------------------------------------------------+
| name | value | description |
+------------------------+-------+------------------------------------------------------------------------------------------------------+
| binlog retention hours | 24 | binlog retention hours specifies the duration in hours before binary logs are automatically deleted. |
+------------------------+-------+------------------------------------------------------------------------------------------------------+
1 row in set (0.23 sec)
Query OK, 0 rows affected (0.23 sec)
Installa mysqldump
-
Prepara il repository.
# Per MySQL
$ yum install https://dev.mysql.com/get/mysql80-community-release-el7-3.noarch.rpm
# Per MariaDB
$ curl -sS https://downloads.mariadb.com/MariaDB/mariadb_repo_setup | sudo bash
-
Installa il pacchetto mysql-client
# Per MySQL
$ yum install -y mysql-community-client.x86_64
# Per MariaDB
$ yum install -y MariaDB-client
-
Crea un dump di dati usando mysqldump eseguendolo all'interno del nodo di destinazione. Prendi nota, con --master-data=2 specificato come opzione, funziona solo per MariaDB ma non in MySQL. Quindi è necessario fare del lavoro extra per MySQL. Ne parleremo più tardi.
## Applicabile per l'approccio MariaDB
[[email protected] ~]# mysqldump -h database-1.xxxxxxx.us-east-2.rds.amazonaws.com -uadmin -p --single-transaction --master-data=2 --databases db1 db2 db3 > backups/dump.sql
Enter password:
[[email protected] ~]# ls -alth backups/dump.sql
-rw-r--r--. 1 root root 196M Oct 18 02:34 backups/dump.sql
-
Installa il server MySQL/MariaDB nel nodo del database di destinazione
# Per MySQL (controlla sempre quale repository di versione è abilitato nel tuo repository yum. A questo punto sto usando MySQL 5.7)
$ yum --disablerepo=* --enablerepo=mysql57-community install mysql-community-common mysql-community-client mysql-community-server
# Per MariaDB
$ yum install MariaDB-server.x86_64
-
Configura l'istanza del server MySQL/MariaDB (my.cnf, autorizzazioni file, directory) e avvia il server
# Configurazione di my.cnf (usando la distribuzione my.cnf utilizzata da ClusterControl)
[MYSQLD]
user=mysql
basedir=/usr/
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
pid_file=/var/lib/mysql/mysql.pid
port=3306
log_error=/var/log/mysql/mysqld.log
log_warnings=2
slow_query_log_file=/var/log/mysql/mysql-slow.log
long_query_time=2
slow_query_log=OFF
log_queries_not_using_indexes=OFF
innodb_buffer_pool_size=2G
innodb_flush_log_at_trx_commit=2
innodb_file_per_table=1
innodb_data_file_path=ibdata1:100M:autoextend
innodb_read_io_threads=4
innodb_write_io_threads=4
innodb_doublewrite=1
innodb_log_file_size=256M
innodb_log_buffer_size=32M
innodb_buffer_pool_instances=1
innodb_log_files_in_group=2
innodb_thread_concurrency=0
innodb_flush_method=O_DIRECT
innodb_rollback_on_timeout=ON
innodb_autoinc_lock_mode=2
innodb_stats_on_metadata=0
default_storage_engine=innodb
server_id=1126
binlog_format=ROW
log_bin=binlog
log_slave_updates=1
relay_log=relay-bin
expire_logs_days=7
read_only=OFF
report_host=192.168.10.226
key_buffer_size=24M
tmp_table_size=64M
max_heap_table_size=64M
max_allowed_packet=512M
skip_name_resolve=true
memlock=0
sysdate_is_now=1
max_connections=500
thread_cache_size=512
query_cache_type=0
query_cache_size=0
table_open_cache=1024
lower_case_table_names=0
performance_schema=OFF
performance-schema-max-mutex-classes=0
performance-schema-max-mutex-instances=0
[MYSQL]
socket=/var/lib/mysql/mysql.sock
[client]
socket=/var/lib/mysql/mysql.sock
[mysqldump]
socket=/var/lib/mysql/mysql.sock
max_allowed_packet=512M
## Reimposta la directory dei dati e reinstalla i file di sistema del database
$ rm -rf /var/lib/mysql/*
## Crea le directory dei log
$ mkdir /var/log/mysql
$ chown -R mysql.mysql /var/log/mysql
## Per MySQL
$ mysqld --initialize
## Per MariaDB
$ mysql_install_db
-
Avvia il server MySQL/MariaDB
## Per MySQL
$ systemctl start mysqld
## Per MariaDB
$ systemctl start mariadb
-
Carica il dump dei dati che abbiamo preso da AWS RDS nel nodo del database di destinazione in locale
$ mysql --show-warnings < backups/dump.sql
-
Crea l'utente di replica dal nodo di origine AWS RDS
MariaDB [(none)]> CREATE USER 'repl_user'@'149.145.213.%' IDENTIFIED BY 'repl_passw0rd';
Query OK, 0 rows affected (0.242 sec)
MariaDB [(none)]> GRANT REPLICATION CLIENT, REPLICATION SLAVE ON *.* TO repl_user'@'149.145.213.%' IDENTIFIED BY 'repl_passw0rd' ;
Query OK, 0 rows affected (0.229 sec)
-
Configura il server MySQL/MariaDB come replica/slave del nodo di origine AWS RDS
## Innanzitutto, cerchiamo o individuiamo il comando CHANGE MASTER
[[email protected] ~]# grep -rn -E -i 'change master to master' backups/dump.sql |head -1
22:-- CHANGE MASTER TO MASTER_LOG_FILE='mysql-bin-changelog.000584', MASTER_LOG_POS=421;
## Eseguire l'istruzione CHANGE MASTER ma aggiungere l'utente/password di replica e il nome host come segue,
MariaDB [(none)]> CHANGE MASTER TO MASTER_HOST='database-1.xxxxxxx.us-east-2.rds.amazonaws.com', MASTER_LOG_FILE='mysql-bin-changelog.000584', MASTER_LOG_POS=421, MASTER_USER='repl_user', MASTER_PASSWORD='repl_passw0rd';
Query OK, 0 rows affected (0.004 sec)
## Quindi avvia i thread slave
MariaDB [(none)]> START SLAVE;
Query OK, 0 rows affected (0.001 sec)
## Controlla lo stato dello slave come va
MariaDB [(none)]> SHOW SLAVE STATUS \G
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: database-1.xxxxxxx.us-east-2.rds.amazonaws.com
Master_User: repl_user
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin-changelog.000584
Read_Master_Log_Pos: 421
Relay_Log_File: relay-bin.000001
Relay_Log_Pos: 4
Relay_Master_Log_File: mysql-bin-changelog.000584
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
Replicate_Do_DB:
Replicate_Ignore_DB:
Replicate_Do_Table:
Replicate_Ignore_Table:
Replicate_Wild_Do_Table:
Replicate_Wild_Ignore_Table:
Last_Errno: 0
Last_Error:
Skip_Counter: 0
Exec_Master_Log_Pos: 421
Relay_Log_Space: 256
Until_Condition: None
Until_Log_File:
Until_Log_Pos: 0
Master_SSL_Allowed: No
Master_SSL_CA_File:
Master_SSL_CA_Path:
Master_SSL_Cert:
Master_SSL_Cipher:
Master_SSL_Key:
Seconds_Behind_Master: 0
Master_SSL_Verify_Server_Cert: No
Last_IO_Errno: 0
Last_IO_Error:
Last_SQL_Errno: 0
Last_SQL_Error:
Replicate_Ignore_Server_Ids:
Master_Server_Id: 1675507089
Master_SSL_Crl:
Master_SSL_Crlpath:
Using_Gtid: No
Gtid_IO_Pos:
Replicate_Do_Domain_Ids:
Replicate_Ignore_Domain_Ids:
Parallel_Mode: optimistic
SQL_Delay: 0
SQL_Remaining_Delay: NULL
Slave_SQL_Running_State: Slave has read all relay log; waiting for more updates
Slave_DDL_Groups: 0
Slave_Non_Transactional_Groups: 0
Slave_Transactional_Groups: 0
1 row in set (0.000 sec)
Ora che siamo stati finalmente in grado di replicare da RDS come origine o master della nostra replica situata in locale. Non è ancora finito. In alcuni casi potresti riscontrare errori di replica come
Last_SQL_Errno: 1146
Last_SQL_Error: Error 'Table 'mysql.rds_heartbeat2' doesn't exist' on query. Default database: 'mysql'. Query: 'INSERT INTO mysql.rds_heartbeat2(id, value) values (1,1602988485784) ON DUPLICATE KEY UPDATE value = 1602988485784'
Poiché in locale non è necessario replicare i dati provenienti dal database MySQL per le tabelle con il prefisso 'rds%', ignoriamo semplicemente queste tabelle durante la replica. Inoltre, potresti non volere che AWS RDS aggiorni e modifichi la tua tabella mysql.user. Per fare ciò, puoi facoltativamente ignorare lo schema o semplicemente un elenco di tabelle come,
STOP SLAVE;
Allora,
SET GLOBAL replicate_wild_ignore_table='mysql.rds%';
o
SET GLOBAL replicate_wild_ignore_table='mysql.%';
Il problema MySQL con --master-data=2
Prendere mysqldump con --master-data=2 richiede privilegi sufficienti che richiedono privilegi SUPER e RELOAD. Il problema è che AWS RDS non lo fornisce all'utente amministratore durante la configurazione e la creazione del database. Per risolvere questo problema, è necessario che il tuo AWS RDS abbia una configurazione master e una replica o slave. Una volta che hai una configurazione slave, prendila come host di origine di destinazione quando prendi mysqldump. Quindi arresta i thread slave dalla tua replica AWS RDS come segue,
rds-replica-mysql> CALL mysql.rds_stop_replication;
Quindi prendi mysqldump senza l'opzione --master-data proprio come di seguito,
mysqldump -h database-1.xxxxxxx.us-east-2.rds.amazonaws.com -uadmin -p --single-transaction --databases db1 db2 db3 > backups/dump.sql
Quindi esegui SHOW SLAVE STATUS\G dalla tua replica AWS RDS e prendi nota del Master_Log_File e Exec_Master_Log_Pos per i quali utilizzerai quando ti connetterai al master AWS RDS per replicare al tuo server locale. Utilizzare queste coordinate durante l'esecuzione di CHANGE MASTER TO… MASTER_LOG_FILE=Master_Log_File, MASTER_LOG_POS=
rds-replica-mysql> CALL mysql.rds_start_replication;
Utilizzo di mydumper
mydumper può essere la tua opzione alternativa qui, specialmente quando il set di dati è molto grande in quanto offre parallelismo e velocità quando si esegue un dump o una copia di backup del set di dati da un nodo RDS di origine. Segui i passaggi seguenti dall'installazione di mydumper al caricamento sul server locale di destinazione.
-
Installa il file binario. I binari possono essere trovati qui https://github.com/maxbube/mydumper/releases.
$ yum install https://github.com/maxbube/mydumper/releases/download/v0.9.5/mydumper-0.9.5-2.el6.x86_64.rpm
-
Fai il backup dal nodo di origine RDS. Ad esempio,
[[email protected] mydumper-2]# /usr/bin/mydumper --outputdir=. --verbose=3 --host=database-1.xxxxxxx.us-east-2.rds.amazonaws.com --port=3306 --kill-long-queries --chunk-filesize=5120 --build-empty-files --events --routines --triggers --compress --less-locking --success-on-1146 --regex='(db1\.|db2\.|db3\.|mydb4\.|testdb5\.)' -u admin --password=admin123
** Message: Connected to a MySQL server
** (mydumper:18904): CRITICAL **: Couldn't acquire global lock, snapshots will not be consistent: Access denied for user 'admin'@'%' (using password: YES)
** Message: Started dump at: 2020-10-18 09:34:08
** Message: Written master status
** Message: Multisource slave detected.
** Message: Thread 5 connected using MySQL connection ID 1109
Ora, a questo punto, mydumper eseguirà un backup dei file sotto forma di file *.gz
-
Caricalo sul server locale di destinazione
$ myloader --host localhost --directory=$(pwd) --queries-per-transaction=10000 --threads=8 --compress-protocol --verbose=3
** Message: 8 threads created
** Message: Creating database `db1`
** Message: Creating table `db1`.`folders_rel`
** Message: Creating table `db2`.`p`
** Message: Creating table `db2`.`t1`
** Message: Creating table `db3`.`AddressCodeTest`
-
Imposta il nodo di destinazione come slave/replica. MyDumper includerà un file chiamato metadati che consiste in coordinate di registro binario tra cui posizioni GTID, ad esempio:
$ cat metadata
Started dump at: 2020-10-18 10:23:35
SHOW MASTER STATUS:
Log: mysql-bin-changelog.000680
Pos: 676
GTID:0-1675507089-3044
## Quindi esegui un change master dalla replica o dal nodo del database MySQL/MariaDB di destinazione di destinazione
MariaDB [jbmrcd_date]> CHANGE MASTER TO MASTER_HOST='database-1.cmu8qdlvkepg.us-east-2.rds.amazonaws.com', MASTER_USER='repl_user', MASTER_PASSWORD='repl_passw0rd', MASTER_LOG_FILE='mysql-bin-changelog.000680', MASTER_LOG_POS
=676;
Query OK, 0 rows affected (0.002 sec)
## Avvia lo slave
MariaDB [jbmrcd_date]> start slave;
Query OK, 0 rows affected (0.001 sec)
A questo punto, hai eseguito la replica da un'istanza Amazon RDS che esegue MySQL/MariaDB. Una volta che l'applicazione è pronta per l'allontanamento dall'istanza Amazon RDS, configura l'endpoint per il server in locale e tutte le transazioni rimanenti dall'istanza RDS verranno replicate in locale, senza che i dati vengano persi per il server on-premise. server prem.
Verifica discrepanze nei dati
Una volta caricati o scaricati i dati sul server locale che funge da replica dall'istanza AWS RDS, è necessario ricontrollarlo eseguendo calcoli di checksum per determinare la distanza dei dati rispetto al fonte Amazon RDS. Ti suggerisco di utilizzare lo strumento pt-table-checksum di Percona, ma puoi crearne uno tuo usando strumenti di checksum come md5 o sha256, ma questo richiede tempo per farlo. Inoltre, l'utilizzo di pt-upgrade può essere d'aiuto anche dopo che la migrazione dei dati utilizzando questo approccio di replica è stata completata.
Conclusione
L'uso di mysqldump o mydumper sono strumenti open source gratuiti, il che è anche un grande vantaggio, specialmente se i tuoi dati sono molto riservati e non vuoi che una terza parte vi acceda. Sebbene possa essere semplice adottare questo approccio, può esserci un lavoro noioso e di grandi dimensioni che può essere coinvolto poiché i test e i doppi controlli seguono sempre al fine di dimostrare che la migrazione viene eseguita completamente senza incoerenze dei dati.