[メモ] Accelerating Software Delivery on AWS

##### https://medium.com/aws-activate-startup-blog/accelerating-software-delivery-on-aws-c63b8696b430 の個人的な翻訳というかメモです。所属する企業や団体における公式見解ならびに公式発表ではございません。

----

多くのStartupにとってのサバイヴおよびスライブのための鍵は、単に素晴らしいアイデアやファンディングだけではなく、クイックにマーケットに進出することと、素早く微調整してプロダクトやサービスをマーケットのニーズにあったものにすることでもあります。
マーケットファーストはとても良いことですが、一方で『 カスタマーが求めるもの vs あなたが"カスタマーが必要とする"と思うもの 』をマーケットに持ち込むことも大切なことです。
そのためには、"プロダクトやサービスを何ヶ月/何年もステルスモードで開発すること"から、"コラボレーティブなアプローチでプロダクトやサービスをカスタマーに素早く届けフィードバックを元に改良をイテレーティブに行っていく"という方向へマインドセットを変える必要があります。

このポストでは、カスタマードリブン開発アプローチをスタートアップが実践する上での方法をAWSのサービスと併せてご紹介します。

## Starting Up Lean
多くのスタートアップおよびいくつかの大企業(その数は増加中)では、"リーンスタートアップ"で紹介された、マーケットのwantsに対応するクイックな意思決定およびプロダクト/サービスの開発といったメソッドを採択しています。これはサービス/プロダクトがマーケットのneedsに見合わなかった場合のプロダクト/サービスの開発およびコストに関するリスクを抑えることにつながります。

"Lean Startupメソッドにおいて鍵となるのは、適切な機能を持った適切なプロダクトを、build-measure-learnフィードバックループと共にイテレーティブなプロセスで開発し続けることで、このプロセスの中心はminimum viable product(MVP)である"
Eric Ries(Lean Startupの著者)はMVPについてこう言っています:

"限られた機能しかもたいなプロダクトでも、それをShipすることで、アーリーアダプターの元に届き、少なくとも何人かのユーザーからは共鳴を受け、ユーザーはお金を払い、ユーザーからのフィードバックを受け取れるようになる"

build–measure–learnフィードバックループと共に、MVPをビルドし、カスタマーからフィードバックを受け、その洞察を次のbuild–measure–learnイテレーションをドライブするために用います。build–measure–learnループをより早く回すことで、素早くカスタマーにtangibleな価値を届けることができ、且つ、ポテンシャルな競合者に対するバーを高くすることが出来ます。

## Becoming Agile
素早くカスタマーフィードバックをMVPに取り込み、time to marketを加速すると、build–measure–learnフィードバックループを回すためにかかる時間をミニマイズする必要性が出てきます。Agile開発のテクニックを取り入れることで、自然にイテレーティブなbuild–measure–learnプロセスを実践できるようになり、インクリメンタルにMVPに対してアップデートを行いながらrapidな開発が出来るようになり、それはfeedback loopの短縮に繋がります。

下記のリーン開発の原則に従うことで、build–measure–learnフィードバックループの素早いアクセラレーションのドライブを可能にします:
- **Eliminate waste** 必要のない開発プロセスや開発機能を避ける
- **Build quality** テスト駆動開発やCIを通じて増え続けるフィードバックに対するアップデートに対しても品質を保つ
- **Deliver rapidly** イテレーティブに開発を行うことで素早くデリバーする

Agile開発を受け入れることで、開発チームはカスタマーフィードバックドリブンなアップデートを素早くとりこんでリリースすることができるようになります。多数のリリースの中でのベロシティの増大は、リリースにおけるテストとデプロイのステップにおける対応の増大を招きます。

テストとデプロイのステップにおけるスループットを増やすことは、時々"last mile"と揶揄されるが、このlast mileにかかるステップを自動化することで解決することができると考えます。

## Delivering Continuously
継続的デリバリーによって、変更開発を行った際にプロダクション環境に投入できるようになるまでの時間が短縮されます。その時間短縮はリリースプロセスの中のビルド、デプロイ、そしてテストのステップの自動化によって達成されます。継続的デリバリーの実装にはステージごとのリリースプロセスモデルであるデプロイメントパイプラインのセットアップが必要です。
AWSは様々なサービスおよびサードパーティーツールとのインテグレーションを提供し、開発パイプラインとパイプラインに沿った方法へのプロセスの変更を可能にしています。AWS CodePipelineはAWSプラットフォーム上で継続的デリバリーをサポートするプライマリなサービスです。

## Building Your Deployment Pipeline
AWS CodePipelineはリリースプロセスのオーケストレーションをサポートします。
AWS CodePipelineでは、リリースのプロセスに関するステップを設計することができ、それぞれのステージの中で行うアクションを他のツールやサービスと共に定義することができます。
パイプラインをセットアップすると、AWS CodePipelineはパイプラインに関連するVersion Control System(GitやSubversionなど)に対する新たなソースコードのチェックインを検知して、変更部分も取り込んでビルドをおこない、プロダクション環境にその変更を反映させる前に、それぞれのステージごとでのデプロイおよびテストを行います。
以下のインストラクションはsource, build, staging, そしてproductionのパイプラインを示しています。

![1-GrO3EkyNKr6SbY7dqSCXzA.png](https://qiita-image-store.s3.amazonaws.com/0/51469/1a340014-2e8d-e5c2-6a66-bd045708dd73.png)

**Source Stage**
パイプラインのSource Stageはバージョン管理システムに関連します。AWS CodePipelineはGithubおよびAmazon S3をバージョン管理システムとしてサポートします。
Source Stageでは、バージョン管理システムに変更が加わったものを検知して、AWS CodePipelineのワークフローをキックします。Githubリポジトリに対するコミットもしくはS3バケットに対するファイルのアップロードがこれの対象になります。

**Build Stage**
Build Stageはいつパイプラインに関連するリポジトリにコミットがあっても、自動的にビルドを行って継続的インテグレーションをサポートします。
Jenkinsを使って継続的インテグレーションを設定したり、custom build actionで現在お使いのビルドツールを使った継続的インテグレーションビルドを実践することができます。

**Staging Stage**
Staging Stateはテストを行うステージで、自動的にデプロイを行い、変更点を含むテストを実施します。このパイプラインは1つ、もしくは複数のステージを持ち、それぞれのステージでそれぞれのテストを行います。例えば、User Acceptance Testing (UAT)、Exploratory testing、Stress testingなどをそれに当たります。

AWS PipelineはAWS CodeDeployもしくはAWS Elastic Beanstalkを使ったデプロイメントのオプションを提供し、テストのステージに関連した変更点のデプロイを行うことを可能にします。また、custom actionを作って既存のデプロイメントツールを使ったデプロイを行うことも出来ます。

AWS CodePipelineはサードパーティーの自動テスティングサービス- Apica, Blazemeter, Ghost Inspector, or Runscope -とのインテグレーションをサポートし、テストステージに応じたテストの自動の実行を可能にします。また、こちらもcustom actionを作って既存の自動テストツールを使ったテストを実行することもできます。

**Production Stage**
Production Stageはプロダクション環境へのデプロイをサポートします。デフォルトでは、パイプライン内の全てのステージでのテストが通ったら、自動的にプロダクション環境へデプロイを行います。
Production Stageへの自動反映をdisableにすることで、user intervention(人によるマニュアル操作)をProductionへのデプロイに必須にすることも出来ます。

## Automating Your Deployments
AWSはAWS Elastic Beanstalk, AWS CodeDeploy, AWS OpsWorks, AWS CloudFormationといったサービスを使ってデプロイの自動化を可能にします。

"どのサービスを利用すべきか？"という質問をよくいただきますが、それぞれで機能がオーバーラップしている部分もあったり、自動デプロイメントにおける特定のユースケースに向いているものもあります。

このセクションでは、それぞれのサービスについて短くご紹介するとともに、特定のデプロイメントにおける特定のサービスについてのガイダンスをご提供します。
それでは、AWS Elastic BeanstalkとAWS CodeDeployのAWS CodePipelineとのインテグレーションについて見ていきましょう。

## AWS Elastic Beanstalk
AWS Elastic BeanstalkはAWSでアプリケーションをデプロイする最も簡単な方法の一つです。ターゲットになるenvironmentのプロビジョニングおよびアプリケーションのデプロイメントの両方をサポートします。
具体的にはAWS Elastic Beanstalkは、EC2インスタンスのプロビジョニング、ロードバランシングの設定、Auto Scalingの設定、ゼロダウンタイムでのデプロイメント、そしてターゲットの環境のモニタリング機能を提供します。
このサービスを使うことで、インフラレイヤの管理から開放され、アプリケーションの開発により多くの時間を割くことができるようになります。
AWS Elastic Beanstalkは下記のプラットフォームのプロビジョンおよびデプロイをサポートします。
- **Apache Tomcat for Java**
- **Generic Java applications**
- **Apache HTTP Server for PHP**
- **Python and Node.js**
- **Nginx for Node.js**
- **Passenger for Ruby**
- **Microsoft IIS 7.5 for .NET**
- **Go**
- **Docker**
AWS Elastic Beanstalkはこれらのスタックに当てはまるWebもしくはApplicationサーバーへのデプロイに非常にフィットします。例えばWordpressサイトをIISやApache HTTP Serverにデプロイするといった用途です。

## AWS CodeDeploy
プロビジョニングをサポートするAWS Elastic Beanstalkとは異なり、AWS CodeDepoyはデプロイメントのプロセスにフォーカスしたサービスです。つまり、デプロイをする前にサーバーをプロビジョニングしておく必要があります。
AWS CodeDeployは言語やスタックにとらわれることなく、オンプレミスもしくはAWSで稼働するAmazon Linux, Red Hat Enterprise Linux, Ubuntu, Windowsの上で動く、どんなアプリケーションスタックにも対応します。
AWS CodeDeployのデプロイメントユニットはrevisionと呼ばれ、変更が含まれるファイル and/or バイナリで構成されます。変更のデプロイメントに必要なスクリプトはAppspecというYAML形式のファイルに定義することができ、CodeDeployに "どこにファイルをコピーするか" と "どのスクリプトとコマンドをどのタイミングで実行するか" を伝えます。
AWS CodeDeployはデプロイメントのプロセスの中で、ターゲットのサーバーのコンフィグレーション用途でPuppet, Ansible, Saltstack, そして Chef の実行をサポートします。
もし、アプリケーションがEC2インスタンスやオンプレミスのサーバーのフリートに対して、ローリングアップデートを行う必要があるのであれば、AWS CodeDeployは良い選択肢です。

## AWS OpsWorks
AWS Elastic Beanstalkと同様に、AWS OpsWorksはターゲットとなる環境へのプロビジョニングとデプロイメントを両方サポートします。
また、AWS OpsWorksはAWS CodeDeployと同様に言語やスタックを選びません。いかなるアプリケーションスタックのデプロイも、AWS OpsWorksでサポートされているOS(オンプレおよびAWS)で稼働するものであれば行うことができます。
AWS OpsWorksはまたより複雑なデプロイメントシナリオもサポートします。例えば複数のレイヤーからなるスタックを組み合わせたアーキテクチャを組むことができます。
レイヤーはChefのレシピを使ってインスタンスの構成のブループリントを提供します。AWS OpsWorksはHAProxy, Memcached, NodeJS App Serverといった複数のビルトインなレイヤーでアーキテクチャを構成します。AWS OpsWorksではまたカスタムレイヤーをあなり自身のChefのレシピで作ることも可能です。
もし、アプリケーションが複雑でマルチレイヤーなデプロイメントを必要とし、例えばAWS Elastic Beanstalkでサポートされていないようなスタックを使うのであれば、AWS OpsWorksは良い選択肢と言えます。一方で、AWS CodePipelineはAWS OpsWorks用のビルトインサポートと行っていないため、AWS OpsWorksを使うのであれば、custom actionを作成してパイプラインの中でAWS OpsWorksを使ったデプロイメントの設定を行う必要があります。

## AWS CloudFormation
AWS CloudFormationはAWSのリソースをプロビジョニングする最も簡単な方法です。アプリケーションの実行に必要なAWSリソースをJSON形式のファイルに記述します。
このJSONファイルをCloudFormation Designerと呼ばれるグラフィカルなツールを使ってAWSリソースのダイアグラムを作成することができます。CloudFormationはAWSリソースが記述されたテンプレートを使ってスタックを構築します。
CloudFormationをデプロイメントのために使うこともできます。更にCloudFormationを、プロビジョニングに対応していないサービスや、プロビジョニングに対応しているサービスでもサポートされていないAWSリソースの稼働といった部分の補完用に用いることもできます。
AWS Elastic Beanstalk と AWS OpsWorks は両方AWSリソースのプロビジョニングに対応していますが、CloudFormationはEBとOpsWorksで直接サポートされていないアディショナルなリソースのプロビジョニングを行うことができます。例えばEBでは.ebextensionsというディレクトリ内にファイルを配置することで、CloudFormationでサポートする全てのAWSリソースのプロビジョニングを行うことが可能です。(内部的にEBがCloudFormationのTemplateに変換して実行します)

## Summary
"機能を想像すること" から "機能がProductionにデプロイされていること" へ変わることで、サイクルは短くなり、ソフトウエアデリバリは加速するが、それには自動化が必要不可欠です。

継続的デリバリはビルド、テスト、そしてリリースプロセスの中のデプロイステップを自動化するアプローチであり、AWS CodePipelineはそれをサポートするプライマリなサービスです。

AWS CodePipelineは自動デプロイの実現のために、AWS CodeDeployおよびAWS Elastic Beanstalkとのインテグレーションをサポートし、自動ビルド/テスト/デプロイのために、サードパーティーツールとの連携をサポートします。

AWSはデプロイメント用に複数のサービスを持っており、それぞれ特定のユースケースをターゲットにしたり、機能がオーバーラップしている部分もあります。
更に詳細に関しては↓のホワイトペーパーをご覧ください。
[Overview of Deployment Options on AWS](https://d0.awsstatic.com/whitepapers/overview-of-deployment-options-on-aws.pdf)