この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
こんにちは!AWS事業本部コンサルティング部のたかくに(@takakuni_)です。
Developers.IO 2022 〜技術で心を揺さぶる3日間〜 にて、「俺のTerraform Pipeline」というテーマでお話しさせていただきました。
TerraformでCI/CDパイプラインを組むならどのような構成が取れるのか、構成例の1つとしてご紹介させていただきました。
動画
スライド
想定する視聴者
- そろそろCI/CDパイプラインでTerraformを使いこなしてみようかなと言う人
- Terraformのコードスキャン(動画だとtfsec)に興味がある人
発表ネタにしたブログ
今回は以下のブログについて、情報を掻い摘んで動画にしました。もしよければ重ねてご覧ください。
情報のアップデート
ここからは先ほど紹介したブログおよび動画時点で気がつかず、今になって紹介したいことがあるので、ここからは「私自身の成長記録」をつらつらと綴っていこうと思います。
みなさんも、以前のブログ、動画、このブログでムキムキのTerraformおじさんへの階段を駆け上がっていきましょう。
TerraformのDockerイメージ
まずはじめに、Amazon ECR Public GalleryでTerraformのDockerイメージが配布されていたことです。
動画時点では、terraform plan/apply
コマンド用のCodeBuildプロジェクトで、毎度INSTALL
フェーズにてTerraformのインストールを行なっていました。
buildspec_before.yaml
version: 0.2
env:
exported-variables:
- BuildID
- BuildTag
phases:
install:
runtime-versions:
golang: 1.14
commands:
- "git clone https://github.com/tfutils/tfenv.git ~/.tfenv"
- "ln -s ~/.tfenv/bin/* /usr/local/bin"
- "tfenv install $TF_VERSION"
- "tfenv use $TF_VERSION"
pre_build:
commands:
- "terraform init -input=false -no-color"
build:
commands:
- "terraform plan -input=false -no-color"
post_build:
commands:
- "export BuildID=`echo $CODEBUILD_BUILD_ID | cut -d: -f1`"
- "export BuildTag=`echo $CODEBUILD_BUILD_ID | cut -d: -f2`"
Amazon ECR Public Galleryで配布されたTerraformのDockerイメージを利用すると先ほどのINSTALL
フェーズを省略することができます。
buildspec_after.yaml
version: 0.2
env:
exported-variables:
- BuildID
- BuildTag
phases:
pre_build:
commands:
- "terraform init -input=false -no-color"
build:
commands:
- "terraform plan -input=false -no-color"
post_build:
commands:
- "export BuildID=`echo $CODEBUILD_BUILD_ID | cut -d: -f1`"
- "export BuildTag=`echo $CODEBUILD_BUILD_ID | cut -d: -f2`"
もたらされる効果
ビルドログを確認するとネットワークの状況にもよりますが、INSTALLフェーズには「6秒」かかったという記録が取れました。
一方でINSTALLフェーズを短縮した場合、INSTALLフェーズは「1秒未満」まで短縮できました。
CodeBuildは実行時間あたりに対して課金が行われるため「コスト最適化」が微々たるものですが見込めます。
Build URL
ブログ時点では、CodeBuildの実行結果をレポート出力する方法として次の形式で出力を行なっていました。
「**https://${AWS::Region}.console.aws.amazon.com/codesuite/codebuild/${AWS::AccountId}/projects/#{TFSEC.BuildID}/build/#{TFSEC.BuildID}%3A#{TFSEC.BuildTag}/?region=${AWS::Region}**」
ご覧の通り、パワープレイな感じがするので調査したところ、CodeBuildでCODEBUILD_BUILD_URL
という環境変数が同じ用途で使えるのでそちらにアップデートを行います。
buildspec.yaml
version: 0.2
env:
exported-variables:
- - BuildID
- - BuildTag
+ - BUILD_URL
phases:
pre_build:
commands:
- "terraform init -input=false -no-color"
build:
commands:
- "terraform plan -input=false -no-color"
post_build:
commands:
- - "export BuildID=`echo $CODEBUILD_BUILD_ID | cut -d: -f1`"
- - "export BuildTag=`echo $CODEBUILD_BUILD_ID | cut -d: -f2`"
+ - "export BUILD_URL=`echo $CODEBUILD_BUILD_URL`"
Cloudformartionテンプレートもかなりスッキリしたのがわかります。
terraform_pipeline.yaml
CodePipeline:
Type: AWS::CodePipeline::Pipeline
Properties:
Name: !Sub "${PrjPrefix}-tf-pipeline"
ArtifactStore:
EncryptionKey:
Id: !GetAtt KeyS3Arthifact.Arn
Type: "KMS"
Location: !Ref BucketArtifacts
Type: "S3"
RoleArn: !GetAtt RoleTfPipelne.Arn
Stages:
- Name: "Source"
Actions:
- Name: "CodeCommit_Source"
ActionTypeId:
Category: "Source"
Owner: "AWS"
Provider: "CodeCommit"
Version: "1"
Configuration:
RepositoryName: !GetAtt CodeCommit.Name
BranchName: !Ref BranchName
PollForSourceChanges: false
OutputArtifacts:
- Name: "Artifact_Source_CodeCommit_Source"
RoleArn: !GetAtt RoleTfPipelne.Arn
RunOrder: 1
- Name: "tfsec_Stage"
Actions:
- Name: "Terraform_Security_Analysis"
Namespace: TFSEC
ActionTypeId:
Category: "Build"
Owner: "AWS"
Provider: "CodeBuild"
Version: "1"
Configuration:
ProjectName: !Ref ProjectTfsec
InputArtifacts:
- Name: "Artifact_Source_CodeCommit_Source"
RoleArn: !GetAtt RoleTfPipelne.Arn
RunOrder: 1
- Name: "Terraform_Stages"
Actions:
- Name: "Terraform_Security_Analysis_Manual_Review"
ActionTypeId:
Category: "Approval"
Owner: "AWS"
Provider: "Manual"
Version: "1"
Configuration:
CustomData: "tfsec review"
- ExternalEntityLink: !Sub "https://${AWS::Region}.console.aws.amazon.com/codesuite/codebuild/${AWS::AccountId}/projects/#{TFSEC.BuildID}/build/#{TFSEC.BuildID}%3A#{TFSEC.BuildTag}/?region=${AWS::Region}"
+ ExternalEntityLink: "#{TFSEC.BUILD_URL}"
RoleArn: !GetAtt RoleTfPipelne.Arn
RunOrder: 1
- Name: "Terraform_Plan"
Namespace: "TERRAFORM"
ActionTypeId:
Category: "Build"
Owner: "AWS"
Provider: "CodeBuild"
Version: "1"
Configuration:
ProjectName: !Ref ProjectTfplan
InputArtifacts:
- Name: "Artifact_Source_CodeCommit_Source"
RoleArn: !GetAtt RoleTfPipelne.Arn
RunOrder: 2
- Name: "Terraform_Plan_Manual_Review"
ActionTypeId:
Category: "Approval"
Owner: "AWS"
Provider: "Manual"
Version: "1"
Configuration:
CustomData: "Terraform plan review"
- ExternalEntityLink: !Sub "https://${AWS::Region}.console.aws.amazon.com/codesuite/codebuild/${AWS::AccountId}/projects/#{TERRAFORM.BuildID}/build/#{TERRAFORM.BuildID}%3A#{TERRAFORM.BuildTag}/?region=${AWS::Region}"
+ ExternalEntityLink: "#{TERRAFORM.BUILD_URL}"
RoleArn: !GetAtt RoleTfPipelne.Arn
RunOrder: 3
- Name: "Terraform_Apply"
ActionTypeId:
Category: "Build"
Owner: "AWS"
Provider: "CodeBuild"
Version: "1"
Configuration:
ProjectName: !Ref ProjectTfapply
InputArtifacts:
- Name: "Artifact_Source_CodeCommit_Source"
RoleArn: !GetAtt RoleTfPipelne.Arn
RunOrder: 4
Snyk IaCもイイぞ
Snyk IaCは、tfsecの代替案として有効なソリューションです。
最近ブログもよく書いているので、重ねてご覧いただければ嬉しいです。
DevelopersIO 2022でSnyk Japanの相澤様に登壇いただきました。(セッションレポートになります。)
まとめ
「俺のTerraform Pipeline」の登壇レポートでした!「俺のTerraform Pipeline」を作ろうとしている方の参考になれば幸いです。
以上、AWS事業本部コンサルティング部のたかくに(@takakuni_)でした!