クラウドワークスのテスト環境を支える技術

クラウドワークスで開発・運用している、開発者に開発環境を配るための社内サービス「tida（てぃーだ）」について紹介します。クラウドワークスでは、Web UIに環境名とインスタンスタイプを入力してしばらく待つだけで、好きなだけテスト環境をつくることができます。

.oO(テスト環境構築の自動化って、あまり話題に登らない気がするのですが、みなさん/他社さんはどうやってるんだろう)

# 何をする社内サービスか

tidaは「てぃーだ」と読み、沖縄で「太陽」を意味する言葉です。エンジニアの数に比例して増えていくテスト環境を統括する太陽のようなイメージで命名しました（弊社で大活躍している[宮古島出身のエンジニア](https://jobs.forkwell.com/engagements/13)が発案してくれました :angel: )

クラウドワークスのエンジニア各自が、クラウドワークスのテスト環境をAWS上に1つ以上自由に持てるようにするサービスです。自分用に1つ、他のエンジニアへの共有用に1つ、のように複数持ってもOKです。Web UIに環境名とインスタンスタイプを入力してしばらく待つと、適切にセットアップされたEC2インスタンスやそのエンドポイントURLが払い出される、というようなものです。

# 利用方法

tidaにはWeb UIが用意されています。tidaのWebサイトにアクセスして、環境名（kuokaなど）とインスタンスタイプ（t2.smallなど）を指定して、「作成」ボタンを押して30分ほど待つと、以下のようなことが自由にできる開発環境（実態は適切にセットアップされたEC2インスタンス1つ）が用意されます。

- SSH接続して様々なミドルウェアの設定等を変更
- RailsアプリをCapistranoでデプロイ
- 特定のURLからそのサーバ上にデプロイしたクラウドワークスにアクセス
- 一定期間アクセス（デフォルトでは3600秒）がなければコスト削減のためインスタンスを自動停止
- 自動停止されたインスタンスで稼働しているクラウドワークスにアクセスすると、自動起動

# 開発の背景

もともとクラウドワークスのいわゆるテスト環境は、とあるVPS上にApacheのVirtualHostとして用意していました。テスト環境は希望すればいくつも持てるようになっていましたが、あくまで同一VPSのApacheが提供する別のVirtualHostです。リソースは共有しているということですね。

テスト環境は社内ではdev環境と呼ばれていて、クラウドワークスの改善点をリリース前に社内で確認するために利用しています。確認する人は、当人だったり他のエンジニアだったり、改善点の発案者・デザイナ・コピーライター・プロダクトオーナーだったり様々です。よくVagrant等で用意されている、開発者個人が確認するために使う「開発環境」とは異なる立ち位置のものです。

組織によっては、こういう環境のことを「ステージング環境」と呼ぶこともあるようです。しかし、弊社にはもっと本番環境と似た構成をCloudFormationやTerraformでセットアップするステージング環境が別にあって、こちらは本番環境とは異なる構成になっているので開発環境と呼んでいます。

# tida以前の問題点

tidaが開発される以前は以下の様な状態になっていました。

1. うっかりVirtualHostの設定を消してしまってテスト環境が全滅することがある
2. 特定のテスト環境にアクセスが集中したり、デプロイ中に他のテスト環境のレスポンスが悪くなることがある
3. テスト環境を追加する作業がめんどう

1は人力で環境構築を行っている以上仕方がないのですが、発生した場合当人だけでなく、前述の開発環境を利用する人全員に影響が出てしまいます。

2については、そんなに贅沢なインスタンスタイプを使っていなかったため、デプロイ中にassets:precompileが実行されるときや、特定のテスト環境にアクセスが集中しているとき、テスト環境が増えすぎてメモリが枯渇してるとき（前述のとおり、すべてのテスト環境が同じVPSに載っていました）など、様々な直接原因によってすべてのテスト環境のレスポンスが悪くなってしまっていました。

3については、ApacheのVirtualHostの追加、Railsアプリのデプロイ先の確保、リバースプロキシ用のnginxの設定追加など何ステップがあり、その領域に詳しくないエンジニアにとっては手間です。クラウドワークスには、温かみのある手作業を自動的に行なってくれるエンジニアもいません。

# tidaの実装

tidaは以下の様なサービスやソフトウェアで実装されています。

- tida(Railsアプリ)
- cw-stack(CloudFormationテンプレートと、Chefによるプロビジョニング方法をRuby DSLで記述することができる内製フレームワーク）
- Hipache(Route 53のレコードセットを動的に追加削除・DNS浸透を待たずにテスト環境のホスト名を即時払い出すためにリバースプロキシとして利用。[nginx-proxy](https://github.com/jwilder/nginx-proxy)とかでもよかったのですが好みで選びました)
- Docker(tida自体のサーバにMySQL、Redis等を直接インストールしたくなかったため)
- AWS(EC2、CloudFormation)

詳細はまたリクエストがあったら書いてみます。

# tida以降

tida以前は以下の様な問題点がありました。

1. うっかりVirtualHostの設定を消してしまってテスト環境が全滅することがある
2. 特定のテスト環境にアクセスが集中したり、デプロイ中に他のテスト環境のレスポンスが悪くなることがある
3. テスト環境を追加する作業がめんどう

1はそもそもテスト環境の追加が人力で、作業ミスの可能性を排除できないところが根本的な問題でした。この部分に相当するテスト環境毎のホスト名の払い出しを行う部分は、tidaとHipacheで自動化されているので、1の可能性は全くなくなりました（その代わり、各ホストへのリバースプロキシとなるHipacheが落ちてしまった場合は、それはそれでテスト環境が全滅することになりますが・・作業起因でそうなることは少なくともなくなっています）。

2については、tidaが環境毎に独立したEC2インスタンスを用意するので、特定のテスト環境の負荷が他に影響することはなくなりました。

3については、Web UIで必要項目を入れて待つだけでよいので、少なくとも手作業による面倒臭さは軽減されました。（ただし、待ち時間が長かったり、UIがわかりづらいことによる混乱はあるようです）

その他、工夫した点は以下です。

* コスト見合いで、できるだけdev-prod parityをできるだけ意識する
    * まだDocker化してないところだと、本番環境を模した構成にすればするほどコストがかかるので、落とし所を見つけることが大切
* アプリのデプロイは本番環境同様Capistranoで（
    * 弊社はChefでインフラ構築自動化をしている関係で、Capistranoだけで単純にデプロイが完結しているわけではないですが）

# まとめ

クラウドワークスの社内サービス「tida」についてご紹介しました。これを機に、他社さんのテスト環境事情についても情報が出てくるとうれしいです :bear: