僕の考えた最強のWEB開発環境

図にするとこんな感じ。

本番にコピーすればそのまま動くために

すべてのサーバは名前(/etc/hosts)で呼び合う。
IPで呼び合うことはしない。
開発用のVMも例外ではない。(名前が違うとseleniumが問題になるため)


サーバには、それぞれ以下の環境変数を定義する。
プログラムには、この値を見て挙動を変えることを期待する。

本番サーバ PRODUCTION
QC系 TEST
開発 DEV


本番にコピーすればそのまま動くをモットーにする。

開発環境

開発者には、一人一VMを配布
非開発者には、共有VMを配布 /home/ユーザ

VMには、開発用のホストと結合テスト用のホストを登録。


なぜ開発者にVMを提供するのか?
データベースを消したり、作り直したり、セキュリティ検査を行ったりするため。
#例えば、selenium でアンケートのテストをしたい場合、同じ質問に2度答えさせるにはデータベースを削除しないと行けない。
よって、とじた環境が望ましい。
このVMは必ずしもローカルにある必要はない。



なぜ非エンジニアには、共有VMを提供するのか?
データベースを作り直したりしない職種にはVMがオーバースペック過ぎる。
もちろん、VMを使ってもいいが、設定等がめんどいならば共有VMも手。


内部のみにしかメールを送らないSMTPがなぜ必要か?
理由は、間違って顧客にメールを送ってしまうのを防ぐため。
一度送ってしまったメールは取消できない。
開発とQC系は、このSMTPを利用する。

開発フロー

開発者はソース管理(開発用)からソースを落としてくる。
↓
開発者VMでデバッグ。
開発者VMでテスト作ったりする。
↓
ある程度動いたので、ソース管理(開発用)にコミット。
↓
CIが感知して30秒程度で終わる「簡単なテスト」を実行。
↓
うまくいったので、本番適応するために結合テストを行うことにする。
修正したソースを、ソース管理(本番用)のところにコピーする。
↓
開発者VMで結合テストのデバッグ
↓
うまく動くようなので、ソース管理(本番系)にコミット。
↓
CIが簡易テストを行う。
↓
ソース管理(本番系)から、QC/最終結合テスト環境にデプロイする。
↓
動作確認
↓
本番サーバにデプロイする
↓
動作確認

結合テストも開発者VMで行うのが特徴かな。(重要)
開発者VMは、開発用サーバと結合用サーバの2つがセットアップされている。

なんか、QC/最終テストいらない気もするよね。

CI

CIはコミット時は簡易テストを行う。
テスト項目にもよるがseleniumで3000テストぐらいつくると2時間ぐらいかかるし。
フルテストは、任意で動かすか、夜中に自動実行する。

本番適応前にフルテストを実行するのが望ましいが、時間が問題。

QCは本番のクローン

予算があれば、QCは本番構成のクローンであるのが望ましい。
本番と同じスペックのサーバ、本番と同じ台数、、、、

予算無いですよね。はい。

だったら、VMにしてもいいので、データベースのレプリケーションや監視項目などは全く同じにしたい。


本番でのトラブル時の再現機としても利用出来ることが望ましい。
たとえば、フェールオーバーが正しく動くかの検証や、新人インフラエンジニアの講習にも使えると思われる。
予防訓練にも使える。マスターデータベースがダウンしたときのシミュレートなどを行う。

課題

1.
また、この構造はソース管理のマージが多発する。
SVNがマージに弱いのが一番の心配事項。
もしかしたら、 hg のようなマージに強いソース管理が望ましいのかもしれない。


2.
テスト用のデータベースについて。
個人情報うんぬんにうるさいやつがいない場合は、本番系のバックアップデータを利用するのが望ましい。
本番データで小規模だと起きない問題点や、小規模だと発生しない問題点とかあるし。


3.
ケータイの実機確認
ケータイはwifiつながらないから、、、
インターネットから開発者VMフォワードする設定を作らないといけない。
専用のドメイン、IPの確保とfirewallの設定とポリシーが必要

運用

1.
プログラムはアプリケーションログを吐く。
どうせ、トラブルが起きるんだから、トラブルが起きたときに原因に気づけるようにする。
もっとログを仕込まなければわかりませんは、敗北。

ログを吐いたら動作が遅くなるようだったら、サーバを増やすことも検討してもいいぐらいだと思う。


2.
プログラムは ASSERT や 未キャッチ例外などを必ずログに落とす。
この時、 stacktrace や GET / POST などのパラメータもこみこみでログを吐く。

そんで、これがあったことを関係者に通知する仕組みを構築する。
問題が起きればつどメールを送るでもいいし、アクセスがあるサーバだったら、5分に一回ログをgrepして通知でもいいだろう。

目的は、トラブルの早期発見早期対応。
サポート部門にお客がTELしてバグが開発にエスカレーションされる前に問題に気づき修正を目指す。


3.
プログラムの動作状況のログを取る。
具体的には、apache の CUSTOMLOG に処理時間 を追加して、analogなどで処理時間を集計する。
そんで、すべての処理が3秒以下で終わっているかなどの確認を行う。


mysql の slow-query をログに落として、時間のかかるクエリーを修正したりする。


4.
サーバの監視とグラフ化
muninなどの監視ソフトを入れてサーバの load average や vmstat 、 sar 、ディスク容量、転送量の監視とグラフ化を行う。
通知項目はまとめて表にしたりwikiに描くのがおすすめ。
監視のしきい値は最初はソフトのディフォルトを使うのがおすすめ。
そんで、実際の運用実績を見ながら、監視のしきい値を増減させる。
いつもCPUすかすかのサーバがCPU使い切ったら何かあるなと思えるわけだし。実際の運用の実績値を数字を見なが上げ下げする。

あとは、この項目を元にSLAを定めて目標を追いかける。


5.
トラブル時のチェックリストを作る。
飛行機のチェックリストみたいに、この時はこうするみたいな手順書を作成する。
load averageが5を超えたらどうする/どうなるのか?
mysqlがダウンしたらどうするのか?
レプリケーションが外れたときの復旧フローなどをリストにまとめて保管する。


6.
ログのローテートと集約はポリシーを定めて適切に行う。
個人的には、1日1回ローテートして、ログを保存かるサーバに日付をつけてコピーが好き。
web01.access.log.2010_09_19.log.gz みたいな感じ。
grepしやすい。また、grepの負荷もあるため本番以外の別サーバに保存するのが望ましい。
これに grepとダウンロード用のwebのUIを付けてあげると、サポートや開発が超絶やりやすくなるのでおすすめ。