AWS CodeDeployの超詳細解説

# はじめに
この記事はDevOps on AWS大全の一部です。
DevOps on AWS大全の一覧は[こちら](https://qiita.com/tech4anyone/items/b06f88035d27c6ef13b2)。

この記事ではCodeDeployとはどういうサービスで何ができるのかを超詳細にまとめています。

具体的には以下流れで説明します。
- AWS CodeDeployとは
- AWS CodeDeploy for オンプレミス/EC2
- AWS CodeDeploy for ECS
- AWS CodeDeploy for Lambda
- AWS CodeDeployのトラブルシューティング

AWSの区分でいう「Level 200：トピックの入門知識を持っていることを前提に、ベストプラクティス、サービス機能を解説するレベル」の内容です。

# この記事を読んでほしい人
- CodeDeployがどういうサービスか説明できるようになりたい人
- CodeDeployを採用するときのベストプラクティスを説明できるようになりたい人
- AWS Certified DevOps Engineer Professionalを目指している人

# AWS CodeDeployとは
AWS CodeDeployとはアプリケーションのデプロイメントを自動化するためのデプロイサービスです。

アプリケーションをデプロイできる先は以下4つです。
1. オンプレミス
2. EC2
3. Lambda
4. ECS

ただし、オンプレミスとEC2にデプロイメントする際にはCodeDeploy Agentのインストールが必要なので忘れないようにしましょう。

CodeDeployは段階的なデプロイメントの制御や失敗時のロールバック機能を有しているためダウンタイムを最小限に抑えたデプロイメントが簡単に実現可能です。

なお、AWS CodeBuildではbuildspec.ymlにビルド内容を記載しましたが、AWS CodeDeployではappspec.ymlにデプロイ内容を記載します。

混同しないように気を付けてください。

# AWS CodeDeploy for オンプレミス/EC2
まずはオンプレミスあるいはEC2へのデプロイメントです。
すでに述べた通り、残り2つのLambdaやECSへのデプロイメントと異なり、CodeDeploy Agentのインストールが必要なのでご注意ください。

## デプロイパターン
デプロイメントのパターンはBlue/Greenかin-placeの2パターンです。

ポイントとしてはどちらのパターンでもデプロイメントするグループをTagあるいはAutoScalingGroupで設定できるという点です。

Tagの場合には特定の値のTagを持ったEC2を1つのグループとして、AutoScalingGroupの場合には指定したAutoScalingGroupを1つのグループとして取り扱い更新していきます。

ただし、Blue/Greenの場合、Tagを使うと手動切り替えのみ、AutoScalingGroupを使うと自動切換えのみであることに注意してください。

Blue/Greenは下図の通り、一時的に新旧2面作りトラフィックをシフトさせます。
そのため、Load Balancerを使ったアーキテクチャであることが必須です。
![](https://storage.googleapis.com/zenn-user-upload/84825629561f-20231106.png)

in-placeは下図の通り、指定された戦略に従って順次デプロイメントしていきます。

![](https://storage.googleapis.com/zenn-user-upload/144962d346cf-20231106.png)

in-placeの切り替え戦略については以下4パターン存在します。
1. AllAtOnce
2. HalfAtATime
3. OneAtATime
4. Custom

それぞれ複数台あるEC2をどのように更新していくかは読んで字のごとくなので説明は割愛します。

in-place戦略をとるときにどのパターンを選ぶかはデプロイメントスピードと既存システムへの影響の天秤で決まります。

ある程度のダウンタイムを許容できるので迅速にデプロイをしたければAllAtOnceですし、デプロイメントにかかる時間が長くなってもよいから可能な限り既存システムに影響を与えたくない、というならOncAtATimeです。

なお、Blue/Greenはin-placeのどのパターンよりも既存への影響が小さいですが、費用がin-placeのどのパターンよりも高くなります。
これは、瞬間とはいえ、BlueとGreenの二面作ることになることが理由です。

試験の際にはコスト最適ならダウンタイムの要件を見てin-placeのどれかを、ダウンタイムの最小化であればBlue/Greenを選ぶようにしましょう。

## デプロイメントフック
アプリケーションをデプロイする際に、特定のタイミングでスクリプト実行をしたいという場面は多々あると思います。

例えば、EC2の中の環境依存の設定を更新したり、デプロイメントされたアプリケーションの正常性確認をしたり、といった用途でのスクリプト実行が想定されます。

そういった要望をかなえるときに使えるのがデプロイメントフックです。
デプロイメントフックのタイミングは下図にまとめました。

![](https://storage.googleapis.com/zenn-user-upload/5a48a1300894-20231106.png)

見るとわかるようにAWS CodeDeployで予約されたフックの前後にある各フックごとにスクリプトを実施できます。

少し細かいですが、各フックをどういう目的で使うことが多いかベストプラクティスに沿って確認しましょう。

- BeforeInstall
	- ファイルの暗号化解除や現在のバージョンのバックアップ作成など、インストール前のタスクに使用します。
- AfterInstall
	- アプリケーションの設定やファイルパーミッションの変更などのタスクに使用します。
- ApplicationStart
	- ApplicationStop 中に停止したサービスを開始するために使用します。
- ValidateService
	- デプロイが正常に完了したことを確認するために使用します。
- BeforeAllowTraffic
	- ロードバランサーに登録する前に、EC2インスタンスでタスクを実行します。

なお、LoadBalancerを使っている場合にはデプロイメントの前にトラフィックを止めることができます。
トラフィックを止める/許可するタイミングとアプリケーションを止める/起動するタイミングの前後性は試験で頻出です。

またApplicationStartのあとにValifateServiceがあるのも試験でよく問われるので覚えておきましょう。

# AWS CodeDeploy for ECS
ECSへのデプロイはタスク定義に従って新しいサービスをデプロイすることが可能です。

![](https://storage.googleapis.com/zenn-user-upload/38d8035cce83-20231106.png)

ECSにデプロイメントするためにCodeDeploy Agentが不要なのはすでに述べたとおりです。

## デプロイパターン
EC2と異なり、デプロイパターンはBlue/Greenのみです。
ただし、トラフィックの切り替え方はCanary、Linear、All at Onceから選べるので柔軟なデプロイ戦略の実装が可能です。

![](https://storage.googleapis.com/zenn-user-upload/bf262ce130c0-20231106.png)

## デプロイメントフック
ECSへのデプロイメントを実施する際のフックはEC2に比べてかなりシンプルです。

![](https://storage.googleapis.com/zenn-user-upload/0c44d12ad336-20231106.png)

EC2と比較して混乱しやすいのがBlockTraffic関連とApplication関連、ValidateServiceがない点です。

これはECSのデプロイメントがBlue/Greenしかないことを踏まえると当たり前ですが、単純にフックだけを暗記しようとすると間違えやすくなっているので気を付けましょう。

# AWS CodeDeploy for Lambda
Lambdaへのデプロイは新しいLambda関数のバージョンを作成することでデプロイが可能です。

![](https://storage.googleapis.com/zenn-user-upload/17abbe3b3af9-20231106.png)

具体的にはLambdaのエイリアスを旧バージョンから新バージョンに切り替えることでデプロイを完了させます。
なお、ECS同様CodeDeploy Agentは不要です。

## デプロイパターン
ECS同様、デプロイパターンはBlue/Greenのみです。
トラフィックの切り替え方もECS同様、Canary、Linear、All at Onceから選べるので柔軟なデプロイ戦略の実装が可能です。

![](https://storage.googleapis.com/zenn-user-upload/b08a5da35c58-20231106.png)

## デプロイメントフック
Lambdaへのデプロイメントを実施する際のフックはECSと比べてもかなりシンプルです。

![](https://storage.googleapis.com/zenn-user-upload/b771cdf35684-20231106.png)

Install関連もなくなるのでトラフィックの切り替え部分だけがフックとして存在します。

# AWS CodeDeployのトラブルシューティング
AWS CodeDeployではデプロイの失敗時あるいはCloudWatchアラームで閾値を超えたときに自動でロールバックすることが可能です。

このシナリオは試験で非常によく聞かれるのでデプロイ失敗だけではなくCloudWatchアラームも使える点を必ず覚えておいて下さい。

また、ロールバック時にはデプロイ成功したリビジョンの中で最新のリビジョンにロールバックされます。
この点も試験でよく聞かれます。

そのほか、実案件でも試験でも頻出のトラブルを以下に列挙しておくのでトラブルシューティング時に読んでみてください。

- Deployment Error: “InvalidSignatureException – Signature expired: [time] is now earlier than [time]”
	- 原因と解決策
		- 時刻同期をとってください。　※AWSであればTimeSyncを使って時刻同期をとるのがベストプラクティスです。

以下3つについてはまとめて記載します。
- The overall deployment failed because too many individual instances failed deployment
- Too few healthy instances are available for deployment
- Some instances in your deployment group are experiencing problems. (Error code: HEALTH_CONSTRAINTS)
	- 原因と解決策
		- CodeDeploy Agentがインストールされていないか、実行されていないか、またはCodeDeploy Agentに到達できない可能性があります。
		- CodeDeployサービスロールまたはIAMインスタンスプロファイルに必要な権限がない可能性があります。
		- HTTPプロキシを使用している場合、CodeDeploy Agentにproxy_uriパラメータを指定してください。
		- CodeDeployとAgentの間で日付と時間が不一致です。時刻同期をとってください。 ※AWSであればTimeSyncを使って時刻同期をとるのがベストプラクティスです。

- AutoScaling内に異なるバージョンのアプリケーションをホストするEC2が存在する
	- 原因と解決策
		- CodeDeployを用いたデプロイ中にEC2のスケールアウトイベントが発生しました。再度デプロイの実行をしてください。デフォルトでは自動で後追いのデプロイを実行します。

# まとめ
この記事ではCodeDeployとはどういうサービスで何ができるのかを超詳細にまとめました。

- AWS CodeDeployとは
- AWS CodeDeploy for オンプレミス/EC2
- AWS CodeDeploy for ECS
- AWS CodeDeploy for Lambda
- AWS CodeDeployのトラブルシューティング

次回はCodeArtifactを超詳細解説します。