AWS Codeサービス群 + ECS/ECR の利用時に躓いた点のメモ

# はじめに

AWS の CodeCommit, CodeBuild, CodeDeploy, CodePipeline をまとめて Code シリーズと呼ぶらしい。 

https://aws.amazon.com/jp/cdp/cicd/

ここのところ、Codeシリーズを用いた CI/CD の自動化を行っていくなかで、かなり躓いたのでメモしておく。 また、関連して ECR へのデプロイも行っていたり、ECS Fargate への Blud/Green デプロイも行ったため、それに関しても記載する。

## CodeCommit

別アカウントの CodeCommit を参照する設定は Management Console から行うことはできない。
色々設定したが、正直最初から複数の AWS アカウントで利用するようなリポジトリを持つ場合、Github を利用した方が正直色々と楽。


## CodeBuild

Docker Image 構築に発生した問題と対応策。

- CodeBuild で [Docker Hub からイメージを持ってくる場合は同一ソースIPの制限に引っ掛かる](https://dev.classmethod.jp/articles/codebuild-has-to-use-dockerhub-login-to-avoid-ip-gacha/) ので DockerHub のアカウントおよびトークンを用意して動作させること
- それでも無料アカウントの場合 100 API / 6時間の制約があるため、どうしようもなければ別途自身の ECR リポジトリを利用するなどの方法が必要


## CodeDeploy / CodePipeline

クロスアカウントで処理を行う場合、パイプラインの各ステージの受け渡しには S3 バケットを利用することになる。 何も考えずにパイプラインの各ステージ (CodeCommit/CodeBuild/CodeDeploy) を構築して、その結果を S3 に保持する場合、AWS がアカウント個別に用意しているマネージドの S3 キーを使って暗号化を行うようになっている。

これ自体は問題ないのだが、これはクロスアカウントで行う場合に問題となる。 具体的には、アカウントA の CodeCommit リポジトリをアカウント B の CodePipeline で取り扱う場合、通常は以下のような設定になる。

- CodeCommitリポジトリ: アカウントA
- ビルド用にダウンロードしたファイル: アカウントB上で CodePipeline 用に用意された S3 バケット

何も設定しない場合、アカウントBの CodePipeline から処理を行ったとしても **アカウントAのマネージドキーで暗号化されたデータがS3バケットに保存されてしまう** 。 言い換えると、アカウントBの後続作業では必要な復号化キーを参照できないため、Artifacts を参照できずにパイプラインが失敗してしまう。

これを解決するためには、アカウントA/B の両方で利用する KMS キーを作成して２つのアカウントで共有して利用する必要がある。 この鍵はアカウントBで作成して利用する。

また、これは動作からの推測になるが、CodePipeline で各フェーズのアーティファクトを最初に参照する場合、CodeBuild の場合は CodeBuild に付与された IAM Role を使うのだが、CodeDeploy の場合は **CodeDeploy ではなく CodePipeline に付与された IAM Role を利用するような挙動を示した。** 具体的には、CodeDeploy の IAM Role には上記で作成した KMS キーの利用権限を与えていたのだが、CodePipeline の IAM Role にはこのキーの利用権限を与えていなかったため、単に `You are missing permissions to access input artifact: BuildArtifact.` のようなエラーメッセージが表示されてしまい、CodePipeline 側に権限が必要という調査に非常に時間がかかった。

とはいえ、CodeDeploy で成果物を生成する場合は再度 S3 にアクセスすることになるので、Codeシリーズで独自の KMS キーを利用する場合、各サービスで利用する全ての IAM Role で該当キーの利用権限があるかを確認すべきである。

## CodePipeline を用いた CloudFormation のデプロイ

CodeBuild で CloudFormation にデプロイするためのコードを生成して、CodeDeploy でデプロイしようと思ったのだが、CodeDeploy のコンソール上で単独でこれを探しても見つからなかった

![SnapCrab_NoName_2023-2-21_22-53-18_No-00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/502582/229c79d9-8c3c-06f6-8326-a5f0a776d5a5.png)

色々と探してみると、このタイプのデプロイを行いたい場合は CodePipeline のデプロイステージのアクション追加から行うことができる。

![SnapCrab_NoName_2023-2-21_22-55-33_No-00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/502582/4b890173-7a9e-6247-05b3-cd808cca8e8c.png)

おそらく、CodeDeploy 単独では CloudFormation の入力セットを取得できないため、入出力の定義が可能な CodePipeline でのみ設定可能になっていると思われる。


## ECR について

整理してみると当たり前の話だが、ある profile がアカウントAのリポジトリAとアカウントBのリポジトリBへの権限を持っている場合、リポジトリA に対してログインを行ってもリポジトリB に対しての権限が同時に付与されるわけではない。 リポジトリA / B 両方のログインが必要。

## ECS Fargate について

- クラスター内のサービスを更新する場合、タスク定義のタスクロールに IAM Role を設定しておかないと enable-execute-command のための UpdateService ができない
    - 利用者自身が更新権限を持っていてもダメな点が分かりづらいので注意
    - [こちら](https://dev.classmethod.jp/articles/tsnote-ecs-update-service-fails-with-invalidparameterexception-in-ecs-exec/)のタスクロールなしのケースに相当
- ウェブ上のコンソールから CodeDeploy の Blue/Green Deployment 対応のサービスを作成しようとする場合、新コンソールでは対応していないので旧コンソールを利用する必要がある
    - 記事執筆時点では新コンソールでは Blue/Green Deployment が選択不可能になっている
- Docker の cap_add オプションを指定したいような場合、これはタスク定義の Linux Parameter で設定する必要がある。 
    - コンソール上に入力項目がないため、自前で JSON でのバージョンアップを使って更新する必要がある。 コンソールに JSON で更新オプションがあるので、これを使って適切な値を記載して新しいバージョンを作成すること
    - なお、一度更新すれば以降の更新では自動的に入ってくるので初回登録のみ必要

# 参考

クロスアカウント跨ぎの Pipeline 構築の参考。

https://techblog.techfirm.co.jp/entry/cross-account-codecommit-codepipeline

https://dev.classmethod.jp/articles/codepipeline-cross-account/