GitHub Copilot で始める Terraform
はじめに
オンプレ技術者であった自分がクラウド担当部署の配属になって、環境構築で IaC (Infrastructure as a Code) を使うようになりました。
クラウド担当部署なので自分の周りにはクラウド エキスパートが大勢いますし、質問すれば色々と教えてくれることとは思いますが、あまりに質問が多くても彼らの時間を奪うことにもなります。
自分で調べるとなると各種公式 Web や Qiita のような技術ブログを活用したりしていますが、参考記事は見つかっても、そこから更に自分の環境や要件に合わせた具体的なコードに落とし込むまでに意外と時間がかかります。
そこで有能な助手を得るべく、会社にお願いしました。
「GitHub Copilot を使わせて!」と。
この記事について
この記事では、GitHub Copilot を活用して Terraform コードを生成し、Azure インフラストラクチャを管理する方法を紹介します。Terraform の基本的な知識があることを前提としていますが、初心者でも理解できるようにステップバイステップで説明します。
GitHub Copilot は IaC 初心者にも役立つということの参考になれば幸いです。
Visual Studio Code の設定
準備
Windows 11 環境で Terraform を記述するための環境を準備します。
ツールとしては、Visual Studio Code、Terraform および Azure CLI を使用します。
まずは、Visual Studio Codeをインストールします。ブラウザで vscode download のように検索すれば簡単に見つけられます。
Terraform と Azure CLI は winget でインストールするのが簡単です。
# PowerShell
winget install Hashicorp.Terraform
winget install Microsoft.AzureCLI
メモ: この記事では実際の展開は行いません
プロジェクト用フォルダーを作成し VSCode を起動します
# PowerShell
md C:\git\pj001
cd C:\git\pj001
code .
VSCode 拡張機能
Azure 環境で便利に Terraform を使うためにいろいろ追加しておきます。
- Japanese Language Pack for Visual Studio Code
- HashiCorp Terraform
- Microsoft Terraform
- GitHub Copilot Chat
- GitHub Copilot for Azure
GitHub Copilot チャットの設定
VSCode 上部の「💬」アイコンでチャット ウィンドウを開き、Copilot のモードを設定します。
-
Agent モードにする
Agent モードにするとプロンプトに応じて直接ファイルを編集してくれます
Ask モードだと ChatGPT のようにチャットツールとして使えます -
Claude Sonnet 4.5
GPT 系より Claude Sonnet 系のほうがおしゃべり(色々書いてくれる)のようなので、自分のように入門者には良いように思いますが、お好みで。
providers.tf と variables.tf を作成
準備が整いましたので、さっそく Terraform プロジェクトのコードを書かせてみます。
まず、Terraform のおまじないとして以下のファイルを作ってもらいます。
-
providers.tf
Terraform プロジェクトにおいて Terraform のバージョン設定とプロバイダー(Azure などのクラウドサービス)の接続設定を定義する重要なファイル -
variables.tf
Terraform プロジェクトにおいて変数パラメータを定義するファイル
既定値を定義しておくことでそのまま展開に使用することもできますが、実環境に適用する場合には、別途terraform.tfvarsファイルに実際の値を設定します
Azure用のproviders.tfを作って だけでも作ってくれますが、いくつか条件を付けてみます。
意図としては、複数の Azure テナントやサブスクリプションが利用可能な環境または Terraform プロジェクトの再利用において、間違った環境に展開を行わないように subscription id および tenant id を定義しておくこと、そして変数で定義することによって再利用を容易にすることになります。
Azure用のproviders.tfを作って
- terraformのバージョンは1.14以上を指定する
- subscription idを指定する
- tenant idを指定する
- 変数はvariables.tfに定義する
✅ Created providerstf and variables.tf files
2つのファイルを作成します:providers.tfとvariables.tfです。
✅ Created providers and variables Terraform files
作成しました。
- providers.tf - Terraform 1.14以上を指定し、AzureRMプロバイダーを設定
- variables.tf - subscription_idとtenant_idの変数定義(両方sensitiveに設定)
変数の値は`terraform.tfvars`ファイルや環境変数で設定できます。
作成された providers.tf は以下のようになっていました。
terraform {
required_version = ">= 1.14"
required_providers {
azurerm = {
source = "hashicorp/azurerm"
version = "~> 4.0"
}
}
}
provider "azurerm" {
features {}
subscription_id = var.subscription_id
tenant_id = var.tenant_id
}
指示した通りに variables.tf ファイルが作成されており、変数はここに定義されています。
variable "subscription_id" {
description = "Azure Subscription ID"
type = string
sensitive = true
}
variable "tenant_id" {
description = "Azure Tenant ID"
type = string
sensitive = true
}
メモ: 実際の値は
variables.tfに直接記載せずに、terraform.tfvarsというファイルを作成して、そこに記述することになります。
terraform.tfvars(.example)については後述します。
リソースグループを作成
Azure リソースを格納するための箱(リソースグループ)を作成してもらいます
リージョンは、最初 japaneast だけ書いておいたらコードに直接埋め込まれてしまったので、「(変数で定義)」と追記しました。
リソース名は Microsoft 推奨になるように条件を付けました。
例を書いておくと、この後作成するリソースに対しても Copilot 側で色々察してリソース名を作成してくれるようになります。
リソースグループを作成する
- リージョンはjapaneast(変数で定義)
- リソース名は<リソース種類>-<プロジェクト>-<環境>-<リージョン>-<インスタンス>に従う
- 例
rg-qiitablog01-dev-jpe-001
- タグを作成する
リソースグループを作成しました。
- variables.tf - リージョン、プロジェクト名、環境、インスタンス番号、タグの変数を追加
- main.tf - 命名規則に従ったリソースグループを定義(例: rg-qiitablog01-dev-jpe-001)
変数のデフォルト値を変更したい場合はterraform.tfvarsファイルで上書きできます。
main.tf というファイルが新たに作成され、リソースグループを作成するコードが作成されています。
resource "azurerm_resource_group" "main" {
name = "rg-${var.project_name}-${var.environment}-${var.location_short}-${var.instance}"
location = var.location
tags = var.tags
}
メモ: 本記事では、自動作成される
main.tfファイル1つにすべてのリソースが作成されていますが、リソースの種類ごとにファイルを分けることもできます。例えば、事前にrg.tfというファイルを作成してそのファイルを開いた状態で「リソースグループを作成」と指示すれば、rg.tfにリソースグループのコードが生成されます。同様にnetwork.tf、vm.tfなどを作成することで、リソースごとにファイルを整理できます。
仮想ネットワークとサブネット
仮想ネットワークといくつかのサブネットを作成してもらいます。Firewall や Gateway などの専用サブネットには決まった名前を指定する必要がありますが、そのあたりは Copilot で分かってくれているでしょうということを期待して用途だけで指示します。
仮想ネットワークとサブネットを作成する
- Azure Firewallサブネットを作成する
- Gatewayサブネットを作成する
- Bastionサブネットを作成する
- VM用サブネット(vm001,vm002)を作成する
- 例
snet-<命名規則>-vm001
仮想ネットワークとサブネットを作成しました。
- 仮想ネットワーク: vnet-qiitablog01-dev-jpe-001
- Azure Firewallサブネット: AzureFirewallSubnet (10.0.1.0/24)
- Gatewayサブネット: GatewaySubnet (10.0.2.0/24)
- Bastionサブネット: AzureBastionSubnet (10.0.3.0/24)
- VM用サブネット:
- snet-qiitablog01-dev-jpe-vm001 (10.0.10.0/24)
- snet-qiitablog01-dev-jpe-vm002 (10.0.11.0/24)
Azure専用サブネット(Firewall、Gateway、Bastion)はAzureの予約済み名前を使用し、VM用サブネットは命名規則に従っています。
ちゃんと専用サブネットは決まった名前を使ってくれています。
ここで興味深いのは、仮想ネットワークの命名規則については指示していないのに Microsoft 推奨のリソース名をつけてくれているというところです。この後作成するリソースについても命名規則は指示しなくてもそれらしいリソース名にしてくれます。
# Virtual Network
resource "azurerm_virtual_network" "main" {
name = "vnet-${var.project_name}-${var.environment}-${var.location_short}-${var.instance}"
location = azurerm_resource_group.main.location
resource_group_name = azurerm_resource_group.main.name
address_space = var.vnet_address_space
tags = var.tags
}
# Azure Firewall Subnet
resource "azurerm_subnet" "firewall" {
name = "AzureFirewallSubnet"
resource_group_name = azurerm_resource_group.main.name
virtual_network_name = azurerm_virtual_network.main.name
address_prefixes = [var.subnet_address_prefixes["firewall"]]
}
# Gateway Subnet
resource "azurerm_subnet" "gateway" {
name = "GatewaySubnet"
resource_group_name = azurerm_resource_group.main.name
virtual_network_name = azurerm_virtual_network.main.name
address_prefixes = [var.subnet_address_prefixes["gateway"]]
}
# Azure Bastion Subnet
resource "azurerm_subnet" "bastion" {
name = "AzureBastionSubnet"
resource_group_name = azurerm_resource_group.main.name
virtual_network_name = azurerm_virtual_network.main.name
address_prefixes = [var.subnet_address_prefixes["bastion"]]
}
# VM Subnet 001
resource "azurerm_subnet" "vm001" {
name = "snet-${var.project_name}-${var.environment}-${var.location_short}-vm001"
resource_group_name = azurerm_resource_group.main.name
virtual_network_name = azurerm_virtual_network.main.name
address_prefixes = [var.subnet_address_prefixes["vm001"]]
}
# VM Subnet 002
resource "azurerm_subnet" "vm002" {
name = "snet-${var.project_name}-${var.environment}-${var.location_short}-vm002"
resource_group_name = azurerm_resource_group.main.name
virtual_network_name = azurerm_virtual_network.main.name
address_prefixes = [var.subnet_address_prefixes["vm002"]]
}
Network Security Group (NSG) とルートテーブル
NSG とルートテーブルを作成してもらいます。アプリケーション要件はこの時点では決まっていないという想定で規則などは無しのままで作成してもらいます。
VM用サブネット用に共通のNSGとルートテーブルを作成して
- NSG規則は不要
- ルート定義は不要
VM用サブネット向けの共通NSGとルートテーブルを作成しました。
- NSG: nsg-qiitablog01-dev-jpe-001-vm
- ルートテーブル: rt-qiitablog01-dev-jpe-001-vm
両方のリソースをsnet-qiitablog01-dev-jpe-vm001とsnet-qiitablog01-dev-jpe-vm002の両サブネットに関連付けています。
terraform.tfvars.example の作成
さて、これまでのリソース作成で必要な変数は variables.tf に定義されています。
実際の環境への展開は variables.tf を直接書き換えるのではなく、その環境用にterraform.tfvars ファイルを作成します。
terraform.tfvars を作成するためのサンプルファイルとして、terraform.tfvars.example というファイルを作成しておきます。
variables.tf と terraform.tfvars は書式が異なっており、内容の書き換えが非常に面倒です。
# variables.tf
variable "subscription_id" {
description = "Azure Subscription ID"
type = string
sensitive = true
}
variable "tenant_id" {
description = "Azure Tenant ID"
type = string
sensitive = true
}
...
# terraform.tfvars
subscription_id = "00000000-0000-0000-0000-000000000000"
tenant_id = "00000000-0000-0000-0000-000000000000"
...
これも Copilot にお願いしてみましょう。
GitHub Copilot では、プロンプトに #file:<filename> と記述することで、特定のファイルを参照した指示ができます。これにより、Copilot が指定したファイルの内容を理解した上で、それに基づいた適切なコードを生成してくれます。
今回の場合、variables.tf の変数定義を読み取って、それに対応する terraform.tfvars.example の形式(変数名 = "値")に自動変換してくれるため、手作業での書き換えが不要になります。
メモ: 複数のファイルを参照したい場合は
#file:file1.tf #file:file2.tfのように複数指定できます。
#file:variables.tf terraform.tfvars.exampleを作成して
- terraform.tfvars.example
を作成しました。
このファイルをコピーしてterraform.tfvarsとして使用し、実際の値(特にsubscription_idとtenant_id)を設定してください。
プロジェクトにリソースを追加して変数定義が増えた場合にも、もう一度指示すれば不足している分も追加してくれます。
重要: 実環境の設定値を記載した
terraform.tfvarsファイルは.gitignoreなどで除外して不用意に公開されないようにします。この記事では git による管理については記載しませんが、
terraform用の.gitignoreを作成してと指示すれば作成してくれます。
デプロイ
展開前に意図したようにコードが作成されているか全体を見直してください。
Copilot に不足している指示を追加したりしてもよいですが、手直ししたほうが早いケースもあります。Visual Studio Code には、Terraform コードを記述する際に有用な公式の拡張機能があり、プロパティの候補をアシストしたり、公式ドキュメントへのリンクを表示して詳細をすぐに調べたりもできます。
作成したコードを Terraform で実行します。
-
terraform.tfvars.exampleをコピーしてterraform.tfvarsファイルを作成します。 -
terraform.tfvarsに必要な設定値を記載します。
terraform plan で文法に問題がある場合にはエラーとなりますのでコードを見直します。Copilot はそれなりに高い精度でコードを生成してくれていますが、場合によっては存在しない属性や値を回答することがあります。
# Powershell
az login --tenant <your-tenant-id>
az account show
terraform init
terraform plan
terraform apply
メモ: この記事では実際の展開は行いません
まとめ
- プログラミングだけではなく、Terraform などの IaC 用にも GitHub Copilot は有効であることが分かると思います
- AI はコード入門者の補助にも役に立つということが分かると思います
-
terraform.tfvarsの作成のように、やることは分かっているのに手作業で対応するのが面倒な作業を精度よく任せることができます - 細かい修正を何が何でもプロンプトで指示して AI を躾けるよりも、手で直したほうが早いケースがあることを忘れてはいけません。手直ししたコードは同様の修正を行う場合に、Copilot が予測して修正候補をアシストしてくれたりします。
そのほかにも簡単に使えて便利な指示方法はあると思いますが、長くなりすぎるので機会がありましたら続編として書いていきたいと思います。
We Are Hiring!