Publishers は、開発当初から Amazon Web Service(AWS) を利用して運用されています。そして、 AWS の中でも Amazon Elastic Compute Cloud (Amazon EC2) がメインでサービスの根幹となる機能をになっています。
今回、この EC2 のインスタンスをサービスを止めることなく、段階的に移管したというお話をしていこうと思います。 HTTPサーバを自分で建てようかと思っている人には、ちょうどいい内容かも!?
サーバ代がめちゃ高い
実は、 Publishers はかなり昔からあるサービスで、 EC2 のインスタンスも、古くて、今から考えるとコストパフォーマンス的には最悪の状況です。こちらのグラフを御覧ください。
サーバ代だけで毎月10万円ほど課金しています。現在のビジネスモデルを考えると、サーバ代が利益率の直接的な要因になっているので、これをどれだけ下げられるかにフォーカスしていかなくてはいけません。今、ドル円が111円くらいですが、円安の影響も利益率に跳ね返ってしまうので、何としてでも、サーバ代を浮かせていきたいところです。
いくつかあるEC2インスタンスのうち、今回注目したのが、ロードバランサ (lb1) です。これは、 c1.medium
というインスタンスタイプで、一ヶ月起動しっぱなしにすると、それだけで1万円は下らないです。そして、アプリケーションが入っているインスタンスに比べると移管が楽そうな感覚があります。まずは、これにメスを入れていこうと思います。
まずは調査
Publishers は他社からある日突然、引き継ぐことになったのですが、なかなかサーバ構成を把握する時間がなかったです。しかし、そうも言ってはいられません。 lb1 がどのような働きをしているかをじっくりと見てみます。
top
コマンドを叩いて、リソースの使用状況を確認します。
$ top
がばがばですね。ほとんど仕事していないような状況だということが解ります。
また、サーバ設計など何もいただいていない状況の中、手探りでインスタンスを移管するので、このサーバがどのような働きをしているのかを知らなければいけません。そのときには、まず、どういうプロセスが動いているのかを知れば良さそうです。 ps
コマンドを使って見てみます。
$ ps aux
これによって、ほとんど Nginx
というHTTPサーバが動いているだけのインスタンスだということが解りました。新しいサーバには Nginx をほぼ同じ設定ファイルと共にインストールするだけだということが解りました。
ここまでの話だと、 ELB (Elastic Load Balancing) で良いではないかという疑問の声も上がりそうです。しかし、今回の Nginx の設定が意外と複雑なため、汎用のロードバランサを入れてしまうとおそらくアプリケーションサーバ側の改修を入れないといけなくなります。なので、今回は、 ELB の導入は見送りました。
インスタンスの作成
EC2インスタンスを作っていきます。 Amazon Linux
は、あまり上手く運用できる気がしないので、 Ubuntu Server 16.04 LTS
を選択しました。
コア数もメモリも必要ないので t2.small
にしました。 t2.small と c1.medium を比べるとコア数は減りますが、メモリが若干、 t2.small の方が多かったりします。
デフォルトの設定のまま、インスタンスをローンチします。プライベートキーをどうするか聞かれるので、いつも使っているものを設定しました。
セキュリティグループの設定
適切にセキュリティグループを設定しないと、 SSH でログインすることができないとおもいます。自分のIPの 22 番を開放するのと、あとは、今回はロードバランサなので、80番(HTTP)と443番(HTTPS)だけ開放します。
セキュリティグループの画面にアクセスし、
EC2インスタンスの画面で、インスタンス名の上で右クリックを押してセキュリティグループを設定します。
最後に、セキュリティグループがきちーっと設定されているかどうかを確認します。
SSHでログイン
やっとこれで、インスタンスにログインできるようになりました。ログインは、 ec2-user
ではなくて、 ubuntu
となります。ホストの IP は、 IPv4 Public IP
と書かれているものを使用します。
$ ssh ubuntu@{EC2のホストIP} -i {プライベートキーのパス}
ロケールの設定
SSH でログインすると毎回、
Last login: Thu Mar 23 10:32:00 2017 from 123.123.123.123
_____________________________________________________________________
WARNING! Your environment specifies an invalid locale.
The unknown environment variables are:
LC_CTYPE=UTF-8 LC_ALL=
This can affect your user experience significantly, including the
ability to manage packages. You may install the locales by running:
sudo apt-get install language-pack-UTF-8
or
sudo locale-gen UTF-8
To see all available language packs, run:
apt-cache search "^language-pack-[a-z][a-z]$"
To disable this message for all users, run:
sudo touch /var/lib/cloud/instance/locale-check.skip
_____________________________________________________________________
という警告が出るので、いろいろと試しましたが、使えるロケールを
$ locale -a
locale: Cannot set LC_CTYPE to default locale: No such file or directory
C
C.UTF-8
en_US.utf8
POSIX
のようにして確認して、その後、
$ sudo locale-gen en_US.UTF-8
として、 en_US.UTF-8
を標準のロケールとすることができました。これで、先ほどの警告は出なくなりました。
必要そうなパッケージのインストール
Ubuntu なので、標準のパッケージ管理ソフトは、 apt-get
ですね。必要そうなパッケージをどんどんインストールしていきます。
$ sudo apt-get update
$ sudo apt-get upgrade
$ sudo apt-get install -y python-pip python-dev build-essential libffi-dev libxml2-dev libxslt1-dev zlibc zlib1g-dev libreadline-dev libxslt1-dev libjpeg62-dev libfreetype6-dev libsqlite3-dev libssl-dev libgdbm-dev libbz2-dev
標準のエディタをVimに
nano とか Emacs の操作方法は閉じる操作もろくにできないので、 Vim
を標準のエディタにします。これによって visudo したら nano を開くというバグを直すことができます。
$ sudo update-alternatives --config editor
There are 4 choices for the alternative editor (providing /usr/bin/editor).
Selection Path Priority Status
------------------------------------------------------------
* 0 /bin/nano 40 auto mode
1 /bin/ed -100 manual mode
2 /bin/nano 40 manual mode
3 /usr/bin/vim.basic 30 manual mode
4 /usr/bin/vim.tiny 10 manual mode
Press <enter> to keep the current choice[*], or type selection number: 3
update-alternatives: using /usr/bin/vim.basic to provide /usr/bin/editor (editor) in manual mode
ntpのインストール
サーバの時刻設定が狂うと、様々な API との通信で、エラーになることがあります。 ntp
をインストールしていきます。どうやら、ntpはインストールされているようなので、有効可するだけでした。
$ sudo apt-get install ntp -y
$ sudo service ntp start
$ sudo systemctl enable ntp
ファイアウォールの設定
セキュリティグループは、上で設定済みですが、念には念をということで。 Ubuntu には ufw
という素敵なファイアウォールがあります。設定は、
$ sudo ufw default deny incoming
$ sudo ufw default allow outgoing
$ sudo ufw allow 22
$ sudo ufw allow 80
$ sudo ufw allow 443
$ sudo ufw enable # or sudo ufw reload
としました。これによって、内部へのアクセスを制限、外部へのアクセスを許可した上で、内部への SSH(20) 、 HTTP(80) 、 HTTPS (443) を許可しました。
ホスト名の設定
EC2 のインスタンスは、落ちてしまうと基本的に IP が変わってしまいます。これによって、ホスト名がIPベースのものだと問題が発生する可能性があります。ホスト名を適切なものに変えておきましょう。
$ sudo hostnamectl set-hostname lb3.publishers.fm
$ sudo hostnamectl
Static hostname: lb3.publishers.fm
Icon name: computer-vm
Chassis: vm
(以下略)
Nginxのインストール
いよいよ、HTTPサーバのインストールです。 lb1 と同じく Nginx を選択します。
$ sudo apt-get install nginx -y
$ sudo service nginx start
$ sudo systemctl enable nginx
この後、 IP 打ってアクセスすると、お決まりのあの画面が見られます。
ログも一応確認しておきましょう。
$ sudo tail -f /var/log/nginx/access.log
126.66.4.51 - - [24/Mar/2017:07:27:22 +0000] "GET / HTTP/1.1" 200 6067 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36" "-" 0.071
としてログも残ることを確認しました。移管のときは、元々のサーバにアクセスが行ってしまうなどのミスがないようにきちーっと確認することが重要です。
SSL を設定ファイルで適応後 SSL が機能しているかチェックします。
ワイルドカードドメインでは一番安い Positive SSL Wildcard
を使用しています。 Publishers は、配信者用にサブドメインを切って使用するので、ワイルドカードドメインに対応した SSL ではないといけないです。
logrotateの設定
logrotate
を設定することで、ログを一定期間毎に保存させたりログの肥大化を防ぎます。
コマンドを叩き、 logrotate が使えることを確認します。
$ sudo apt-get install logrotate -y
$ logrotate
logrotate 3.8.7 - Copyright (C) 1995-2001 Red Hat, Inc.
This may be freely redistributed under the terms of the GNU Public License
Usage: logrotate [-dfv?] [-d|--debug] [-f|--force] [-m|--mail=command] [-s|--state=statefile]
[-v|--verbose] [--version] [-?|--help] [--usage] [OPTION...] <configfile>
/etc/logrotate.d/nginx
があれば、それでほとんど設定は完了していて、
/var/log/nginx/*.log {
daily
missingok
rotate 14
compress
delaycompress
notifempty
create 0640 www-data adm
sharedscripts
prerotate
if [ -d /etc/logrotate.d/httpd-prerotate ]; then \
run-parts /etc/logrotate.d/httpd-prerotate; \
fi \
endscript
postrotate
invoke-rc.d nginx rotate >/dev/null 2>&1
endscript
}
の様になっていれば、問題ないです。 rotate
で14日間ログを保持してくれて、それ以降は compress
によりGzip圧縮されます。ただし、 delaycompress
されているので、1回目のローテーションでは圧縮されずに、2回目以降のローテーションで圧縮されるようになります。
logrotate が毎日動いているかどうかは、
$ sudo cat /etc/cron.daily/logrotate
とか、
$ sudo cat /var/lib/logrotate/status
でチェックできます。ここまでで、基本的なHTTPサーバができあがりました。実際、もっとやった作業としては細かいですが、割愛させていただきます。
Cloud Watchの設定
Cloud Watch による監視も入れておきましょう。
- 落ちているかどうか
StatusCheckFailed >= 1 for 10 minutes
- CPU使用率が連続して 70% を超えているか
CPUUtilization >= 70 for 5 minutes
の2つの監視設定をしました。では、AWSの画面に戻って、
status check
cpu
などで監視する項目を検索するとよいでしょう。
アラート先や、分単位での設定をします。
これで監視の設定は完了です。落としてみたりしてメールが飛ぶか確認して見るとよいです。 Cloud Watch の監視は安く、数十円とかで絶大なる安心感を得ることができます。ぜひ使ってみてください。
Elastic IPの設定
ロードバランサのために、Elastic IP(固定IP)を設定します。
Scope は VPC のものにしないといけません。ご注意ください。 Allocate で設定できます。
作成できたら、EC2インスタンスに最後関連付けして完了です。
Classic Linkの設定
古い EC2 インスタンス (non-VPC) を使用している場合は、おそらく VPC には直接接続できません。なので、 Classic Link
を設定することで、おなじ VPN 内で VPC 内のインスタンスと通信できます。
VPC を指定すると、その VPC 関連のセキュリティグループを選択することになります。
ここが、一番何していいかわからず苦労したところかもしれないです。ネットで検索してのですが、 non-VPC のインスタンスをどうやって、 VPC に接続するのか上手く探しあげることができませんでした。こういうときは、大体は問題設定を脳に与えて昼寝することです。目覚めたときに答えが見えるようになっていることが多いです。
Route 53の設定
Route 53(DNS) の設定をします。 Elastic IP で作成したIPアドレスを、 Route 53 の設定画面に入力していきます。
数分から数時間するとDNSレコードが切り替わっていることが確認できるはずです。 nslookup
コマンドで確認しましょう。
$ nslookup publishers.fm
Server: 10.0.1.1
Address: 10.0.1.1#53
Non-authoritative answer:
Name: publishers.fm
Address: 123.123.123.123
適切なIPアドレスに切り替わっていれば、完了です。そして、十分な時間が立った後、旧インスタンス lb1 にアクセスが来ていないことを確認します。
$ tail -f /var/log/nginx/access.log
このときに、ログがタラタラと出力されるようだとまだ、DNSレコードが切り替わっていない可能性があります。
ちなみに、最後は、検索エンジンとかマーケティングツールのボットからのアクセスだけになりました。 TTL (Time to live) をあえて無視して必要に応じてキャッシュさせているのでしょう。帯域に負荷をかけないための工夫なのかもしれません。
46.229.168.72 - - [26/Mar/2017:21:24:02 +0900] "GET /article/14506/ HTTP/1.1" 200 9412 "-" "Mozilla/5.0 (compatible; SemrushBot/1.2~bl; +http://www.semrush.com/bot.html)" "-" 5.369
46.229.168.68 - - [26/Mar/2017:21:24:03 +0900] "GET / HTTP/1.1" 200 7190 "-" "Mozilla/5.0 (compatible; SemrushBot/1.2~bl; +http://www.semrush.com/bot.html)" "-" 0.570
46.229.168.69 - - [26/Mar/2017:21:24:17 +0900] "GET /article/7979 HTTP/1.1" 301 5 "-" "Mozilla/5.0 (compatible; SemrushBot/1.2~bl; +http://www.semrush.com/bot.html)" "-" 0.184
46.229.168.74 - - [26/Mar/2017:21:24:31 +0900] "GET /editor/755/ HTTP/1.1" 200 4276 "-" "Mozilla/5.0 (compatible; SemrushBot/1.2~bl; +http://www.semrush.com/bot.html)" "-" 0.288
このようにして、DNSレコードが確実に切り替わったことを確認した後、 lb1 を落として完了になります。TTL が切れてからも、大体1日以上掛かりますね。スマホや IE とかは特に、DNSをずーっとキャッシュするみたいな動きをしていました。
移管を終えて
EC2 の古いロードバランサの設計を調べつつ、新しく作成したロードバランサに切り替えることでコスト削減を図りました。
サーバ停止することなく、問題もなく移管が完了できたので、 AWS のインフラの簡易さと汎用性の高さに感謝するところではあります。特に、 Classic Link などの前方互換の機能が充実しているのもさすがというところですね。
心臓を痛めることなく移管ができ、この勢いのまま、他のインスタンスも新しいものに移管していければ幸いです。時間が許すのであれば。
この記事を読んだあとに
- 書いた人のツイッター – Follow me!
- 『売上を3年連続20%成長させた18の秘訣』
- 運営しているアクションゲーム