Terraform は required_providers のバージョン制約で「許容範囲」を宣言し、.terraform.lock.hcl で「実際に使う厳密なバージョン」を固定します。両者の役割を正しく分けると、CI での偶発的なアップグレードを防ぎつつ、計画的な更新が可能になります。
本稿では制約の書き方、ロックの更新タイミング、CI/チーム運用のコツ、エラー時の対処をまとめ、Associate 試験で問われがちなポイントを明確にします。
required_providers は「どのプロバイダを、どのソースから、どのバージョン範囲で許可するか」を宣言します。これはあくまで範囲指定であり、厳密な単一バージョンの固定ではありません。
.terraform.lock.hcl は terraform init 実行時に作成/更新され、実際に選ばれた厳密なバージョンとチェックサムを固定します。ロックが存在する限り、通常の init はロックの内容を優先し、勝手なアップグレードは行いません(アップデートは -upgrade を明示)。
チームでの再現性を担保するには、ルートモジュールの .terraform.lock.hcl を VCS にコミットします。再利用目的の公開モジュールではロックファイルを含めないのが一般的です。
| 要素 | 定義場所 | 主な役割 | 試験での要点 |
|---|---|---|---|
| required_providers | terraform ブロック内 | プロバイダのソースと許容バージョン範囲を宣言 | 制約は範囲指定。~> の意味を正確に把握 |
| version(制約) | required_providers の version 文字列 | インストール候補を絞り互換性境界を明示 | ~>1.2 は <2.0、~>1.2.3 は <1.3 を許可 |
| .terraform.lock.hcl | 作業ディレクトリ(ルート) | 選定済みの厳密バージョンとプラットフォーム別チェックサムを固定 | ロックはコミット。更新は -upgrade または providers lock |
| terraform init / -upgrade | CLI | ロックを尊重して初期化。-upgrade で制約内の最新へ更新 | 通常 init は勝手に上げない。更新は明示的に行う |
最小構成例(制約とロックの関係)
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0" # 5.x のみ許可(制約)
}
}
}
# 初回: terraform init で最新の 5.x が選定され、.terraform.lock.hcl に固定
# 以後: terraform init はロックを優先。更新したい時だけ terraform init -upgrade制約は SemVer に基づき、演算子で範囲を定義します。~> は悲観的制約で、指定桁より上位の変更を拒否します。メジャーの上げ止まりを効かせ、パッチ/マイナーの取り込みを許可するのに有効です。
制約を厳しくしすぎるとアップグレードが困難になり、緩すぎると予期せぬ破壊的変更を招きます。チームでは基本方針(例: メジャーロック、マイナー可)を決めて統一しましょう。
代表的な制約パターン
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0" # 5.x の最新を許可
}
azurerm = {
source = "hashicorp/azurerm"
version = ">= 3.80, < 4.0" # 明示的な範囲指定
}
google = {
source = "hashicorp/google"
# version を省略: 制約なし(ロック無ければ最新版が選定)
}
github = {
source = "integrations/github"
version = "= 6.3.0" # 完全固定(推奨は範囲)
}
}
}
# 注意: 制約を変更して、ロックに記録されたバージョンが範囲外になると、
# 次回 init でエラーになり、-upgrade の実行が求められます。.terraform.lock.hcl は、選ばれた各プロバイダの厳密なバージョンと、各プラットフォームごとのチェックサムを保持します。これにより再現性の高い init が可能になります。
通常の terraform init はロックに記録された版を優先し、制約範囲内でも勝手に更新しません。更新したい場合にだけ terraform init -upgrade を用います。複数 OS/アーキで動かす場合は terraform providers lock -platform を使って、対象プラットフォームのチェックサムを事前に追加しておくとよいでしょう。
init 時の意思決定フロー(制約・ロック・レジストリ)
ロックの更新と複数プラットフォームのチェックサム追加
# 制約内で最新に更新してロックを書き換える
terraform init -upgrade
# CI/複数OS向けに事前にチェックサムを追加
terraform providers lock \
-platform=linux_amd64 \
-platform=darwin_arm64 \
-platform=windows_amd64
# 変更後は .terraform.lock.hcl をコミット日常の CI では通常の terraform init を使い、ロックに従って計画/適用を行います。定期的なメンテナンスジョブでのみ -upgrade を使い PR を作ることで、安全に更新を取り込めます。
社内ネットワーク/エアギャップ環境では、CLI 設定ファイルの provider_installation でミラーを優先し、必要に応じて特定プロバイダの直接ダウンロードを禁止して再現性を高めます。
CI 例(通常パイプラインと週次アップグレード)
# 通常パイプライン
terraform init -input=false
terraform validate
terraform plan -input=false
# 週次のアップグレードジョブ(別ブランチで実行)
terraform init -upgrade -input=false
# ここで .terraform.lock.hcl のみ変更されることを確認し、PR 作成
git add .terraform.lock.hcl
git commit -m "chore: upgrade providers within constraints"
# push → CI で plan を確認
# ミラー設定(~/.terraformrc または terraform.rc)
provider_installation {
filesystem_mirror {
path = "/opt/terraform/providers" # 事前にミラー同期
}
direct {
exclude = ["hashicorp/aws"] # aws はミラー必須。見つからなければ失敗
}
}制約とロックの不一致や、プラットフォーム追加時のチェックサム不足で init が失敗することがあります。エラーメッセージを読み、制約調整または -upgrade、providers lock のいずれが必要かを切り分けます。
ネットワークやミラー設定の不整合でも取得に失敗します。source アドレスの誤りやミラーに該当版が無い、といった基本的な点も見直してください。
状況別のコマンド例
# 制約を保ったままロックを更新
terraform init -upgrade
# 新規プラットフォームをロックへ追加
terraform providers lock -platform=linux_arm64
# 制約の見直し例(メジャーを上げる)
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 6.0" # 5.x → 6.x へ移行する場合
}
}
}
# その後に init -upgrade を実行試験では、制約とロックの役割分担、~> の意味、init と -upgrade の使い分け、ロックファイルのコミット方針が頻出です。言い換え問題にも対応できるよう、キーワードで覚えておくと取りこぼしが減ります。
最小の暗記スニペット
terraform {
required_providers {
aws = { source = "hashicorp/aws", version = "~> 5.0" }
}
}
# init: ロック尊重 / init -upgrade: 制約内で更新
# ロックはコミットして再現性を担保Associate
問題 1
チームは AWS プロバイダでメジャーバージョン 5 を維持しつつ、日常の CI で予期せぬ更新を避けたい。ただし月に一度は 5.x の最新へ計画的に更新したい。最も適切な運用はどれか。
正解: A
制約で 5.x に範囲を絞り、ロックをコミットして再現性を担保。通常の init ではロックを優先し、-upgrade でだけ制約内最新を取り込み、レビュー可能な PR を作るのが最適。B は更新が手作業で非効率、C は再現性がなく不安定、D は CLI バージョンの制約でありプロバイダ管理ではない。
.terraform.lock.hcl はコミットすべきですか?
はい。ルートモジュールでは再現性のためにコミットするのが推奨です。他者が利用する再利用モジュール(公開モジュールなど)では、利用者側のルートでロックされるため、通常ロックファイルは含めません。
メジャーをまたぐアップグレードはどう進めますか?
required_providers の制約を新メジャーを許す形(例: ~> 6.0)に変更し、terraform init -upgrade を実行してロックを更新します。各プロバイダのリリースノートを確認し、plan の差分をレビューしてから適用します。
複数の OS/CPU で CI を回す場合の注意点は?
terraform providers lock -platform を使って対象プラットフォームのチェックサムを事前にロックへ追加し、.terraform.lock.hcl をコミットします。レジストリへ直接出られない環境では、CLI 設定ファイルの provider_installation でミラーを優先する構成にします。
NicheeLab編集部
データエンジニアリング・クラウド資格の専門家。Databricks・Snowflake等の認定資格を保有し、実務経験に基づいた問題作成・解説を行っています。NicheeLab運営。
Terraform HCL 構文の基礎:Block / Attribute / Expression を正しく使い分ける
Terraform Associate で頻出の HCL 構文を、ブロック・属性・式の3視点で整理。実務で迷いがちな書き...
Terraform Authoring & Ops Pro: 上位資格の範囲と対策
上位レベルを想定したTerraformの設計・運用ドメインを整理し、実務で通用する対策を提示。モジュール設計、ステート運...
Terraform Providers の基本: プラグイン型アーキテクチャを正しく使いこなす
Associate レベルで押さえるべき Provider の基礎、インストール、バージョニング、認証、エイリアス運用を...
Terraform Resourceブロック徹底ガイド: 最小単位のリソース定義
Associateレベルで押さえるべきResourceブロックの構造、依存関係、メタ引数、ライフサイクル制御を実務目線で...
Terraform Data Source徹底理解:既存リソースの参照で壊さず足す
Terraform Associate向けに、Data Sourceを用いた既存リソース参照の基本、選択基準、評価順序、...