[レポート]サーバレスアプリケーションにおけるCICD #SVS336 #reinvent

SVS336 - CI/CD for serverless applications のレポートとなります。
2019.12.17

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

はじめに

SVS336 - CI/CD for serverless applications セッションのレポートです。

CI/CDとはなにか

我々が呼ぶ「CI」とは、Continuous integration - 継続的インテグレーションを意味し、「CD」は Continuous delivery - 継続的デリバリーか Continuous deployment - 継続的デプロイを意味します。

パイプラインで考えてみる

このパイプライン構成はサーバレスで行う上ではそれほど重要ではありません。ウォーターフォールのようなものであれば、大体同じ様な段階を踏みます。

CICDがとても重要だと周知されていることも踏まえた上で、なぜCICDが重要なのか、幾つかのポイントについて触れていきます。

CICDの重要性

自動化は重要です。1回あるいは50回を繰り返しても、それぞれで同じくらいの時間で完了します。常にマニュアルでの操作を用いられると同じ時間では終わりません。

また、例え話として、

ボブがいつものコンピュータでコンパイルに成功し、zipドライブでzip保存して、チェックの厳しい学校でUSBスティックドライブとして使おうとします。でも何らかの理由で使うことができない。スージーに渡したところ、彼女は問題なく実行でき、わずかなチップとともにこっそりと本番へ上げた。

もしあなたのCICDが誰かの手を介するのであれば、それは自動化ではありません。CICDは自動化を通して、毎回同じくらいの時間での動作を期待できることが極めて重要です。

継続的インテグレーションのパイプライン

CICDや他のCDを掘り下げると次の図のようになります。

まず、継続的インテグレーションがあります。これはどれでも同じです。やるべきことは明確です。開発者はコードをコミットし、ビルド上で自動的にマージ、テストされます。そしてOKするために必要な何らかの修正をします。

継続的デリバリーに移行する時にはこのようになります。2つめのステップは自動でOKとなります。実際にステージングにプッシュしますが、本番には決して自動反映しません。

多くの人たちは自身で作ったユニットテストやカバレッジを信じて見るのが好きですが、開発者視点で他の誰かあるいはたくさんの開発者達から見られることも好きです。そして誰かに承認してもらって、差し戻してほしくはありません。進めてほしいのです。やるべきことは終わったのだから承認すべきです。

OKすると、全自動化されたシステムによって、継続的デリバリーから継続的デプロイとなります。自動化されたソース管理、自動化されたビルド、自動化されたステージングへのデプロイ、あるいはテストが発生し、本番へ自動デプロイがされます。下の図は実際に行われていることを表しています。

Amazon.comは多量の自動化しているテストでのカバーをAWSにて行い、Pushし、1分間に何百万回もデプロイします。嘘みたいな信じられないくらいの回数ですが、毎日数多くのデプロイを行っています。本当に数え切れません。

CICDパイプラインを組み立てる上で重要なことは、必要なツールとサービス選びです。サービスのCICDパイプラインを作る時、通常のCICDパイプラインとそれほど異なっているようには見えません。他のCICDパイプラインを元にするのはよくやりそうですが、やってはいけません。必要なツールについて述べていきます。

必要なツールについて

AWS SAM

素晴らしいものです。SAMはサービスアプリケーションモデルで、CloudFormationの上で組みたてられるようにデザインされました。CloudFormationを使っているのであれば、SAMに移るのはとても簡単です。本当に切り替えやすくなっているからです。SAMはサーバレス、リソース、関数、API、DynamoDB Tableのようなシンプルなテーブルといった、様々なものをCloudFormation上で作成することに別れを告げさせるでしょう。

何を行うのかというと、CloudFormationではLambdaを作る際にとても長いコードを目にしました。SAMではこれがとても短くなります。どうやっているかというと、幾つもの自動化したいことについて推測して提案してくれるのです。

SAMは伝統的なAWS CloudFormationのリソースとミックスでき、特別な状態のサービスリソースとして使うことができます。S3、Kinesis、Step Function等についてはどうするのかというと、パラメータマッピングの利用と、CloudFormationとしての出力をサポートします。データ周辺を動的に渡す手段があります。テンプレートを見ながら移植し、refsubのような関数定義を実施することも可能です。これらはとても動的にリファクタリングされます。他のデータから取得するためのimport valueも利用可能です。

REST API化はできません。もしもREST APIを作っていて、動作している機能を構築済みであれば、同じフォルダにそれら用のJSONを入れます。これが手っ取り早いです。

AWS SAM Template

20行程度の雑多な例があります。

Lambda 関数を作るにあたり、関数固有のロールを付与しています。そして、サーバレスで扱う上で各Lambdaが必要とするイベントを付与しています。イベントドリブンのアーキテクチャだからです。イベントの実行はLambdaのトリガーとなり、APIを実行させます。SAMはほんの僅かながらAPIを問題なく動かすに十分なものとなっています。

API Gateway経由のAPIと、パラメータを渡せる{/ProductID}を前においたパスをつくり、GETメソッドのみが通過するようにします。勿論、複数のルートを持つようにしたり、全てに呈して認証のようなものを追加することも可能です。

締めはテーブルです。たったの2行でDynamoDBが指定できます。必要であればHashやKey、ID、動的なキャパシティを指定します。必要に応じて増やしたり減らしたり、データを暗号化しつつDynamoDB Tableに渡します。DynamoDBに馴染みがなければYoutubeでRick Houlihanのビデオを見ましょう。

とてもパワフルなデータベースで、サイバーマンデーやブラックフライデーのような高負荷な事例に使われ、Amazon.comでの高速なinput/outputをカバーしています。

この20行程度の例は、下図のようなシンプルなアーキテクチャになります。

DynamoDBのポリシー行を見ていきます。粒度の細かい権限設定をしてみます。

テーブルの読み込みを可能したい場合、関数は読み込みのみが可能でいずれにも書き込みができない、読み込み専用の権限をセットアップします。権限付与は非常に簡単です。SAMにはローカルでの開発でこれらを行うことに使えるツールがあります。CICDのSAM Templateが使えて、アプリケーションをデプロイするのに使うインフラ構成のコードにもなり、インフラ構成やコードが実施できます。

Code Repository

コードリポジトリを使っていない、あるいは持っていない場合は、CodeCommitを使いましょう。

gitを元にしたリポジトリで、その強力さは使うための理由として十分です。とても強力なセキュリティが必要だとか、IAMと結びつけたいとか、コードを本当に厳密にする必要があるのであれば、CodeCommitを推奨します。GitHubがとても強力なセキュリティを持っていることは明確ですが、AWSアカウントのセキュリティでも可能です。

GitHubやGitLabやそれ以外の色々な種類の選択肢とCodeCommitには互換性があります。

GitHubはCodeBuildとCodePipeLineの両方で互換性があり、GitHubからコードのビルドをトリガーでき、丁寧なパイプラインが利用できます。

BitBucketはCodeBuildと連携します。

GitLabは直接は連携しませんが、様々なhookやプライベートリポジトリのビルドを可能にするために必要なトリガーを組み立てることができます。

最後に、これ以上はない、全てのベースになるgitです。業界標準です。CodeCommitそのものですが、gitはAWS内で管理されたリポジトリを取得できませんし、たくさんの管理や処理能力が必要なこともできません。

AWS CodePipeLine

CodePipelineはオーケストレーションツールです。CICDを組み立てる時や、CICDを編集したい時に本当に欠かせない存在です。何故CodePipeLineの利用を強く推奨するのかというと、誰かがコミットしたものを取り込んでパスする場合に、編成しつつCodePipeLineを用いたパイプラインでビルドできるからです。

サードパーティとの連携は重要です。JenkinsあるいはHudson、TeamCity、及び同様のパートナーとパイプラインのように連携することができます。CodePipeLineを使うと、周りからOKの嵐でパスすることでしょう。

これは基本的で単純な開発用パイプラインをCodePipeLineで作成したものです。この例で使っているツールは、チェックにCodeCommitを使い、ビルドにはCodeBuildを使っています。CloudFormationでデプロイする時、変更セットを作成し、すでに公開されているものに対して変更セットを評価します。すでに公開されているものと同じなら何も行わずデプロイもしませんが、変更点がある場合はデプロイを行います。

幾つかのシンタックスと文法チェックを行い、問題ないか確認します。問題なければ変更セットを実施します。デプロイの3ステップ目に注目しましょう。これらの異なるステージはそれぞれにステップがあり、3つめのステップは「run stub」と呼ばれます。これが実行されると幾つもの柔軟なビルドが走ります。注目することとして、ソースの選択肢にLambdaがあることです。これが何を意味するかというと、開発環境にデプロイする度に環境上で自動化されたスクリプトのテストがLambdaを使って実行されるということです。

Lambdaを多用したくないというのもよくわかります。Lambdaは実際AWSにおけるアーミーナイフのようなもので、Lambdaを多用することで色々な事が可能になります。

先程、ソースのビルド、デプロイ、テストまでを見てきました。このプロセスは自動でも手動でも継続でき、継続することでアーティファクトをステージングにデプロイします。ステージングにデプロイすると変更セットが作成されます。

変更セットとは異なるやりかたも利用可能です。同じテンプレートにて、開発環境用パラメータ、ステージング用パラメータを使い分ける方法です。ステージングへのデプロイで何が起こるかというと、変更セットの作成により変更セットが実行され、APIテストが実施されます。知りたいのは、それらの制御方法と例えばLanScopeのようなパートナーの使い方だと思います。

数多くの様々な選択肢によって、最終的にはテストを完了させることができるでしょう。

AWS CodeBuild

CodeBuildはbuildspecを用いて動作します。

パラメータを渡せたり、複数のフェイズをもたせる事ができます。インストールを追加したり、プレビルドしたりできます。コンテナでどうやって動いているかというと、互換性のあるフレイバーのおかげです。これらがコマンドを実行します。システム上でコマンドを実行できたなら、CodeBuildでも実行可能でしょう。

AWS CloudFormation

CloudFormationはAWS上でインフラ構成をコードとして扱う中心地です。

あとがき

マイクロサービスのCICD化について、使うべきツールについて踏み込んだセッションでした。

後半、AWS SAMに関する内容等も触れられていたのですが、すでに上がっているレポートと被る箇所が多かったため省いています。気になる方は、以下の記事の参照及び当エントリーで触れたセッション動画の視聴をおすすめします。

[レポート] AWS SAM toolkit:サーバーレスアプリケーションの構築、テスト、デバッグ DEM158 #reinvent

[レポート]AWS Lambdaを用いたマイクロサービスの構築 #SVS343 #reinvent