非インフラエンジニアがTerraformを恐れなくなるまで
はじめに
スターフェスティバルの 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 のドキュメントを参照してください。
例えば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 のコマンドは各リソースのドキュメントの最下部に記載されています。
import ブロック
import コマンドで取り込んでも良いのですが、
Terraform 1.5 以降では、import ブロックを用いて、コマンド実行でリソースを管理下に取り込むことが可能です。
import {
to = aws_s3_bucket.bucket
id = "bucket-name"
}
import コマンドでは
- 一度にひとつずつしか取り込めない
- 状態がすぐに変更され、事前に結果をプレビューできない
といったやりづらさがあったのですが、
import ブロックを使用することで、事前に plan で結果を確認できるのと、複数のリソースを一度に取り込むことが可能です。
plan で確認し問題なければ apply を実行すると適用されます。
管理されていないリソースをimportするのまとめ
ということで、import は既存リソースを管理下に取り込むためのコマンドです。
直接的にリソースに変更を加えることはないので、安心して運用していきましょう。
状態に変更は加わるので、他作業者と並行して作業を行う場合は注意していきましょう。
おわりに
恐怖心は、知らないことに対する不安から生じます。
さて知らないこともだいぶ減りましたかね?
あとは何回か手を動かせば、恐怖心はなくなるでしょう。
安心して平穏に作業できることを祈っております。
Discussion