はじめまして。カヤック技術部の杉山です。 主にクライアントワークでサービスを開発しています。
今回は、クライアントワークで運用している、テストサイトの仕組みに関して書きます。
「テストサイト」の概要
クライアントワークでは、日々たくさんの案件を開発しています。 それぞれの案件では、多くの場合、Webサイトもしくは、WebAPIを公開するためのサーバーが必要になります。 実際の公開時には、案件ごとに専用のクラウドコンピューティングサービスを契約し、セットアップすることになりますが、 利用して良いサービスの確認が必要であったり、サービスの契約まで時間がかかったりするため、すぐには決まらない場合があります。そのため、開発時や検証時には、カヤック側でテストサイトを用意し、確認やプレビューを行っています。
さらに以下のような要望にも対応する必要があります。
- 出来るだけ時間をかけず開発環境を用意したい
- 案件ごとに、必要なミドルウェアが異なるため、出来るだけ汎用的なサーバーを用意する必要がある
- WebSocketを利用する場合がある
- Webサイトの表示にBASIC認証を設定する必要がある
- 特定のユーザーのみがssh接続できるようにユーザー管理がしたい
- git push 時に自動デプロイしたい
- httpsで表示出来る必要がある
- お金は節約したい
以上の条件から、サーバー構成の概要は以下のようにしました。
この構成で、自動的に構築できる仕組みを作っています。
利用技術
- Amazon DynamoDB
- Amazon EC2 Simple Systems Manager (SSM)
- Amazon CloudWatch
- AWS Lambda
- AWS Certificate Manager (ACM)
大まかな流れ
作成時
基本的な方針として、DynamoDBのトリガーを使うことで処理が行われるようにしています。
DynamoDBにセットアップ構成の書かれたレコードを追加すると、トリガーでLambda functionが呼び出されます。
レコードには以下のような情報を登録しています。
- 公開されるドメイン
- 登録日時
- 削除日
- 起動元となるAMI
- ソースをCloneするリポジトリ・ブランチ
- リポジトリ内で公開されるディレクトリ
- BASIC認証のユーザー名・パスワード
まずAMIを元に、EC2インスタンスを起動させます。 EC2インスタンスが起動したイベントをトリガーに、さらに処理を続けます。
起動したEC2には、SSMエージェントがインストールしてあり、SSH接続することなく、 インスタンスIDの指定で、Lambda functionからコマンドを実行しセットアップを完了させています。
削除時
サイトが残り続けてしまわないように、CloudWatchによって、定期的にLambda functionを実行し、削除期限が切れているレコードを探し、削除します。 実際には、期限が切れそうになったら警告を送る、削除時にはAMIを作成、さらに一定期間で、AMIの削除ということも行っています。
細かい説明
SSM
実行先のEC2にSSMエージェントと、EC2のロールにAmazonEC2RoleforSSMポリシーを追加します。 実行元に、AmazonSSMFullAccessポリシーを追加すれば、任意のコマンドがInstanceIDの指定で実行できるようになります。
ユーザー管理
開発者がSSH接続できるようにユーザーを生成します。
Githubのリポジトリにアクセスできる、特定のTeamに所属するGithubユーザーを、Linuxユーザーとして作成します。 GithubのAPI経由で、User名・public keyを取得し、Linux Userとして登録しています。
自動デプロイ
Git Push 時に、自動でテストサイト内のプログラムを更新するため、 EC2内に、Git Pullを行うWebhook用のスクリプトを用意し、Supervisorで常時起動させています。
呼び出し側は、GithubのAPI経由で、そのアクセスURLを登録しています。
Git Pull 用の ssh key は、Lambda function上で生成し、Githubに登録、private key は EC2上に保存します。
https
証明書はACMでワイルドカード証明書を取得しています。 ACMが割り当てられるのは、CFかLBなので、ALBを置いて割り当てています。
ELBではなくALBを選択している理由は、WebSocketのサポートがあるためです。
どのテストサイトのドメインであっても、すべてALB経由でアクセスしたいので、 Route53で取得したドメインのサブドメインを、ワイルドカードの指定ですべてALBに割り当てています。
ALBにはホストベースのルーティング機能が無いので、ALBの後ろにEC2を置き、ルーティングを行っています。
basic認証
Basic認証の作成・更新は、 DynamoDBの更新のトリガーによって、 Lambda functionからSSMで.htpasswdファイルを書き換えています。
遅延実行
起動直後のEC2は、実際にはまだSSMコマンドが実行できず、少しの間待つ必要がありました。 遅延させてLambda functionを実行しています。
遅延実行には、SQSではなく、DynamoDBを使った遅延実行を実装しています。 SQSで遅延させることができる時間には制限があるためです。
DynamoDBに、実行するLambda function名、Payload、発火時間を設定し保存し、 CloudWatchによって、定期的にDynamoDBをチェックし、発火時間が来たときに、Lambda functionを呼び出しています。
DynamoDBへのレコード追加
最小限の工数で開発するため、初期開発ではコマンドラインツールを作成しました。 現在は構築した仕組みがうまく運用できているので、GUI版を開発し、テスト中です。
さいごに
以上、こんな仕組みになっていました。 実際作るよりも、移行までの計画や、どういう仕組みにするかを考える方が大変でした。
こんな仕事も面白そうだと思った人はこちらか ら! 杉山のブログを読んだと書いてもらえると、筆が進みます。