Technical Blog テクニカルブログ
  1. HOME
  2. テクニカルブログ
  3. 【NIC x Ops(にこぷす)通信】(Terraform編)【連載】本当に買い?HCP Terraform Premiumをゆるっと検証 〜気になる「運用自動化」と「ガバナンス」ってぶっちゃけどうなの?(全6回)

【NIC x Ops(にこぷす)通信】(Terraform編)【連載】本当に買い?HCP Terraform Premiumをゆるっと検証 〜気になる「運用自動化」と「ガバナンス」ってぶっちゃけどうなの?(全6回)

投稿者:種田

【第3回】コード書かずにインフラ作れる?「No-Code Provisioning」をポチポチしてみた

目次

  1. 導入:Premiumの世界へようこそ(全体俯瞰)
  2. 【管理者設定】編:レジストリ登録の概要と公式の「モジュール設計」
  3. 【プロビジョニング実行】編:実際にやってみた検証と現場目線の考察
  4. まとめ:実務におけるNo-Codeモジュールの「理想の境界線」
  5. 次回予告

皆さま、こんにちは!
このテックブログでは、IT運用に関する内容を連載、「にこぷす通信」をお届けしています。

「NIC x Ops(にこぷす)」とは?

NIC x Ops(にこぷす)』とは、
私たちの会社であるNTTインテグレーション(NI+C)の運用ノウハウと、
IBMさんの強力なソリューションを
Collaboration(コラボレーション)させた、IT運用高度化シリーズ(Ops)のニックネームなんです。

現代のIT運用の現場は、システムの複雑化や人手不足など、課題が山積みです。そんな現場を少しでも楽に、そしてエンジニアの皆さんが笑顔で「攻めの運用」ができるように支えたい。そんな想いがこの「にこぷす」には込められています。

「にこぷす」には、Instana(可観測性)のほかにも、Turbonomic(リソース最適化)Terraform(インフラ自動化)など、IT運用を劇的に変える製品がたくさんあります。

これからもこの通信を通して、「IT用語は難しいけれど、中身を知ればこんなに便利で面白いんだ!」というテクニカルな内容をご紹介していきますので、どうぞよろしくお願いします。

1. 導入:Premiumの世界へようこそ(全体俯瞰)

連載第3回となる今回は有償版でのみ利用できる「No-Code Provisioning(ノーコード・プロビジョニング)」を検証します!

「インフラをセルフサービス化したいけれど、開発チームに自由に作らせてクラウド破産や野良リソース化するのは怖い……」という管理者の悩みを解決する機能です。

大まかな流れは、下にある図解の通り。管理者が「インフラの型」をレジストリに仕込んでおけば、開発者はコードを1行も書かずに、GUI画面をポチポチするだけで安全にインフラを展開できます。

No-Code Provisioning の全体像

プラットフォームの共通化から開発者のセルフサービス利用までの流れ

管理者側の操作の流れ(標準化と公開)
STEP 01

標準モジュールの開発

インフラ管理者がセキュリティ定義や設計基準を満たしたHCLコードを構築します。

Terraform HCL
👉
👉
STEP 02

VCSへのコミット

GitHubやGitLabなどのリポジトリにコードを格納し、バージョン管理下におきます。

Git VCS
👉
👉
STEP 03

レジストリ登録 & 有効化

HCP TFレジストリに同期させ、「No-Code provisioning」を有効(ON)にします。

HCP TF No-Code
⬇️ 準備完了!アプリ開発者がノーコードで使える状態に
利用者側の操作の流れ(セルフサービス実行)
STEP 04

GUIからパラメータ入力

開発者は画面から必要なパラメータ(環境名やスペック等)を入力するだけで申請可能です。

GUI Form Self-Service
👉
👉
STEP 05

自動Workspace展開

HCP TFが裏側で自動的にWorkspaceを作成し、割り当てられた変数をセットして起動します。

Workspace Auto Run
👉
👉
STEP 06

クラウドインフラ展開

Plan & Applyが自動走査され、AWS等の指定したクラウドへ安全にリソースが生成されます。

AWS Azure GCP

今回は「設計者目線」で仕様を深掘りします

とはいえ、ただの画面ツアー記事では面白くありません。

実際にモジュールを自作して使い倒してみると、「いつものTerraformコード」の感覚で書くとGUI側でちょっと意外な挙動をすることが見えてきました。

  • default 値を設定した変数は、利用者の画面でどう見えなくなるのか?
  • 仕込んだ validation ブロックは、画面ではなくどこで牙をむくのか?
  • カタログを分けたいときのリポジトリやディレクトリのスマートな切り方は?

今回は、仕込み側(インフラ管理者)の目線に立って、「コードがGUIのどこに現れるかの裏表マップ」「自動Planフェーズでの挙動を見据えた、失敗させない優しさ設計のコツ」をサクッと解説していきます。

それでは、管理者の仕込み画面(Organization設定)から見ていきましょう!

2. 【管理者設定】編:レジストリ登録の概要と公式の「モジュール設計」

2.1. レジストリ登録の3ステップ(概要)

HCP Terraformの「Registry」メニューから「Private Library」を開き、基本的には以下の流れでNo-Codeモジュールを有効化します。

  1. リポジトリの接続:GitHub等にあるモジュールのHCLコードを紐付ける。
  2. Settingsの確認:対象モジュールの詳細画面から設定(Settings)へ移動する。
  3. No-Codeの有効化:「Enable no-code provisioning」にチェックを入れて保存する。

具体的な画面操作やキャプチャ付きの手順については、非常に手厚い公式チュートリアルが用意されているため、そちらをご参照ください。本稿では、ここからの本質である「設計」にフォーカスを当てていきます。

2.2. Private RegistryとNo-Code画面の仕組み

仕込みが完了すると、HCP Terraformの画面上には「管理者向けのPrivate Registry画面」が生成され、さらにそれを有効化することで「利用者向けのNo-Codeプロビジョニング画面」が自動生成されます。

私たちが普段書いているHCLコードやMarkdownが、具体的にどう画面にレンダリングされるのか、基本仕様の対応マップを整理しました。

2.2.1. 管理者向け:Private Registryでの見え方

コードをリポジトリと連携するだけで、ドキュメント生成ツールを使ったかのようなUIが自動で構築されます。

  • Readme タブ:モジュール直下にある README.md の内容がそのまま表示されます(利用ガイドとして活用できます)。
  • Inputs タブ:コード内の variable ブロックの定義を元に、自動でテーブル形式のリストが生成されます。
  • Outputs タブ:コード内の output ブロックの定義を元に、こちらも自動で一覧化されます。

💡 補足: この「Inputs」と「Outputs」の出力形式や見た目のクオリティは、私たちが普段リポジトリのドキュメント整備でよく使っている terraform-docs markdown document コマンドで出力されるドキュメント形式(型・説明・デフォルト値のリスト)に非常に近い質感でレンダリングされます。
terraform docs で README を自動生成するパイプラインを組んでいると内容が冗長になります。

2.2.2. 利用者向け:No-Codeプロビジョニング(GUI)画面への連動

こちらがワークスペースの作成画面の設定で、コードの書き方によって利用者が触るワークスペースの作成画面のUIがダイナミックに変化します。

  • 画面に表示される項目の条件: variables.tfdefault 値が設定されていない変数のみが、利用者に入力を求める「必須フォーム項目」として画面に現れます。デフォルト値が設定されている変数は、画面上からは表示されません。
  • 変数の「型(type)」によるUIの変化:
    • type = string:自由記述ができる通常の「テキスト入力」フォームになります。
    • type = bool:「True / False」を選ぶプルダウンリストが自動で設定されます。
  • ドロップダウン オプション: 通常は自由記述になってしまう string 型の変数であっても、HCP Terraformの画面側で、「事前に管理者が決めた値から選ばせるドロップダウンリスト」へとUIをグレードアップさせることができます。

2.3. 公式が求める「ノーコードのためのモジュール設計」

No-Code Provisioningを有効化するにあたり、ただ手元にある既存のコードをそのまま登録すれば良いわけではありません。公式ドキュメントのModule Designでは、ノーコード利用者が迷わず安全にインフラを作れるようにするための重要な設計指針が示されています。

要件の肝となるのは、大きく以下の2点です。

  • デフォルト値(defaults)の活用: 利用者に変更させたくない共通のパラメータ(シリアルポートの無効化やプロジェクト共通のSSH鍵の禁止など)は、コード側で default 値を設定して「固定化」する。
  • リスト(入力の選択肢化)の活用: 自由記述によるタイポやルール外の入力を防ぐため、変数はHCP TF側の選択肢機能を使い、ドロップダウンで「選ぶだけ」の優しいUIにする。

「この公式ルール通りに変数をガチガチに仕込めば、完璧なノーコード画面ができるはず!」

ということで、この要件に沿って実際にモジュールを設計し、利用者が触るワークスペース作成画面へと駒を進めてみました。しかし、実際に動かしてみると、Terraform本来の仕様に則った「ちょっと意外な挙動」が見えてきたのです。次の章で詳しくレポートします!

3. 【プロビジョニング実行】編:実際にやってみた検証と現場目線の考察

3.1. 検証環境の前提条件とターゲット構成

具体的な検証に入る前に、まずは今回ノーコード化するインフラの前提条件と全体構成を整理しておきます。

Google Cloud側のプロジェクトや、HCP Terraformと安全に認証連携するための WIF(Workload Identity Federation) は設定済みという前提で進めます。

今回検証のテーマに掲げたのは、「インフラに詳しくない開発者でも、CISベンチマーク(CIS v8)に準拠したセキュアなVMインスタンスを一括で安全に作れる環境」 の実現です。 セキュリティのベストプラクティスを担保するため、Compute Engine(GCE)にデフォルトの強力な権限を持たせるのではなく、専用のサービスアカウント(SA)を個別に生成して紐付ける 設計にしています。これに伴い、器となるVPCやサブネットもセットでプロビジョニングするコードを用意しました。

ターゲットとなる全体構成図は以下の通りです。

検証するインフラの全体構成図

今回の検証で作成するインフラ構成(CIS v8準拠)
IaC実行環境
HCP Terraform
🔐 WIF認証連携
▼ デプロイ
Google Cloud プロジェクト(設定済み)
ネットワーク基盤
🌐 VPCネットワーク
└ 📍 専用サブネット
🖥️ GCE インスタンス
🛡️ CIS v8 準拠
セキュリティ基盤
🔑 専用サービスアカウント
(最小権限の原則に基づき個別生成)
🔗 インスタンスへ紐付け

このセキュアなインフラ構成のクオリティを担保しつつ、「いかに開発者が迷わずにセルフサービスで展開できるか」を目指し、今回はアプローチの異なる2つの設計パターンを用意して検証を進めました。

それぞれのパターンの概要を表した構成図が、以下の通りです。

パターン①:マルチワークスペース(疎結合)型
プラットフォームチーム管理
VPC Workspace
(vpc)
HCP TF State & Outputs
(subnet_self_link)
SA Workspace
(service-account)
HCP TF State & Outputs
(sa_email)
▼ data参照 (tfe_outputs)
開発者(ノーコード)管理
App Workspace
(standard-modules)
🖥️ GCE Instance
パターン②:オールインワン(密結合)型
シングルワークスペース(一括生成)
no-code-all-in-one Workspace
(メインモジュール)
▼ 内部モジュール呼び出し
vpc-stack
sa-stack
gce-stack
▼ 一括で自動プロビジョニング
🌐 VPC / Subnet
🔑 Service Account
🖥️ GCE Instance

各パターンについて

  • パターン①:マルチワークスペース(疎結合)型 ネットワーク(VPC)やセキュリティの根幹となるサービスアカウント(SA)といった「共通基盤リソース」は、プラットフォームチームが別のワークスペースで事前に作成・管理。開発者が使うノーコード画面からは、tfe_outputs を使ってそれらの情報を動的に参照し、GCEインスタンスだけを安全に切り出すアプローチです。
  • パターン②:オールインワン(密結合)型 1つのノーコード用ワークスペースを立ち上げるだけで、内部で vpc-stack などの子モジュールを芋づる式に呼び出し、ネットワークの作成から権限設定、インスタンスのデプロイまでを一撃で丸ごと揃えてしまうアプローチです。

3.2. パターン①(疎結合型)の試行錯誤と「開発者に優しい」最終着地点

プラットフォームチームが基盤をお膳立てする「パターン①:マルチワークスペース(疎結合)型」ですが、利用者にどこまで自由度を持たせるかについて、実は一発で答えが出たわけではありません。

現場での運用を想定し、泥臭く試行錯誤を繰り返した3つのステップをご紹介します。

ステップ1:標準モジュールを調整(app_name と project_id のみ指定)

まずは手始めに、名前のバッティングを避けるために app_name(インスタンス名)と、デプロイ先となる project_id(Google CloudのプロジェクトID)の2つだけを必須入力(default値なし)にし、その他はデフォルト値が効くようにモジュールを調整して登録してみました。

  • 挙動: 開発者は画面で「インスタンス名」と「プロジェクトID」を打ち込むだけで、残りのパラメータは安全なデフォルト値が自動適用され、迷うことなくリソースを作成できます。名前の衝突も起きません。
  • 直面した壁: 一見これで良さそうに見えましたが、実務を考えると大きな問題がありました。デフォルト値で作成されたマシンスペックなどを後から少し変更したいとなった場合、ノーコードの申請画面からは変更できません。作成されたワークスペースの「Variables」画面にわざわざ移動して、変数を手動でオーバーライド(上書き)しなければならないのです。これではインフラに詳しくない開発者にとってはハードルが高く、結局Terraformの知識を求められるため「完全なセルフサービス」とは言えない状態でした。
コード(参考)
terraform {
  required_version = ">= 1.5.0"

  required_providers {
    google = {
      source  = "hashicorp/google"
      version = "~> 7.40.0"
    }
    tfe = {
      source  = "hashicorp/tfe"
      version = "~> 0.54.0"
    }
  }
}

provider "google" {
  project = var.project_id
  zone    = var.zone
}
provider "tfe" {
  hostname = var.tfe_hostname
}

data "tfe_outputs" "vpc" {
  organization = var.hcp_organization
  workspace    = var.vpc_workspace_name
}

data "tfe_outputs" "sa" {
  organization = var.hcp_organization
  workspace    = var.sa_workspace_name
}

check "tfe_output_subnet_self_link" {
  assert {
    condition     = can(data.tfe_outputs.vpc.values.subnet_self_link)
    error_message = "リモートのHCP Terraformワークスペース '${var.vpc_workspace_name}' から 'subnet_self_link' の出力が見つかりませんでした。次の点を確認してください: 1) ワークスペース名が正しいこと。 2) ソースワークスペースが正常に適用(apply)されていること。 3) ワークスペースの出力が正しく共有されていること。"
  }
}

check "tfe_output_sa_email" {
  assert {
    condition     = can(data.tfe_outputs.sa.values.email)
    error_message = "リモートのHCP Terraformワークスペース '${var.sa_workspace_name}' から 'email' の出力が見つかりませんでした。次の点を確認してください: 1) ワークスペース名が正しいこと。 2) ソースワークスペースが正常に適用(apply)されていること。 3) ワークスペースの出力が正しく共有されていること。"
  }
}

resource "google_compute_instance" "this" {
  project        = var.project_id
  name           = "${var.app_name}-instance-1"
  machine_type   = var.machine_type
  zone           = var.zone
  tags           = concat(var.tags, ["iap"])
  can_ip_forward = false
  metadata = {
    enable-oslogin         = var.enable_oslogin ? "TRUE" : "FALSE"
    block-project-ssh-keys = true
    serial-port-enable     = false
  }

  boot_disk {
    initialize_params {
      image = var.boot_disk_image
    }
  }

  network_interface {
    subnetwork = data.tfe_outputs.vpc.values.subnet_self_link
    # 外部IPを付与しない
  }

  shielded_instance_config {
    enable_secure_boot          = true
    enable_vtpm                 = true
    enable_integrity_monitoring = true
  }

  service_account {
    email  = data.tfe_outputs.sa.values.email
    scopes = ["cloud-platform"]
  }

  dynamic "scheduling" {
    for_each = var.enable_spot_vm ? [1] : []
    content {
      provisioning_model          = "SPOT"
      preemptible                 = true
      instance_termination_action = "STOP"
      automatic_restart           = false
      on_host_maintenance         = "TERMINATE"
    }
  }
}
variable "project_id" {
  description = "リソースを作成するGCPプロジェクトのID。"
  type        = string
}

variable "zone" {
  description = "GCEインスタンスを作成するゾーン。"
  type        = string
  default     = "asia-northeast1-b"
}

variable "app_name" {
  description = "GCEインスタンスなどのリソース名に使われるアプリケーション名。"
  type        = string
  validation {
    condition     = can(regex("^[a-z]([-a-z0-9]*[a-z0-9])?$", var.app_name))
    error_message = "app_nameは、先頭を小文字にし、以降は小文字、数字、ハイフンのみ使用できます。末尾にハイフンは使えません。"
  }
}

variable "machine_type" {
  description = "GCEインスタンスのマシンタイプ。"
  type        = string
  default     = "e2-micro"
}

variable "sa_workspace_name" {
  description = "サービスアカウントのメールアドレスを含むHCP Terraformワークスペース名。"
  type        = string
  default     = "ワークスペース名(要置換)"
}

variable "enable_spot_vm" {
  description = "trueの場合、GCEインスタンスをSpot VMとして作成します。"
  type        = bool
  default     = false
}

variable "enable_oslogin" {
  description = "trueの場合、インスタンスでOSログインを有効にします。"
  type        = bool
  default     = true
}

variable "hcp_organization" {
  description = "HCP Terraformの組織名。"
  type        = string
  default     = "組織名(要置換)"
}

variable "vpc_workspace_name" {
  description = "サブネット情報を持つHCP Terraformワークスペース名。"
  type        = string
  default     = "ワークスペース名(要置換)"
}

variable "tfe_hostname" {
  description = "Terraform Enterprise/Cloudのホスト名。"
  type        = string
  default     = "app.terraform.io"
}

variable "boot_disk_image" {
  description = "起動ディスクに使用するイメージ。"
  type        = string
  default     = "debian-cloud/debian-11"
}

variable "tags" {
  description = "インスタンスに適用するネットワークタグのリスト。"
  type        = list(string)
  default     = []
}
output "instance_name" {
  description = "The name of the GCE instance."
  value       = google_compute_instance.this.name
}

output "internal_ip" {
  description = "The internal IP address of the GCE instance."
  value       = google_compute_instance.this.network_interface[0].network_ip
}

output "external_ip" {
  description = "The external IP address of the GCE instance."
  value       = length(google_compute_instance.this.network_interface[0].access_config) > 0 ? google_compute_instance.this.network_interface[0].access_config[0].nat_ip : null
}

ステップ2:変数の全開放と、疎結合特有のめんどくささ(迷走期)

「ワークスペース側で上書きさせるのがダメなら、最初からノーコード画面でスペックやディスクサイズを自由に入力・変更できるように変数をたくさん開放すればいいじゃないか」と、自由度を上げる方向に舵を切ってみました。しかし、これが次の罠を生みます。

  • インフラ非専門家には難しすぎる: インフラに詳しくない開発者に「マシンスペックはどうしますか?」「ディスクサイズは?」と自由入力させると、タイポやルール違反が多発し、そもそも「迷わず安全に作れる」というノーコードの価値がブレてしまいました。
  • 疎結合ゆえの隠れた壁: さらに、今回はマルチワークスペース型なので、別ワークスペースにあるサブネットを参照するために「HCP TFの組織名(Organization)」や「参照先ワークスペース名」の入力まで開発者に求められる構成になっていました。アプリ開発者からすれば「インフラ側のワークスペース名なんて知るか!」という話で、これではセルフサービス化のハードルが高すぎます。

そのため、管理者が「組織名」や「参照先ワークスペース名」などのインフラ都合の変数は、すべてコード側の default 値に仕込んで画面から完全に隠蔽する決断をしました。

ステップ3:最終着地点。日本語の選択肢で包み込む「おまかせ設計」

試行錯誤の結果、「固定できるものは極力固定する」というガバナンスを敷きつつ、開発者が直感的に選べる「わかりやすい日本語の変数から、コード側で各パラメータにマッピングしてセットする」というアプローチに辿り着きました。

最終的に、開発者が画面で入力・選択する項目を以下の4つだけに絞り込みました。

  1. app_name(自由記述): 名前のバッティングを避けるための、唯一の自由入力項目。これがそのままVMインスタンス名になります。
  2. machine_type(ドロップダウン):n2-standard-2 のようなクラウドの型番を直接記述させるのではなく、Variable Options機能を使って、以下のような直感的な日本語の選択肢を用意しました。
    • おまかせ(コスト重視)
    • おまかせ(バランス)
    • おまかせ(安定性重視)
    • (その他、事前にプラットフォームチームが検証・ピックアップした特定の型番(n2-standard-2 など))
  3. enable_spot_vm(ドロップダウン / True or False): machine_type特定の型番(n2-standard-2 など)を選択した場合のコスト最適化の選択肢として、「SPOT VM」を有効化するかどうかも画面から選べるようにしました。
  4. premission_level(ドロップダウン): CIS v8準拠のためのサービスアカウント(SA)の権限設定も、開発者にIAMロールを選ばせるのではなく、用途に合わせた選択肢を提示します。
    • 最小限(デフォルト)
    • Webサーバー用
    • データ処理ワーカー
    • 管理・オペレーション用踏み台サーバー
    • CI/CDランナー

⚙️ 【こだわり検証】裏側で仕込んだ「おまかせ優先」の条件分岐ロジック

ここでプラットフォームチームとしてひと工夫加えたのが、「machine_type で何を選んだかによって、スポットVMの挙動を自動制御する」という裏側のコード設計です。

ノーコード画面でユーザーが自由に組み合わせを選べるようにすると、「おまかせ(安定性重視)」を選んでいるのに「スポットVM=True(いつ落ちるか分からない)」という、矛盾したちぐはぐな設定で申請されてしまうリスクが生じます。

そこで、コード側に以下のような条件分岐を仕込みました。

  • 「おまかせ系」が選択された場合: ユーザーが画面でスポットVMを「有効」にしていたとしても、コード側でそれをスルーし、「おまかせ設定(あらかじめ管理者が決めた安定性・コストの基準)」を強制的に優先させて上書きします。
  • 「特定の型番(n2-standard-2 など)」が選択された場合: ユーザーが指定したスペックへのこだわりを尊重し、画面で選んだ「スポットVMを有効化する」という意思表示がそのままクラウド側に反映されるように連動させます。

💡 検証のまとめ:管理者の「仕込みの優しさ」が光る結果に

この構成にしたことで、インフラに詳しくない開発者でも「名前を決めて、用途(おまかせ)を選んで、ポチるだけ」で、裏側のVariables画面で上書きなんてややこしい操作をすることなく、CIS v8に準拠したセキュアで最適なスペックのVMが安全にデプロイされる環境が整いました。

変数をただ開放したり、後から上書きさせたりするのではなく、「日本語の選択肢で優しく包み込み、矛盾した設定は裏側のコードで綺麗に制御(翻訳)してあげる」という、プラットフォームチームの仕込みの優しさ(設計力)こそが、No-Code Provisioningを成功させる最大の鍵だと痛感させられる検証結果となりました。

3.3. パターン②(オールインワン型)の検証:一発展開の快適さと「CIDR設計」の壁

続いて、ネットワークからサービスアカウント、VMインスタンスまでを1つのモジュール内で芋づる式に丸ごと生成する「パターン②:オールインワン(密結合)型」の検証結果です。

マルチワークスペース型での試行錯誤を踏まえ、こちらもインフラ非専門家である開発者が迷わないUIを目指して仕込みを行いました。

【検証】開発者の入力項目とUI

このパターンで開発者がノーコード画面で入力・選択する項目は、最終的に以下の3つだけに絞り込みました。

  1. app_name(自由記述): すべての器のベースとなる名前。これがVM名、VPC名、SA名のプレフィックス(接頭辞)に動的にマッピングされます。
  2. machine_type(ドロップダウン): パターン①のステップ3と同様に、「おまかせ(コスト重視)」「おまかせ(バランス)」などの日本語の選択肢から選ばせる形を流用しました。
  3. subnet_ip_cidr_range(自由記述): 新しく切り出す専用サブネットのIP範囲(例: 10.0.1.0/24)を入力するテキストフォームです。
⭕ メリット:究極のスタンドアロン環境と「ゴミが残らない」美しさ

実際に動かしてみて再認識したのが、他との依存関係が一切ない「完全自己完結型(スタンドアロン)」としての圧倒的な手軽さです。

  • 他ワークスペースへの依存がゼロ: パターン①のように、プラットフォームチームの事前準備(Outputsの共有設定など)を待つ必要がありません。開発者が思い立った瞬間にボタンをポチるだけで、自分だけの独立したクリーンな検証インフラ環境が綺麗に立ち上がります。
  • 削除(Destroy)時にゴミが残らない: 検証が終わり、開発者がワークスペースを削除すると、VMだけでなくVPCもサービスアカウントも丸ごと根こそぎ消え去ります。「VMだけ消して、作成したVPCや野良SAがクラウド上にポツンと残って課金やセキュリティの肥やしになる」といったインフラ管理者お馴染みの頭痛の種が、物理的に発生しないのは最高に美しい挙動です。
  • 名前のバッティングは綺麗に回避: 「同じプロジェクト内で同じモジュールを使ったら、リソース名が重複してエラーになるのでは?」という懸念も、すべてのリソース名に app_name の変数を変数展開で組み込むようにコード側で仕込んでおいたため、完全に回避できました。
❌ デメリット・直面した課題:自由記述のCIDRはバッティングしやすい

しかし、このオールインワン型にも、運用を考えると無視できない「惜しい壁」が立ちはだかりました。それが subnet_ip_cidr_range(サブネットのCIDR範囲)の指定 です。

  • インフラ未経験者に「CIDRを入力しろ」は酷である: いくらノーコード化しても、画面に「サブネットのCIDRを入れてね」とテキストボックスが空欄で置いてあると、インフラに詳しくない開発者は迷ってしまいます。
  • 同じプロジェクト内での「サブネット重複」エラー: さらに致命的なのが、Google Cloudの同じプロジェクト内でこのモジュールが複数立ち上がる際、開発者が適当に手入力したIP範囲(10.0.0.0/16とか指定されると。。)が、他の人がすでに作ったサブネットと重複してPlanやApplyでエラーになるという問題です。これでは結局、「空いているIP帯をインフラチームに聞いてから入力する」という手戻りが発生し、完全なセルフサービス化のブレーキになってしまいます。

管理者の次なる一手:サブネット帯も「選ぶだけ」に仕込む

この課題に対するプラットフォームチームとしての改善案(仕込みの工夫)は、やはりテキスト入力を撲滅することです。

CIDRも自由記述にさせるのではなく、あらかじめプラットフォームチーム側で「開発検証用として使っていい社内ネットワークの空き帯域」をいくつかピックアップ(例:10.100.1.0/24, 10.100.2.0/24, 10.100.3.0/24…)し、「使いたいネットワークの番号をリストから選ぶだけ」のドロップダウンUIに仕込んであげるのが、このオールインワン型を実務で成功させるための「最後のピース」だと感じました。


4. まとめ:実務におけるNo-Codeモジュールの「理想の境界線」

今回はシンプルなVMインスタンスをベースに、疎結合(パターン①)と密結合(パターン②)の2つのアプローチで No-Code Provisioning の挙動を検証してきました。

単体のVMを動かすだけでも多くの仕込みのコツが見えてきましたが、この機能を実務で120%活かすための「設計の結論」が見えてきたので、最後にまとめとして考察を残しておきます。

本領発揮は「特定のユースケース」に特化させたとき

今回は1台のVMインスタンスをターゲットにしましたが、公式ドキュメントの Module Design(Build for a specific use case)にもある通り、本来この機能は「Web3層構造(フロント・アプリ・DB)を丸ごとまとめて一発展開する」といった、特定のユースケースに特化した塊で提供したときに最大の効果を発揮します。

開発者が「検証用のWebアプリ環境がひとつ欲しい」となった際、サーバーやデータベースのコードをそれぞれ個別にポチポチ申請させるのではなく、「一般的なWeb3層スタック」としてパッケージ化して提供してあげるのが、セルフサービス化の理想形です。

現場目線で感じた、リアルな「モジュールの境界線」

では、どこからどこまでを1つのノーコードモジュールに詰め込む(密結合にする)のが正解なのでしょうか? 今回の検証を通じて、筆者が実務の落としどころとして最適だと感じた「理想の境界線」がこちらです。

📦 1つのノーコードモジュールに「まとめて」入れていいもの

  • GCEインスタンス(アプリケーションサーバー)
  • Cloud SQL(データベース基盤)
  • Load Balancer(LB / 負荷分散・エンドポイント)
  • 上記それぞれに紐づく「専用サービスアカウント(SA)」

アプリケーションの構成要素や、それに直結する最小権限のSA、フロントのLBなどは、用途(ユースケース)に応じてスペックや増減が変わるため、1つのテンプレートにまとめて一括生成・一括削除(Destroy)できるようにするのが圧倒的に便利です。

🛠️ プラットフォームチームが「事前に」作っておくべきもの

  • VPCネットワーク
  • 各種Firewallルール(セキュリティの共通壁)

一方で、パターン②の検証で「CIDRのバッティング問題」に直面したように、ネットワークの根幹や、会社全体のセキュリティポリシーを司るFirewallルールなどは、ノーコード側で毎回切り出すべきではありません。 これらはプラットフォームチームがあらかじめ共通基盤として安全に構築(事前準備)しておき、開発者はノーコード画面から「それらを参照して乗っかるだけ(パターン①の構成)」にするのが、ガバナンスと利便性を両立させるベストプラクティスだと感じました。

最後に

No-Code Provisioningは、ただ開発者を楽にさせるためのツールではありません。 「ここまでは自由に使っていいよ、でもここから先は管理者が守っているからね」という安全な境界線をコードとUIで表現し、開発チームとインフラチームの距離を縮めるための強力な架け橋です。

変数の隠蔽や日本語のマッピングなど、プラットフォームチームのちょっとした「仕込みの優しさ」次第で社内のIaC推進スピードが劇的に変わりますので、Premiumプランを導入された際はぜひガッツリと仕込んでみてください!


💡 おまけ:検証を通じて見えてきた「仕込みのノウハウ&Tips」

今回のマルチワークスペース型やオールインワン型など、すべての検証を進めていく中で、プラットフォームチームがNo-Codeモジュールを仕込む際に「ここを意識すると一気にクオリティが上がる!」と感じた実践的なTipsをまとめました。これから設計される方はぜひ参考にしてください。

  • description は「開発者ファースト」の優しい表現に変える
    いつものインフラエンジニア向けに書く「The ID of the project」といった無機質な英語の解説はNGです。ノーコード画面では、この記述がそのままユーザーへのヘルプテキスト(注釈)になります。「GCPのプロジェクトIDを入力してください(例: hoge_fuga-dev)」のように、日本語で、かつ具体的な入力例まで添えてあげるのが、ユーザーを迷わせないための優しさです。
  • 利用者の「インフラ習熟度」に合わせて入力項目をデザインする
    「どこまで変数を隠蔽して、どこからドロップダウンで選ばせるか」の正解は、利用する開発チームのスキルセットによって変わります。全くインフラが分からないチームなら今回のように「おまかせ(3項目)」で包み込むのがベストですし、少し知識があるチームならマシンスペックだけ直接型番を選ばせるなど、相手に合わせてカスタマイズ(チューニング)する設計力が求められます。
  • validation ブロックでエラー時の案内まで優しく設計する
    No-Code Provisioningに限った話ではありませんが、変数には validation ブロックを積極的に仕込んでおくのがおすすめです。万が一開発者がルール外の値や不適切な形式を入力してしまった場合でも、Plan実行時に「何がダメで、どう修正すべきか」を分かりやすい日本語メッセージで伝えてあげることで、無用な躓きや管理者への問い合わせを未然に防ぐことができます。
  • 【超マニアックTips】並び順を制御するために変数名に「採番」を仕込む
    検証中に気づいた最大の盲点が、HCP Terraformの画面上では変数の入力項目が「変数名(Variable Name)のアルファベット昇順」で強制的に並んでしまうという仕様です。 何も考えずに project_idapp_name と定義すると、画面上では app_name が一番上にきてしまいます(本当はプロジェクトIDを最初に選ばせたいのに!)。 これを綺麗に制御するために、コード側で 01_project_id02_app_name03_machine_type のようにあえて変数名の頭に番号を振って採番しておく工夫をすると、画面の入力フローが劇的に美しく整います。

5. 次回予告:コンソールから勝手に弄った奴は誰だ

無事に安全なインフラが自動生成されて万々歳……とはいかないのが運用のリアル。インフラが立ち上がった後、管理者を待ち受ける最大の恐怖が「開発者がコンソールから良かれと思って手動で設定を変えてしまう」という野良変更(ドリフト)です。

コードと実環境の乖離は、セキュリティホールや謎のエラーの温床になります。というわけで、次回の「にこぷす通信」第4回は、インフラの「勝手な変更」を仕組みで解決するこちらのテーマをお届けします!

【第4回】コンソールから勝手に弄った奴は誰だ。ドリフト検知で「野良変更」は許さないよ

手動で加えられた「内緒の変更」をHCP Terraformがどのように自動で嗅ぎつけ(ヘルスチェック)、どうやって自動修復(Remediation)していくのか。Health Checks(ドリフト検知)機能の実力をガッツリ検証します。次回もお楽しみに!

「にこぷす通信」について

「NIC × Ops(にこぷす)通信」は、隔週で皆さまに情報をお届けします。
このシリーズでは、Instana(可観測性)をはじめ、Turbonomic(リソース最適化)やTerraform(インフラ自動化)など、IT運用を劇的に変える製品をピックアップしていきます。
これからも最新の技術検証をチームで継続し、皆さまの現場ですぐに役立つ「有益な知見」を全力で共有していきます。 次回の連載もお楽しみに!

ページのトップへ