投稿者:ソリューション担当

はじめに



この記事はterraform Advent Calendar 2020の18日目です。今年は案件やら何やらで外部活動できなかったですが、なんとかアドベントカレンダーには参加できました。
Terraformのアドベントカレンダーに投稿しているため釈迦に説法かも知れませんが、社内ブログで記載しているため、Terraformに関しての概要、メリット・デメリットを記載いたします。

Terraformはクラウド、オンプレ含めたインフラ構築作業を手作業ではなく自動で実施できるツールとなっています。他のインフラ構築可能なツールとしてAnsible等の名前も上がったりしますが、Terraformはインフラ構築がメインレイヤとなっています。名前を出したAnsibleはインフラ構築からOSレイヤ、ミドルウェアインストールまで幅広く対応ができます。Terraformはミドルウェア導入等はできませんが、その分他ツールと比べて幅広い範囲での利用ができます。
よくある例では、Terraformでインフラ構築、Ansibleでうわものの設定といったように使い分けられます。

メリット・デメリットは以下の通りとなります。

  • メリット
    • コードがあれば同じ環境をすぐに構築できる
    • 手動で1時間かかる内容が数分で作業可能
  • デメリット
    • ディレクトリ構造やコード記載方法等、普段インフラ作業する人が想定しない考慮事項が出てくる
    • コード作成するには時間がかかるため、その時間でインフラ構築ができてしまう

今回はGCPの構築案件でTerraformを利用した際に感じたこと、上記で書いたデメリットにどうやって挑んだか?に関して紹介します。

前提

SI企業がTerraformを案件で利用するとしたら?という観点で記載しています。
なので既に運用している人、利用している人からしたら物足りない、こういう方法もあるといった感想が出ると思いますので、もし何かあればお気軽にコメントいただければと思います。

まとめ

早速ですがこの記事のまとめです。詳細は各項目にて記載していますが、この記事で言いたいこととしては下記内容です。
- コードを設計書とするかどうかは要検討
- ディレクトリ構造はわかりやすいもので。最初から背伸びしない
- コードチェックはplan結果も一緒に確認するほうがいい

Terraformを利用した際のあれこれ

設計書の作成方法

設計書はコードをベースとしました。設計書を作成するとコードと同じことを記載するため、個別の設計書作成を今回は実施しませんでした。

これに関しては正直なところ、お客様含めてどれだけ取り組みに理解してくれるかだと思います。
設計書の内容をコードに落とし込んでいるとはいえ、コードを見てわからないとあまり意味がないですし、お客様や社内の運用チームにもレクチャーが必要となります。
なので今回はコード全体にコメントを記載し、「このコードでは何をしているか」という箇所を重点的にわかるようにしました。
詳細設計書を作ってからコードに落とすのもいいかもですが、修正が2度手間となるため、一長一短かなと思います。

今回のディレクトリ構造

今回のTerraformのディレクトリ構造は大まかに以下の通りとなります。全体を載せると長くなるため、VPCの構成のみを記載いたします。
Terraform
└─VPC/
    ├─ resources/
    │ ├─ resource-main.tf
    │ ├─ resource-variables.tf
    │ ├─ provider.tf                
    │ ├─ backend.tf               
    │ ├─ prd/                         
    │ │  └─ var.tfvars
    │ └─ stg/              
    │    └─ var.tfvars
    └─ modules/
      └─ vpc/                
        ├─ vpc-main.tf
        └─ vpc-variables.tf


今回はオーソドックスにサービスのコンポーネントごとにフォルダを分け、その中でmoduleとresourceを作成しています。その結果、以下要素で良かったと思いました。
  • 構造がシンプルになっている
    • GCEやGCS、VPCの修正はどこを行えばいいかわかりやすい
  • 管理しやすいこと
    • フォルダのコンポーネントごとにみるため、構成がわかりやすい
  • 複数人で作成を行うため作業分担がしやすい
    • 上記にひも付きますが、コンポーネントごとに作業の振り分けができました
別け方も色々とあるかと思いますが、個人的にはこの別け方が比較的わかりやすいものでした。最初に実施する場合はとっつきやすいかと思います。

今回作成したコード


またコードに関しては一部抜粋となりますが、以下の通りとなっています。コード内に記載しているコメントは省略しています。全文を見たい方はこちらからご確認ください(ディレクトリ構造が多少違いますが、やっていることは一緒です)

resource "google_compute_subnetwork" "subnet-create-resource" {
  for_each = var.subnet

  ip_cidr_range = lookup(each.value, "ip_cidr_range", null)
  name = lookup(each.value, "subnet_name", null)
  network = google_compute_network.vpc-create-resource[lookup(each.value, "subnet_self_link_network_name", null)].name
  description = lookup(each.value, "description", null)
  private_ip_google_access = lookup(each.value, "private_ip_google_access", null)
  project = lookup(each.value, "subnet_project", null)
  region = lookup(each.value, "subnet_region", null)

  dynamic "secondary_ip_range" {
    for_each = lookup(each.value, "secondary_ip_ranges", null)
    content {
      range_name    = secondary_ip_range.value.range_name
      ip_cidr_range = secondary_ip_range.value.ip_cidr_range
    }
  }
}


こちらのコードの詳細は別ブログにて記載しますが、このコードで実行すると色々と都合がよかったです。
一部ですが、上記モジュールを利用した場合のtfstateのサンプルが以下となります。

{
  "module": 【module名】,
  "mode": "managed",
  "type": "google_compute_subnetwork",
  "name": 【利用するmodule名】,
  "each": "map",
  "provider": "provider.google",
  "instances": [
    {
      "index_key": 【subnet名#1,
      "schema_version": 0,
      "attributes": {
      【設定値の詳細】
        ex)
        "description" : "sample-subnet-1",
        "name" : "sample-subnet-1",
        "project" : "test-sample-project"
      },
      "private": 【ランダム値】,
      "dependencies": [
      ]
    },
    {
      "index_key": 【subnet名#2,
      "schema_version": 0,
      "attributes": {
     【設定値の詳細】
        ex)
        "description" : "sample-subnet-2",
        "name" : "sample-subnet-2",
        "project" : "test-sample-project"
      },
      "private": 【ランダム値】,
      "dependencies": [
      ]
    }
  ]
}


index_keyに作成するサブネット名が記載されるため、tfstate確認時に見やすくなります。
これなら必要な設定をmodule側で定義できていれば、tfstateを確認するだけでどうなっているかの状況把握がやりやすいかと思います。
またこのような形で記載しているため、terraformのplan時もどのコンポーネントを作成するかが非常にわかりやすく、レビューがしやすかったです。

改めてまとめ



改めて、この記事のまとめです。
  • コードを設計書とするかどうかは要検討
    • 詳細設計書とコードも用意するパターンか、全体をまとめた資料は用意して詳細部分をコードにしておくかはプロジェクトの納期、方針に合わせたほうがいいかもしれないです。
  • ディレクトリ構造はわかりやすいもので。最初から背伸びしない
    • Terraformのディレクトリ構造は悩ましいものです。最初はわかりやすいところから始めるといいかと思います。
  • コードチェックはplan結果も一緒に確認するほうがいい
    • 正直コードレベルで見ても、パラメータとしてのチェックくらいしかわからないです。コードを実行したら何が作られるか?も含めてplan結果も確認したほうがいいです。


最後に


弊社はGCPの構築、提案も実施しております。詳細はこちらからご確認ください。
まだまだ新人の立場ですが、案件の取り組みや考え方は従来からある既存技術だけでなく、最新技術やInfrastructure as Codeを利用した構築など、弊社はSI企業としては比較的柔軟に対応できていると思います。(他SI企業の友人の話を聞いてもそうかも?と思います) 無料コンサルティングも実施しておりますので、興味がございましたらよろしくお願いいたします。