リモート検証環境をAWS上で構築したお話。

[Leverages Advent Calendar 2019](https://qiita.com/advent-calendar/2019/leverages) 12日目
エンジニアの[@poster-keisuke](https://twitter.com/posterkeisuke)の記事です。

昨日は村本くんの[「てっくらんち」はじめました](https://tech.leverages.jp/entry/2019/12/11/000000) でした。


### ことのはじまり
はじまりは、上長との1on1時の会話中に

```
自分)
「メインプロジェクト1ヶ月くらい落ち着きそうなので、短期でできそうなタスクとかないですかねー？」

上長)
「そしたら最近開発環境周りで、不満が起こっているっぽいからちょっと調べてみてよ」

自分)
「何したらいいか分からないですが、とりあえずやってみますねw」
```
(的な流れだったと思います)
のようなざっくりした依頼を受け取とり

とりあえず、話を聞いてみないと**誰が何に不満を持っているのか**
分からなかったので、関係者数名にヒアリングしてみることにしました。

### ヒアリング調査
まずは開発に関わる人たちをリストアップし、誰に何を聞くかの準備を進めました。

自分が所属している医療・介護系のサービスを運営する組織は、

- プロジェクトが大きく3つ
- 各プロジェクト約10人くらい（業務委託さんも含めて）
- 加えてテックチームと呼ばれるチームが存在する（SREとか機械学習とかを推進してくれている）
- 全体で40人以上の組織

その中でも、問題がありそうなのは
[看護のお仕事](https://kango-oshigoto.jp/) や [きらケア](https://job.kiracare.jp/)などのオウンドメディアを運用するチームだということがわかったので、所属するチームの人に話を聞いてみることに。

職種は偏りが無いように

- エンジニア
- デザイナー
- プランナー(マーケター)
 
にそれぞれに聞くことにしました。
人数はだいたい1職種あたり2人ほどずつ。
別途リーダーにもヒアリングしました。

とりあえずわかっていることは、「開発環境周りで、不満が起こっている」っぽいということだけだったので、普段どのように作業しているのかをベースに話を聞くことにしました。

すると、(なんとなくですが)普段どのような流れで仕事を進めているのかが見えてきました。
と、同時に以下のような問題(っぽもの)が浮かび上がってきました。

```
・ Dockerの開発環境を利用して、自PCのIPを限定公開する形でUI周りのレビューを受けていた
    ・ UIの確認をレビュアーに依頼するとき、自分とレビュアーが一緒にいるタイミングでしか時間が取れない
    ・ 開発環境レビュー中は、ブランチを変更できないので作業がストップする
    ・ ローカルでの検証は時間がかかる
・ 自由に使えるリモートの環境があったが、色々問題があってなくなってしまった
```

など。(一部抜粋)
他にも開発環境周りの問題などもありましたが、**レビュー時の問題**がクリティカルであると感じ、
リモートに検証環境を作ってあげることでこのあたり問題を解決できそうだな。
と目星をつけ、どのように解決できるかなと考え始めました。

### 解決策が満たすべき必要要件を洗い出す
問題は把握したので、次はどのように解決するかを考えました。
いきなり解決策を模索するのではなく、まずは解決策を実現するのに必要な要件を以下のように洗い出しました。

```
・ 作業者と確認者が非同期で利用可能
・ 作業者の作業を止めることなく、確認者が利用可能
・ 作業者及び確認者のフローを（なるべく）変更することなく、利用可能
・ とりあえずなので、まずはたくさんのお金をかけずに実現可能
```
洗い出した要件をもとに、調査を進めることにしました。
また、ここでテックチームの心強い後輩いっちーが合流して、二人で解決策を考えることになりました。

### 事例調査

#### Herokuの見積もり
上記の要件から、最初に思いついたのはHerokuの[Review Apps](https://devcenter.heroku.com/articles/github-integration-review-apps)というものでした。
機能を簡単に説明すると、PRを出すとそのPRの環境が自動で立ち上がる。
というようなものです。

先程定めた要件を満たしているかを調査したところ、予算感が合わず断念・・・
（上記の場合、Heroku側にDBを作るとか、[Private Space Peering](https://devcenter.heroku.com/articles/private-space-peering)などを使えば実現可能では合ったものの、コストを考えると・・・:thinking_face:）

また、AWSを利用しているためDBなどの接続を考えると、外部サービスを利用するより自社で環境を構築する必要がありそうだ。ということがわかりました。

先程定めた要件をアップデートします。

```
・ 作業者と確認者が非同期で利用可能
・ 作業者の作業を止めることなく、確認者が利用できる
・ 作業者及び確認者の開発フローを変更することなく、利用可能
・ とりあえずなので、まずはたくさんのお金をかけずに実現可能
・ 外部サービスを利用せず、AWSを利用して自分たちで環境を構築する( <- New!!)
```

次はそれを踏まえて、自社で検証環境を構築されている例をいくつか探すことにしました。

#### 他社さんの事例調査
いくつか調査する中で、参考にさせていただいたのはSmartHRさんの記事でした。

https://tech.smarthr.jp/entry/2017/03/01/112300
https://tech.smarthr.jp/entry/2017/06/02/142600

(余談ですが、当時はKUFUという社名だったことを知らなかったです。)

いっちーに費用の見積もりをお願いしたところ、
比較的安く環境を構築できそうとの見積もりをもったので、（当時AWSについてはEC2とRDSくらいしか触ったことがなかったんですが)記事に記載された全体像をもとにAWS上に環境を構築することにしました。


### 設計

利用したサービスは以下です。

- ECS
- EC2
- ECR
- Codebuild
- Lambda

それがこちらです。

![Untitled Diagram (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/140786/2e9ac3a2-eb55-81c7-9981-e171d43542e6.png)


(実際は今の形になるまで、2転3転していますw)
大きなEC2のインスタンス上にコンテナを立て、それをポート番号によって振り分けるというものです。

作成された環境は、`{IP}:{Port}` の形でGithubへ通知されます。
<img width="620" alt="Screen Shot 2019-12-10 at 11.52.05.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/140786/456c4c7e-197e-b3ec-018b-3566ecb50b34.png">


これで、要件を満たした上で解決策を実現することができました:confetti_ball:

- 作業者のフローは（ほぼ）何も変えることなく、環境構築することが可能
- 確認者がレビューの際に見れるように、出されたPRに対してコメントを書き込む

これで、誰も意識せずに利用できるような環境が利用可能になります。
（管理者である僕らはめちゃめちゃ意識しなければいけないのですがw）

ただ、この形になるまでにいろいろな問題にぶち当たりました。
苦悩をすべて綴るとかなりの長文になってしまうので一部だけご紹介すると

- 当初CircleCI -> CodebuildとしていたのですがGithubのPR番号を取得できずに断念・・・
- 大人の都合で、プロジェクトごとにDockerfileを置けないのでECRにビルド用イメージを置き、その中でDockerfileを作成する（DinD）
- Lamdaの実行時間?の問題で、Githubにコメントができなかったため、wait関数を使って無理やり処理を止めた

などなど。

### 運用
さて、実際にこれを(α版として)運用してみて2ヶ月ほど立ちましたが、
利用してくれる方にSlackで感想を聞いてみたところ

```
・表示がすごくすごく早いので確認側のストレスが少ない
・ブランチを変えられるので複数施策を並行してできる
・実装者がいない時でも見れるのは便利
・実装者がやることはほとんどなく手間がとても少なくて良い！
```
(ニュアンスこんな感じです。実際の文章とは異なります。)

など、実際に自分たちが特に気にして作った部分がきちんと評価されておりました（よかったよかった:raised_hands:）

また調査段階では、
「確認できる環境がないから故に、レビューで細かなところを指摘しにくかった」
という意見もあったのですが、今ではそうした細かな議論もGithubのコメントや口頭でやり取りされているように感じます（主観です。）

レビューの待ち時間がなくなったことによって、各自の作業効率も上がったということもお聞きしました。

一方で、改良の余地はまだまだ存在していて、そちらについても聞いてみたところ、

```
・検証環境ができあがるまで、時間がかかる
・検証環境が同時に立ち上げられる数が決まっており、立たない時があるのと不要なものを消してもらうフローの連携がうまく取れていない
```

などが挙がりました。
前者はビルド時間の関係で、現状30分ほどかかってしまっているため生じている問題です。
こちらは別途他の方が、ビルド時間を短縮させようと頑張ってくれているようです。

後者はEC2のインスタンスサイズを調整している関係で、同時にコンテナが立ち上がる数を制限しており、不要なタスクを削除して運用しているのですが、そちらが少々煩雑になってしまっております・・・

### 今後どうしていく予定？
これらの意見を踏まえて、今後やりたいこと（現在やっていることも含め）はこんな感じです。

#### 削除部分を自動化
先程ちょこっと書きましたが、現状EC2のインスタンスサイズが固定されているかつ、インスタンスのサイズもさほど大きく無いものを利用している為、逐一不要なコンテナを手動で削除して運用しております。

せっかくECSを利用しているので、オートスケールなども組み込み
PRを出す -> 環境立ち上がる
PRをマージ -> 環境クローズ

のような利用シーンが実現できないかなと思っております。

これらを自動化することで、作業者はますます何も気にすることなく検証環境を利用することができるようになり、より本質的な議論の時間を増やせるのではないかと思っております。

#### AWS CDKを利用する
今回作成した検証環境は、現在一部のプロジェクトだけで運用されております。
ありがたいことに、他のプロジェクトからも利用したいとの声が上がってきており（自分調べ）
それらを対応するためには、まずIaCが必要だと考えております。

早くほかのプロジェクトでも使えるように現在AWSのCDKを利用してコード化しております。
(CDKについては、また別の機会で記事にまとめたいと思っております)

## まとめ
今回は、検証環境を作るまでのプロセスをまとめて記事にしてみました。

- タスク依頼
- ヒアリング調査
- 必要要件の洗い出し
- 事例調査
- 設計
- 実装
- 運用

というような流れの中で、自分が何を考えて意思決定をしていたかをまとめてみました。
顧客（社内顧客）が必要なものは何かということを、1から実践できたとても良い機会だったと思います。

書き出してみると、思っていた以上に長文になってしまいました。
長々とお付き合いいただきありがとうございました。