TerraformをGoogle Cloudで使ってみた

記事タイトルとURLをコピーする

G-gen の杉村です。 Infrastructure as Code (IaC) を実現する Terraform を Google Cloud (旧称 GCP) で使ってみました。

Terraform

Terraform とは

Terraform は Infrastructure as Code (IaC) を実現するオープンソース (Mozilla Public License v2.0) のツールです。

Google Cloud (旧称 GCP) のほか Amazon Web Services (AWS) や Microsoft Azure にも対応しており、 IaC ツールとして根強い人気を誇ります。

Terraform では独自フォーマットの設定ファイルでリソースを記述し、コマンドラインツールで操作します。また状態 (state) がファイルとして保存され、実環境と設定ファイルの差分が把握されます。

設定ファイルでクラウドインフラを管理できるため、 IT インフラのバージョン管理や CI/CD (継続的インテグレーション / 継続的デリバリ) を可能にします。

Google Cloud では公式の IaC ツールとして Cloud Deployment Manager が存在しているものの、事実上 Terraform が Google Cloud の IaC ツールとして定着しています。

使ってみる

Cloud Shell

Google Cloud の Web コンソールには Cloud Shell が備わっており、ローカル PC にツールをインストールしたり作業用の VM を起動しなくてもブラウザ上で Linux ベースの作業スペースを使うことができます。

Google Cloud コンソール にログインし、右上の四角いアイコンをクリックします (マウスオーバーすると Cloud Shell をアクティブにする と表示されます) 。

Cloud Shell を起動

始めて起動する場合は 1 分程度待つ必要があるかもしれませんが、2回目以降は数秒程度になります。しばらくすると黒いターミナル画面が出てきます。

以下スクリーンショットの赤枠部分をドラッグして上下に動かすと、ターミナル画面のサイズを変えることができます。

ターミナル画面

Terraform コマンドの確認

実は Cloud Shell にはデフォルトで Terraform がインストール済みです。

terraform --version と入力してエンターを押してみてください。

$ terraform --version
Terraform v1.2.8
on linux_amd64

Your version of Terraform is out of date! The latest version
is 1.2.9. You can update by downloading from https://www.terraform.io/downloads.html

もしローカル PC に Terraform をインストールしたい場合、 公式サイト 等をご参照ください。

ファイル作成

フォルダを作ってその中に Terraform 設定ファイルを作成します。

ここでは Cloud Storage バケットを定義するための storage.tf というファイルを作成します。ファイル名は任意です。

mkdir terraform-demo
cd terraform-demo

touch storage.tf

エディタでの編集

なんと Cloud Shell には ブラウザ上で動作するコードエディタまで付属しています。エディタを開くため、以下スクリーンショットの エディタを開く ボタンを押下します。

エディタを開く

左側のファイルエクスプローラから先程の storage.tf を選択し、編集します。

エディタ画面

以下の設定内容を貼り付けて、保存 ( File メニューから Save もしくは Ctrl + S 押下) します。

<任意のリソース名> は任意の名称に置き換えてください。これは Terraform 内でリソースを一意に特定するための識別子です。その左側にある "google_storage_bucket" はこのリソースの種類を表します。

また <バケット名> を世界で一意になるように置き換えてください。これが Cloud Storage バケット名となります。

resource "google_storage_bucket" "<任意のリソース名>" {
  name          = "<バケット名>"
  location      = "asia-northeast1"
  
  force_destroy = true
  uniform_bucket_level_access = true

  lifecycle_rule {
    condition {
      age = 5
    }
    action {
      type = "Delete"
    }
  }
}

上記は以下のような Cloud Storage バケットを定義する設定です。

設定名
バケット名 <バケット名>
ロケーション asia-northeast1 (東京)
force_destroy 有効 (バケット削除時にオブジェクトが残っていたら中身を全て削除してからバケット削除)
均一なアクセス制御 有効
ライフサイクル 5 日で削除

リソースタイプごとにパラメータの設定方法が定義されており Terraform の公式リファレンスから確認可能です。

Terraform 初期化

次に、コマンドを実行して Terraform の初期化を行います。エディタの編集部分下部に白いターミナルが表示されていますので、そこからコマンドを実行するか、エディタ上部の ターミナルを開く ボタンを押して先程の黒いターミナルに戻ることもできます。

terraform init コマンドを実行してください。 Terraform has been successfully initialized! と表示されたら成功です。

terraform init の実行
このコマンドを実行すると、カレントディレクトリの配下にある *.tf が自動的に読み込まれ、必要なファイルがセットアップされます。

今回はリソースタイプが google_storage_bucket のリソースが定義されているので、自動的に Google 用の プロバイダ がダウンロードされてセットアップされます。プロバイダとは Terraform 本体とは別個のバイナリであり AWS や Google Cloud など対応するプラットフォームごとに存在しています。

ls -la コマンドを実行すると、以下のように . から始まる隠しファイルが生成されていることが分かります。

$ ls -la
total 20
drwxr-xr-x  3 sugimura sugimura 4096 Sep 19 02:04 .
drwxr-xr-x 27 sugimura     1001 4096 Sep 19 01:19 ..
-rw-r--r--  1 sugimura sugimura  294 Sep 19 01:02 storage.tf
drwxr-xr-x  3 sugimura sugimura 4096 Sep 19 02:04 .terraform
-rw-r--r--  1 sugimura sugimura 1155 Sep 19 02:04 .terraform.lock.hcl

確認コマンド

次は terraform plan コマンドを実行します。カレントディレクトリにある *.tf 設定ファイルが環境にどのような影響を及ぼすかを事前に確かめるためのコマンドです。

$ terraform plan

Terraform used the selected providers to generate the following execution plan. Resource
actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  # google_storage_bucket.ggen-test-storage will be created
  + resource "google_storage_bucket" "ggen-test-storage" {
      + force_destroy               = true
      + id                          = (known after apply)
      + location                    = "ASIA-NORTHEAST1"
      + name                        = "ggen-test-storage"
      + project                     = (known after apply)
      + self_link                   = (known after apply)
      + storage_class               = "STANDARD"
      + uniform_bucket_level_access = true
      + url                         = (known after apply)

      + lifecycle_rule {
          + action {
              + type = "Delete"
            }

          + condition {
              + age                   = 5
              + matches_prefix        = []
              + matches_storage_class = []
              + matches_suffix        = []
              + with_state            = (known after apply)
            }
        }
    }

Plan: 1 to add, 0 to change, 0 to destroy.

──────────────────────────────────────────────────────────────────────────────────────────

Note: You didn't use the -out option to save this plan, so Terraform can't guarantee to
take exactly these actions if you run "terraform apply" now.

Plan: 1 to add, 0 to change, 0 to destroy. は環境に新しいリソースが作成されることを意味しています。

実際にリソースを作成したり更新する前に毎回 terraform plan を実行することで、意図しない変更に事前に気がつくことができます。

適用

実際にリソースを作成するため terraform apply を実行します。

実行すると plan を実行したときと同じような環境差分の表示に加えて以下のプロンプトが表示されます。

Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.

  Enter a value: 

yes を入力して Enter を押下すると、実際に環境に適用されます。

Apply complete! Resources: 1 added, 0 changed, 0 destroyed. が表示されれば成功です。

Cloud Storage のコンソール画面で、バケットが作成されたことを確認してください。ライフサイクルポリシーも設定されているはずです。

環境の削除

環境を削除する場合は terraform destroy を実行します。

先程と同じようにプロンプトが表示されますので yes を入力して Enter を押下します。これで環境が削除されます。

Cloud Storage に状態 (state) を保存する

前提知識

状態 (state) とは

Terraform の 状態 (state) とは Terraform が把握している実環境の現在の状態です。 Terraform は state をファイルとして保持します。

「状態をファイルとして保持せず、常に実環境を見てくれればいいのに。そうしないとファイルと実環境の差異が生まれてしまうのでは」と考える人もいるかもしれません。しかし「複数リソースの依存関係を保持する」「設定ファイルと実リソースのマッピングを保持する」「毎回実環境を精査すると多数の API コールが走りリソースが多い場合に処理が重すぎる」などの理由で Terraform は state をファイルとして保持しています ( 参考 ) 。

state は tfstate ファイル として保管され、先程の手順で実行するとファイルはローカル (Cloud Shell) に保存されます。もしローカル PC で Terraform を実行したら、ローカル PC に保管されます。

状態 (state) の共有

しかし、これでは複数人で Terraform 設定ファイルを管理する場合に問題が生じます。

誰かのローカルの tfstate ファイルが保存されていたのでは、この人が毎回 terraform plan terraform apply する必要が出てきます。これではチーム開発や CI/CD は実現できません。

これを解決するため tfstate ファイルをリモート管理することができます。 Google Cloud では Cloud Storage バケット に tfstate ファイルを保管し、これを共有することができます。

実際にやってみます。

バケットの作成

tfstate ファイルを保存するためのバケットを手動で作成しておきます。

このバケットを Terraform で作成しても構いません。しかし「 Terraform の管理に使われるファイルを保管するバケットが Terraform で管理されるべきではない」という考え方もできるため、今回は手動で作成することにします。

バックエンド構成の作成

以下のようなファイルを backend.tf として新規作成し、先程作成した storage.tf と同じディレクトリに配置します。

terraform {
 backend "gcs" {
   bucket  = "ggen-terraform-demo"
   prefix  = "terraform/state"
 }
}

再 init

terraform init を実行します。 Terraform has been successfully initialized! という表示が出たら成功です。

バケットの中身を見てみると terraform/state フォルダの中に tfstate ファイルが生成されているはずです。

バケット内の tfstate ファイル

これ以降は terraform planterraform apply を実行するたびに最新の状態がバケットから取得され、 apply により環境が更新されるとバケット上の tfstate ファイルが更新されます。

これに加えて Terraform 設定ファイルを Git 等でバージョン管理することで、複数人による開発・管理が可能になります。

杉村 勇馬 (記事一覧)

執行役員 CTO / クラウドソリューション部 部長

元警察官という経歴を持つ現 IT エンジニア。クラウド管理・運用やネットワークに知見。AWS 12資格、Google Cloud認定資格11資格。X (旧 Twitter) では Google Cloud や AWS のアップデート情報をつぶやいています。