Dokumen ini memberikan panduan dan rekomendasi untuk pengembangan yang efektif dengan Terraform di beberapa anggota tim dan alur kerja.
Panduan ini bukan merupakan pengantar untuk Terraform. Untuk pengantar penggunaan Terraform dengan Google Cloud, baca Mulai menggunakan Terraform.
Pedoman gaya dan struktur umum
Rekomendasi berikut mencakup gaya dan struktur dasar untuk konfigurasi Terraform Anda. Rekomendasi berlaku untuk modul Terraform yang dapat digunakan kembali dan untuk konfigurasi root.
Praktik terbaik:
Ikuti struktur modul standar.Gunakan konvensi penamaan.
Gunakan variabel dengan hati-hati.
Ekspos output.
Gunakan sumber data.
Batasi penggunaan skrip kustom.
Sertakan skrip helper di direktori terpisah.
Tempatkan file statis di direktori terpisah.
Lindungi resource stateful.
Gunakan pemformatan bawaan.
Batasi kompleksitas ekspresi.
Gunakan
count
untuk nilai bersyarat.Gunakan
for_each
untuk resource iterasi.Publikasikan modul ke registry.
Mengikuti struktur modul standar
- Modul Terraform harus mengikuti struktur modul standar.
- Mulai setiap modul dengan file
main.tf
, tempat resource berada secara default. - Dalam setiap modul, sertakan file
README.md
dalam format Markdown. Dalam fileREADME.md
, sertakan dokumentasi dasar tentang modul. - Tempatkan contoh dalam folder
examples/
, dengan subdirektori terpisah untuk setiap contoh. Untuk masing-masing contoh, sertakan fileREADME.md
mendetail. - Buat pengelompokan logis resource dengan file dan
nama deskriptifnya sendiri, seperti
network.tf
,instances.tf
, atauloadbalancer.tf
.- Jangan memberikan file-nya sendiri kepada setiap resource. Kelompokkan resource berdasarkan
tujuan bersama. Misalnya, gabungkan
google_dns_managed_zone
dangoogle_dns_record_set
didns.tf
.
- Jangan memberikan file-nya sendiri kepada setiap resource. Kelompokkan resource berdasarkan
tujuan bersama. Misalnya, gabungkan
- Dalam direktori root modul, hanya sertakan Terraform
(
*.tf
) dan file metadata repositori (sepertiREADME.md
danCHANGELOG.md
). - Tempatkan dokumentasi tambahan dalam subdirektori
docs/
.
Menggunakan konvensi penamaan
Beri nama semua objek konfigurasi menggunakan garis bawah untuk membatasi beberapa kata. Praktik ini memastikan konsistensi dengan konvensi penamaan untuk jenis resource, jenis sumber data, dan nilai lainnya yang sudah ditetapkan. Konvensi ini tidak berlaku untuk argumen nama.
Direkomendasikan:
resource "google_compute_instance" "web_server" { name = "web-server" }
Tidak direkomendasikan:
resource "google_compute_instance" "web-server" { name = "web-server" }
Untuk menyederhanakan referensi ke resource yang merupakan satu-satunya dari jenisnya (misalnya, satu load balancer untuk seluruh modul), beri nama resource
main
.- Diperlukan upaya mental ekstra untuk mengingat
some_google_resource.my_special_resource.id
versussome_google_resource.main.id
.
- Diperlukan upaya mental ekstra untuk mengingat
Untuk membedakan resource dari jenis yang sama satu sama lain (misalnya,
primary
dansecondary
), berikan nama resource yang bermakna.Buat nama resource dalam bentuk tunggal.
Dalam nama resource, jangan ulangi jenis resource. Contoh:
Direkomendasikan:
resource "google_compute_global_address" "main" { ... }
Tidak direkomendasikan:
resource "google_compute_global_address" "main_global_address" { … }
Menggunakan variabel dengan hati-hati
- Deklarasikan semua variabel di
variables.tf
. - Berikan nama deskriptif untuk variabel yang relevan dengan penggunaan atau
tujuannya:
- Input, variabel lokal, dan output yang merepresentasikan nilai
numerik—seperti ukuran disk atau ukuran RAM—harus diberi nama dengan
unit (seperti
ram_size_gb
). Google Cloud API tidak memiliki unit standar, sehingga penamaan variabel dengan unit akan membuat unit input yang diharapkan jelas bagi pengelola konfigurasi. - Untuk unit penyimpanan, gunakan awalan satuan biner (pangkat 1024)—
kibi
,mebi
,gibi
. Untuk semua satuan pengukuran lainnya, gunakan awalan satuan desimal (pangkat 1000)—kilo
,mega
,giga
. Penggunaan ini cocok dengan penggunaan dalam Google Cloud. - Untuk menyederhanakan logika bersyarat, berikan nama positif untuk variabel boolean—misalnya,
enable_external_access
.
- Input, variabel lokal, dan output yang merepresentasikan nilai
numerik—seperti ukuran disk atau ukuran RAM—harus diberi nama dengan
unit (seperti
- Variabel harus memiliki deskripsi. Deskripsi otomatis disertakan dalam dokumentasi yang dibuat secara otomatis pada modul yang dipublikasikan. Deskripsi menambahkan konteks tambahan bagi developer baru yang tidak dapat diberikan oleh nama deskriptif.
- Berikan jenis yang ditentukan untuk variabel.
- Jika sesuai, berikan nilai default:
- Untuk variabel dengan nilai yang tidak bergantung pada lingkungan (seperti ukuran disk), berikan nilai default.
- Untuk variabel dengan nilai khusus lingkungan (seperti
project_id
), jangan berikan nilai default. Dengan cara ini, modul panggilan harus memberikan nilai yang bermakna.
- Gunakan default kosong untuk variabel (seperti string atau daftar kosong) hanya jika membiarkan variabel tetap kosong adalah preferensi valid yang tidak ditolak API yang mendasarinya.
- Gunakan variabel dengan bijak. Hanya buat parameter nilai yang
harus bervariasi untuk setiap instance atau lingkungan. Saat memutuskan apakah akan mengekspos
variabel, pastikan ada kasus penggunaan konkret untuk mengubah
variabel tersebut. Jika hanya ada sedikit peluang bahwa variabel mungkin diperlukan,
jangan mengekspos variabel tersebut.
- Penambahan variabel dengan nilai default kompatibel dengan versi lama.
- Penghapusan variabel tidak kompatibel dengan versi lama.
- Jika literal digunakan kembali di beberapa tempat, Anda dapat menggunakan nilai lokal tanpa mengeksposnya sebagai variabel.
Mengekspos output
- Atur semua output dalam satu file
outputs.tf
. - Berikan deskripsi yang bermakna untuk semua output.
- Dokumentasikan deskripsi output di file
README.md
. Buat deskripsi secara otomatis di commit dengan alat seperti terraform-docs. - Tampilkan semua nilai berguna yang mungkin perlu dirujuk atau dibagikan oleh modul root. Terutama untuk modul open source atau modul yang sangat sering digunakan, ekspos semua output yang berpotensi untuk konsumsi.
Jangan meneruskan output secara langsung melalui variabel input, karena hal itu akan mencegahnya ditambahkan dengan benar ke grafik dependensi. Untuk memastikan bahwa dependensi implisit dibuat, pastikan referensi output diatribusikan dari resource. Dibandingkan mereferensikan variabel input untuk instance secara langsung, teruskan atribut seperti yang ditunjukkan di sini:
Direkomendasikan:
output "name" { description = "Name of instance" value = google_compute_instance.main.name }
Tidak direkomendasikan:
output "name" { description = "Name of instance" value = var.name }
Menggunakan sumber data
- Tempatkan sumber data di samping resource yang mereferensikannya. Misalnya, jika Anda mengambil gambar yang akan digunakan dalam meluncurkan instance, tempatkan gambar tersebut di samping instance, bukan mengumpulkan resource data dalam filenya sendiri.
- Jika jumlah sumber data menjadi besar, pertimbangkan untuk memindahkannya ke
file
data.tf
khusus. - Untuk mengambil data yang relatif terhadap lingkungan saat ini, gunakan jenis interpolasi variabel atau resource.
Membatasi penggunaan skrip kustom
- Gunakan skrip hanya jika diperlukan. Status resource yang dibuat
melalui skrip tidak diperhitungkan atau dikelola oleh Terraform.
- Hindari skrip kustom, jika memungkinkan. Hanya gunakan resource ini jika resource Terraform tidak mendukung perilaku yang diinginkan.
- Setiap skrip kustom yang digunakan harus memiliki alasan yang terdokumentasi dengan jelas untuk rencana penghentian penggunaan yang ada dan ideal.
- Terraform dapat memanggil skrip kustom melalui penyedia, termasuk penyedia lokal eksekutif.
- Tempatkan skrip kustom yang dipanggil oleh Terraform di direktori
scripts/
.
Menyertakan skrip helper di direktori terpisah
- Atur skrip helper yang tidak dipanggil oleh Terraform di
direktori
helpers/
. - Dokumentasikan skrip helper di file
README.md
dengan penjelasan dan contoh pemanggilan. - Jika skrip helper menerima argumen, sediakan pemeriksaan argumen dan
output
--help
.
Meletakkan file statis di direktori terpisah
- File statis yang direferensikan Terraform tetapi tidak dijalankan (seperti
skrip startup yang dimuat ke instance Compute Engine) harus diatur
ke dalam direktori
files/
. - Letakkan HereDocs yang panjang dalam file eksternal, terpisah dari HCL-nya.
Referensikan dengan
fungsi
file()
. - Untuk file yang dibaca menggunakan
fungsi
templatefile
Terraform, gunakan ekstensi file.tftpl
.- Template harus ditempatkan di direktori
templates/
.
- Template harus ditempatkan di direktori
Melindungi resource stateful
Untuk resource stateful, seperti database, pastikan perlindungan penghapusan diaktifkan. Contoh:
resource "google_sql_database_instance" "main" {
name = "primary-instance"
settings {
tier = "D0"
}
lifecycle {
prevent_destroy = true
}
}
Menggunakan pemformatan bawaan
Semua file Terraform harus sesuai dengan standar terraform fmt
.
Membatasi kompleksitas ekspresi
- Batasi kompleksitas setiap ekspresi interpolasi individual. Jika banyak fungsi diperlukan dalam satu ekspresi, pertimbangkan untuk membaginya menjadi beberapa ekspresi menggunakan nilai lokal.
- Jangan pernah ada lebih dari satu operasi ternary dalam satu baris. Sebagai gantinya, gunakan beberapa nilai lokal untuk membuat logika.
Menggunakan count
untuk nilai bersyarat
Untuk membuat instance resource secara bersyarat, gunakan
argumen meta count
.
Contoh:
variable "readers" {
description = "..."
type = list
default = []
}
resource "resource_type" "reference_name" {
// Do not create this resource if the list of readers is empty.
count = length(var.readers) == 0 ? 0 : 1
...
}
Berhati-hatilah saat menggunakan variabel yang ditentukan pengguna ketika menetapkan variabel count
untuk
resource. Jika atribut resource disediakan untuk variabel tersebut (seperti
project_id
) dan resource tersebut belum ada, Terraform tidak dapat
membuat rencana. Sebagai gantinya, Terraform melaporkan error
value of count cannot be computed
.
Dalam kasus tersebut, gunakan variabel enable_x
yang terpisah untuk melakukan komputasi
logika bersyarat.
Menggunakan for_each
untuk resource iterasi
Jika Anda ingin membuat beberapa salinan resource berdasarkan resource input,
gunakan
argumen meta
for_each
.
Memublikasikan modul ke registry
Modul yang dapat digunakan kembali: Publikasikan modul yang dapat digunakan kembali ke registry modul.
Modul open source: Publikasikan modul open source ke Terraform Registry.
Modul pribadi: Publikasikan modul pribadi ke registry pribadi.
Modul yang dapat digunakan kembali
Untuk modul yang dimaksudkan untuk digunakan kembali, selain panduan sebelumnya, gunakan panduan berikut.
Praktik terbaik:
Mengaktifkan API yang diperlukan dalam modul.Menyertakan file pemilik.
Merilis versi yang diberi tag.
Jangan mengonfigurasi penyedia atau backend.
Mengekspos label sebagai variabel.
Mengekspos output untuk semua resource.
Menggunakan submodul inline untuk logika yang kompleks.
Mengaktifkan API yang diperlukan dalam modul
Modul Terraform dapat mengaktifkan layanan apa pun yang diperlukan menggunakan
resource google_project_service
atau
modul project_services
.
Menyertakan aktivasi API akan mempermudah demonstrasi.
- Jika disertakan dalam modul, aktivasi API harus
dapat dinonaktifkan dengan mengekspos variabel
enable_apis
yang ditetapkan secara default ketrue
. Jika disertakan dalam modul, aktivasi API harus menetapkan
disable_services_on_destroy
kefalse
, karena atribut ini dapat menyebabkan masalah saat bekerja dengan beberapa instance modul ini.Contoh:
module "project-services" { source = "terraform-google-modules/project-factory/google//modules/project_services" version = "~> 12.0" project_id = var.project_id enable_apis = var.enable_apis activate_apis = [ "compute.googleapis.com", "pubsub.googleapis.com", ] disable_services_on_destroy = false }
Menyertakan file pemilik
Untuk semua modul bersama, sertakan file
OWNERS
(atau
CODEOWNERS
di GitHub), yang mendokumentasikan penanggung jawab untuk modul ini. Sebelum permintaan
pull apa pun digabungkan, pemilik harus menyetujuinya.
Merilis versi yang diberi tag
Terkadang modul memerlukan perubahan yang dapat menyebabkan gangguan dan Anda perlu menyampaikan efeknya kepada pengguna agar mereka dapat menyematkan konfigurasi mereka ke versi tertentu.
Pastikan modul bersama mengikuti SemVer v2.0.0 saat versi baru diberi tag atau dirilis.
Saat mereferensikan modul, gunakan batasan versi untuk disematkan ke versi utama. Contoh:
module "gke" {
source = "terraform-google-modules/kubernetes-engine/google"
version = "~> 20.0"
}
Jangan mengonfigurasi penyedia atau backend
Modul bersama tidak boleh mengonfigurasi penyedia atau backend. Sebagai gantinya, konfigurasikan penyedia dan backend di modul root.
Untuk modul bersama, tentukan versi penyedia minimum yang diperlukan dalam
blok required_providers
,
sebagai berikut:
terraform {
required_providers {
google = {
source = "hashicorp/google"
version = ">= 4.0.0"
}
}
}
Kecuali terbukti sebaliknya, asumsikan bahwa versi penyedia baru akan berfungsi.
Mengekspos label sebagai variabel
Izinkan fleksibilitas dalam pelabelan resource melalui antarmuka modul.
Pertimbangkan untuk menyediakan variabel labels
dengan nilai default peta kosong, seperti
berikut:
variable "labels" {
description = "A map of labels to apply to contained resources."
default = {}
type = "map"
}
Mengekspos output untuk semua resource
Variabel dan output memungkinkan Anda melakukan inferensi dependensi antara modul dan resource. Tanpa output apa pun, pengguna tidak dapat mengurutkan modul dengan benar sehubungan dengan konfigurasi Terraform mereka.
Untuk setiap resource yang ditentukan dalam modul bersama, sertakan setidaknya satu output yang mereferensikan resource tersebut.
Menggunakan submodul inline untuk logika yang kompleks
- Modul inline dapat Anda gunakan untuk mengatur modul Terraform yang kompleks ke dalam unit-unit yang lebih kecil dan menghapus duplikat resource umum.
- Tempatkan modul inline di
modules/$modulename
. - Perlakukan modul inline sebagai modul pribadi, bukan untuk digunakan oleh modul luar, kecuali jika dokumentasi modul bersama secara khusus menyatakan sebaliknya.
- Terraform tidak melacak resource yang difaktorkan ulang. Jika Anda memulai dengan beberapa
resource di modul level atas lalu memasukkannya ke submodul,
Terraform akan mencoba membuat ulang semua resource yang telah difaktorkan ulang. Untuk mengurangi perilaku
ini, gunakan
blok
moved
saat pemfaktoran ulang. - Output yang ditetapkan oleh modul internal tidak otomatis ditampilkan. Untuk membagikan output dari modul internal, ekspor ulang modul tersebut.
Modul root Terraform
Konfigurasi root (modul root) adalah direktori kerja tempat Anda menjalankan Terraform CLI. Pastikan konfigurasi root mematuhi standar berikut (dan pedoman Terraform sebelumnya, jika berlaku). Rekomendasi eksplisit untuk modul root menggantikan panduan umum.
Praktik terbaik:
Meminimalkan jumlah resource di setiap modul root.Menggunakan direktori terpisah untuk setiap aplikasi.
Membagi aplikasi ke dalam subdirektori khusus lingkungan.
Menggunakan direktori lingkungan.
Mengekspos output melalui status jarak jauh.
Menyematkan ke versi penyedia minor.
Menyimpan variabel dalam file
tfvars
.Memeriksa file
.terraform.lock.hcl
.Meminimalkan jumlah resource di setiap modul root
Penting untuk menjaga konfigurasi root tunggal agar tidak bertambah terlalu besar, dengan terlalu banyak resource yang disimpan dalam direktori dan status yang sama. Semua resource dalam konfigurasi root tertentu di-refresh setiap kali Terraform dijalankan. Hal ini dapat menyebabkan eksekusi yang lambat jika resource yang disertakan dalam satu status terlalu banyak. Aturan umum: Jangan sertakan lebih dari 100 resource (dan idealnya hanya beberapa lusin) dalam satu status.
Menggunakan direktori terpisah untuk setiap aplikasi
Untuk mengelola aplikasi dan project secara independen, tempatkan resource untuk setiap aplikasi dan project di direktori Terraform-nya sendiri. Layanan dapat mewakili aplikasi tertentu atau layanan umum seperti jaringan bersama. Tempatkan semua kode Terraform untuk layanan tertentu dalam satu direktori (termasuk subdirektori).
Memisahkan aplikasi ke dalam subdirektori khusus lingkungan
Saat men-deploy layanan di Google Cloud, bagi konfigurasi
Terraform untuk layanan tersebut menjadi dua direktori level teratas: direktori modules
yang berisi konfigurasi aktual untuk layanan dan
direktori environments
yang berisi konfigurasi root untuk setiap
lingkungan.
-- SERVICE-DIRECTORY/
-- OWNERS
-- modules/
-- <service-name>/
-- main.tf
-- variables.tf
-- outputs.tf
-- provider.tf
-- README
-- ...other…
-- environments/
-- dev/
-- backend.tf
-- main.tf
-- qa/
-- backend.tf
-- main.tf
-- prod/
-- backend.tf
-- main.tf
Menggunakan direktori lingkungan
Untuk membagikan kode di seluruh lingkungan, referensikan modul. Biasanya dapat berupa modul layanan yang menyertakan konfigurasi Terraform bersama dasar untuk layanan tersebut. Dalam modul layanan, input umum hard code dan hanya memerlukan input spesifik lingkungan sebagai variabel.
Setiap direktori lingkungan harus berisi file berikut:
- File
backend.tf
, mendeklarasikan lokasi status backend Terraform (biasanya Cloud Storage) - File
main.tf
yang membuat instance modul layanan
Setiap direktori lingkungan (dev
, qa
, prod
) sesuai dengan
ruang kerja Terraform
default dan men-deploy versi layanan ke lingkungan tersebut. Ruang kerja ini
mengisolasi resource khusus lingkungan ke dalam konteksnya sendiri. Hanya gunakan
ruang kerja default.
Tidak direkomendasikan untuk memiliki beberapa ruang kerja CLI dalam suatu lingkungan karena alasan berikut:
- Konfigurasi di setiap ruang kerja mungkin akan sulit diperiksa.
- Memiliki satu backend bersama untuk beberapa ruang kerja tidak direkomendasikan karena backend bersama akan menjadi titik tunggal kegagalan jika digunakan untuk pemisahan lingkungan.
- Meskipun penggunaan ulang kode dapat dilakukan, kode menjadi lebih sulit dibaca karena harus dialihkan
berdasarkan variabel ruang kerja saat ini (misalnya,
terraform.workspace == "foo" ? this : that
).
Untuk informasi selengkapnya, lihat referensi berikut:
Mengekspos output melalui status jarak jauh
Pastikan Anda mengekspos output yang berguna dari instance modul dari modul root.
Misalnya, cuplikan kode berikut melewati output project ID dari instance modul factory project sebagai output dari modul root.
# Project root module
terraform {
backend "gcs" {
bucket = "BUCKET"
}
}
module "project" {
source = "terraform-google-modules/project-factory/google"
...
}
output "project_id" {
value = module.project.project_id
description = "The ID of the created project"
}
Lingkungan dan aplikasi Terraform lainnya hanya dapat mereferensikan output level modul root.
Dengan menggunakan status jarak jauh, Anda dapat mereferensikan output modul root. Untuk mengizinkan penggunaan oleh aplikasi dependen lainnya untuk konfigurasi, pastikan Anda mengekspor informasi yang terkait dengan endpoint layanan, ke status jarak jauh.
# Networks root module
data "terraform_remote_state" "network_project" {
backend = "gcs"
config = {
bucket = "BUCKET"
}
}
module "vpc" {
source = "terraform-google-modules/network/google"
version = "~> 9.0"
project_id = data.terraform_remote_state.network_project.outputs.project_id
network_name = "vpc-1"
...
}
Terkadang, seperti saat memanggil modul layanan bersama dari direktori lingkungan, sebaiknya ekspor ulang seluruh modul turunan, seperti berikut:
output "service" {
value = module.service
description = "The service module outputs"
}
Menyematkan ke versi penyedia minor
Di modul root, deklarasikan setiap penyedia dan sematkan ke versi minor. Hal ini
memungkinkan upgrade otomatis ke rilis patch baru sekaligus tetap mempertahankan target
yang solid. Agar konsisten, beri nama file versi dengan versions.tf
.
terraform {
required_providers {
google = {
source = "hashicorp/google"
version = "~> 4.0.0"
}
}
}
Menyimpan variabel dalam file tfvars
Untuk modul root, sediakan variabel menggunakan file variabel .tfvars
. Agar
konsisten, beri nama file variabel dengan terraform.tfvars
.
Jangan tentukan variabel menggunakan opsi command line
var-files
atau var='key=val'
alternatif. Opsi command line bersifat singkat
dan mudah dilupakan. Menggunakan file variabel default lebih dapat diprediksi.
Memeriksa file .terraform.lock.hcl
Untuk modul root, file kunci dependensi .terraform.lock.hcl
harus diperiksa dalam kontrol sumber. Hal ini memungkinkan pelacakan dan
peninjauan perubahan dalam pilihan penyedia untuk konfigurasi tertentu.
Komunikasi lintas konfigurasi
Masalah umum yang muncul saat menggunakan Terraform adalah cara berbagi informasi di berbagai konfigurasi Terraform (mungkin dikelola oleh tim yang berbeda). Umumnya, informasi dapat dibagikan antarkonfigurasi tanpa harus disimpan dalam satu direktori konfigurasi (atau bahkan satu repositori).
Cara yang direkomendasikan untuk membagikan informasi di antara berbagai konfigurasi Terraform adalah dengan menggunakan status jarak jauh untuk mereferensikan modul root lainnya. Cloud Storage atau Terraform Enterprise adalah backend status pilihan.
Untuk membuat kueri resource yang tidak dikelola oleh Terraform, gunakan sumber data dari penyedia Google. Misalnya, akun layanan Compute Engine default dapat diambil menggunakan sumber data. Jangan gunakan sumber data untuk membuat kueri resource yang dikelola oleh konfigurasi Terraform lain. Cara ini dapat membuat dependensi implisit pada nama dan struktur resource yang mungkin dirusak secara tidak sengaja oleh operasi Terraform normal.
Bekerja dengan resource Google Cloud
Praktik terbaik untuk menyediakan resource Google Cloud dengan Terraform terintegrasi dalam modul Cloud Foundation Toolkit yang dikelola oleh Google. Bagian ini mengulang beberapa praktik terbaik tersebut.
Menyimulasikan image virtual machine
Secara umum, sebaiknya Anda membuat image virtual machine menggunakan alat seperti Packer. Terraform kemudian hanya perlu meluncurkan mesin menggunakan gambar yang telah dibuat sebelumnya.
Jika gambar yang dibuat sebelumnya tidak tersedia, Terraform dapat menyerahkan virtual
machine baru ke alat manajemen konfigurasi dengan blok provisioner
. Sebaiknya
hindari metode ini dan hanya gunakan sebagai
upaya terakhir.
Untuk membersihkan status lama yang terkait dengan instance, penyedia yang memerlukan
logika penghapusan harus menggunakan blok provisioner
dengan when = destroy
.
Terraform harus memberikan informasi konfigurasi VM ke manajemen konfigurasi dengan metadata instance.
Mengelola Identity and Access Management
Saat menyediakan asosiasi IAM dengan Terraform, tersedia beberapa resource yang berbeda:
google_*_iam_policy
(misalnya,google_project_iam_policy
)google_*_iam_binding
(misalnya,google_project_iam_binding
)google_*_iam_member
(misalnya,google_project_iam_member
)
google_*_iam_policy
dan google_*_iam_binding
membuat asosiasi IAM otoritatif,
dengan resource Terraform berfungsi sebagai satu-satunya
sumber tepercaya untuk izin yang dapat ditetapkan ke resource yang relevan.
Jika izin berubah di luar Terraform, Terraform pada eksekusi berikutnya akan menimpa semua izin untuk mewakili kebijakan seperti yang ditetapkan dalam konfigurasi Anda. Hal ini mungkin masuk akal untuk resource yang sepenuhnya dikelola oleh konfigurasi Terraform tertentu, tetapi hal ini berarti peran yang dikelola secara otomatis oleh Google Cloud akan dihapus, yang berpotensi mengganggu fungsionalitas beberapa layanan.
Untuk mencegah hal ini, sebaiknya gunakan resource google_*_iam_member
secara langsung atau
modul IAM dari Google.
Kontrol versi
Seperti bentuk kode lainnya, simpan kode infrastruktur di kontrol versi untuk mempertahankan histori dan memungkinkan rollback yang mudah.
Praktik terbaik:
Menggunakan strategi cabang default.Menggunakan cabang lingkungan untuk konfigurasi root.
Memungkinkan visibilitas yang luas.
Jangan pernah melakukan commit secret.
Mengatur repositori berdasarkan batasan tim.
Menggunakan strategi cabang default
Untuk semua repositori yang berisi kode Terraform, gunakan strategi berikut secara default:
- Cabang
main
adalah cabang pengembangan utama dan merepresentasikan kode terbaru yang disetujui. Cabangmain
dilindungi. - Pengembangan terjadi pada cabang fitur dan perbaikan bug yang bercabang dari
cabang
main
.- Beri nama cabang fitur dengan
feature/$feature_name
. - Beri nama cabang perbaikan bug dengan
fix/$bugfix_name
.
- Beri nama cabang fitur dengan
- Setelah perbaikan bug atau fitur selesai, gabungkan kembali ke cabang
main
dengan permintaan pull. - Untuk mencegah konflik penggabungan, lakukan rebase cabang sebelum menggabungkannya.
Menggunakan cabang lingkungan untuk konfigurasi root
Untuk repositori yang menyertakan konfigurasi root yang di-deploy langsung ke Google Cloud, diperlukan strategi peluncuran yang aman. Sebaiknya buat cabang terpisah untuk setiap lingkungan. Dengan demikian, perubahan pada konfigurasi Terraform dapat dipromosikan dengan menggabungkan perubahan antara cabang yang berbeda.
Memungkinkan visibilitas yang luas
Buat kode sumber dan repositori Terraform dapat dilihat secara luas dan dapat diakses di seluruh organisasi engineering oleh pemilik infrastruktur (misalnya, SRE) dan pemangku kepentingan infrastruktur (misalnya, developer). Hal ini memastikan pemangku kepentingan infrastruktur dapat memiliki pemahaman yang lebih baik tentang infrastruktur yang mereka andalkan.
Dorong pemangku kepentingan infrastruktur untuk mengirimkan permintaan penggabungan sebagai bagian dari proses permintaan perubahan.
Jangan pernah melakukan commit secret
Jangan pernah melakukan commit secret ke kontrol sumber, termasuk dalam konfigurasi Terraform. Sebagai gantinya, upload file ke sistem seperti Secret Manager dan referensikan menggunakan sumber data.
Perlu diingat bahwa nilai sensitif tersebut mungkin masih berakhir di file status dan mungkin juga diekspos sebagai output.
Mengatur repositori berdasarkan batasan tim
Meskipun Anda dapat menggunakan direktori terpisah untuk mengelola batas logis antara resource, batas organisasi dan logistik menentukan struktur repositori. Secara umum, gunakan prinsip desain yang memisahkan konfigurasi dengan persyaratan persetujuan dan pengelolaan yang berbeda ke dalam repositori kontrol sumber yang berbeda. Untuk menggambarkan prinsip ini, berikut beberapa kemungkinan konfigurasi repositori:
Satu repositori pusat: Dalam model ini, semua kode Terraform dikelola secara terpusat oleh satu tim platform. Model ini berfungsi paling baik ketika ada tim infrastruktur khusus yang bertanggung jawab atas semua pengelolaan cloud dan menyetujui setiap perubahan yang diminta oleh tim lain.
Repositori tim: Dalam model ini, setiap tim bertanggung jawab atas repositori Terraform mereka sendiri, tempat mereka mengelola semua yang terkait dengan infrastruktur yang mereka miliki. Misalnya, tim keamanan mungkin memiliki repositori tempat semua kontrol keamanan dikelola, dan tim aplikasi masing-masing memiliki repositori Terraform sendiri untuk men-deploy dan mengelola aplikasinya.
Mengatur repositori sepanjang batas tim adalah struktur terbaik untuk sebagian besar skenario perusahaan.
Repositori yang dipisahkan: Dalam model ini, setiap komponen Terraform logis dibagi dalam repositorinya sendiri. Misalnya, jaringan mungkin memiliki repositori khusus dan mungkin ada repositori factory project terpisah untuk pembuatan dan pengelolaan project. Cara ini paling efektif di lingkungan yang sangat terdesentralisasi dengan peralihan tanggung jawab yang sering dilakukan antar- tim.
Contoh struktur repositori
Anda dapat menggabungkan prinsip-prinsip ini untuk membagi konfigurasi Terraform di berbagai jenis repositori:
- Dasar
- Khusus aplikasi dan tim
Repositori dasar
Repositori dasar yang berisi komponen pusat utama, seperti IAM organisasi atau folder. Repositori ini dapat dikelola oleh tim cloud pusat.
- Dalam repositori ini, sertakan direktori untuk setiap komponen utama (misalnya, folder, jaringan, dan sebagainya).
- Dalam direktori komponen, sertakan folder terpisah untuk setiap lingkungan (dengan mempertimbangkan panduan struktur direktori yang disebutkan sebelumnya).
Repositori khusus aplikasi dan tim
Deploy repositori khusus aplikasi dan tim secara terpisah untuk setiap tim guna mengelola konfigurasi Terraform khusus aplikasi yang unik.
Operasi
Menjaga keamanan infrastruktur Anda bergantung pada kepemilikan proses yang stabil dan aman untuk menerapkan update Terraform.
Praktik terbaik:
Selalu membuat rencana terlebih dahulu.Menerapkan pipeline otomatis.
Menggunakan kredensial akun layanan untuk CI.
Menghindari impor resource yang sudah ada.
Jangan mengubah status Terraform secara manual.
Meninjau pin versi secara rutin.
Menggunakan kredensial default aplikasi saat berjalan secara lokal.
Menetapkan alias ke Terraform.
Selalu membuat rencana terlebih dahulu
Selalu buat rencana terlebih dahulu untuk eksekusi Terraform. Simpan rencana ke file output. Setelah pemilik infrastruktur menyetujuinya, jalankan rencana. Meskipun membuat perubahan prototipe secara lokal, developer harus membuat rencana dan meninjau resource yang akan ditambahkan, diubah, dan dihancurkan sebelum menerapkan rencana.
Menerapkan pipeline otomatis
Untuk memastikan konteks eksekusi yang konsisten, jalankan Terraform melalui alat
otomatis. Jika sistem build (seperti Jenkins) sudah digunakan dan diadopsi secara luas,
gunakan sistem tersebut untuk menjalankan perintah terraform plan
dan terraform apply
secara otomatis.
Jika tidak ada sistem yang tersedia, gunakan
Cloud Build
atau
Terraform Cloud.
Menggunakan kredensial akun layanan untuk continuous integration
Ketika dijalankan dari mesin di pipeline CI/CD, Terraform akan mewarisi kredensial akun layanan dari layanan yang menjalankan pipeline. Jika memungkinkan, jalankan pipeline CI di Google Cloud karena Cloud Build, Google Kubernetes Engine, atau Compute Engine memasukkan kredensial tanpa mendownload kunci akun layanan.
Untuk pipeline yang berjalan di luar Google Cloud, pilih workload identity federation untuk mendapatkan kredensial tanpa mendownload kunci akun layanan.
Menghindari impor resource yang sudah ada
Jika memungkinkan, hindari mengimpor resource yang sudah ada
(menggunakan terraform import
), karena
hal ini dapat mempersulit pemahaman tentang asal dan konfigurasi
resource yang dibuat secara manual. Sebagai gantinya, buat resource baru melalui Terraform
dan hapus resource lama.
Jika menghapus resource lama akan menimbulkan toil yang signifikan,
gunakan perintah terraform import
dengan persetujuan eksplisit. Setelah resource
diimpor ke Terraform, kelola resource secara eksklusif dengan Terraform.
Google menyediakan alat yang dapat Anda gunakan untuk mengimpor resource Google Cloud ke status Terraform. Untuk informasi selengkapnya, baca bagian Mengimpor resource Google Cloud ke status Terraform.
Jangan mengubah status Terraform secara manual
File status Terraform sangat penting untuk mempertahankan pemetaan antara
konfigurasi Terraform dan resource Google Cloud. Kerusakan dapat menyebabkan
masalah infrastruktur besar. Saat modifikasi pada status Terraform
diperlukan, gunakan perintah
terraform state
.
Meninjau pin versi secara rutin
Penyematan versi akan memastikan stabilitas, tetapi mencegah perbaikan bug dan peningkatan lainnya disertakan ke dalam konfigurasi Anda. Oleh karena itu, tinjau pin versi untuk Terraform, penyedia Terraform, dan modul secara rutin.
Untuk mengotomatiskan proses ini, gunakan alat seperti Dependabot.
Menggunakan kredensial default aplikasi saat berjalan secara lokal
Saat melakukan iterasi secara lokal pada konfigurasi Terraform, developer harus
melakukan autentikasi dengan menjalankan
gcloud auth application-default login
untuk membuat kredensial default aplikasi. Jangan mendownload kunci akun
layanan, karena kunci yang didownload lebih sulit dikelola dan diamankan.
Menetapkan alias ke Terraform
Untuk mempermudah pengembangan lokal, Anda dapat menambahkan alias ke profil command shell:
alias tf="terraform"
alias terrafrom="terraform"
Keamanan
Terraform memerlukan akses sensitif ke infrastruktur cloud Anda agar dapat beroperasi. Mengikuti praktik terbaik keamanan ini dapat membantu meminimalkan risiko terkait dan meningkatkan keamanan cloud Anda secara keseluruhan.
Praktik terbaik:
Menggunakan status jarak jauh.Mengenkripsi status.
Jangan menyimpan secret dalam status.
Menandai output yang sensitif.
Memastikan pemisahan tugas.
Menjalankan pemeriksaan sebelum penerapan.
Menjalankan audit berkelanjutan.
Menggunakan status jarak jauh
Untuk pelanggan Google Cloud, sebaiknya gunakan backend status Cloud Storage. Pendekatan ini mengunci status untuk memungkinkan kolaborasi sebagai tim. Tindakan ini juga memisahkan status dan semua informasi yang mungkin bersifat sensitif dari kontrol versi.
Pastikan hanya sistem build dan administrator dengan hak istimewa tinggi yang dapat mengakses bucket yang digunakan untuk status jarak jauh.
Untuk mencegah pengubahan status pengembangan secara tidak sengaja ke kontrol sumber, gunakan gitignore untuk file status Terraform.
Mengenkripsi status
Meskipun bucket Google Cloud dienkripsi saat nonaktif, Anda dapat menggunakan
kunci enkripsi yang disediakan pelanggan
untuk memberikan lapisan perlindungan tambahan. Lakukan hal ini dengan menggunakan
variabel lingkungan GOOGLE_ENCRYPTION_KEY
. Meskipun tidak boleh ada secret
dalam file status, selalu enkripsi status sebagai langkah pertahanan tambahan.
Jangan menyimpan secret dalam status
Ada banyak resource dan penyedia data di Terraform yang menyimpan nilai secret dalam teks biasa pada file status. Jika memungkinkan, hindari menyimpan secret dalam status. Berikut adalah beberapa contoh penyedia yang menyimpan secret dalam teks biasa:
Menandai output yang sensitif
Dibandingkan mencoba mengenkripsi nilai sensitif secara manual, Anda dapat mengandalkan dukungan bawaan Terraform untuk pengelolaan status sensitif. Saat mengekspor nilai sensitif ke output, pastikan nilai tersebut ditandai sebagai sensitif.
Memastikan pemisahan tugas
Jika Anda tidak dapat menjalankan Terraform dari sistem otomatis yang tidak dapat diakses pengguna, terapkan pemisahan tugas dengan memisahkan izin dan direktori. Misalnya, project jaringan akan sesuai dengan akun layanan Terraform jaringan atau pengguna yang aksesnya dibatasi ke project ini.
Menjalankan pemeriksaan sebelum penerapan
Saat menjalankan Terraform di pipeline otomatis, gunakan alat seperti
gcloud terraform vet
untuk
memeriksa output rencana terhadap kebijakan sebelum
diterapkan. Dengan melakukannya, Anda dapat mendeteksi regresi keamanan sebelum terjadi.
Menjalankan audit berkelanjutan
Setelah perintah terraform apply
dijalankan, jalankan pemeriksaan keamanan otomatis.
Pemeriksaan ini dapat membantu memastikan bahwa infrastruktur tidak berubah ke
status yang tidak aman. Alat berikut adalah pilihan yang valid untuk jenis pemeriksaan ini:
Pengujian
Pengujian modul dan konfigurasi Terraform terkadang mengikuti pola dan konvensi yang berbeda dari pengujian kode aplikasi. Meskipun menguji kode aplikasi paling banyak melibatkan pengujian logika bisnis aplikasi itu sendiri, pengujian kode infrastruktur secara menyeluruh memerlukan deployment resource cloud nyata untuk meminimalkan risiko kegagalan produksi. Ada beberapa pertimbangan saat menjalankan pengujian Terraform:
- Menjalankan pengujian Terraform akan menciptakan, mengubah, dan menghancurkan infrastruktur nyata, sehingga pengujian Anda berpotensi memerlukan waktu yang lama dan biaya yang mahal.
- Anda tidak bisa hanya menguji unit arsitektur menyeluruh. Pendekatan terbaik adalah dengan membagi arsitektur Anda menjadi beberapa modul dan mengujinya satu per satu. Manfaat pendekatan ini mencakup pengembangan iteratif yang lebih cepat karena runtime pengujian yang lebih cepat, pengurangan biaya untuk setiap pengujian, dan penurunan peluang kegagalan uji dari faktor-faktor di luar kendali Anda.
- Hindari menggunakan kembali status jika memungkinkan. Mungkin ada situasi saat Anda melakukan pengujian dengan konfigurasi yang memiliki data yang sama seperti konfigurasi lain, tetapi idealnya setiap pengujian harus dilakukan terpisah dan tidak boleh menggunakan kembali status di seluruh pengujian.
Praktik terbaik:
Menggunakan metode pengujian yang lebih murah terlebih dahulu.Memulai dari yang kecil.
Mengacak project ID dan nama resource.
Menggunakan lingkungan terpisah untuk pengujian.
Membersihkan semua resource.
Menggunakan metode pengujian yang lebih murah terlebih dahulu
Ada beberapa metode yang dapat Anda gunakan untuk menguji Terraform. Dalam urutan biaya, waktu proses, dan kedalaman dari atas ke bawah, metrik tersebut meliputi:
- Analisis statis: Menguji sintaksis dan struktur konfigurasi
tanpa men-deploy resource apa pun menggunakan alat seperti compiler, linter,
dan uji coba. Untuk melakukannya, gunakan
terraform validate
. - Pengujian integrasi modul: Untuk memastikan bahwa modul berfungsi dengan benar, uji setiap modul secara terpisah. Pengujian integrasi untuk modul melibatkan deployment modul ke dalam lingkungan pengujian dan memverifikasi bahwa resource yang diharapkan telah dibuat. Ada beberapa framework pengujian yang memudahkan penulisan pengujian sebagai berikut:
- Pengujian menyeluruh: Dengan memperluas pendekatan pengujian integrasi ke seluruh lingkungan, Anda dapat mengonfirmasi bahwa beberapa modul dapat berfungsi bersama. Dalam pendekatan ini, deploy semua modul yang membentuk arsitektur di lingkungan pengujian baru. Idealnya, lingkungan pengujian harus semirip mungkin dengan lingkungan produksi Anda. Meskipun biayanya mahal, tetapi memberikan keyakinan besar bahwa perubahan tidak merusak lingkungan produksi Anda.
Memulai dari yang kecil
Pastikan pengujian Anda saling melengkapi satu sama lain secara iteratif. Sebaiknya jalankan pengujian yang lebih kecil terlebih dahulu, lalu lanjutkan ke pengujian yang lebih kompleks, menggunakan pendekatan fail fast.
Mengacak project ID dan nama resource
Untuk menghindari konflik penamaan, pastikan konfigurasi Anda memiliki project ID yang unik secara global dan nama resource yang tidak tumpang-tindih dalam setiap project. Untuk melakukannya, gunakan namespace untuk resource Anda. Terraform memiliki penyedia acak bawaan untuk ini.
Menggunakan lingkungan terpisah untuk pengujian
Selama pengujian, banyak resource yang dibuat dan dihapus. Pastikan lingkungan diisolasi dari project pengembangan atau produksi untuk menghindari penghapusan yang tidak disengaja selama pembersihan resource. Pendekatan terbaik adalah meminta setiap pengujian membuat project atau folder baru. Untuk menghindari kesalahan konfigurasi, pertimbangkan untuk membuat akun layanan khusus untuk setiap eksekusi uji.
Membersihkan semua resource
Menguji kode infrastruktur berarti Anda men-deploy resource yang sebenarnya. Agar tidak dikenai biaya, pertimbangkan untuk menerapkan langkah pembersihan.
Untuk menghancurkan semua objek jarak jauh yang dikelola oleh konfigurasi tertentu, gunakan
perintah terraform destroy
. Beberapa framework pengujian memiliki langkah pembersihan
bawaan untuk Anda. Misalnya, jika Anda menggunakan Terratest, tambahkan
defer terraform.Destroy(t, terraformOptions)
ke pengujian. Jika menggunakan
Kitchen-Terraform, hapus ruang kerja Anda menggunakan
terraform kitchen delete WORKSPACE_NAME
.
Setelah menjalankan perintah terraform destroy
, jalankan juga prosedur pembersihan
tambahan untuk menghapus resource yang gagal dihancurkan Terraform. Lakukan hal ini dengan
menghapus project yang digunakan untuk eksekusi uji atau menggunakan alat seperti
modul project_cleanup
.
Mengoptimalkan waktu proses pengujian
Untuk mengoptimalkan waktu eksekusi uji, gunakan pendekatan berikut:
- Jalankan pengujian secara paralel. Beberapa framework pengujian mendukung pengoperasian
beberapa pengujian Terraform secara bersamaan.
- Misalnya, dengan Terratest, Anda dapat melakukannya dengan menambahkan
t.Parallel()
setelah definisi fungsi pengujian.
- Misalnya, dengan Terratest, Anda dapat melakukannya dengan menambahkan
- Uji secara bertahap. Pisahkan pengujian Anda ke dalam konfigurasi independen
yang dapat diuji secara terpisah. Dengan pendekatan ini, Anda tidak perlu melalui
semua tahap saat menjalankan pengujian dan siklus pengembangan
iteratif juga menjadi lebih cepat.
- Misalnya, di Kitchen-Terraform, bagi pengujian dalam suite terpisah. Saat melakukan iterasi, jalankan setiap suite secara terpisah.
- Demikian pula, dengan menggunakan Terratest, gabungkan setiap tahap pengujian Anda dengan
stage(t, STAGE_NAME, CORRESPONDING_TESTFUNCTION)
. Menetapkan variabel lingkungan yang menunjukkan pengujian yang akan dijalankan. Misalnya,SKIP
STAGE_NAME="true"
. - Framework pengujian blueprint mendukung eksekusi yang dirilis bertahap untuk pengujian.
Langkah selanjutnya
- Mengekspor resource Anda ke dalam format Terraform.
- Mengimpor resource Anda ke status Terraform.
- Menyimpan status Terraform di bucket Cloud Storage.
- Mengelola infrastruktur sebagai kode dengan Terraform, Cloud Build, dan GitOps.