aws-cdkを用いた開発事例の紹介

これははてなエンジニアAdvent Calendar 201812月7日の記事です。

昨日はid:susisuさんの「分割」できる疑似乱数生成器でした。

こんにちは。はてなでSREとして働いているid:taketo957です。

現在、所属しているチームにてAWSのプロビジョニングを行う際に、aws-cdkを試験的に利用しています。

本記事では、aws-cdkについて簡単に紹介し、はてなで実際にどのように利用しているかを紹介します。

はじめに

aws-cdkについて簡単に説明します。aws-cdkは、2018年8月に開発者プレビューとして紹介されました。これによると、

AWS CDK はソフトウェア開発のフレームワークであり、クラウドのインフラストラクチャをコードで定義して CloudFormation でプロビジョニングできます。CDK は AWS のサービスと統合され、高レベルかつオブジェクト指向の抽象概念を使ってAWS リソースを定義できます。

とあります。aws-cdkを用いることによって、CloudFormationによるAWSのリソース定義を、ある程度のベストプラクティスが内包された高レベルなライブラリ群によって扱うことができるようになります。

2018年12月の執筆時点での対応言語は、TypeScript、JavaScript、.NET、Javaとなっており、今後はPythonのサポートが予定されているみたいです。 (https://github.com/awslabs/jsii によるとRubyも期待できそう?)

aws-cdkの構造

aws-cdkの構造を理解するには、以下の図がわかりやすいです。(下記のIssueより引用)

github.com

f:id:taketo957:20181206230900p:plain
CDKのアーキテクチャ

  • L2: aws-cdk内でConstruct Libraryとして提供されている部分で、デフォルト設定やベストプラクティスなどが内包されたライブラリ群です。
  • L1: aws-cdk内でcloudformation libraryとして提供されている部分で、CloudFormationのリソース定義から自動生成されているようです。

これらを利用して定義したものを、AWS CDK Toolkitを通じて、CloudFormationのtemplateに変換したり、stackをdeployしたり、deployされたstackとの差分を確認したりできます。

はてなでの利用例

aws-cdkについて簡単に説明したところで、実際にはてなにおいてどのように利用しているかの一例を紹介します。

はてなでは、開発中のbranchを展開し、それを外部から参照できるようにする開発環境のことをdevhostと読んでいます。 具体的には、{branchname}.test.comようなドメインで外部からそのbranchのアプリケーションを参照できる環境です。

今回は、ECSを用いてdevhostの仕組みを構築しました。 このECSを用いたdevhostをaws-cdkを用いて構築した事例を紹介します。

今回のECSを用いたdevhostの要件としては以下のようなものがありました。

  • branchごとに外部から参照できる環境を容易に作成したり、削除できたりできること
  • 上述の環境を管理できるUI(構成図の下部に構成だけ載せていますが今回の記事では触れません)

devhostの仕組みを実現するための、全体の構成は以下のような感じです。

f:id:taketo957:20181207114428p:plain
devhost構成図

リクエストを受ける部分(図上部)は非常に単純です。 Route53を用いて開発用のドメインのHostedZoneとRecordSetを管理し、ALBを用いてbranchごとの環境を展開したECSのServiceに振り分けています。

以下がaws-cdkを用いた具体的な例です。

gist.github.com

上記の両方の要件を満たすためのポイントは、branch名に応じて動的に作成する部分(上記の例では EcsServiceStack )を独立したstack定義として切り出すことです。(かなり省略していたり、簡単のための単一のファイルにまとめたりしていますが雰囲気だけでも伝われば幸いです)

タスク定義に用いるコンテナのimageにはあらかじめ、branch名に対応するtagを付与してあります。 また、ALBではHostヘッダによるtargetの振り分けを行っています。このホスト名はbranch名から生成していますが、あらかじめbranch名をURLで用いることができる形に正規化しておいてあげる必要があります。ListenerにTargetGroupを追加する際に、ListenerのRuleのPriorityの値が被らないように制御してあげる必要がある点もポイントの一つです。

肝心のbranch名に関しては、aws-cdkのcontextという機能を用いて実行時に受け渡しています。

Passing in External Values to Your AWS CDK App — AWS Cloud Development Kit

これまでの定義を用いて、例えば以下のコマンドを実行することで hoge.example.com というドメインから、 hoge ブランチの内容を確認できる環境を立ち上げたりしています。

$ cdk synth EcsService -c 'devhost:branchname=hoge'
$ cdk deploy EcsService -c 'devhost:branchname=hoge'

終わりに

今回は開発者プレビュー版のaws-cdkを用いて実際に開発環境を構築した事例を紹介させていただきました。

aws-cdkを用いることでアプリケーションエンジニアにも構成管理を積極的に行ってもらえるようになったりと、チーム内でポジティブな変化を日々感じています。

一方で、開発者プレビュー段階であることは事実で日常的にbreaking changeと付き合っていく覚悟は必要になってきます。 実際に所属しているチームでは、日常的にaws-cdkに対してPRを送るなどしてコミットしたりしています。

とはいえ、プログラミング言語を通じてAWSのリソース管理を行うことで、CloudFormationを素で利用するよりも柔軟にリソース管理を行うことができると感じています。(例えば、aws-cdk自体もnodeのアプリケーションであるので、Lambdaで動かして何かを行うといったことも可能だと思います)

これからどんどんコミュニティが活性化してくといいですね!

はてなエンジニアAdvent Calendar 2018、明日はid:wtatsuruさんです!