Upgrade to Pro — share decks privately, control downloads, hide ads and more …

20200522_FGDC_Terraform_CloudでGitOpsを使用したCI_CDパイプラインを構築する.pdf

 20200522_FGDC_Terraform_CloudでGitOpsを使用したCI_CDパイプラインを構築する.pdf

2e2c49f6f3fa33b8f5aad5841774c211?s=128

nezumisannn

May 22, 2020
Tweet

Transcript

  1. Terraform Cloudを利用した GitOps CI/CDパイプライン FGDC #1 2020/05/22 株式会社ビヨンド 寺岡 佑樹

  2. 自己紹介 resource “my_profile” “nezumisannn” { name = “Yuki.Teraoka” nickname =

    “ねずみさん家。” company = “beyond Co., Ltd.” job = “Site Reliability Engineer” twitter = “@yktr_sre” skills = [“Terraform”,”Packer”] }
  3. LB APP DB

  4. LB APP DB

  5. Environment Production

  6. Follower Environment Production

  7. QA Team Environment QA

  8. ここで起こり得る問題点 • 構築した人しか構成を把握していない ◦ 認識の齟齬が発生 ◦ 参照していた手順書が古い • 影響範囲が不明瞭のため構成変更が怖い ◦

    設定変更したら動かなくなった ◦ 本番環境でダウンタイムが発生してしまった • どのような手順を踏めば良いのかがわからない ◦ 手順が形として残っていないので参考にできない ◦ 設定変更前の検証に時間がかかる ◦ 開発効率とリリーススピードの低下
  9. Infrastructure as Code • インフラの構成をコードとして記述すること • TerraformもIaCを実現するツールの1つ

  10. Terraform • Hashicorpによって開発されているツール • マルチプロバイダー ◦ AWS / GCP /

    Azureなど数々のクラウドサービスの構築を自動化できる ◦ HCL(Hashicorp Configuration Language)と呼ばれる独自言語で記述する resource "aws_instance" "web" { count = 1 ami = "ami-04560ec17deca7cc2" instance_type = "t3.micro" subnet_id = element(local.dmz_subnet_ids, count.index) key_name = data.terraform_remote_state.mng.outputs.key_pair_name vpc_security_group_ids = [ aws_security_group.ec2.id ] }
  11. Infrastructure as Codeの効果 • インフラ構成をコードとしてレビューできるようになる • ソースコードと同じくバージョン管理できるようになる • モジュール化によってコードの再利用ができる ◦

    他環境への横展開が容易になる
  12. Environment Production

  13. ここで起こり得る問題点 • 誰でもデプロイ出来てしまう ◦ デプロイフローの未確立 ◦ Terraformをローカル実行 ◦ オペレーションミスの誘発 •

    反映前のレビューが出来ていない ◦ コードの記述ミスに気づけない
  14. CI/CD • アプリケーション開発のビルド/テスト/デプロイを自動化する手法 • インフラもIaCと組み合わせることでCI/CDの恩恵を得ることができる

  15. Terraform Cloud • チームでのTerraformの実行を補助するアプリケーション ◦ 一貫した信頼性の高い Terraformの実行環境 ◦ 状態ファイル(tfstate)やアクセスキーなどのシークレットの共有 ◦

    インフラストラクチャへの変更を承認するためのアクセス制御 ◦ Terraformのモジュールを共有するためのプライベートレポジトリ ◦ Terraformの構成内容を管理するためのポリシー制御
  16. CI/CDの効果 • 構築及びデプロイフローを全メンバーで共通化することができる ◦ コードレビューの徹底 ◦ オペミスの防止 ◦ 新規メンバーの参入障壁を減らす •

    手動から自動に変わることでリリーススピードが向上する
  17. 実装例 • Terraform Cloudを利用した実装例をご紹介します • 詳細は以下のブログにも記載しています • https://beyondjapan.com/blog/2020/04/terraform-cloud-gitops-cicd/

  18. None
  19. • SREがTerraformのモジュールを記述してGitLabにPush • Team AとTeam Bのメンバーが利用する

  20. $ tree . ├── README.md ├── examples │ └── vpc

    │ ├── main.tf │ ├── outputs.tf │ ├── provider.tf │ ├── terraform.tfstate │ ├── terraform.tfstate.backup │ ├── terraform.tfvars │ └── variables.tf ├── main.tf ├── outputs.tf └── variables.tf 2 directories, 11 files ディレクトリ構造 モジュール本体 サンプルコード
  21. モジュール本体 引数の型定義 リソース定義 variable "vpc_config" { description = "VPC Config"

    type = object({ name = string cidr_block = string enable_dns_support = bool enable_dns_hostnames = bool }) default = { name = "" cidr_block = "" enable_dns_support = false enable_dns_hostnames = false } } resource "aws_vpc" "vpc" { cidr_block = var.vpc_config.cidr_block enable_dns_support = var.vpc_config.enable_dns_support enable_dns_hostnames = var.vpc_config.enable_dns_hostnames tags = { Name = var.vpc_config.name } }
  22. サンプルコード モジュール定義 変数定義 $ git tag v1.0.0 $ git push

    origin v1.0.0 変数代入(tfvars) module "vpc" { source = "../../" vpc_config = { name = "vpc-${var.project}-${var.environment}" cidr_block = "10.0.0.0/16" enable_dns_support = true enable_dns_hostnames = true } public_subnet_config = { name = "subnet-${var.project}-${var.environment}-public" route_table_name = "route-${var.project}-${var.environment}-public" internet_gateway_name = "igw-${var.project}-${var.environment}" subnets = { ap-northeast-1a = "10.0.10.0/24" ap-northeast-1c = "10.0.11.0/24" ap-northeast-1d = "10.0.12.0/24" } ~~~~ SNIP ~~~~ } variable "project" { description = "Project Name" } variable "environment" { description = "Environment" } project = "terraform-vpc-module" environment = "prod"
  23. • GitLabにPushしたモジュールをPrivate Module Registryにインポートする

  24. 引数定義 リソース一覧

  25. • Terraform CloudにWorkSpaceを作成する • Terraformのコードで記述された構成を PRJごとやサービスごとなど意味のある単位に分割するための論理グループ

  26. ワークスペース

  27. • Teamごとに作成したいインフラの構成をTerraformで記述する • SREsが記述したモジュールを利用する

  28. $ tree . ├── backend.tf ├── main.tf ├── outputs.tf ├──

    providers.tf └── variables.tf 0 directories, 5 files ディレクトリ構造
  29. 変数定義 • 引数として渡す値を格納する変数を定義 • 定義のみ行い代入はローカルで行わない ##################### # Project ##################### variable

    "project" { description = "Project Name" } variable "environment" { description = "Environment" } ##################### # AWS Common ##################### variable "access_key" { description = "AWS Access Key" } variable "secret_key" { description = "AWS Secret Key" } variable "role_arn" { description = "AWS Role ARN for Assume Role" } variable "region" { description = "AWS Region" }
  30. 変数代入 • Terraform Cloudで変数を代入 • シークレットはSensitive Valueにする

  31. tfstate ステート管理 • ローカルで管理しない • remote-backendの記述を行う • WorkSpaceを指定してTerraform Cloudで管理する terraform

    { backend "remote" { hostname = "app.terraform.io" organization = "Org-Name" workspaces { prefix = "team_b_prj_b_prod" } } }
  32. モジュール定義 • Private Module Registryのモジュールを指定 • 利用したいバージョンを指定 module "vpc" {

    source = "app.terraform.io/Org-Name/module-vpc/aws" version = "1.0.0" vpc_config = { name = "vpc-${var.project}-${var.environment }" cidr_block = "10.0.0.0/16" enable_dns_support = true enable_dns_hostnames = true } public_subnet_config = { name = "subnet-${var.project}-${var.environment }-public" route_table_name = "route-${var.project}-${var.environment }-public" internet_gateway_name = "igw-${var.project}-${var.environment }" subnets = { ap-northeast-1a = "10.0.10.0/24" ap-northeast-1c = "10.0.11.0/24" ap-northeast-1d = "10.0.12.0/24" } }
  33. • WorkSpaceに各Teamのリポジトリを登録する • GitへのPushをトリガーにterraform planが自動実行される

  34. リポジトリ登録 ファイル読込 リポジトリ選択

  35. module "vpc" { source = "app.terraform.io/Org-Name/module-vpc/aws" version = "1.0.0" vpc_config

    = { name = "vpc-${var.project}-${var.environment }" cidr_block = "10.0.0.0/16" enable_dns_support = true enable_dns_hostnames = true } public_subnet_config = { name = "subnet-${var.project}-${var.environment }-public" route_table_name = "route-${var.project}-${var.environment }-public" internet_gateway_name = "igw-${var.project}-${var.environment }" subnets = { ap-northeast-1a = "10.0.10.0/24" ap-northeast-1c = "10.0.11.0/24" ap-northeast-1d = "10.0.12.0/24" } } コード変更 "subnet-${var.project}-${var.environment }-pub"
  36. 自動Plan

  37. • Planの結果を元にレビューを行う • 意図した内容であれば Applyを承認する

  38. 承認後Apply

  39. • Applyするとtfstateが更新される

  40. tfstate

  41. • Terraform Cloudの動作状況が通知される

  42. Slack通知 • PlanとApply時に通知される • 他のメンバーもデプロイ状況を把握できる

  43. まとめ • Terraformはいいぞ! • とハッシュタグ付きでツイートしてみてください(いいねします)

  44. 終わり