この記事は:birthday:アイスタイル Advent Calendar 2020:birthday:22日目の記事になります
はじめまして、サービスインフラを担当していますkamiyamakと申します。
弊社ではオンプレミスとパブリッククラウドを併用しておりますが、私はネットワーク周りを見ることが多いです。
半年ほど前、とあるプロジェクトでAWS環境を構築することになったのですが、その際チームの先輩から「Terraformで作ってみよか」とお達しが下り、Terraformによるコード化とGitlab CIによる自動デプロイを整備しました。
構成

- GitlabプロジェクトのイベントをSlackに通知するためインテグレーションを有効にする
 - tfstateファイルをS3に配置
 - ステージ構成は
fmt>init>plan>apply - terraform apply は任意のタイミングで行えるようmanual実行にする
 
Gitlab、Gitlab runner は既に環境があったため、そちらを利用しています。
整備までの流れ
- GitlabのイベントをSlackで通知する
 - Terraform用IAMアカウント作成
 - tfstate用S3バケット作成
 - main.tf作成
 - .gitlab-ci.yml作成
 - パイプラインのテスト実行
 
GitlabのイベントをSlackで通知する
プロジェクト設定のインテグレーションから Slack notifications を有効にし、Webhook URLを入れます。

Terraform用IAMアカウント作成
TerraformがAWSリソースを操作するためのIAMアカウントを作成します。
こちらはマネジメントコンソールから作成しました。
そしてGitlabプロジェクトのVariableにクレデンシャルを登録しておきます。

tfstate用S3バケット作成
tfstateファイルをS3に配置するため、こちらも予め作成しておきます。マネジメントコンソールから作成しました。
main.tf作成
バージョン、プロバイダー、tfstateを格納するバックエンドを指定します。
terraform {
  required_version = ">= 0.12"
}
provider "aws" {
  version = "~> 2.7"
  region  = "ap-northeast-1"
}
terraform {
  required_version = "0.12.26"
  backend "s3" {
    bucket = "hogehoge-bucket"
    region  = "ap-northeast-1"
    key     = "terraform.tfstate"
    encrypt = true
  }
}
resource "aws_s3_bucket" "hogehoge-bucket" {
  bucket = "hogehoge-bucket"
  versioning {
    enabled = true
  }
}
.gitlab-ci.yml作成
HashiCorpのTerraform docker imageを使って各ステージでTerraformコマンドを実行します。
Terraformはバージョンによって書き方が大きく変わるため、バージョンを指定しています。
image:
  name: hashicorp/terraform:0.12.26
  entrypoint: [""]
.artifacts: &artifacts
  paths:
    - '.terraform'
stages:
  - fmt
  - init
  - plan
  - apply
fmt:
  stage: fmt
  script:
    - terraform fmt -check=true
  tags:
      - docker
init:
  stage: init
  script:
    - terraform init
  artifacts: *artifacts
  only:
    - master
  tags:
      - docker
plan:
  stage: plan
  script:
    - terraform plan
  artifacts: *artifacts
  only:
    - master
  tags:
      - docker
apply:
  stage: apply
  script:
    - terraform apply -auto-approve
  when: manual
  artifacts: *artifacts
  only:
    - master
  tags:
      - docker
パイプラインのテスト実行
ここまでできたらマージしてパイプラインの動作を確認します。


Apply complete まで行きました。
applyコマンドの出力に aws_s3_bucket と出ているのでTerraformで管理しているリソースということがわかります。
これでCI/CDが整備できました。
あとはTerraformのコードを書いていくだけです。
さいごに
昨年から引き続き 本番環境でやらかしちゃった人 Advent Calendar 2020 が盛り上がっていますね。
私も何度か本番環境でやらかしちゃってる人でして・・。
当然二度と繰り返さないよう対策を講じます。手順にチェック観点を追加するなどしてなんとか回避しますが、手動オペレーションのままのため、やらかしてしまう可能性が残ったままになっていました。
また普段の運用では、ドキュメントをしっかり残して属人化しないよう心掛けていますが、日々のタスクに追われメンテナンスされず信頼性が落ちていき、結局サーバやルータにSSHしてコマンドで確認して…ということがあります。
今回作成したCI/CDではGitの作業だけでオペレーションが完結しますし(applyはマニュアルですが)、変更履歴も残るため、運用効率が上がったと感じました。
簡単に使えることがわかったのでTerraform以外にも利用範囲を広げていきたいです。
かなり初心者の内容になってしまいましたが、様々なメリットに気づくことができ、私にとって良い経験になりました。
機会をくださったチームの先輩、開発チームの皆様に感謝です。
