CFnと手動でCodeDeployをコンテンツ上書きオプションで実行する

おはようございます、もきゅりんです。

先日、今更ですが、CodeDeployでコンテンツ上書きオプションについて知る機会がありました。

Blue/Greenデプロイ他、コンテナでのデプロイ環境も整ってきているため、あまり利用機会もないようにも思えますが、まとめておきます。

自分はこれまで、既存ファイルがある場合、scripts/beforeInstall.bashとかで全消ししてファイルを追加する、だったりBlue/Greenデプロイで対応していました。

この件、改めて調べてみると、結構長い間、appspec.yml で対応してくれよ、ずっと待ってる...というやり取りがなされていたようです。

Add Support for "Overwrite" instruction in appspec.yml "Files" section #14

とりあえず、やってみて説明を挟んでいこうと思います。

なお、Bule / Greenデプロイに興味・関心ある際はこちらをご確認下さい。

CloudFormationとAWS CLIで作るCodeDeploy(Blue/Green)環境

目次

構成

構成は以下となります。 複数インスタンスにする必然性はなかったのですが、折角LBも含めたし、ということで冗長化してみました。

codedeploy

前提

  • Packerが使えること

  • AWS CLIが利用できること

  • GitHubリポジトリが利用できてPersonal access tokensを取得していること

  • 上記GitHubのaccess tokensをSecrets Managerに格納していること

不足していた場合、これらについては下記記事を参考にしてみて下さい。

AWS CLI のインストール

PackerがIAM RoleとMFAに対応していました

[小ネタ] SecretsManagerを使ってCFnのGitHubTokenをシークレットにする

やること

  1. PackerでAMIを作成
  2. CFnでCodePipelineを構築
  3. CodeDeployを手動で再デプロイ
  4. GitHub上のファイルを何か更新して確認
  5. やっていることの説明

起動するインスタンスのAMIはPackerで作成して、AWSの構成はCFnで作成します。

利用するファイルは下記GitHubに格納されています。

cmoqrin/codedeploy-overwrite

上記を任意のディレクトリに保存します。テンプレート等を格納したファイルは以下の構成です。

$ tree
.
├── CFnTemplate
│   ├── demo.template.yml
│   ├── deploy.sh
│   └── envfile
├── Packer
│   └── packer-nginx.json
├── appspec.yml
└── index.html

こちらをご自身のGitHubリポジトリにForkするとか別途Pushするなどして下さい。

1. PackerでAMIを作成

19行目の YOUR_PROFILE は自身の ~/.aws/config のprofileをご確認下さい。

MFA入力が必要だとして、以下コマンドで作成します。

123456は実際のtokenを入力して下さい。

packer build -var "mfa_code=123456" Packer/packer-nginx.json

作成されたら、IDを取得して控えます。

aws ec2 describe-images --filters "Name=name,Values=demo-nginx-ami" --query 'Images[*].{ID:ImageId}'

参考:

PackerがIAM RoleとMFAに対応していました

2. CFnでCodePipelineを構築

CFnTEmplate/envfile を更新していきます。

AMIIDに先ほど控えたAMIIDを記入します。

EC2のキーペア名を記入します。

CodePipelineでデプロイするための情報を記入します。

(GitHubSecretは何でも良いです。)

# e.g.
export GitHubRepositoryName=codedeploy-overwrite
export GitHubAccountName=cmoqrin
export GitHubSecret=secret
export Branch=master
export ApplicationName=Application
export DeploymentGroupName=DeploymentGroup
export PipelineName=CodePipeline

テンプレート内の OAuthToken をSecrets Managerで設定したものに更新します。

参考:

[小ネタ] SecretsManagerを使ってCFnのGitHubTokenをシークレットにする

そしたらスタックを作成します。

cd CFnTemplate
./deploy.sh

5分くらいで完了するはずです。

CodePipelineを見にいきます。

ここでも5分くらい待ちます。。

fail deploy

失敗しました。

詳細リンクから確認しにいきましょう。

3. CodeDeployを手動で再デプロイ

deploy detail1

fail deploy2

既にファイルがあるよって叱られていますね。

fail reason

では、そのデプロイIDを元に手動で再デプロイしにいきましょう。

redeploy

デプロイグループのオーバーライドからコンテンツの上書きを選んでデプロイします。

codedeploy contents overwrite

ここからまた10分ほど待ちます。。(1台4,5分です。。)

成功です。

redeploy success

では、ALBのDNS名からブラウザで確認してみましょう。

確認できましたー

browser check1

4. GitHub上のファイルを更新して確認

index.html を編集してGitにPushしてみましょう。

また、10分くらい。。

codepipeline success

確認できました2ー

broswer check2

5. やっていることの説明

何度読んでもいまいち理解しにくかったので、整理しておきます。

要点は下記2点です。

  1. CodeDeployでロールバックが出来ること
  2. 既存のコンテンツのロールバック動作を手動で設定できること

まず、1点目ですが、CodeDeployのロールバックは自動ロールバックおよび手動ロールバックが可能です。

手動ロールバックは一旦今回は関係ないので置いておきます。

自動ロールバックについては、以下のいずれかまたは両方を選択してロールバックを実行できます。

  • デプロイが失敗したときにロールバックする
  • アラームのしきい値が一致したときにロールバック

2点目、既存のコンテンツのロールバック動作です。

CodeDeploy を使用した再デプロイおよびデプロイのロールバックには、このように記載されています。

CodeDeploy エージェントは、前回のデプロイでインストールされたすべてのファイルを各インスタンスから削除します。 前回のデプロイに含まれていないファイルがデプロイ先に表示された場合は、次回のデプロイ時にこれらのファイルを CodeDeployで処理する方法を選択できます。

下記の中から既存のコンテンツのロールバック動作を選択できます。

  • Fail the deployment(失敗)
  • コンテンツの上書き
  • コンテンツの保持

さて、デプロイが失敗したときにロールバックする、を設定してデプロイを実行しました。

既存にファイルが含まれると失敗します。

該当のデプロイに対して、次回デプロイ時の既存コンテンツのロールバック動作を「コンテンツの上書き」に設定して手動で再度デプロイし直します。

初回のデプロイのため、どのファイルもデプロイリストには含まれていません。もちろん、既存のファイルもデプロイリストには含まれていません。

ということで、2点目で説明した既存コンテンツのロールバック設定から、既存のコンテンツを上書きします。

次回からは、上書きされたファイルはデプロイリストに含まれるため、ファイルは正常にデプロイされます。

自分はなかなか理解しにくくかったので、まとめてみました。

今回は待ちが長くてしんどかったですね。。

(コンテナのデプロイの速さに慣れていたため逆にビックリしました。。)

以上です、どなたかのお役に立てば幸いです。

参考/紹介

PackerがIAM RoleとMFAに対応していました

[小ネタ] SecretsManagerを使ってCFnのGitHubTokenをシークレットにする

CodeDeploy を使用した再デプロイおよびデプロイのロールバック