Terraformのstate解析とimportブロック応用
stateは「コードと実物の対応表」
Terraform はコード(あるべき姿)と実際のリソースの間に、state という対応表を持ちます。
コード state 実リソース
aws_s3_bucket.logs → bucket-id: logs-9f2a1c → AWS上のS3バケット
plan が計算するのは「コードと state の差」ではなく、コード・state・実物の三者の差です。ここを取り違えると挙動が読めません。
- コードにあり state に無い → 新規作成しようとする
- state にあり実物が無い → 作り直そうとする(手で消された場合)
- 実物にあり state に無い → Terraform は存在を知らない(触らない)
最後のケースが、手作業で作られたリソースの状態です。放置すると、同じ名前で作ろうとして衝突したり、消したつもりが残り続けたりします。これを解消するのが import です。
importブロック
かつては terraform import コマンドで1件ずつ state へ登録していました。適用してみるまで結果が分からず、間違えると state を壊す危険がありました。
現在は import ブロックをコードに書く方式が使えます。
import {
to = aws_s3_bucket.logs
id = "logs-9f2a1c"
}
resource "aws_s3_bucket" "logs" {
bucket = "logs-9f2a1c"
}
利点は plan で結果を事前に確認できることです。取り込んだ結果コードと実物に差があれば、plan が「変更あり」として見せてくれます。差が出たらコード側を実物に合わせるのが原則で、逆にすると取り込んだ瞬間に本番が書き換わります。
さらに terraform plan -generate-config-out=generated.tf で、実物からリソース定義の雛形を生成できます。手で書き写す作業が減り、属性の書き漏らしも防げます。
大量のリソースを取り込む
数十〜数百件を手作業で書くのは現実的ではありません。実務では次の流れを組みます。
- クラウドのAPIやCLIで既存リソースを列挙する(タグやリソースグループで絞る)
- state を読み、既に管理下にあるものを除外する
- 残りから import ブロックを機械生成する
planを回し、差分が出た項目だけを人が確認する
state は JSON です。terraform show -json で機械可読な形が得られ、リソースの種類・アドレス・属性を取り出せます。state ファイルを直接編集してはいけません — 書式は内部仕様で、版によって変わります。読むのは可、書くのはコマンド経由が原則です。
stateそのものの運用
- 秘密情報が入る — DBのパスワードなどが平文で含まれることがあります。リポジトリに置かない。リモートバックエンド(S3 + 暗号化など)に置きます
- ロックが要る — 2人が同時に
applyすると state が壊れます。ロック機構のあるバックエンドを使います - 分割の単位を決める — 1つの巨大な state は
planが遅く、影響範囲も広くなります。環境・サービス単位で分けます - [[GitOps(Atlantis)]] と組み合わせる — 適用をPR経由に寄せると、誰がいつ state を動かしたかが追えます
初学者向けポイント
planのforces new resourceを必ず読む — 取り込み後の最初のplanで出たら、コード側が実物と食い違っているサインです。適用すると消えます- 取り込みは一度に全部やらない。種類ごとに小さく分けると、差分の確認が現実的な量に収まります
terraform state rmは state からの登録解除で、実リソースは消えません。逆にdestroyは実物を消します。この2つを取り違えると事故になります
関連技術とのつながり
- [[IaC]] — コードで定義する考え方。import は「後からコード管理下へ入れる」操作
- [[クラウドコンピューティング]] — 取り込む対象のリソース群
- [[GitOps(Atlantis)]] — 適用をPR経由に寄せ、state の変更を追跡可能にする
- [[CI/CD]] — 取り込み用の生成処理と
planを自動化する場所 - [[JSON Schema]] —
terraform show -jsonの出力を機械的に扱うときの考え方
Q: 「実リソースは存在するがstateに無い」状態でTerraformはどう振る舞う?
- [ ] 自動的に取り込む
- [ ] 削除しようとする
- [x] 存在を知らないため何もしない
解説: 放置すると同名で作ろうとして衝突したり、消したつもりが残り続けたりします。importで解消します。
Q: `terraform import` コマンドに対するimportブロックの利点はどれ?
- [x] `plan` で取り込み結果を事前に確認できる
- [ ] stateファイルが不要になる
- [ ] 実行が速くなる
解説: 適用前に差分が見えるため、コードと実物の食い違いを事前に直せます。
Q: 取り込み後の最初の `plan` で `forces new resource` が出たときの正しい対応はどれ?
- [ ] そのまま適用する
- [x] コード側を実物に合わせて書き直す
- [ ] stateファイルを直接編集する
解説: そのまま適用すると実リソースが作り直されます。stateの直接編集は書式が内部仕様のため禁じ手です。