GitHubのメインブランチへのプッシュをトリガーとして、Terraformを使用してS3バケットにソースコードを自動的にコピーするAWS CodePipelineを構築しました。Code ConnectionsとCodeStar Connectionsの違いに伴うハマりどころや、GitHubとの連携設定の手順、さらに個人での利用を考慮したCodePipelineとGitHub Actionsの比較について解説します。
目次
注意点
aws_codeconnections_connection
aws_codestarconnections_connection
GitHub非公開リポジトリを作る。sample-private-repository
として、デフォルトブランチはmaster
としてみた。
Code PipelineやCode ConnectionsはTerraformでサクッとデプロイする。
※IAMポリシーはガバガバなので、頑張りたければ絞って
# 変数定義variable "github_owner" { description = "GitHubのオーナー名または組織名" type = string default = "koshian2"}variable "github_repo" { description = "GitHubリポジトリ名" type = string default = "sample-private-repository"}variable "github_branch" { description = "デプロイに使用するGitHubのブランチ" type = string default = "master"}variable "s3_bucket_name" { description = "デプロイ先のS3バケット名" type = string default = "codepipeline-deploy-destination-bucket"}variable "connection_name" { description = "Code Connectionsの名前" type = string default = "MyGitHubConnection"}
これでvar.github_repo
のvar.github_branch
にPushが入ったときに、指定したバケットに自動的に転送されるようになるが、GitHubとの連携にマネジメントコンソールから初期設定が必要。それを次以降に説明する。
# main.tf# S3バケットの作成resource "aws_s3_bucket" "deploy_bucket" { bucket = var.s3_bucket_name force_destroy = true}# Code Connectionsの作成resource "aws_codeconnections_connection" "github_connection" { name = var.connection_name provider_type = "GitHub"}resource "aws_s3_bucket_versioning" "versioning_deploy" { bucket = aws_s3_bucket.deploy_bucket.id versioning_configuration { status = "Enabled" }}# IAMロールの作成resource "aws_iam_role" "codepipeline_role" { name = "codepipeline_service_role" assume_role_policy = jsonencode({ Version = "2012-10-17", Statement = [{ Effect = "Allow", Principal = { Service = "codepipeline.amazonaws.com" }, Action = "sts:AssumeRole" }] })}# IAMポリシーの作成resource "aws_iam_policy" "codepipeline_policy" { name = "codepipeline_policy" description = "Policy for CodePipeline to access S3 and CodeStar Connections" policy = jsonencode({ Version = "2012-10-17", Statement = [ # S3へのアクセス許可 { Effect = "Allow", Action = [ "s3:GetObject", "s3:PutObject", "s3:ListBucket" ], Resource = [ aws_s3_bucket.deploy_bucket.arn, "${aws_s3_bucket.deploy_bucket.arn}/*" ] }, # Code Connectionsへのアクセス許可 { Effect = "Allow", Action = [ "codestar-connections:UseConnection" ], Resource = aws_codeconnections_connection.github_connection.arn }, # CodePipelineがAWSサービスにアクセスするための基本的な権限 { Effect = "Allow", Action = [ "codebuild:BatchGetBuilds", "codebuild:StartBuild", "codestar-connections:UseConnection" ], Resource = "*" } ] })}# IAMロールにポリシーをアタッチresource "aws_iam_role_policy_attachment" "codepipeline_policy_attachment" { role = aws_iam_role.codepipeline_role.name policy_arn = aws_iam_policy.codepipeline_policy.arn}# CodePipelineの作成resource "aws_codepipeline" "pipeline" { name = "MySimplePipeline" role_arn = aws_iam_role.codepipeline_role.arn pipeline_type = "V2" artifact_store { type = "S3" location = aws_s3_bucket.deploy_bucket.bucket encryption_key { type = "KMS" # デフォルトのS3管理キーを使用 id = "alias/aws/s3" } } stage { name = "Source" action { name = "GitHub_Source" category = "Source" owner = "AWS" provider = "CodeStarSourceConnection" version = "1" output_artifacts = ["source_output"] configuration = { ConnectionArn = aws_codeconnections_connection.github_connection.arn FullRepositoryId = "${var.github_owner}/${var.github_repo}" BranchName = var.github_branch } } } stage { name = "Deploy" action { name = "S3_Deploy" category = "Deploy" owner = "AWS" provider = "S3" input_artifacts = ["source_output"] version = "1" configuration = { BucketName = aws_s3_bucket.deploy_bucket.bucket Extract = "true" } } }}
マネジメントコンソールからCodePipeline→パイプラインを見ると、「MySimplePipeline」が失敗しているのがわかる。これはGitHubに接続できていないため。
CodeConnectionsはどこにあるのかというと、CodePipelineの下の「設定」→「接続」部分。ここに「MyGitHubConnection」が保留中になっている。
このあとポップアップが出てくるのでいくつか許可していく。
「Installed GitHub Apps」に「AWS Connector for GitHub」があれば成功。前のバージョンのCodeStar Connectionsで導入すると、その横の「Authorized Github Apps」にアプリができているが、そちらではこのパイプラインは正常に動作しない。
CodePipelineにも戻り「変更をリリースする」などをクリック
今度はパイプラインの実行に成功している。
S3バケットを見ると、ソースコードが同期されているのがわかる。
GitHubのブラウザから「test.md」を作り、メインブランチに直でマージする。
するとすぐにCodePipelineが走り、S3バケットに反映されている。バージョニング入れたときのコストは気になるが、ある程度デカくなったらS3のライフサイクルルールを入れろということなのだろう。
CodePipelineの料金はAWSの公式ページより以下の通り
V1 タイプのパイプラインの場合: アクティブなパイプライン(30 日以上存在していて、その月に少なくとも 1 つのコード変更が発生したパイプライン) ごとに1か月あたり 1.00 USD を支払います。その月に新しいコード変更がないパイプラインに対しては、料金は発生しません。アクティブなパイプラインは、1 か月に満たない分に対して按分計算されません。パイプラインは、作成後の最初の 30 日間は無料です。
V2 タイプのパイプラインの場合: アクション実行時間 1 分あたり 0.002 USD を支払います。アクション実行時間は、パイプライン内のアクションが実行開始してからそのアクションが完了状態に達するまで分単位で計算され、最も近い分単位に切り上げられます。手動承認およびカスタムアクションタイプを除くすべてのアクションタイプに対して課金されます。
V1 タイプのパイプラインの場合: 1 か月あたり 1 つの無料のアクティブなパイプライン。
V2 タイプのパイプラインの場合: 1 か月あたり 100 分の無料のアクション実行。無料のアクション実行時間は、アカウント内の V2 パイプラインの数に関係なく、アカウント内のすべての V2 パイプライン間で共有されます。これらは各暦月の初めに自動的にリセットされます。未使用の分が翌月に繰り越されることはありません。
1ヶ月に500分以上CI/CDが走ればV1のほうが安いが、普通に考えるとV2一択だと思われる。上記のTerraformはV2で書いているが、TerraformのデフォルトだとV1でデプロイされてしまうので要注意。
一方でGitHub Actionsの無料枠は以下の通り。
プラン Storage 分 (月あたり)
GitHub Free 500 MB 2,000
普通に考えるとGitHub Actionsのほうが無料枠は大きいので、特段大きなストレージが必要とかでなければActionsでいいように思える。
GitHub Actionsとの大きな違いは、CodePipelineはAWSの閉じた環境で利用できるという点だ。もし公開リポジトリでActionsを走らせてしまうと、ActionsのTerraformのログが見れてしまうことになるので、ここにうっかりセンシティブな値が入ると結構まずいことになる。
「非公開リポジトリならいいでしょ」と思うが、GitHubのリポジトリは必要になって一時的に公開することがあるので、AWSへのデプロイログみたいなのは個人的にあまり公開したくない。そこをAWSと密結合にかつ閉じた環境でできるというのは結構メリットが大きい。
どちらかというとCodePipelineは企業向けというより、個人~少人数向けのような気がする。企業向けならEnterpriseプランでActionsのリッチなVMや、大量の無料枠が使えるし、非公開リポジトリ設定も組織側で結構統制が取れる。しかし、個人だとそこらへん貧弱だったりガバガバになりがちなので、AWSへのデプロイをCI/CDをCodePipelineというのは結構ありな選択な気がした。
少なくとも自分が個人のリポジトリでAWSのCI/CDを動かすなら、多少課金があってもCodePipelineはありかなと思った。どっちかというとActionsでデプロイは個人だと危なっかしくてやりたくないというのが本音(バイナリのビルドぐらいだったら全然問題ないが)。CI/CDでのスクリプトの自由度はまだ見れてないので、今後使ってみたら評価変わるかもしれない。
Shikoan's ML Blogの中の人が運営しているサークル「じゅ~しぃ~すくりぷと」の本のご案内
技術書コーナー
北海道の駅巡りコーナー