Skip to main content
BlogDevOps

Terraform 1.16: Yang Baru dan Cara Upgrade dengan Aman

Terraform 1.16 menambah import block di module, store block terraform_data, destroy = false, dan graph Mermaid. Lihat yang berubah dan apa yang diuji dulu.

Matthews Wong

Software Engineer

Oktober 202611 menit baca
Terraform 1.16: Yang Baru dan Cara Upgrade dengan Aman

Ringkasan Utama

Terraform 1.16, dirilis 26 Agustus 2026, menambahkan import block di dalam module, store block pada terraform_data untuk nilai ephemeral dan sensitive, lifecycle destroy = false, mode kegagalan action, dan output graph Mermaid. Upgrade notes hanya memuat satu item, bastion_host_key pada provisioner. Pin versi minor, jalankan plan yang representatif, dan anggap destroy = false sebagai berhenti mengelola, bukan melindungi.

Saya membuka halaman rilis Terraform 1.16.0 dengan harapan ini rilis minor yang tenang, lalu menghitung enam fitur baru, empat belas enhancement, dan sebelas bug fix. Kebanyakan baris menarik hanya satu kalimat, dan dua di antaranya terdengar seperti fitur keamanan saat pertama saya baca. Salah satu kesan itu ternyata keliru.

Post ini membaca release notes v1.16.0, changelog 1.16, dan halaman dokumentasi HashiCorp terkini untuk tiap fitur. Setiap nomor PR berasal dari release notes. Saya tidak menjalankan 1.16 pada state file asli, jadi kalau dokumentasi diam, saya katakan begitu alih-alih menebak.

Isi 1.16, dihitung dari release notes

Release notes v1.16.0 bertanggal 26 Agustus 2026 dan terbagi menjadi fitur baru, enhancement, bug fix, satu catatan umum, dan satu upgrade note. Upgrade guide sendiri menyebut 1.16 sebagai rilis minor di seri stabil 1.0 yang menghormati compatibility promises 1.0, dan mengarahkan Anda ke changelog untuk detailnya.

BagianJumlahYang saya lihat dulu
Fitur baru6Import block di module (#38352), store block pada terraform_data (#38298), mode on_failure pada action (#38722), ditambah perubahan untuk provider dan binary Linux s390x (#38384).
Enhancement14lifecycle destroy = false (#38784), output Mermaid untuk terraform graph (#38719), -json untuk state show dan workspace list, event before_destroy dan after_destroy pada action (#38668).
Bug fix11Import block kini menghormati local name provider (#38338) dan memberi error yang benar untuk target yang ada di state tetapi tanpa konfigurasi (#38782).
Upgrade notes1Provisioner kini menerapkan bastion_host_key dengan benar, jadi verifikasi konfigurasi provisioner sebelum upgrade (#38318).

Satu baris lagi ada di bagian Notes: init kini memunculkan error lebih awal untuk kombinasi flag -upgrade dan -lockfile=readonly (#38561). Kalau job CI memakai keduanya, job itu kini gagal di init, bukan belakangan. Perubahan seperti ini terlihat seperti regresi sampai Anda membaca barisnya.

Import block kini bisa berada di dalam module

Catatan 1.16 menyebut import block didukung di dalam module (#38352). Keuntungan praktisnya adalah kepemilikan: module yang membungkus resource yang sering diadopsi, seperti bucket atau DNS zone, bisa membawa logika adopsinya sendiri, tanpa meminta setiap pemanggil menambah import di root.

# modules/data-bucket/imports.tf
# The module that owns the resource now also owns the import.
variable "existing_bucket_name" {
  type    = string
  default = null # null = a fresh environment, nothing to adopt
}

resource "aws_s3_bucket" "this" {
  bucket = coalesce(var.existing_bucket_name, "acme-data-new")
}

# Documented shape: "to" must match a resource block's address,
# and "id" must be known during the plan.
import {
  for_each = var.existing_bucket_name == null ? toset([]) : toset(["adopt"])
  to       = aws_s3_bucket.this
  id       = var.existing_bucket_name
}

# Wrong (before 1.16): put this import block in the root module and
# address it as module.data_bucket.aws_s3_bucket.this, so every caller
# of the module has to know about the adoption.
# Right (1.16): leave the root module alone and let the module carry it.

Dokumentasi import mencantumkan argumennya: to, yang harus cocok dengan alamat resource block yang ada, id, yang harus diketahui saat plan, identity sebagai alternatif id, serta for_each dan provider sebagai meta-argument. Dokumentasi itu tidak menyebut batasan module maupun perubahan 1.16, jadi release notes adalah satu-satunya sumber untuk perilaku barunya. Contoh di atas buatan saya sendiri, disusun dari aturan argumen yang terdokumentasi.

Rilis yang sama memperbaiki dua edge case import. Import block menghormati local name provider (#38338), dan target import yang ada di state tetapi tanpa konfigurasi kini mengembalikan error yang benar (#38782). Import tetap menetapkan kepemilikan state, jadi baca plan hasilnya sebelum apply: infrastruktur yang ada bisa berbeda dari konfigurasi yang Anda tulis.

terraform_data mendapat store block untuk nilai ephemeral

terraform_data kini punya store block yang menyimpan nilai ephemeral dan sensitive dari plan sampai apply (#38298). Dokumentasi menjelaskan empat setelan: input, yang write-only dan menerima tipe apa pun termasuk nilai ephemeral, replace, sensitive, dan version.

# Follows the documented example: an ephemeral value is written into
# a store block and read back through a sensitive attribute.
ephemeral "random_password" "db" {
  length = 24
}

resource "terraform_data" "db_password" {
  store {
    input     = ephemeral.random_password.db.result
    sensitive = true # lands in store.sensitive_output, not store.output
    version   = 1    # bump to accept a new input; otherwise it is ignored
  }
}

Mekanismenya lebih penting daripada headline-nya. Input yang disimpan disalin ke store.output, atau ke store.sensitive_output saat sensitive bernilai true, dan keduanya saling eksklusif. Jika version diatur, perubahan pada input tidak sampai ke output kecuali version ikut berubah. Jadi version adalah tombol eksplisit untuk memutuskan kapan nilai baru diterima.

Atribut sensitive tetap merupakan nilai di state. Dokumentasi menyebut input disalin ke atribut output di state, jadi store block memindahkan secret dari konfigurasi ke state file, dengan tanda sensitive. Itu hanya seaman enkripsi backend dan siapa yang bisa membaca state, dan saya tidak akan menaruh credential berumur panjang di sana demi menghemat satu data source.

Sebelum memakai store untuk hal rahasia, baca state file Anda seperti orang asing: jalankan terraform state pull dan cari nama atributnya. Apa yang Anda temukan adalah yang bisa dilihat backend dan setiap orang dengan akses state.

lifecycle destroy = false: tidak seaman kedengarannya

Release notes menjelaskan enhancement ini sebagai lifecycle block yang mendukung destroy = false untuk mencegah destruction (#38784). Dokumentasi lifecycle saat ini berbunyi lain: setel destroy ke false untuk menghapus resource dari state tanpa menghancurkan resource infrastruktur yang sebenarnya. Dua hal itu berlawanan, dan dokumentasi menjelaskan yang kedua.

MekanismeYang terjadi di stateYang terjadi pada objek asli
lifecycle destroy = falseResource dihapus dari stateTetap berjalan dan tidak dikelola
lifecycle prevent_destroy = trueTetap di state; plan yang akan menghancurkannya gagalTidak dihancurkan, tetapi plan error
Menghapus resource blockResource dihapus dari stateDihancurkan, bahkan dengan prevent_destroy, menurut dokumentasi lifecycle
removed block, destroy defaultResource dihapus dari stateDihancurkan kecuali destroy diatur ke false
# Syntax from the lifecycle documentation. The page gives no example,
# so check this on a throwaway state before you trust it on a database.
resource "aws_db_instance" "legacy" {
  # ...
  lifecycle {
    destroy = false # stop tracking it, leave the instance running
  }
}

# Not the same as the guard that refuses to plan a destroy at all:
resource "aws_db_instance" "guarded" {
  # ...
  lifecycle {
    prevent_destroy = true # plan fails if it would destroy this
  }
}

Halaman lifecycle tidak menjelaskan interaksi destroy = false dengan terraform destroy dan tidak memberi contoh, jadi snippet di atas hanya mengikuti sintaks terdokumentasi. Halaman removed block menegaskan semantik yang sama: destroy yang diatur false menghapus resource dari state tanpa menghancurkannya, yang direkomendasikan saat Anda menyerahkan resource ke tool atau tim lain. Anggap destroy = false sebagai saklar serah terima dan simpan prevent_destroy untuk perlindungan.

Action: mode kegagalan, event destroy, dan simbol caller

Action trigger mendapat setelan on_failure dengan tiga nilai (#38722). Halaman invoke-actions mendokumentasikan ketiganya, dan defaultnya adalah halt.

on_failureEfek pada applyResource di-taint
halt (default)Menghentikan apply dan melaporkan errorTidak
continueMencatat error sebagai warning dan lanjutTidak
taintMenghentikan apply dan melaporkan errorYa, diganti pada apply berikutnya
# From the invoke-actions documentation: a notification that must not
# block the apply, so on_failure is continue instead of the default halt.
resource "aws_lambda_function" "example" {
  # ... resource arguments ...

  lifecycle {
    action_trigger {
      events     = [after_create]
      actions    = [action.aws_lambda_invoke.notify]
      on_failure = continue
    }
  }
}

action "aws_lambda_invoke" "notify" {
  config {
    function_name = "my_function"
    payload       = caller.output # one action, many calling resources
  }
}

# Run the action by hand, with no resource change:
#   terraform apply -invoke=action.aws_lambda_invoke.notify

Di catatan yang sama: action mendapat event before_destroy dan after_destroy, dan konfigurasi action bisa membaca simbol caller untuk resource pemanggil (keduanya #38668). Halaman invoke-actions hanya mendokumentasikan after_create dan after_update, jadi untuk event destroy dan atribut caller yang persis saya bergantung pada release notes saja. Action juga kini menghormati semua dependency resource, dan -invoke bisa digabung dengan -target untuk memilih instance resource pemanggil (#38845).

Perubahan kecil yang menyelesaikan gangguan nyata

terraform graph bisa mengeluarkan Mermaid dengan -format=mermaid (#38719), dan state show serta workspace list menerima -json (#23940, #38397). terraform console menerima -scope dengan alamat module (#31861), dan binary Linux s390x siap pakai kini tersedia (#38384).

# A pull-request-friendly dependency graph. The flag is from the
# 1.16.0 release notes (#38719); the graph docs page still describes DOT.
terraform graph -format=mermaid > graph.mmd

# Machine-readable output where scripts used to scrape text.
terraform state show -json aws_s3_bucket.this
terraform workspace list -json

# Evaluate an expression inside one module instead of the root.
terraform console -scope=module.data_bucket

Catatan soal dokumentasi yang tertinggal: halaman perintah graph yang saya baca masih menjelaskan output DOT yang dirender dengan Graphviz dan tidak mencantumkan opsi -format. Flag itu berasal dari release notes, jadi jalankan terraform graph -help pada binary Anda sebelum memasangnya di CI. Untuk pull request, Mermaid berguna karena renderer Markdown bisa menggambarnya langsung, meski estate besar perlu di-scope agar tetap terbaca.

Di mana ini bisa menjebak Anda

Sisi tajamnya bukan di fitur utama. Inilah yang akan saya sampaikan ke tim sebelum upgrade:

  • destroy = false menghapus resource dari state dan membiarkan objek asli tidak dikelola, sehingga laporan drift tidak lagi menyebutnya.
  • Store block menyalin input ke state, jadi nilai sensitive hanya dilindungi backend dan kontrol akses Anda.
  • bastion_host_key kini diterapkan dengan benar oleh provisioner, jadi konfigurasi yang diam-diam mengabaikannya bisa berperilaku lain (#38318).
  • init kini gagal lebih awal saat -upgrade dan -lockfile=readonly digabung (#38561), yang bisa mematahkan pipeline yang selama ini jalan karena kebetulan.

Jangan membaca destroy = false sebagai jaring pengaman. Kalau Anda ingin Terraform menolak plan destroy, itu prevent_destroy. Memakai yang salah pada database mengubah pelindung yang Anda kira ada menjadi resource yang sudah dilupakan Terraform.

Tak satu pun alasan ini cukup untuk melewatkan 1.16. Rilis ini menghormati compatibility promises 1.0, dan satu upgrade note-nya sempit. Alasannya adalah menguji keempat item di atas pada salinan konfigurasi asli Anda, bukan pada module hello-world.

Yang dilakukan hari Senin

Jalur upgrade singkat yang sesuai dengan apa yang benar-benar diubah release notes:

  1. Cari bastion_host_key di kode Anda dan uji ulang setiap provisioner yang memakai bastion host.
  2. Periksa skrip CI untuk pemanggilan init yang memakai -upgrade dan -lockfile=readonly sekaligus.
  3. Pin versi minor di required_version dan di image CI agar laptop dan pipeline sama.
  4. Jalankan plan representatif pada root module terbesar Anda dan harapkan tanpa perubahan; selidiki apa pun yang muncul.
  5. Cari lifecycle block yang akan Anda tulis dengan destroy = false dan pastikan masing-masing memang serah terima yang disengaja.
# versions.tf - pin the minor so CI and laptops agree
terraform {
  required_version = ">= 1.16.0, < 1.17.0"
}

# CI: on a representative root module, a plan that must be clean
terraform version
terraform init -upgrade
terraform plan -detailed-exitcode -out=tfplan   # exit 0 clean, 2 changes
terraform graph -plan=tfplan -format=mermaid > plan-graph.mmd

# Provisioners with a bastion: grep before the upgrade, not after
grep -rn "bastion_host_key" --include=*.tf .

Setelah itu, adopsi fitur baru satu per satu. Import block di module dan graph Mermaid berisiko rendah. Perlakukan store dan destroy = false sebagai perubahan yang perlu review di pull request.

Terraform 1.16 adalah rilis minor yang berguna, dengan dua fitur paling berisiko yang bernama seperti fitur keamanan. Baca halaman dokumentasinya, bukan ringkasan satu baris, sebelum memakai destroy = false atau store, pin versinya, dan biarkan plan yang representatif menunjukkan apakah upgrade-nya tenang.

FAQ

Pertanyaan Umum

Jawaban singkat untuk pertanyaan yang paling sering diajukan pembaca tentang topik ini.

Apa yang baru di Terraform 1.16?

Terraform 1.16.0, dirilis 26 Agustus 2026, mencantumkan enam fitur baru dan empat belas enhancement. Yang paling penting adalah import block di dalam module, store block pada terraform_data, lifecycle destroy = false, mode on_failure untuk action trigger, dan output Mermaid dari terraform graph. Rilis ini juga menambah -json pada state show dan workspace list.

Apakah ada breaking change di Terraform 1.16?

Release notes memuat satu upgrade note: provisioner kini menerapkan bastion_host_key dengan benar, jadi verifikasi konfigurasi provisioner sebelum upgrade. Upgrade guide menyebut 1.16 sebagai rilis minor yang menghormati compatibility promises 1.0. Perhatikan juga bahwa init kini gagal lebih awal saat -upgrade dan -lockfile=readonly digabung.

Apakah lifecycle destroy = false melindungi resource dari penghancuran?

Tidak, menurut dokumentasi lifecycle opsi ini menghapus resource dari state tanpa menghancurkan objek infrastruktur aslinya. Untuk membuat Terraform menolak plan yang akan menghancurkan resource, gunakan prevent_destroy = true. Uji destroy = false pada state percobaan sebelum memakainya pada hal yang penting.

Apakah store block pada terraform_data aman untuk secret?

Store block menerima input ephemeral dan menyalinnya ke atribut output di state, atau ke sensitive_output saat sensitive bernilai true. Artinya nilainya tetap berada di state file, dengan tanda sensitive. Keamanannya bergantung pada enkripsi backend dan siapa yang bisa membaca state.

Bagaimana cara membuat graph Mermaid di Terraform 1.16?

Jalankan terraform graph -format=mermaid, flag yang tercantum di release notes 1.16.0. Halaman dokumentasi perintah graph masih menjelaskan output DOT, jadi pastikan flag itu dengan terraform graph -help pada binary Anda. Output Mermaid bisa ditempel ke tool Markdown yang merender diagram.