VPSマシンを移行した

このブログをホスティングしているVPSマシンを移行したのでその記録。

2019/6/22の時点でこのブログはConoHaのVPS(512MB)で運用していた。
当時はお金の関係で一番安いプランを選んでいたが、やっぱり1GBはあった方が嬉しいので変更することにした。

ただConohaのプランでは

  • 512MB … SSD20GB
  • 1GB以上 … SSD50GB

となっており、同じサーバのままアップグレードはできない。
したがって新たに1GBサーバを立てて移行、その後に512MBサーバを破棄する流れにした。

どうせなので、今まで使用していたCentOS 7からUbuntu 18.04にOS変更することにした。
理由は↓のあたりである。

  • CentOSはある程度触ったから
  • よっぽど堅牢なものを組まない限りyumの基本パッケージでの構築をしないことがわかった
  • rpm入れまくってパッケージマネージャがごちゃごちゃになってた

移行するもの

移行前スペック

  • CentOS 7
  • CPU 1core
  • Mem 512MB
  • SSD 20GB

移行後スペック

  • Ubuntu 18.04
  • CPU 2core
  • Mem 1GB
  • SSD 50GB

移行サービス

これ512MBでよく回してたな…

方針

  • home directoryをtar.gzで固めて移す
  • web directoryをtar.gzで固めて移す
  • 必要なconfig fileを適切な場所に移す
  • mysqlをdockerにする(後述)

移行

なるべくWebサービスを止めないように意識しながら移行したつもりである。
ちなみに今後出てくる敗北数は予期せぬサービス停止が発生したことを意味する(不穏)。

ConoHaのプライベートネットワーク

  • サブネット: 172.16.0.0/21
  • CentOS: 172.16.0.1
  • Ubuntu: 172.16.0.2

プライベートネットワークに繋ぐと1Gbpsの回線をゲットできる。
ただ繋ぐためには一度マシンを落とさなければならない。
また、マニュアルの通り、プライベートネットワークの接続で提供されるのはインタフェースのみなので、IPアドレスなどの設定は自身で行う必要がある(ConoHaのコントロールパネルでIPアドレスを入れたのは意味がなかったのでは…?)。

$ diff -u /etc/netplan/10-gmovps.yaml{.save,}
...
+        eth1:
+            addresses: [172.16.0.2/21]
+            dhcp4: false
+            dhcp6: false
+            accept-ra: false
+            optional: true
...

はじめに

Webコンソールで鍵を入れる

$ mkdir .ssh
$ curl -o .ssh/known_hosts https://github.com/ryotosaito.keys

以降は手元からsshで処理ができる

$ ssh xxx.xxx.xxx.xxx

iptables → ufw

CentOSではiptablesを使っていた(firewalldでは?という質問はNG)
Ubuntuではそれ(ら)の代わりに標準でufwを採用している。

Uncomplicated Firewallの名前通り、設定はめっちゃ簡単だった。

$ ufw enable
$ ufw accept ssh
$ ufw accept http
$ ufw accept https
# VPN ports
$ ufw accept isakmp
$ ufw accept ipsec-nat-t

mysql → docker

これまで通りmysqlのインスタンスをわけて管理するのでもよかったのだが、取り回しが楽そうなdocker管理に切り替えることにした。
そうでもしないとdockerを実運用しなさそうだったというのもある。
Ubuntuでのdockerのインストールは公式ドキュメントを参考に、gpg鍵とリポジトリを加えてから行う。

まずは移行元マシンでsqlファイルを書き出し、転送をする

# 書き出し
$ mysqldump -S /path/to/mysql.sock --databases ctf -p > ~/ctf.sql
# 転送
$ scp ~/ctf.sql 172.16.0.2:.

続いて移行先マシンでdocker mysqlを起動、リストアをする。
ポイントはボリューム(-v)でデータをローカルに永続化することと、 --restart unless-stoppedオプションで自動(再)起動にすること。

# 初期化、ランダムパスワードを有効化
$ docker run -itv "$PWD/ctf:/var/lib/mysql" --name=ctf-mysql -e "MYSQL_RANDOM_ROOT_PASSWORD=yes" mysql
# パスワードを取得したらC-p, C-qで抜けて一度コンテナを止める
$ docker stop ctf-mysql

# 自動(再)起動オプションをつけて再度走らせる
$ docker run -ditv "$PWD/ctf:/var/lib/mysql" -p 3306:3306 --name=ctf-mysql --restart unless-stopped mysql
# リストア
$ docker exec -i ctf-mysql sh -c 'exec mysql -uroot -p"password"' < ~/ctf.sql 

v8.0以降のmysqlは従来(v7.x以前)とデフォルトのパスワードハッシュ方式が違う。
デフォルトでcaching_sha2_passwordになっているが、mysql_native_passwordでないとPHPのPDOからアクセスできないのであらかじめ解決する(1敗)。

mysql> ALTER USER 'username'@'%' IDENTIFIED WITH mysql_native_password BY 'password'

ちなみにWordpressでこんなエラーが出て気づいた。

Warning: mysqli_real_connect(): (HY000/2002): No such file or directory in /.../wp-includes/wp-db.php on line 1612
実際のエラー画面

後で追加で調べたところ、DB初期化のコマンドを以下のようにすればもっと良いみたい。

$ docker run -itv "$PWD/ctf:/var/lib/mysql" --name=ctf-mysql -e "MYSQL_RANDOM_ROOT_PASSWORD=yes" mysql --default-auth=mysql_native_password

今回は複数のDBを走らせるために、ホストポートの割り当てを3306から順番に行った。
IANAのサイト(https://www.iana.org/assignments/service-names-port-numbers/service-names-port-numbers.xhtml)にサービスと予約ポート番号の割り当てが書いてあったので、自分が使いそうなものと競合していなければバンバン使うことにした。

DNS

移行先でサービスを走らせたものから順にAレコードのIPアドレスを書き換えることで両方のマシンで受け付けられるようにした。
TTLは3600だったので、全レコードを切り替えてから1時間以上経てば旧マシンを停止しても問題ない計算になる。

Nginx

CentOSの時に入れていたphp-fpmはlocalhost:9000(PHP7)とlocalhost:9001(PHP5)で通信を受け付けていた(PHP5しか対応していなかったものは移行をきっかけに一度閉鎖することにした)。
aptでインストールしたphp-fpmは初期設定がドメインソケットだったのでこれをそのまま使うことにした。
よってnginx.confにある全てのモジュール設定を書き換える必要がある(3敗)。

$ diff -u /etc/nginx/conf.d/www.conf{.old,}
...
     location ~ \.php$ {
         root                 /path/to/webroot;
-        fastcgi_pass         127.0.0.1:9000;
+        fastcgi_pass         unix:/run/php/php7.2-fpm.sock;
         fastcgi_index        index.php;
         fastcgi_param        SCRIPT_FILENAME $document_root$fastcgi_script_name;
         include              fastcgi_params;
     }
...

また、sslの証明書や鍵をちゃんと移して、configの更新もしておく。

ちなみにこれを機にnginx.confにひとまとめに書いていたものを細かく分割してconf.dディレクトリに入れた。

PHP

旧マシンの各webrootをそれぞれtar.gzでまとめ、scpで移して展開する。

$ tar cvzf web.tar.gz webroot/
$ scp web.tar.gz 172.16.0.2:/path/to/webroot

新マシンで動かす際はサービスに必要なPHP拡張をあらかじめ入れておく(1敗)。

$ apt -y install php-mysql php-mbstring ...

また、document rootのownerをちゃんと正しておく(1敗)。

$ chown -R www-data: /path/to/webroot

また、PDOのdsnに書いていたhostが今までlocalhostでも動いたにも関わらず、127.0.0.1と書かないと接続できなかった(1敗)。
これの原因はわかっていない。

VPN

strongswanをインストールして、configとかsecretを移すだけ。
systemctl restart strongswanを打ち忘れて「設定が反映されない!」と焦った人がいるらしい。

最後に

全部rootでやっていたので一般ユーザを加えるのを忘れていた(usermodの後rebootが必要だったので計2敗)

$ useradd -m user
$ passwd user
# Ubuntuの標準sudoグループはwheelではなくadminだった
$ usermod -aG admin user
# dockerグループを追加しないとdockerが叩けない(dockerのドメインソケットにアクセスできない)
$ usermod -aG docker user

自分のローカルマシン上で、旧マシンドメインのssh鍵と新マシンIPのssh鍵を破棄する。

$ ssh-keygen -R ryotosaito.com
$ ssh-keygen -R xxx.xxx.xxx.xxx
$ ssh ryotosaito.com

まとめ

ちょっと負けすぎやしませんかね…
本気で透過的な移行をするのであれば一時的なサブドメインを登録して試せばよかったなと後悔。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です