Friday, March 25, 2022

MySQL Replication setting between On-premises and AWS via SSH tunnel

I was struggled to complete migration task of on-premises MySQL database to AWS, as we had tight budget which is unable to afford dedicated VPN connection service between these two environments.


 There were 3 following options were given to achieve the mission.

  1. Setup SSL configuration on on-premises MySQL server.
    => This requires me to change current configuration on running server, so I said "No thanks".

  2. Implement internet VPN connection with the use of OpenVPN.
    => This requires me a lots of effort, test and verification process, I immediately turned down.

  3. Establish SSH tunneling between two environments.
    => This is it!

Below image is overview of establishing SSH tunnel between on-premises and AWS.





And the summary is 
  1. Setup ssh and mysqlrouter on both environments.
  2. Establish SSH tunnel from bastion@AWS to bastion@on-premises.
  3. bastion@AWS listen replication request on 56446, and the request redirects to its 53306.
  4. The request received on bastion@AWS:53306 flows to bastion@on-premises:56446 via SSH tunnel.
  5. bastion@on-premises passes the request to DB1:53306 as it configured at MySQL router.



Actual configurations would be like followings.

mysqlrouter: bastion@AWS
[DEFAULT]
logging_folder = /var/log/mysqlrouter
[logger]
level = debug
filename = mysqlrouter.log
#timestamp_precision = second
[routing:basic_failover]
# To be more transparent, use MySQL Server port 3306
bind_address = 0.0.0.0
bind_port = 56446 # listening Aurora replication slave
routing_strategy = first-available
mode = read-write
destinations = 127.0.0.1:53306 # ssh tunnel
# If no plugin is configured which starts a service, keepalive
# will make sure MySQL Router will not immediately exit. It is
# safe to remove once Router is configured.
[keepalive]
interval = 60



mysqlrouter: bastion@on-premises
[DEFAULT]
logging_folder = /var/log/mysqlrouter

[logger]
level = debug
filename = mysqlrouter.log
#timestamp_precision = second

[routing:basic_failover]
# To be more transparent, use MySQL Server port 3306
bind_address = 0.0.0.0
bind_port = 56446        # ssh tunnel port
routing_strategy = first-available
mode = read-write
destinations = DB1:53306    # to master database

# If no plugin is configured which starts a service, keepalive
# will make sure MySQL Router will not immediately exit. It is
# safe to remove once Router is configured.
[keepalive]
interval = 60




Establishing SSH tunnel (Run on bastion@AWS)
ssh -L 53306:0.0.0.0:56446 onpremises_user@1.1.1.1 -i /actual_ssh_key_path




Avoid ssh connection time-out
watch -n10 ls -l /tmp




Setup replication user on on-premises MySQL server
mysql> create user 'repl'@'%' identified with mysql_native_password by 'replpassword';
mysql> GRANT REPLICATION CLIENT, REPLICATION SLAVE ON *.* TO 'repl';




Get master file position of on-premises MySQL server
mysql> show master status\G
*************************** 1. row ***************************
             File: mysql-bin.009516
         Position: 1367403
     Binlog_Do_DB:
 Binlog_Ignore_DB:
Executed_Gtid_Set: 8bxxxx-xxxx-11e5-8ebd-xxxxx69757cf:1-38xxxx5990,
1 row in set (0.00 sec)



Replication setup on AWS database server (Aurora)
mysql> CALL mysql.rds_set_external_master ('IP addr of bastion@AWS', 53306, 'repl', 'replpassword', 'mysql-bin.009516', 1367403, 0);

mysql> CALL mysql.rds_start_replication;

mysql> show slave status\G
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: 172.16.0.70
                  Master_User: repl
                  Master_Port: 56446
                Connect_Retry: 60
              Master_Log_File: mysql-bin.009516
          Read_Master_Log_Pos: 1428514
               Relay_Log_File: relaylog.002290
                Relay_Log_Pos: 1098342
        Relay_Master_Log_File: mysql-bin.009516
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes



This worked well for me, even running for 2 weeks without any network failure!