Edited at

10年モノのインフラを3年がかりでカイゼンした

More than 1 year has passed since last update.

(株)うるる に2015/06初に入社してから2018/08末で、インフラのカイゼンに一区切りついたのでまとめます。

10年モノというのは うるるで運営しているサービスが最長で10年 ほど経ってスゴイことになってました。

3年がかりなのは、インフラ大好きエンジニアが社内に少なくて、私の独り相撲で時間かかってしまいました。

カイゼンの内訳はざっくりこんな。

構成要素
2015/06初
2018/08末

CI
Jenkins
CircleCI

監視と通知
zabbix(ログインできない)
Datadog & CloudWatchの混成

MySQLサーバー
MySQL on EC2
RDS (MultiAZ)

メール送信
EC2から直接送信とSESの混成
Mailgunで固定IP

crontab
EC2にSSHしてcrontab -e
wheneverでGitHub管理

crontabで動かしてるシェルスクリプト
EC2にSSHしてvi。SCPで配布
GitHub管理

ログファイル
EC2のEBSにひたすら蓄積
CloudWatch Logs

EC2の中身
viして同ロールのEC2にSCPで配布
AnsibleでGitHub管理

Solrサーバー
Master/Slaveが1セット
Blue/Green構成

AWSアカウント
1垢に複数サービスが雑居
1垢1サービス & VPCでprod/stg/devに分割

ネットワーク
EC2 Classic
VPC


CI

いちおうJenkinsが立ってました。失敗して赤くなってるジョブが大半で、かといって誰が治すわけでもなく、よくわからないけど失敗したり成功したり、とにかく不安定でした。

CloudWatchのメトリクスで眺めて、EBSのIOPSクレジットの枯渇から激遅になって、Jenkinsジョブのタイムアウト設定で失敗になる、まで明らかにしました。その時の対処は、IOPSクレジット上限サイズの1TBのSSDのEBSを付けることと、同時並行で動けるJenkinsジョブ数に上限を設けることで、落ち着くようになりました。

とはいえ「Jenkinsおじさん」問題があるので、CIをどうにか民主化する必要があります。SaaSから検討して、TravisCIとCircleCIが最終候補になって、トラブルシュートをSSHでできるのを決め手に、CircleCIを導入しました。

8月末にCircleCI1.0が死んだときの2.0への移行作業はわりとキツかった。


監視と通知

計測、管理、改善の原則にしたがって、現状を可視化できるようにしたかったので。

zabbixが稼働して通知も来ていたものの、ログインできる人がいない。わけがわからないですね。社内に声かけて、EC2のSSH鍵とzabbixの認証に使ってたOpenLDAPのSSH鍵を入手して、OpenLDAPの管理者アカウントのパスワードを変更して、ようやくzabbixにログインできました。ついでにログインできる人が少ないので、共有アカウントを発行して、OneLoginに接続して、エンジニアなら誰でも見れるようにしました。

zabbixに入ってみると、監視項目がザル。EC2インスタンスは、エラーログの監視、ロードアベレージの監視、ストレージ空きの監視、程度。ダッシュボードも無い。


  • 障害発生をユーザーからカスタマーサポートチームへの問い合わせで気づく、

  • 営業メンバーがお客様のオフィスでデモしてる最中に白画面(HTTP 5xx)で気づく、

  • 朝、出社するとオフィスがざわついてて気づく

こんな状況だったので、zabbixを超いい感じにしても駄目な未来がみえました。もっと簡単に管理できるもの、当時はSaaS型が流行りはじめたころで、NewRelicとかMackerelとかのSaaS型から、最終的にDatadogを選びました。


MySQLサーバー

サービス本体のMySQLは入社時点でRDSになっていたのですが、社員がちゃんと関与していなかったサブシステムのMySQLがやばいことになっていました。AMIを取っているものの、mysqldumpでバックアップが失敗してる。このEC2が消滅したらどのくらい困るのかアプリのエンジニアに聞くと、いやそれは大いに困る、サービスのデータが数日抜けてお客様からクレームがくる程度に困ると。怪談です。

幸いにしてcron起動のバッチジョブのためだけのMySQLだったので、cronを止めて、mysqldumpして、予め立てておいたRDSに投入するだけでした。


メール送信

AWS SESは、料金の安さやセットアップの簡単さなどから、まあ普通に使うサービスです。しかし、SESからユーザーまでのログを取れない、そのくせバウンスレートでいきなり止められたりする。トラブルに弱い。

SESから受け取ってくれないお客様もいて、その方々のために、EC2にpostfix立てて送信もしてました。バッチサーバーもWebサーバもメール送信するので、SPFレコードに全台のIPアドレスが記載してあるという。SPFレコードに記載できる文字数に上限があって、サービスのスケールの上限でした。テレビ対応で増強したときは諦めてました。

このあたりの運用改善を主眼に、Mailgunに移行しました。結果、


  • SPFレコードはMailgunのみになったので、スケールの上限が外れた

  • Mailgunの過去2週間の送信ログで、カスタマーサポートチームがお客様と会話できるようになった


crontabと、crontabで動かしてるシェルスクリプト

6割くらいのシェルスクリプトはGitHub管理されていたのですが、4割くらいはEC2サーバーに転がっていました。そのEC2サーバーでオペミスこいてシェルスクリプトが消滅したら、どうリカバリするんだと。GitHub管理に改めました。

crontabの6割くらいは、リリース時にwheneverで投入していましたが、残りはcrontab -eしていたようです。オペミス消滅どうリカバリの流れで、GitHub管理に改めました。


ログファイル

EC2のEBSにひたすら蓄積していました。EBS、高いんですよね。しかもトラブルがおきるとSSHしてシェル芸で調査するという。1台だけならともかく、複数台編成のウェブサーバーだと、もう1台でサンプリングで調べるみたいな状況でした。

ログを保管してくれるSaaSはいくつか出始めたころでしたが、安いのと、とりあえず保管できればいいしで、CloudWatchLogsを選択しました。


EC2の中身

crontabの管理状況や、zabbix設定がそんなだったので、もはや何も驚きません。EC2インスタンスの中身はブラックボックス。秘伝のタレが継ぎ足され続けてて、構築手順はAMIから立てるしかない状況でした。

MySQLの追い出し、crontabのコード化、シェルスクリプトのGitHub管理、の流れで、Ansibleで管理することにしました。PuppetやChefがまあまあ辛くて、Ansibleならsshできれば動くしいいんじゃね?みたいに流行りはじめた頃でした。


  • ps, chkconfig, netstatなどで稼働してるデーモンを調べて、

  • /etcのどこかに散らかってる設定ファイルをかき集めて、

  • ansible経由でEC2インスタンスに設置できるようにして、

というリバースエンジニアリングでansible化を進めていきました。最終的に、Amazon提供のAMIから立てたEC2インスタンスを新規作成して、このansibleコードを使ってセットアップして、アプリをデプロイして、動作に差異がないことをもって、ブラックボックスが解消できました。


Solrサーバー

Solrなので、定義変更するとインデックス作り直しになるのですが、クラスタがひとつだけだと果てしない困難があります。クラスタがふたつあればいいじゃん、いわゆるblue/green deploymentだぜ、からのちょろちょろっと手順を整備して、capistranoとansibleも調整して、で実現しました。


AWSアカウント & VPC

ここまでで、EC2内の諸々がGitHub管理されて、新規作成からansible適用とアプリコードデプロイで完全動作することが保証できました。

しかしEC2が立っているのは、EC2 Classicネットワークです。残念です。これがために、ALB, WAFが使えず、EC2のt2やc4,m4などの世代が利用できません。さらに、AWSアカウントはひとつで、全サービスがごたまぜになってます。いろいろと奇跡的です。

AWSアカウント移設をしつつ、移設先はVPCにする、という引っ越しをしました。そのときの予備調査が https://qiita.com/sasasin/items/17135d5c5465fc53d385 だったりします。

一度に全要素を引っ越すのは、サービスのダウンタイムと私の体力を考えると無理だったので、


  • RDS移設


    • ElasticIPで許可して、アカウント跨ぎで接続できるようにした



  • Solr移設


    • blue/greenのスタンバイ側を引越先で稼働、blue/greenスイッチ



  • ウェブサーバー移設

  • バッチサーバー移設

  • S3移設

というように段階を踏んで実施しました。


総括

いやもう本当よくやったよ私。自画自賛。