🕍

Terraformをアップデートしたいそこのあなたへ

2021/09/11に公開

どうもこんにちは、Terraform初心者です。

...待ってください帰らないでください。

僕は確かにterraform初心者ですが、参加したインターンで5つほどのプロジェクトを最新(執筆時点では1.0.6)へアップデートしてきました。その際ハマったところや得られた知見について共有したいと思っています。

はじめに

今回僕が話せるのは0.11.x系以上からのアップデートになります。
それ以前のバージョンについてはこちらの記事では対応しかねますので悪しからず。。。

それでは、いきましょう!

準備確認

  • tfenv
  • .terraform-version ファイル

バージョンアップの際、バージョンを行ったり来たりすることもあるので、tfenvはマストだと思います!インストールはこちらから
.terraformは作業ディレクトリになければ作っておくと勝手にtfenvを切り替えてくれるので便利です。(〇〇env系のよくあるやつです)ちなみにこんな感じ↓

.terraform-version
0.12.29

0.11.x系から0.12.x系へのアップデート

コマンド系

バージョンを変えたときはterraform init --reconfigureとオプションをつけてあげないと怒られるので気をつけておきましょう!
それと0.12.xと0.13.xにはterraform 0.12upgradeterraform 0.13upgradeというtfファイルを書き換えてくれるコマンドがあるのでそちらも使います。

構文系

0.11 -> 0.12ではHCLのバージョンアップにより構文の変更が多くみられるかと思います。
多くはエラーや警告文などで解決できる(= 入れたり入れなかったり、ダブルクォートを外したり)のですが、listを求める場所で

list欲しいぜ = [ listその1, listその2 ]

のようになっている箇所ではHCL2では二重配列になっていてアウトになるので以下のように組み込みのconcatで結合すると解決したりしなかったりします。

list欲しいぜ = concat(listその1, listその2)

手順

改めて手順をまとめると以下のようになります。

  1. .terraform-versionを書き換える 0.12.29がおすすめ!
  2. terraform init --reconfigure
  3. terraform 0.12upgrade
  4. terraform plan [-var-fileの読み込みなど]

~~~ 一旦ここまで ~~~

  1. stateの書き換え

4までができれば勝ちです。
ちなみにここで意図しない差分が出たら注意しましょう!怖いなと思ったら該当箇所を一旦ignore_changesに入れちゃうのもありです(どの段階でignore_changesに入れたか覚えておきましょう、、、)。

resource "なんちゃら" "なんちゃら" {
...
  lifecycle {
    ignore_changes = [
      該当のもの,
      parameterなど
    ]
  }
}

さて手順5ですが、
A. リソースに変更を加えても大丈夫だからリソースも変更しながら進めたい!
B. リソースの変更は怖いのでstateファイルだけ書き換えたい
と二つのパターンがあるかと思います。

Aの場合はterraform apply [-var-fileなど...]
Bの場合はterraform refresh [-var-fileなど...]

を実行すれば良いです。applyrefreshでは、前者はtfstateの書き換えとリソースの変更を行うのですが、後者はtfstateの書き換えのみ行う(リソースに変更を加えない)という違いがあります。よしなに使い分けましょう。(適当)

0.12.29から0.13.1へのアップデート

0.12.x系から0.13.x系にアップデートしたい方こんにちは。
なんか見出しのバージョンが具体的になってると思った方がたくさんいるでしょう...
これは僕の推奨手順なので、我が道を行ってもらっても良いのですが、僕は他のマイナーバージョンを通ると失敗しました。
特に0.13.0に上げると毎回terraformがクラッシュしました😇

構文系

なんかあったかな?
list(any)はやめましょう。大体list(string)です。くらいかな?

コマンド系

基本的に0.12の際の手順をなぞっていく形になります。
terraform 0.13upgradeをするとversions.tfが知らない間に作られたりするかもしれないですが、気のいい奴なので消すなり、共存するなりしてください。

手順

  1. .terraform-versionを書き換える 0.13.1がおすすめ!
  2. terraform init --reconfigure
  3. terraform 0.13upgrade
  4. terraform plan [-var-fileの読み込みなど]
  5. terraform apply or terraform refresh

成功しましたか?
もしこんなエラーが出たあなた!これは「tfstateが古いので読み取れないよ」と言われています。
0.12.x系に上げた時にapplyrefreshはしましたか?してないですよね?バージョンを戻ってrefreshしてきてください!💨

Instance data.terraform_remote_state.vpc data could not be decoded from the
state: cannot decode dynamic from flatmap.

さて、ここまですんなりとこれたあなたはほとんど目標達成したも同然です。
実はあとのバージョンは一足飛びにバージョンアップできます。

0.13.x系から最新版、そして伝説へ...

実は0.13.x系から最新版までのアップデートは大変ではありません(感想には個人差があります)
変更点としては

  • awsなどのプロバイダーの変更
  • template_fileリソースの非推奨
    など後は、細かいものだったと思います。

手順

さて、いきなり手順ですが
先程versions.tfができた場合はrequired_versionを変更するのを忘れないでください。
消した場合はmain.tfのterraform {...}にrequired_versionを付け足しておきましょう

  1. 上記のrequired_versionの対応をした上で、.terraform-versionを書き換える
  2. terraform init --reconfigure
  3. terraform plan [-var-fileの読み込みなど]
  4. terraform apply or terraform refresh

上記の中で

│ Error: Invalid legacy provider address
│
│ This configuration or its associated state refers to the unqualified provider "aws".

などprovider関連のエラーが出た場合には以下の魔法のコマンドを打つと解決します。プロバイダーの変更コマンドです。
体感ではaws, template, archiveなどが出やすいのかなと感じました。

terraform state replace-provider registry.terraform.io/-/<provider名> hashicorp/<provider名>

template_file関連

あとは警告文なのですが、resource template_file は dataじゃないのか?のようなものが出る時があります。
これはtemplate_fileリソースが非推奨になっているため出るようです。

hoge.tf
...
  hoge = template_file.this.rendered
}

resource "template_file" "this" {
  ...
}

これをtemplate_fileリソースを削除してtemplatefile関数を使用します。

hoge.tf
...
  hoge = templatefile(<filepath>, {
    # jsonなどの中で使用している変数
    fugafuga = local.fugafuga
  })
}

# resource "template_file" "this" {
#   ...
# }

これで警告文は消えるかと思います。
ただ、template_fileリソースは削除したので、destroyは出てしまいます。。。

まとめ

以上の手順で最新版のterraformにアップデートできるんじゃないかなと思っていますが、他にもいける手順があったり、この記事通りでは動かないなどありましたらご気軽に教えていただきたいです!
それでは、駄文失礼しました!

Discussion