Gitへのプッシュをトリガーに、自動でBlue/Greenデプロイを行う

<h2>目次</h2>
<ol>
<li>背景</li>
<li>前提</li>
<li>CodePipelineでSorceを作る(ECR+S3)</li>
<li>Blue/Greenデプロイに必要なリソースを作成</li>
<li>デプロイをしてみる</li>
</ol>
<h2>背景</h2>
<p><strong>前回記事</strong>
<a href="https://qiita.com/masa_skd30/items/0b888f337c801fc3ceab">ECR・ECSを使用して、Blue/Greenデプロイを行う</a>  </p>
<p>Blue/Greenデプロイには成功しましたよっと。<br>
前回までの状態だと、「ECRへのプッシュ」から「Blue/Greenデプロイ」までにコンソールでぽちぽちやらなきゃいけなかったので、そこを自動化していこうと思う。<br>
俺、これが成功したらインフラは中断してアプリの開発の続きをやるんだ…（遠い目）  </p>
<h2>失敗したケース</h2>
<h3>やろうとしていたこと</h3>
<ol>
<li>ビルド用サーバーでNuxtビルド  </li>
<li>ビルドしたファイルを元に手動でDockerイメージ作成  </li>
<li>作成したDockerイメージをECRにプッシュ  </li>
<li>ECRへのプッシュをトリガーにデプロイ開始  </li>
</ol>
<h3>参考にしたもの</h3>
<p><a href="https://dev.classmethod.jp/articles/ecr_push_ecs_simple_codepipeline/">ECRへのPushでECSをデプロイするだけのシンプルなCodePipelineを試す</a>  </p>
<h3>結果</h3>
<p>これを参考にしてみたけど、S3に格納したimagedefinitions.json（正確にはimagedefinitions.json.zip）を読み込んだところで、「jsonの形式としておかしいよ」的なエラーが出てこける。<br>
何度見てもimagedefinitions.jsonの形式は間違っていないし、「UTF-8で保存しなきゃいけない」というルールも見逃していないし、謎が謎を呼ぶ感じに。<br>
どなたか、原因に心当たりのある方は教えてください。（根本的な部分で何かを見落としている可能性は大きい、とは自覚しています）  </p>
<h3>問題点</h3>
<p>色々と問題点がある。<br>
　①そもそも4がうまく動いてくれない<br>
　②1,2の手順を手動でやらなければいけない<br>
　③ソースコードの管理について何も考えていない  </p>
<p>特に③がやばい。<br>
「ゆくゆくはGitで~」とか考えていたけど、もうGit食わず嫌い感が滲み出ている。<br>
「ゆくゆくは」っていつやねん。  </p>
<h2>ちょっとやり方を変えてみる</h2>
<p>「じゃあいつGit使い始めるの？」<br>
<strong>「今でしょ！！！」</strong><br>
という茶番を頭に巡らせつつ、やり方を変えてみる。</p>
<ol>
<li>ビルド用サーバーでNuxtビルド  </li>
<li>ビルドしたファイルをCodeCommitへプッシュ  </li>
<li>CodeBuildでビルド  </li>
<li>CodeBuildの結果を元にデプロイ開始  </li>
</ol>
<h2>参考</h2>
<p><a href="https://dev.classmethod.jp/articles/codepipeline-ecs-codedeploy/">CodePipelineからECSにBlue/Greenデプロイする</a>  </p>
<p>概ねはこちらの参考記事を元にしましたが、何点か変更した点があるので記載しておきます。</p>
<h2>CodeDeploy用の設定ファイルが読み込まれないことに対する修正</h2>
<ul>
<li>appspec.yaml  </li>
<li>taskdef.json  </li>
</ul>
<p>これらのファイルは、参考記事だとリポジトリ直下に置いていて、<br>
"Source"のステージで「SourceArtifact」として出力し、<br>
"Deploy"のステージで入力しています。</p>
<p>ただこれだとこけました。  </p>
<div class="codehilite"><pre>Exception while trying to read the task definition artifact file from: @@@@@  
</pre></div>


<p>どうやら、SourceArtifactのサイズが大きすぎたのが原因の様です。<br>
<a href="https://qiita.com/hareku/items/a4575de31571071d879e">CodeDeployでtask definitionが読み込めない時の対処法</a>  </p>
<p>とはいえ、NuxtのアプリだしSourceArtifactのサイズを下げることはできないし…<br>
ということで、  </p>
<ul>
<li>appspec.yaml  </li>
<li>taskdef.json  </li>
</ul>
<p>これらのファイルはzipで固めてS3上に置いて、別のArtifactとして出力することにしました。  </p>
<p>具体的には、"Source"のステージにアクションを追加し、以下の様に設定。  </p>
<table>
<thead>
<tr>
<th>設定項目</th>
<th>設定名</th>
</tr>
</thead>
<tbody>
<tr>
<td>アクションプロバイダー</td>
<td>S3</td>
</tr>
<tr>
<td>バケット</td>
<td>該当バケット名</td>
</tr>
<tr>
<td>S3オブジェクトキー</td>
<td>該当zipファイル名</td>
</tr>
<tr>
<td>出力アーティファクト</td>
<td>S3OutArtifuct</td>
</tr>
</tbody>
</table>
<p>当然"Deploy"ステージも編集して、両ファイルの入力元は「S3OutArtifuct」としました。</p>
<h2>Dockerのビルド失敗に対する修正</h2>
<p>何度もテストを繰り返していると、突然CodeBuildがこけました。  </p>
<div class="codehilite"><pre>error pulling image configuration: toomanyrequests: Too Many Requests. Please see https://docs.docker.com/docker-hub/download-rate-limit/
</pre></div>


<p>「何もいじっていないのになぜ？」と思っていたら、どうやらDocker Hubのダウンロード回数制限なるものがあったらしい。  </p>
<p>こちらの記事を参考に、buildspec.ymlにDockerへのログイン処理を追加しました。<br>
<a href="https://dev.classmethod.jp/articles/codebuild-has-to-use-dockerhub-login-to-avoid-ip-gacha/">“Too Many Requests.” でビルドが失敗する…。AWS CodeBuild で IP ガチャを回避するために Docker Hub ログインしよう！という話</a>  </p>
<h2>Deployのステップ1のうち、installが終わらないことに対する修正</h2>
<p>installの状態で終わらず、1時間のタイムアウトを迎える…。<br>
AMIのロールか！？とか色々と見直してみたけど、一向に解決せず。<br>
と思ったら、buildspec.ymlの記述が間違っていました…<br>
宣言した環境変数名と、使用している環境変数名が違うっていう、ボーンヘッド中のボーンヘッド…  </p>
<h2>最終的に</h2>
<p>上記の修正点だけ気をつければ、問題なくデプロイを実行することができました。<br>
ひとまず、ようやくAWS周りのお仕事から解放された…<br>
これを見た方々の自動デプロイが、スムーズにいくことを祈っています。  </p>