👻

非インフラエンジニアがTerraformを恐れなくなるまで

2023/12/12に公開

はじめに

スターフェスティバルの DPontaro です!

Terraform触るのこわかったけど、だいぶ薄れてきたので恐れなくなるまでの道のりを紹介します。

Terraformとは

Terraform は Infrastructure as Code(IaC)という考え方を実現するためのツールの一つです。
IaC はインフラの構築や変更をコードとして管理・適用するアプローチであり、これによりインフラの変更履歴や再現性を確保することができます。
AWS、Azure、GCP など、多数のクラウドサービスやオンプレミスのツールと連携可能です。

Terraform 触るのこわい

弊社のアプリケーションのインフラもTerraformで管理されており非インフラエンジニアが変更することもあります。
私も多分に漏れず、変更の機会が出てきたのですが当初変更を加えるのはとても怖かったです。
己の操作一つで、すべてをふっ飛ばしてしまうのではないかと😨

恐怖はなぜ生じるのか

恐怖心は、知らないことに対する不安から生じます。
仕組みを知らなければ今目の前の操作が与える影響もわからず、前述のような恐怖につながるわけです。
Terraformの仕組みを知ることで、恐怖心を取り除くことができます。
ということで、私が恐怖がなくなるまでに知ったことを紹介します。

前提

  • 今回の事例は既に構築されているTerraformの環境があり、それを非インフラエンジニアが変更するという想定です。イチから構築する工程などは今回は扱いません。
  • Terraform のバージョンは 1.6.2 を使用しています。

初期化

怖いですよね。初期化。
なんか全部まっさらになりそうですよね。
terraform init というコマンドは作業をするうえで必ず実行することにはなるんですが
本当に叩いて大丈夫?と不安で仕方なかったです。
ということで安心できるように関連する用語を紹介します。

tfstate

Terraform は 「現在のインフラの状態」tfstate というファイルで管理しています。
これにより実際のインフラと Terraform のコードの差分を把握できます。
開発を一人で行う場合、tfstate をローカルで管理することもありますが、複数人での開発や運用の場合、Amazon S3 のような中央のストレージに保存して、チームで共有するのが一般的です。
tfstate は Terraform の実行時に自動で変更されていくため、絶対に手動で変更してはいけません。
誤った変更が行われると、予期しない問題が発生する可能性があります。

provider

Terraform がクラウドのリソースを操作するためには、そのクラウドベンダー専用の provider をインストールする必要があります。これがないと、該当のクラウドの操作はできません。

terraform init

Terraform の作業を始める前の第一歩は、 terraform init コマンドの実行です。このコマンドで、必要な provider のインストールなど、基本的な初期設定が自動で行われます。
初期設定は下記のような terraform というブロックに記述されています。
使用するバージョンや、 provider, tfstate の保存先などが記述されています。

terraform {
  required_version = ">= 1.2.0"

  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.17.0"
    }
  }

  backend "s3" {
    region         = "ap-northeast-1"
    bucket         = "example-terraform-state"
    key            = "example.tfstate"
    encrypt        = true
    dynamodb_table = "example-terraform-state-lock"
  }
}

dynamodb_table

前述の terraform ブロック中に dynamodb_table という項目が出てきますがこれは、 tfstate のロックを管理するための DynamoDB テーブルです。tfstate のロックは、複数人での作業時に、同じ tfstate を同時に変更することを防ぐために使用します。

.terraform

terraform init を実行すると、.terraform というディレクトリが生成されます。この中には、ローカルの tfstate ファイルなどが保存されます。直接編集は避けてください。

.lock.hcl

依存性の管理をするロックファイルです。 terraform init を実行したときに生成され、使用する provider のバージョンなどの詳細情報を固定(ロック)します。このファイルを Git で管理することで、チームメンバー間で同じバージョンの provider を使用することが保証されるため、環境の一貫性が確保されます。

初期化のまとめ

ということで init で行っているのはあなたのローカルでの作業環境を行うための準備なので、安心して実行してください。
大丈夫、壊れないよ⭐

管理されたリソースに変更を加える

変更を加える。。怖いですよね。
何か手を加えて取り返しのつかないことになったらどうしよう。いやだなーこわいなー。
コマンド打ち込んだら、destroy とか平気で言ってくるんですよね。いやだなーこわいなー。
でもちゃんとルール理解すれば大丈夫です。

resource

Terraform で、具体的なインフラの部品(例:AWS の EC2、RDS)を定義する部分です。どんなリソースを管理できるかは、使用している provider のドキュメントを参照してください。

https://registry.terraform.io/providers/hashicorp/aws/latest/docs

例えばS3のバケットであれば

resource "aws_s3_bucket" "example" {
  bucket = "my-tf-test-bucket"

  tags = {
    Name        = "My bucket"
    Environment = "Dev"
  }
}

最低限の記述ですが、バケット名の指定やタグの指定を上記のように行います。
既存の resource がわからなければ provider のドキュメントを漁っていきましょう。

terraform plan

Terraform のコードに変更を加えた後、 terraform plan コマンドでその変更がどう影響するかを確認できます。
create(作成)、update(更新)、destroy(削除)の 3 つの操作が表示されるため、実際の適用前に期待通りの変更になっているかをチェックしましょう。

Terraform used the selected providers to generate the following execution
plan. Resource actions are indicated with the following symbols:
  ~ update in-place
  - destroy
+/- create replacement and then destroy

弊社では PR を出したら CI で plan 結果が表示されるように GitHubActions が設定されており
レビュアーは plan 結果を確認して問題なければ approve するという運用を行っています。

あくまでどのような変更がかかるかを確認するためのコマンドなので、 実際にはインフラの変更は行われません。
安全・安心!!!

terraform apply

plan で確認した結果が問題なければ terraform apply コマンドで 実際にインフラの変更を行います。
コマンド実行後適用前に'yes'と入力を求められ、入力後適用されます。
入力を求めない強制実行のオプションもありますが、手動実行の際に使うことはないでしょう。

弊社では一部リポジトリでは main ブランチへマージした段階で自動で apply するといった運用も行われています。

変更を加えるのまとめ

ということで、実際に変更を加えるのは terraform apply です。
こちらを実行する際には事前に terraform plan で変更内容を確認しておけば安心して実行できることでしょう!

管理されていないリソースをimportする

import というと、何かしらデータの変更が起こりそうですよね。
どこになにがどう import されるかわからず、なんか壊れたらどうしよう。いやだなーこわいなー。

terraform import

terraform import は、すでに存在するリソースを Terraform の管理下に取り込むためのコマンドです。
import のコマンドはリソースの種類によって異なります。
例えば、S3 のバケットを import する場合は下記のようになります。

% terraform import aws_s3_bucket.bucket bucket-name

import のコマンドは各リソースのドキュメントの最下部に記載されています。
https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket

import ブロック

import コマンドで取り込んでも良いのですが、
Terraform 1.5 以降では、import ブロックを用いて、コマンド実行でリソースを管理下に取り込むことが可能です。

import {
  to = aws_s3_bucket.bucket
  id = "bucket-name"
}

import コマンドでは

  • 一度にひとつずつしか取り込めない
  • 状態がすぐに変更され、事前に結果をプレビューできない

といったやりづらさがあったのですが、
import ブロックを使用することで、事前に plan で結果を確認できるのと、複数のリソースを一度に取り込むことが可能です。
plan で確認し問題なければ apply を実行すると適用されます。

管理されていないリソースをimportするのまとめ

ということで、import は既存リソースを管理下に取り込むためのコマンドです。
直接的にリソースに変更を加えることはないので、安心して運用していきましょう。
状態に変更は加わるので、他作業者と並行して作業を行う場合は注意していきましょう。

おわりに

恐怖心は、知らないことに対する不安から生じます。

さて知らないこともだいぶ減りましたかね?
あとは何回か手を動かせば、恐怖心はなくなるでしょう。
安心して平穏に作業できることを祈っております。

スタフェステックブログ

Discussion