Praktik terbaik tentang pengelolaan dependensi

Dokumen ini memberikan rekomendasi untuk mengekspresikan dependensi antara resource di konfigurasi Terraform Anda.

Lebih mendukung dependensi implisit daripada dependensi eksplisit

Ketergantungan sumber daya muncul ketika satu sumber daya bergantung pada keberadaan sumber lainnya Google Cloud Platform. Terraform harus bisa memahami dependensi ini untuk memastikan bahwa resource dibuat dalam urutan yang benar. Misalnya, jika resource A memiliki dependensi pada resource B, resource B dibuat sebelum resource A.

Dependensi konfigurasi Terraform dapat dibuat melalui deklarasi dependensi implisit dan eksplisit. Dependensi implisit dideklarasikan melalui referensi ekspresi, sedangkan dependensi eksplisit ditentukan dengan menggunakan depends_on argumen meta. Argumen depends_on menentukan bahwa Terraform harus menyelesaikan semua tindakan pada objek yang menjadi dependensi resource atau modul, sebelum melanjutkan dengan objek dependen.

Sementara kedua pendekatan memastikan urutan operasi yang benar, dependensinya sering kali lebih efisien dalam merencanakan pembaruan dan penggantian resource. Hal ini karena Terraform dapat dengan cerdas melacak isian tertentu yang terlibat dalam dependensi implisit, untuk menghindari perubahan pada resource dependen jika kolom spesifik tersebut tetap tidak diubah dalam dependensi.

Dibandingkan dengan dependensi implisit, dependensi eksplisit menyampaikan informasi spesifik. Ini berarti bahwa Terraform hanya dapat merumuskan lebih banyak rencana konservatif untuk pembuatan, pembaruan, dan penggantian resource dalam tidak adanya pengetahuan tentang atribut tertentu yang membentuk ketergantungan. Dalam praktiknya, hal ini memengaruhi urutan pembuatan resource oleh Terraform dan cara Terraform menentukan apakah resource memerlukan update atau pengganti.

Kami merekomendasikan penggunaan dependensi eksplisit dengan argumen meta depends_on hanya sebagai pilihan terakhir ketika ketergantungan antara dua sumber daya disembunyikan dan tidak dapat dinyatakan melalui dependensi implisit.

Dalam contoh berikut, layanan proyek yang diperlukan harus diaktifkan sebelum membuat set data BigQuery. Dependensi ini dideklarasikan secara eksplisit:

Tidak direkomendasikan:

module "project_services" {
  source  = "terraform-google-modules/project-factory/google//modules/project_services"
  version = "~> 14.4"

  project_id = var.project_id
  activate_apis = [
    "bigquery.googleapis.com",
    "bigquerystorage.googleapis.com",
  ]
}

module "bigquery" {
  source       = "terraform-google-modules/bigquery/google"
  version      = "~> 5.4"

  dataset_id   = "demo_dataset"
  dataset_name = "demo_dataset"
  project_id   = var.project_id
  depends_on = [module.project_services] # <- explicit dependency
}

Contoh berikut menggantikan dependensi eksplisit dengan model dependensi dengan mereferensikan argumen project_id sebagai output project_id dari resource project_services:

Direkomendasikan:

module "bigquery" {
  source       = "terraform-google-modules/bigquery/google"
  version      = "~> 5.4"

  dataset_id   = "demo_dataset"
  dataset_name = "demo_dataset"
  project_id   = module.project_services.project_id # <- implicit dependency
}

Penggunaan dependensi implisit memungkinkan deklarasi yang tepat atas dependensi, seperti menentukan informasi yang tepat yang perlu yang dikumpulkan dari objek upstream. Hal ini juga mengurangi kebutuhan untuk membuat perubahan di beberapa tempat, sehingga dapat mengurangi risiko kesalahan.

Mereferensikan atribut output dari resource dependen

Saat Anda membuat dependensi implisit dengan mereferensikan nilai dari upstream ke resource, pastikan untuk hanya mereferensikan atribut output, nilai yang belum diketahui. Tindakan ini akan memastikan bahwa Terraform menunggu resource upstream dibuat sebelum menyediakan resource saat ini.

Dalam contoh berikut, referensi resource google_storage_bucket_object argumen nama resource google_storage_bucket. Argumen telah diketahui selama fase perencanaan Terraform. Artinya, saat Terraform membuat resource google_storage_bucket_object, kode ini tidak menunggu Resource google_storage_bucket dibuat karena mereferensikan resource (nama bucket) tidak membuat dependensi implisit antara google_storage_bucket_object dan google_storage_bucket. Hal ini mengalahkan tujuan deklarasi dependensi implisit antara dua sumber daya.

Tidak direkomendasikan:

# Cloud Storage bucket
resource "google_storage_bucket" "bucket" {
  name = "demo-bucket"
  location = "US"
}

resource "google_storage_bucket_object" "bucket_object" {
  name   = "demo-object"
  source = "./test.txt"
  bucket = google_storage_bucket.bucket.name # name is an input argument
}

Sebagai gantinya, resource google_storage_bucket_object harus mereferensikan id atribut output dari resource google_storage_bucket_object. Sejak id adalah atribut output, nilainya hanya ditetapkan setelah pembuatan resource telah dieksekusi. Oleh karena itu, Terraform akan menunggu pembuatan resource google_storage_bucket_object untuk diselesaikan sebelum memulai pembuatan resource google_storage_bucket_object.

Direkomendasikan:

resource "google_storage_bucket_object" "bucket_object" {
  name   = "demo-object"
  source = "./test.txt"
  bucket = google_storage_bucket.bucket.id # id is an output attribute
}

Terkadang tidak ada atribut output yang jelas untuk direferensikan. Misalnya, pertimbangkan contoh berikut saat module_a mengambil nama objek yang dihasilkan sebagai input. Di dalam module_a, nama file digunakan untuk membaca file. Jika Anda menjalankan kode ini apa adanya, Anda akan mendapatkan pengecualian no such file or directory, yang disebabkan oleh Terraform yang mencoba membaca file tersebut selama perencanaannya , yaitu saat file belum dibuat. Dalam hal ini, pemeriksaan atribut output dari resource local_file mengungkapkan bahwa tidak ada isian yang jelas yang dapat Anda gunakan sebagai pengganti input nama file argumen.

Tidak direkomendasikan:

resource "local_file" "generated_file" {
 filename = "./generated_file.text"
 content = templatefile("./template.tftpl", {
   project_id = var.project_id
 })
}

module "module_a" {
 source = "./modules/module-a"
 root_config_file_path = local_file.generated_file.filename
}

Anda bisa mengatasi masalah ini dengan memasukkan dependensi eksplisit. Sebagai, pastikan menambahkan komentar tentang alasan diperlukannya dependensi eksplisit:

Direkomendasikan:

module "module_a" {
 source = "./modules/module-a"
 root_config_file_path = local_file.generated_file.filename
 depends_on = [local_file.generated_file] # waiting for generated_file to be created
}

Langkah selanjutnya