Terraformでインフラをコード管理してよかったこと
結論
- 変更差分を事前に把握でき、安心して適用できるようになった
- PRレビューで意図を共有でき、チームやAIにも相談しやすくなった
- 誤操作を避けつつ、問題時は確実に戻せるという安心感が生まれた
- 検証の再現性が上がり、学習と改善の速度が上がった
この結論の通りでしかないのですが、もう少し詳しく書いてみたので時間がある方は続きも読んでみてください。最後に簡単ですが導入手順の例も書いてみました。
前提・環境
対象は既存の Azure 環境で、これをコード管理に移行しました。構成は App Service が4つあり、各サービスに slot を2つ、さらに Application Gateway、Redis、Storage などを含む中規模構成で、リソース数が多く運用の手間がかかっていました。Azure ポータルでは「どこを変えると何が変わるか」を追いづらく、設定が戻る・見落とすといった不安が常にありました。
よかったこと
その1. 変更差分を事前に把握できて安心
terraform plan のコマンドで「どのリソースの、どの属性が、どう変わるか」を明示的に確認できます。意図した差分だけを適用できるため、「他のリソースも巻き込んでいないか」の不安が減りました。想定外の変更が出たら、その場で止まれるのも良かったです。
その2. PRレビューで意図を共有しやすい
コードなのでPRでレビューできます。また、コード内にコメントで「設定の意図」「参考リンク」「判断理由」などを残すことができるのも良いです。
その3. AIに相談しやすい
現状の設定を正確にAIに共有できます。コンソール前提だと、画面遷移や設定項目を文章やスクショで説明する必要があり、情報はどうしても抜けやすいです。また、AIからは「こう設定して」のような指示だけが返りがちで、実際の設定変更までは到達しません。コード管理なら、AIにそのままモジュールやリソース定義を渡せるので、具体的な差分や修正案(PRレベルの提案)まで返ってきます。その提案をレビューして即コミット・適用でき、往復の手間が大きく減りました。
その4. 誤操作を防ぎ、確実にロールバックできる
ポータルの手作業と比べて、誤クリックで設定が変わるリスクが減りました。問題があってもGitの履歴から「以前の状態」に戻せるため、復旧の方針を取りやすいです。
その5. 検証の再現性が高まり、学習が進む
検証環境で設定のトライアンドエラーをしたとき、どの変更が挙動に効いているかを追いやすく、一歩ずつ前進している実感が持てました。ポータル運用だと「なぜ上手くいったか」が曖昧になりがちですが、コードなら変更点が明確です。
その6. 複数環境の整合性を保ちやすい
slotを含む複数環境でも、変えてよい差分と共通化すべき部分をコードで整理できます。変数・locals・モジュール等で表現できるため、環境間のブレが減りました。今回はslotを含めると12環境あるため、各環境の比較をするのが大変だったのですが、コード化されたことで、差分は変数とlocalsに寄せ、共通部分はモジュールに閉じ込めるといった対応ができました。結果として12環境を横並びで目視比較する作業がほぼ不要になりました。
おわりに
手で触っていた頃よりも、安心して変更できるようになりました。導入は少し手間でしたが、運用フェーズの心の負担が目に見えて減ったので、やってよかったなと思います。Terraform はさまざまなインフラサービスに対応しているので、今後環境を構築する際は、まず Terraform の導入を検討したいです。
おまけ: Azureの場合の導入例
1. Azure にログインする
ローカルから操作する場合、Terraform の AzureRM Provider は Azure CLI の認証情報を利用します。事前にサインインし、対象サブスクリプションを選んでおくことで、この後行う import や plan が Azure のAPIへ正しくアクセスできます。
az login
az account set --subscription "<subscription-id>"
2. AzureRM Provider の設定
AzureRM Provider の宣言を置きます。場所はルートモジュール(main.tf と同じディレクトリ)で、ファイル名は任意です。慣習的に versions.tf と providers.tf に分けることが多いようです。
terraform {
required_providers {
azurerm = {
source = "hashicorp/azurerm"
# version はプロジェクト方針に合わせて固定
}
}
}
provider "azurerm" {
features {}
}
3. Terraformを初期化する
terraform init
4. 管理対象のリソースを決め、仮コードを書く
この次に行う import では、Terraform の state と実体リソースを「どのリソース定義にひも付けるか」を示す必要があります。先に仮コード(リソースブロックやモジュール呼び出しの雛形)を置いておくと、リソースアドレスが確定し、import が通ります。
仮コードの例: App Service の雛形
resource "azurerm_app_service" "example" {
name = var.app_service_name
resource_group_name = var.resource_group_name
location = var.location
app_service_plan_id = var.app_service_plan_id
}
5. 既存リソースを import する
# 例: App Service を取り込む(subscription idなどは自分の環境のものに置き換え)
terraform import azurerm_app_service.example "/subscriptions/<sub>/resourceGroups/<rg>/providers/Microsoft.Web/sites/<name>"
6. terraform plan が no changes になるまでコードを整える
terraform plan
差分が出なくなっていれば、現状の状態を Terraform コードで正しく表現できています。以降は安心して設定変更を進められますし、管理対象のリソースや設定を追加することも可能です。
Discussion