CodeDeployでEC2にアプリケーションをデプロイ 【CodeFamily Practices 3/7】
概念
EC2、オンプレミス、Lambda、ECSへのアプリケーションのデプロイを自動化するサービス。
-
仕組み
デプロイターゲットへCodeDeployエージェントをインストール。エージェントはS3からアプリケーションデータを取得し、ターゲットへインストール。
ライフサイクルイベントをappspec.ymlに記述してデプロイを管理。
インスタンス上のアプリケーションを中断してデプロイを行うインプレースデプロイ。 古いバージョンとは別に新しいバージョンをデプロイすることで、アプリケーションの中断を最小限に抑えるBlue/Greenデプロイがある。
デプロイタイプ | コンピューティング プラットフォーム |
---|---|
インプレース | EC2 オンプレミス |
Blue/Green | EC2 オンプレミス Lambda ECS |
デプロイ設定
CodeDeployがデプロイ中に使用するルール、成功条件、失敗条件。
-
EC2、オンプレミス
インプレースとBlue/Greenで条件が異なる。
デプロイ設定 | インプレース | Blue/Green |
---|---|---|
CodeDeployDefault.AllAtOnce | 一度にできる限り多くのインスタンスへデプロイ。 1つでもデプロイできると成功。 |
一度にできる限り多くのインスタンスへデプロイ。 すべてのインスタンスへルーティングし、一つでも正常に再ルーティングできれば成功。 |
CodeDeployDefault.HalfAtATime | 一度に最大で半分のインスタンスへデプロイ。 少なくとも半分デプロイできると成功。 |
一度に最大で半分のインスタンスへデプロイ。 一度に最大半分のインスタンスへルーティングし、少なくとも半分のインスタンスへ再ルーティングできれば成功。 |
CodeDeployDefault.OneAtATime | 一度に一つのインスタンスへデプロイ。 すべてのインスタンスへデプロイできると成功。 |
一度に一つのインスタンスへデプロイ。 一度に一つのインスタンスへトラフィックをルーティングし、すべてのインスタンスへ再ルーティングできると成功。 |
-
ECS
決められた時間ごとに10%ずつトラフィックを移行する線形(Liner)、10%だけトラフィックを移行してから時間差で残りのトラフィックを移行させるカナリア(Canary)、すべてのトラフィックを移行するオールインワンから選択。
デプロイタイプ | 方法 |
---|---|
CodeDeployDefault.ECSLinear10PercentEvery1Minutes | 毎分10%ずつトラフィックを移行。 |
CodeDeployDefault.ECSCanary10Percent5Minutes | 最初に10%のトラフィックを移行し、5分後に90%を移行。 |
CodeDeployDefault.ECSAllAtOnce | すべてのトラフィックを移行。 |
-
Lambda
ECSと同様。
デプロイタイプ | 方法 |
---|---|
CodeDeployDefault.LambdaLinear10PercentEvery1Minute | 毎分10%ずつトラフィックを移行。 |
CodeDeployDefault.LambdaCanary10Percent5Minutes | 最初に10%のトラフィックを移行し、5分後に90%を移行。 |
CodeDeployDefault.LambdaAllAtOnce | すべてのトラフィックを移行。 |
appspecファイル
YAMLもしくはJsonで記述。
-
version
0.0
のみ記述可。 -
hooks
デプロイライフサイクルイベントで使用するスクリプトもしくはLambda関数を指定。 -
resource (Lambda,ECSのみ)
デプロイするLambda、ECSに関する情報を指定。 -
os (EC2,オンプレミスのみ)
デプロイするインスタンスのオペレーティングシステムを指定。
linuxもしくはwindowsを指定。 -
permissions (EC2,オンプレミスのみ)
アクセス権限(chmodコマンドと同様)、アクセスコントロールなど、インスタンスへのコピー後にアクセス許可をディレクトリやファイルに適用。 -
files (EC2,オンプレミスのみ)
インストールイベントで、インスタンスにコピーするファイル名を指定。
appspec.yml
version: 0.0
os: linux
files:
- source: /index.html
destination: /var/www/html/
hooks:
BeforeInstall:
- location: scripts/install_dependencies
timeout: 300
runas: root
- location: scripts/start_server
timeout: 300
runas: root
ApplicationStop:
- location: scripts/stop_server
timeout: 300
runas: root
リビジョン
アプリケーションのバージョン。
コンピューティングプラットフォームにインストールされたCodeDeployエージェントが、S3からアプリケーションデータを取得してデプロイを実施。
デプロイに使用するソースデータを圧縮し、ディビジョンのバケットへアップロード
特定のCodeDeployサービスロール使用時にアクセスできるように、バケットポリシーを設定。
プリンシパルはデプロイに使用するIAMサービスロールarn。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::123456789012:role/CodeDeployRole"
},
"Action": [
"s3:Get*",
"s3:List*"
],
"Resource": "arn:aws:s3:::bucketname/*"
}
]
}
アプリケーションのバージョンと名前の関連付けを実施。
AWS CLIのdeployコマンドを使用。
コマンド | 機能 |
---|---|
create-application | アプリケーションの作成。 |
--applocation-name | アプリケーションの名前。IAMもしくはアカウント内において一意であること。 オプション --application-name は必須。 |
push | コンテンツとappspecファイルをZipファイルに圧縮してバンドルにし、S3へアップロード。 オプション --application-name と--s3-location は必須。 |
--s3-location | アップロードするバケットとオブジェクトキーをs3:/// の形式で入力。 |
--ignore-hidden-files | 隠しファイルを除いてアップロード 。 |
aws deploy create-application --application-name Myapplication_Name
Zipファイルに圧縮格納するバケットの名前とオブジェクトキーを指定。
ルートディレクトリにappspecファイルやソースコードのディレクトリなどを含めるように圧縮。
aws deploy push \
--application-name SampleApp_Linux \
--s3-location s3://bucketname/Myapplication_Name.zip \
--ignore-hidden-files
使用方法
EC2にApacheサーバーを起動。バンドルにあるhtmlファイルをドキュメントルートに配置。
※公式ドキュメントチュートリアル。
以下のappspec.ymlを使用。
appspec.yml
version: 0.0
os: linux
files:
- source: /index.html
destination: /var/www/html/
hooks:
BeforeInstall:
- location: scripts/install_dependencies
timeout: 300
runas: root
- location: scripts/start_server
timeout: 300
runas: root
ApplicationStop:
- location: scripts/stop_server
timeout: 300
runas: root
サービスロールの作成
EC2用サービスロール
「ロールを作成」を選択。
信頼されたエンティティタイプをAWSのサービス、
ユースケースをEC2で選択。
AmazonEC2RoleforAWSCodeDeployポリシーを選択。
AmazonSSMManagedInstanceCoreポリシーを選択。
任意のロール名を付与。
CodeDeploy用サービスロール
信頼されたエンティティタイプをAWSのサービス、
ユースケースをCodeDeployで選択。
AWSCodeDeployRoleポリシーはデフォルトでアタッチ済み。
任意のロール名を付与。
EC2の作成
以下の設定でパブリックサブネットにEC2を起動。
セキュリティグループは、ポート80番・ソース0.0.0.0/0で設定。
項目 | 設定 |
---|---|
インスタンス名 | CodeDeploy-Demo |
マシンイメージ | Amazon Linux 2023 |
インスタンスタイプ | t2.micro |
キーペア | キーペアなしで続行 |
パブリックIPの自動割り当て | 有効化 |
IAM instance profile | 前述で作成したEC2用サービスロール |
リビジョンの作成
S3にリビジョン格納用のバケットを作成。
バージョニングを有効化にし、パブリックアクセスはブロックのまま。
アクセス許可に、以下のバケットポリシーを追加し、CodeDeployエージェントのアクセスを許可。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::123456789012:role/CodeDeployRole"
},
"Action": [
"s3:Get*",
"s3:List*"
],
"Resource": "arn:aws:s3:::codedeploydemobucket202304011201/*"
}
]
}
ローカル環境から以下のコマンドを実行し、バンドルされたアプリケーションZipファイルをアップロード。
aws deploy create-application --application-name SampleApp_Linux
aws deploy push \
--application-name SampleApp_Linux \
--s3-location s3://codedeploydemobucket202304011201/SampleApp_Linux.zip \
--ignore-hidden-files
CodeDeployの設定
CodeDeployのコンソール画面から「アプリケーションの作成」」を選択。
任意のアプリケーション名を入力し、コンピューティングプラットフォームは「EC2/オンプレミス」を選択
アプリケーションを作成後、「デプロイグループの作成」を選択。
以下の設定でデプロイグループを作成。
項目 | 設定 |
---|---|
デプロイグループ名 | MyDemoDeloymentGroup |
サービスロール | 前述で作成したCodeDeploy用サービスロール。 |
デプロイタイプ | インプレース |
タググループ | キー:Name、値:CodeDeploy-Demo ※前述で作成たEC2のタグを入力。 |
CodeDeployエージェントのインストール | 今すぐ更新し、更新をスケジュール。 |
デプロイ設定 | CodeDeployDefault.OneAtTime |
ロードバランシング | 無効 |
デプロイの作成
「デプロイの作成」を選択。
以下の設定を入力。
デプロイを作成すると、自動的にデプロイを開始。
項目 | 設定 |
---|---|
デプロイグループ | MyDemoDeloymentGroup |
リビジョンタイプ | S3 |
リビジョンの場所 | S3://codedeploydemobudket202340111201/SampleApp_Linux.zip |
リビジョンファイルの種類 | .zip |
デプロイグループのオーバーライド | CodeDeployDefault.OneAtTime |
ロールバック | 無効 |
デプロイ成功画面。
EC2へアクセスし、アプリケーションのインストールを確認。
まとめ
EC2へアプリケーションをインストールする、シンプルなデプロイを習得。
appspec.ymlについて掘り下げなかったので、LambdaやECSのデプロイ時にライフサイクルイベントなどをトライしてみたい。
合わせて読みたい👀👉CodeFamily Practicesの記事
CodeCommitとローカル環境の連携 【CodeFamily Practices 1/7】
CodeBuildでビルドプロジェクトを作ってみよう 【CodeFamily Practices 2/7】
CodePipelineでシンプルなパイプラインを構築してみた 【CodeFamily Practices 4/7】
CodePipelineとCloudformationで、API Gatewayをビルド【CodeFamily Practices 5/7】
CodePipelineとServerless Frameworkでビルド【CodeFamily Practices 6/7】
CodePipelineとTerraformで、API Gatewayをビルド【CodeFamily Practices 7/7】
Discussion