こんにちは、チーム活性化サービス「Goalous」のリードエンジニアを務めている吉田です。
今回はGoalousがHTTP/1.1からHTTP/2に移行した経緯と実際にどのように移行したのかをお話します。
なぜ移行したか
僕達は先月までサービス全体の大規模なパフォーマンス改善を1ヶ月半以上かけて行っていました。
Goalousは以前からレスポンスの悪さがかなり目立っていて、「表示速度が遅い」という意見が多く寄せられていました。 開発チームとしてはユーザーのストレスを軽減してサービスの使い心地を向上させたい、 「サクサク動かせるようにしたい」という思いが前々からありましたが ただ機能追加・改善がどうしても優先的になってしまい手をつけることが出来ずにいました。
しかしサービスを有料化する前にはどうしても対応したかったこともあり、 今年5月にチームの総力をあげてサービス全体のパフォーマンス改善に取り組むことが決定しました。 HTTP/2への移行はそのパフォーマンス改善の一つの取り組みです。 HTTP/2のメリットの詳細は今回は省略しますが、詳しく知りたい方はこちらを参照下さい。
HTTP/2への移行を決めたのは、リクエストとレスポンスの多重化等のメリットを享受したかったのと、他にもう一つ僕達にとって重要な理由がありました。 それはAWSの問題です。
GoalousではAWSのOpsWorks(Chefを使用してクラウドエンタープライズでアプリケーションを設定および運用するための設定管理サービス)を使用しています。
OpwsWorksはOpsWorksスタックとOpsWorks for Chef Automateの二種類があり Goalousで使用しているのはOpsWorksスタックです。
OpsWorksのスタックはChefのバージョンが11か12によって明確に区別されます。 僕達はずっとChef11のスタックを使用していましたが、もうそろろそろChef12にバージョンアップしたかったので 今回のHTTP2/移行が良い機会となりました。
あとはロードバランサーがELBではなくALBじゃないとHTTP/2を使用出来ないので思い切って Chef12+ALBの全く新しいスタックを作ることに決めました。
どう移行したか
GoalousのChefのレシピは残念ながら公開出来ないので、本記事においてはあくまで OpsworksのChef12スタックとALBをどう構成してHTTP/2を実現するか に焦点を絞り、サンプルのChefレシピを使ってミニマムな構成の手順を説明します。
参考:Use Application Load Balancers with your AWS OpsWorks Chef 12 Stacks
Step1.ALB作成
基本的にはAWSの公式ドキュメントに沿って作成します。
ただしステップ 5: ターゲットグループのターゲットを設定するはスキップしてください。 インスタンス作成とターゲットグループへのターゲット登録はOpsWorksで行います。
Step2.OpsWorksスタック作成
OpsWorksのダッシュボードページで、スタック追加ボタンをクリックします。

スタック追加ページに遷移後、まずChef12 Stackを選んだ上で、
- Stack name
- Region
- VPC
- Default subnet
- Default operating system
- Default SSH key
をそれぞれ入力します。

次に赤枠で「Use custom Chef cookbooks」でYesを選択して 上記で触れたサンプルのChefレシピのGitリポジトリを指定します。
- Repository type: Git
- Repository URL: https://github.com/awslabs/opsworks-example-cookbooks
入力後、右下のスタック追加ボタンをクリックしてスタックが追加されたことを確認してください。

Step3.ELB APIの権限付与
既にDefault IAM instance profileで選択したprofileにELB API関連の権限が付与されている場合はスキップして構いません。
Step2で作成したStackを選択してください。 Stackの詳細情報が表示されますので、Advanced Optionグループ内にある Default IAM Instance Profileの赤枠の登録済みprofileのリンクをクリックします。

ロール詳細ページでロールポリシーの作成ボタンをクリックします。

カスタムポリシーを選択して次へ進みます。

ポリシー名を入力し、以下のELB API権限を与える為のJSONを貼り付け、ポリシー適用を完了します。

Step4.Layer作成
作成したStackを選択後、左メニューのLayerタブをクリックしてLayer追加リンク(もしくは右上の追加ボタン)をクリックします。

NameとShort nameに任意の文字列を入力して作成完了します。

ALBターゲットグループとOpsWorksスタックの紐付け
ポイント 2017年8月現在ではまだOpsWorksスタックのロードバランサーの設定はALBは対応していません。 従ってスタックとALBの紐付けはChefのレシピで行う必要があります。
作成されたLayerのSettingリンクをクリックします。

General Settingsタブ内でCustom Jsonという項目があります。 ここでStep1で作成したALBのターゲットグループとOpsWorksスタックの紐付けを行います。

Custom Jsonのテンプレートを以下に記載します。 このJSONをCustom Jsonのテキストエリア内に貼り付けてください。
次にtarget_group_arnの値をStep1で作成したALBのターゲットグループのARN文字列に置き換えます。 ターゲットグループのARNを確認する方法としては EC2のコンソールで左メニューからターゲットグループを選択後、Step1で作成したターゲットグループを選択します。 画面下にターゲットグループの詳細情報が表示され、その中にARNの項目がありますので 値文字列をコピーして上記のCustom Json内に貼り付けた上で設定を保存します。

実行するChefレシピの設定
Recipesタブに移動して以下の様にレシピをライフサイクルイベントに割り当て、設定を保存します。 ・Setup:alb_support::install_http_server,alb_support::attach_to_albのレシピを追加 ・Shutdown:alb_support::detach_from_alb,alb_support::uninstall_http_serverのレシピを追加
※あくまでOpsWorksでALBを使ってHTTP/2リクエストを実現する為のサンプルです。 実際はApacheやNginx等のWebサーバーのインストールは他のレシピに組み込んであると思いますので その場合、alb_support::install_http_server,alb_support::uninstall_http_serverは不要になります。

EC2インスタンス追加〜HTTP/2リクエストの確認
OpsWorksの左メニューからInstancesを選択後、インスタンスを追加します。

追加したインスタンスを起動します。

起動に成功したら、Route53でALBと紐付けたドメインにアクセスします。 HTTP/2のリクエストになっていますね!

実際のプロジェクトにどう組み込むか
今回はサンプルのレシピを使ってChef12+ALBのスタックでHTTP/2のリクエストを確認するところまで説明しました。 しかしこれを実際のプロジェクトで使用するとなると、
- Chef12スタックではコミュニティクックブックがレシピ実行時に自動的にimportされなくなったのでどうするか
- devやstageの各環境のスタックで参照するレシピをいかに自動的に生成するか
などなど、いくつもの課題があります。
それらの課題の解決は次回の記事で_実践編_として執筆する予定ですので しばらくお待ちください。