📜 ⬆️ ⬇️

Transfer site (s) without downtime and data loss between dedicated servers

It would seem that difficult to move the site to another server? Probably many of us copied their first homepages from hosting to hosting in search of the best, while still at school or in the first years of university. Or, hanging on noodles to the management, explained that this task is not solved instantly and the site will not work for a day, because DNS is such a thing ...

If in general, a foolish task, right? But how to make everything perfect? So that without downtime, so that there are no discrepancies in the database, so that any avatars-pictures are lost, when the DNS record IN A is updated and half of the users have an old site, and half have a new one. And if it is highload? Or the site made several generations of the “best” programmers who consider it their duty to create a new connection to the database in their “module” for the site. Finally, if such sites> 10?


How long will it take? How many precious minutes the site will not work \ will not work correctly?

For some reason I did not find any article on Habré, so I decided to write a few tricks on how to transfer a clumsy project or several at once so that the chef was pleased with the stable work of the site.
')
All this is more relevant for sites written in PHP, for administrators faced with projects that do not use frameworks, cms and head when writing code.

1. File Transfer

The best way to use ssh with rsync is:

rsync -avz -e ssh @.:/// /// 

So rsync synchronizes folders incrementally, that is, it copies only what is missing and will not touch something new. For example, you can write a small bash script that will synchronize all folders from the old server to the new one at the time of the DNS update, but still the best option would be to synchronize the folders with the -n key (--dry-run) after a couple of days just to see the discrepancies. I think in the rsync documentation there are solutions for any file synchronization tasks. The program must be installed on both servers.

Using FTP, rsync cannot work, then we use lftp:

 lftp -e 'mirror -- -; bye;' -u :@. 


2. Database transfer using MySQL

On both machines, open the MySQL server port to the world:
 [mysqld] ... bind-address = * #127.0.0.1 ... 


I will write an example of how I make backups every day, clipping from logrotate.d:
 #!/bin/bash CMD="mysqldump --defaults-file=/root/my.cnf --no-create-info=FALSE --order-by-primary=FALSE --force=FALSE --no-data=FALSE --tz-utc=TRUE --flush-privileges=FALSE --compress=TRUE --replace=FALSE --host=localhost --insert-ignore=FALSE --extended-insert=TRUE --quote-names=TRUE --hex-blob=FALSE --complete-insert=FALSE --add-locks=TRUE --port=3306 --disable-keys=TRUE --delayed-insert=FALSE --create-options=TRUE --delete-master-logs=FALSE --comments=TRUE --default-character-set=utf8 --max_allowed_packet=1G --flush-logs=FALSE --dump-date=TRUE --lock-tables=TRUE --allow-keyw ords=FALSE --events=FALSE --databases --routines" for i in $(mysql --defaults-file=/root/my.cnf --batch --skip-column-names -e 'SHOW DATABASES' | grep -v '^information_schema$'); do if [ ! -e /srv/dumps/$i ]; then mkdir -m 700 /srv/dumps/$i; fi $CMD $i | gzip -c > /srv/dumps/$i/$i.sql.gz done 

/root/my.cnf
 [client] user = root password = passw 

Why not the classic "mysqldump -u root -p database> dump.sql"? Then the view and stored procedures will not be saved. Correctly makes MySQL Workbench dumps, from there I took this command.

Next, in the $ CMD variable, add -h ip_old_server and change the line $ CMD $ i | gzip -c> /srv/dumps/$i/$i.sql.gz to:
 $CMD $i | mysql -u root -ppasswod $i 

Of course, you must first create all the databases:
 mysql --defaults-file=/root/my.cnf --batch --skip-column-names -e 'SHOW DATABASES' | grep -v '^information_schema$' 

3. Redirect all connections to localhost: 3306 - the old server to the new server

Quite simply, use ssh tunnel (after stopping mysql):
 ssh -Nf -L 3306:REMOTE_IP:3306 user@localhost 

And ssh is required only on the local machine. Checking:
 netstat -lnpt | grep 3306 telnet 127.0.0.1 3306 

We receive remote MySQL server by the local machine. Everything would be fine, but if the MySQL client sees that the connection goes to localhost, then it connects to the server via a local socket and cannot disassociate it from any settings. Those.
 telnet localhost 3306 

Or, as usual, we write in scripts:
 $resource = new mysqli('localhost', 'user', 'password'); 

They will not work, because such a connection will also be processed via a local socket. Of course, you can go over all connections of the site and replace localhost with 127.0.0.1 or the external IP of the server will work, but there is a better way.

You need to edit the files in the hex editor:
 libmysqlclient.so.15.0.0 libmysqlclient_r.so.15.0.0  (   mysql) libmysqlclient.so.16.0.0 libmysqlclient_r.so.16.0.0 

Find the only match in the localhost text and replace it with something else, like lacalhost, in both files. After local connections will work through TCP / IP! The only MySQL does not allow users whose remote host can only have localhost privileges. This should be fixed by% during the transfer.

Skip the web server settings, this topic is full of materials.
As a result, we have two working machines with one database server. Easy reconfigure the DNS and go to sleep!

ps I also had an idea to proxy requests from the old server to the new one via nginx. Has anyone done this?

upd:
Also, I do not pretend to a better solution, rather I seek it. What do you think?

Source: https://habr.com/ru/post/155555/


All Articles