GitLab で自動デプロイを実施するには GitLab CI/CD が使えるのですが、今回は AWS CodePipeline (と CodeCommit、CodeBuild) を使って AWS SAM プロジェクトの自動デプロイを構成してみました。
前提 (なぜ GitLab CI/CD を使わないのか)
GitLab CI/CD の実行環境 (Runner) として、GitLab が提供している Shared runner とユーザーが用意する Specific runner があり、この上で Docker コンテナを動かす形になります。
管理が楽な Shared runner + 公式の (提供元が信頼できる) Docker イメージを使いたいところですが、
そして、
上記の条件により、Docker コンテナ内に Python と Go 両方のランタイムが必要になります。
そのような (公式提供の) Docker イメージはなさそうだったので、
- Python か Go の公式イメージを使い、CD 中にもう片方をインストールする
- 両方のランタイムをインストールした自前の Docker イメージを作成して使う
どちらかになりますが、前者は CD の時間が伸びること、後者は自前ビルドの管理の手間が増えるため、できれば避けたいです。
そこで、GitLab と AWS CodePipeline+CodeCommit+CodeBuild の連携による自動デプロイを試すことにしました。
構成
GitLab 上のリポジトリを CodeCommit にミラーリングし、CodeBuild でデプロイを実施します。
GitLab への git push
で自動デプロイが走るようにするため、 CodePipeline で CodeCommit と CodeBuild を繋げる必要があります。
AWS SAM プロジェクトを作成
プロジェクトを作成し、リポジトリを構成します。
プロジェクト名は aws-sam-sample としました。
sam init --name aws-sam-sample --runtime go1.x --package-type Zip cd aws-sam-sample git init
デプロイ設定を samconfig.toml に記述します。
version = 0.1 [default] [default.deploy] [default.deploy.parameters] stack_name = "aws-sam-sample" s3_bucket = "aws-sam-cli-managed-default-samclisourcebucket" s3_prefix = "aws-sam-sample" region = "ap-northeast-1" confirm_changeset = false capabilities = "CAPABILITY_IAM"
CodeBuild のビルド仕様ファイル buildspec.yml を作成します。
version: 0.2 phases: install: runtime-versions: golang: latest build: commands: - sam build post_build: commands: - sam deploy --debug
コミットします。
git add . git commit -m"Initial commit"
CodeCommit のリポジトリを作成
CodeCommit にミラーリング用のリポジトリを作成します。
以下のリポジトリ URL (HTTPS) が与えられました。
https://git-codecommit.ap-northeast-1.amazonaws.com/v1/repos/aws-sam-sample
ミラーリング用の AWS ユーザーを作成
GitLab から CodeCommit へ git push
できるようにするためのユーザーを作成します。
以下のようなシンプルな権限で十分なので、専用ユーザーにした方が良いです。
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "codecommit:GitPull", "codecommit:GitPush" ], "Resource": "arn:aws:codecommit:ap-northeast-1:XXXXXXXXXXXX:aws-sam-sample" } ] }
作成後、ユーザーの「認証情報」タブの「AWS CodeCommit の HTTPS Git 認証情報」で認証情報を作成します。
生成されたユーザー名 (ServiceUserName) とパスワード (ServicePassword) は、次の GitLab の設定で使用します。
GitLab のリポジトリを作成 & ミラーリングの設定
リポジトリを作成し、Settings→Repository→Mirroring repositories に CodeCommit のリポジトリ情報を入力します。
「Git repository URL」は CodeCommit リポジトリに前述の ServiceUserName を付与した URL (以下の形式) を、「パスワード」は ServicePassword を指定します。
https://ServiceUserName@git-codecommit.ap-northeast-1.amazonaws.com/v1/repos/aws-sam-sample
ソースコードを GitLab にプッシュ
プロジェクトのソースコードを一旦 GitLab にプッシュし、CodeCommit にミラーリングされることを確認します。
CodeBuild のビルドプロジェクトを作成
CodeBuild のビルドプロジェクトを作成します。
「ソースプロバイダ」は AWS CodeCommit、「リポジトリ」は CodeCommit のリポジトリを指定します。
「環境」については、デフォルトの値を選んでいきます。「サービスロール」は「新しいサービスロール」を選び、後でロールに AWS SAM のデプロイに必要なポリシーをアタッチすることにします。
CodeBuild のサービスロールにデプロイ権限を付与
今回はサンプルなので、デプロイに必要なポリシーをロールに直接アタッチしました。
- IAMFullAccess
- AmazonS3FullAccess
- AmazonAPIGatewayAdministrator
- AWSCloudFormationFullAccess
- AWSLambda_FullAccess
実運用する際には、CloudFormation が AssumeRole するためのデプロイ用ロールを別途用意し、それに PassRole するポリシーを作成してアタッチする等で権限を制限するのが安全かと思います。
デプロイの動作確認
CodeBuild で「ビルドを開始」を選択し、デプロイが完了するか確認します。
CodePipeline のパイプラインを作成
自動デプロイを構成するため、CodePipeline のパイプラインを作成します。
「サービスロール」は「新しいサービスロール」で良いです。
ソースステージに CodeCommit のリポジトリを、ビルドステージに CodeBuild のプロジェクトを追加します。
自動デプロイの動作確認
手元のリポジトリに適当にコミットを追加し、GitLab にプッシュします。
自動でデプロイが走り、完了することを確認します。
自動デプロイでは「送信者」が codepipeline になっています。
メリット/デメリット
以上で一通りの流れを確認しました。
GitLab CI/CD と比較した場合のメリットは、
- ビルド/デプロイ環境を管理する必要がない
- ビルド/デプロイ処理の自由度が高い
- GitLab 側に与える AWS へのアクセス権限を最小化できる (CodeCommit の GitPush/Pull のみ)
- GitLab CI/CD でデプロイする場合はデプロイ用ロールのクレデンシャルを与える必要がある
- 構成管理が AWS 側に集約できる
- デプロイログ→CloudWatch
デメリットとしては、
- CodePipeline+CodeCommit+CodeBuild 分のコストがかかる
余談
sam build
には --use-container
オプションがあり、コンテナ上でビルドを実行することができます (sam build
を実行する環境にビルド用ランタイムが必要ない) 。
そのため、当初は GitLab CI/CD 上で Docker in Docker による方法を検討しましたが、Specific runner が必要であり、結局外部リソースを持つことになります。
(そして --use-container
は Go に対応していないため無意味でした)
CodeBuild のビルド/デプロイ環境 (Docker イメージ) を GitLab CI/CD で使えないかとも考えましたが、AWS 外には提供されてないようで、また使えたとしても内容的にかなりサイズが大きいと思われるため、無キャッシュ時のデプロイに時間がかかることが懸念されました。
まとめ
GitLab で管理しているプロジェクトを AWS CodePipeline で自動デプロイする構成を試しました。
金銭的コストは増えますが、最終的なデプロイ先が AWS であるならば、構成の柔軟性、管理の一元化、セキュリティの面から見て価値があると思います。
参考 URL
GitLabとAWS CodePipelineを使ってAWS ECS/FargateのCI/CD | KeisukeYamashita