Slide 1

Slide 1 text

AWS Codeシリーズを使った TerraformのCICDパイプラインの作り方

Slide 2

Slide 2 text

プロフィール 名前:檜山 準(ひやま じゅん) 所属:I◯◯◯ お仕事:クラウドエンジニア(設計、構築、運用保守) https://twitter.com/hiyanger https://qiita.com/hiyanger https://zenn.dev/hiyanger 最近よく使う技術:AWS、IaC、CI/CD  出身:栃木県 よかったら フォローしてね!

Slide 3

Slide 3 text

もくじ 全体構成 商用環境 CodeBuild / CodePipeline IAMロール 商用環境 S3 / KMS 検証環境 CodeCommit IAMロール 商用環境 CodeBuild / CodePipeline 実際に運用して困ったこと ロール系もお仕事で運用することを 考えてしっかり全リソース許可とかは基本せず、 セキュアなポリシーを意識してます

Slide 4

Slide 4 text

全体構成

Slide 5

Slide 5 text

全体構成 ※黒線:パイプラインのメイン動作 緑線:アーティファクト系の動作 オレンジ線:Terraformのバックエンド動作

Slide 6

Slide 6 text

全体構成 クロスアカウントにより、developブランチは検証、mainブランチは商用というリポジトリの一元管理が可能。 ※黒線:パイプラインのメイン動作 緑線:アーティファクト系の動作 オレンジ線:Terraformのバックエンド動作

Slide 7

Slide 7 text

【商用】 CodeBuild CodePipeline IAMロール

Slide 8

Slide 8 text

【商用】CodeBuild / CodePipeline IAMロール

Slide 9

Slide 9 text

【商用】CodeBuild / CodePipeline IAMロール ■ CodeBuild / terraform plan   # AWS管理ポリシー   ・ReadOnlyAccess   # ユーザー管理ポリシー   ・ログ出力のためのCloudWatchの出力許可   ・アーティファクト/tfstate S3入出力の許可   ・terraformを動作させるECRの動作許可   ・terraform排他制御のためのDynamoDBの動作許可   ・APIキーを暗号化してる場合のDecrypt許可(必要なら) ■ CodeBuild / terraform apply  # AWS管理ポリシー   ・IAMFullAccess   ・PowerUserAccess ■ Codepipeline   # ユーザー管理ポリシー   ・検証CodeCommitへのAssumeRole   ・アーティファクトS3入出力の許可   ・CodeBuildの動作許可

Slide 10

Slide 10 text

【商用】 S3 KMS

Slide 11

Slide 11 text

【商用】アーティファクト S3 / KMS

Slide 12

Slide 12 text

【商用】アーティファクト S3 / KMS ■ KMS  # AWS管理ポリシー   ・ルートユーザーへの全許可   ・管理ユーザーへのアクセス許可   ・CodeBuild、CodePipeline、検証rootへの利用許可   ・CodeBuild、CodePipeline、検証rootへの一時許可 ■ S3  # AWS管理ポリシー   ・バケット/ポリシー削除拒否   ・SSL以外のアクセス拒否   ・検証CodeCommitからのList/Get/Put許可  # ライフサイクルルール   ・30日で設定

Slide 13

Slide 13 text

【検証】 CodeCommit IAMロール

Slide 14

Slide 14 text

【商用】CodeCommit IAMロール ■ 信頼ポリシー data "aws_iam_policy_document" "codecommit_assume_role_policy" { statement { actions = ["sts:AssumeRole"] principals { type = "AWS" identifiers = ["arn:aws:iam::${var.account-prd}:root"] } } } ■ AWS管理ポリシー   ・商用アーティファクトS3へのPut許可   ・商用アーティファクトS3/KMSへのアクセス許可   ・CodeCommitへのアクセス許可

Slide 15

Slide 15 text

【商用】 CodeBuild CodePipeline

Slide 16

Slide 16 text

【商用】CodeBuild(terraform plan/apply) resource "aws_codebuild_project" "codebuild-terraform-plan" { name = "${var.env}-codebuild-terraform-plan" service_role = module.common.codebuild-terraform-plan-role_arn encryption_key = "arn:aws:kms:ap-northeast-1:${var.account-id}:key/${var.prd-art ifact-terraform-kms-id}" artifacts { type = "CODEPIPELINE" } environment { compute_type = "BUILD_GENERAL1_SMALL" image = "public.ecr.aws/hashicorp/terraform:1.5.7" type = "LINUX_CONTAINER" environment_variable { name = "dir" value = var.env } } source { type = "CODEPIPELINE" buildspec = "buildspec_terraform_plan.yml" } } ※applyはplanを読み替えるだけでOK! ※AWSコンソールから設定できないので  CLIやterraformからデプロイや!

Slide 17

Slide 17 text

【商用】CodeBuild(buildspec) version: 0.2 phases: build: commands: - cd $dir - terraform init -input=false -no-color - terraform plan -input=false -no-color artifacts: files: - '**/*' version: 0.2 phases: build: commands: - cd $dir - terraform apply -input=false -auto-approve -no-color artifacts: files: - '**/*' buildspec_plan.yml buildspec_apply.yml

Slide 18

Slide 18 text

【商用】CodePipeline(Source) resource "aws_codepipeline" "codepipeline-terraform" { name = "${var.env}-codepipeline-terraform" role_arn = aws_iam_role.codepipeline-terraform-role.arn stage { name = "Source" action { name = "Source" category = "Source" owner = "AWS" provider = "CodeCommit" version = "1" output_artifacts = ["source_output"] role_arn = "arn:aws:iam::${var.account-dev}:role/stg-codecommit-terraform- role" configuration = { RepositoryName = "stg-codecommit-terraform" BranchName = "main" } } } ※Pipelineも同じくAWSコンソールから  設定できないのでCLIやterraformからデプロイや!

Slide 19

Slide 19 text

【商用】CodePipeline(plan / approval) stage { name = "Build-Plan" action { name = "terraform-plan" category = "Build" owner = "AWS" provider = "CodeBuild" input_artifacts = ["source_output"] output_artifacts = ["plan_output"] version = "1" configuration = { ProjectName = "${var.env}-codebuild-terraform-plan" } } } stage { name = "Approval" action { name = "plan-approval" category = "Approval" owner = "AWS" provider = "Manual" version = "1" } }

Slide 20

Slide 20 text

【商用】CodePipeline(apply / S3 / KMS) stage { name = "Build-Apply" action { name = "terraform-apply" category = "Build" owner = "AWS" provider = "CodeBuild" input_artifacts = ["plan_output"] version = "1" configuration = { ProjectName = "${var.env}-codebuild-terraform-apply" } } } artifact_store { location = aws_s3_bucket.artifact-terraform.id type = "S3" encryption_key { id = aws_kms_alias.artifact-terraform.arn type = "KMS" } } }

Slide 21

Slide 21 text

実際に運用して困ったこと

Slide 22

Slide 22 text

実際に運用して困ったこと × 改善が難しい デプロイは基本的にコードを経由する必要があるため、構築の瞬発力が落ちる IaCの特性上やむを得ない。どうしても急ぎなら手動とかで。 plan/applyでエラーが起こると構築が止まってしまう planはローカルで。applyまで検証したいなら別環境とかでやる。 手動変更やローカルから直applyされると、都度確認が必要になる テスト中はやむを得ない手動変更とかが起きる。 その間はパイプラインを止めておくなど、うまくスケジュールする。 共通リソースがあるので、商用だけ一部先行着手とかが難しい developとmainは共通化されるので共通リソースも中途半端に デプロイされてしまう。先行してやるなら手動やローカルから流す。 ※チーム構成 全体4名(ガッツリ書く人2名、そこそこ書く人2名、Lambda等は別部隊で記述) ◯ 改善が可能 terraformを使えるメンバーが少なかったので、applyの依頼が集中 少なくともインフラチームはみんな使えた方がいい。 記述方法が個人間で差がでる 事前に軽い規約は作ったが、まだまだ弱かった。 開発同様、より強い規約の制定が必要。

Slide 23

Slide 23 text

Thanks!! CodeCommitを使ったパイプライン運用するならほぼ必須の構成 だと思うのでぜひチャレンジしてみてください!この資料の情 報だけでも十分に構築できるかと思います。また、Terraformで 一度書いてしまえばさまざまなプロジェクトでも流用できるか と思います! 本資料 https://speakerdeck.com/hiyanger/aws-codesirizuwoshi-tuta -terraformnocicdpaipurainnozuo-rifang https://twitter.com/hiyanger https://qiita.com/hiyanger https://speakerdeck.com/hiyanger https://zenn.dev/hiyanger