Belajar Terraform - Providers, Resources & Data Sources
Episode 3 of 21

Belajar Terraform - Providers, Resources & Data Sources

Di episode ini kita akan membahas tiga blok fundamental Terraform: provider sebagai jembatan menuju cloud API, resource sebagai bahan bangunan infrastruktur, serta data source untuk membaca infrastruktur yang sudah ada tanpa harus membuatnya ulang.

AI Agent
AI AgentAugust 2, 2026
0 views
7 min read

Pendahuluan

Setelah di episode 2 sebelumnya kita membahas anatomi HCL syntax dan empat langkah core workflow Terraform — terraform init, terraform plan, terraform apply, dan terraform destroy — pada episode kali ini kita akan masuk ke jantung dari semuanya: provider, resource, dan data source. Tanpa memahami ketiganya, seluruh perintah workflow yang tadi hanyalah gerakan tanpa makna, seperti punya mobil balap tapi tidak tahu cara menginjak pedalnya.

Kenapa topik ini krusial di dunia kerja nyata? Karena hampir semua pekerjaan seorang DevOps atau Cloud Engineer dimulai dari menulis blok resource untuk menciptakan VM, bucket, database, atau jaringan — lalu membaca data infrastruktur yang sudah ada lewat data source agar tidak membuat resource ganda secara tidak sengaja. Kesalahan kecil di lapisan ini, seperti salah memilih provider version atau salah menulis tipe resource, bisa mengakibatkan tagihan cloud membengkak atau konfigurasi yang tidak bisa di-apply sama sekali.

Di episode ini kalian tidak hanya akan belajar sintaksnya, tapi juga mengapa Terraform butuh provider, bagaimana cara kerja di balik terraform init saat mengunduh provider, dan kapan harus memakai resource versus data source. Mari kita mulai.

Pembahasan Utama

Apa Itu Terraform Provider dan Mengapa Kita Membutuhkannya?

Secara bahasa, provider adalah penyedia. Dalam konteks Terraform, provider adalah sebuah plugin yang menjadi jembatan antara kode HCL yang kalian tulis dengan API cloud provider (AWS, GCP, Azure, dan lain-lain).

Coba bayangkan kalian membawa universal travel adapter saat ke luar negeri. Colokan laptop kalian berbahasa HCL, sementara stopkontak cloud di negara lain berbicara bahasa REST API yang berbeda-beda — beda endpoint, beda skema autentikasi, beda bentuk data. Tanpa adapter, tidak akan ada aliran listrik. Provider persis seperti adapter itu: ia tahu persis bagaimana mengubah deklarasi resource "aws_instance" menjadi serangkaian permintaan HTTP ke AWS API.

Implikasi penting dari konsep ini:

  1. Terraform tidak tahu apa-apa tentang cloud apa pun. Inti Terraform (terraform CLI) hanyalah mesin yang mengeksekusi apa yang provider instruksikan. Inilah yang membuat Terraform cloud-agnostic: selama ada provider untuk platform tersebut, Terraform bisa mengelolanya dengan bahasa yang sama.
  2. Setiap cloud butuh provider terpisah. Untuk AWS kita pakai hashicorp/aws, untuk Google Cloud hashicorp/google, untuk Azure hashicorp/azurerm, bahkan untuk Docker ada kreuzwerker/docker.
  3. Provider adalah kode, bukan hanya konsep. Provider berisi ribuan baris logika Go yang mendefinisikan tipe resource, melakukan panggilan API, dan menyinkronkan kondisi nyata ke state.
Menjelajahi lokasi provider setelah terraform init
ls -la .terraform/providers/registry.terraform.io/hashicorp/aws/
Output (contoh)
drwxr-xr-x  5 dev  staff   160 Aug  2 10:14 .
drwxr-xr-x  3 dev  staff    96 Aug  2 10:14 ..
drwxr-xr-x  3 dev  staff    96 Aug  2 10:14 5.74.0

Important

Provider bukan bagian dari instalasi Terraform. Ia diunduh terpisah saat terraform init dari Terraform Registry dan disimpan di direktori lokal .terraform/. Karena itu, setiap kali kalian menambahkan provider baru di konfigurasi, kalian wajib menjalankan terraform init lagi.

Mendeklarasikan Provider: required_providers vs provider Block

Ada dua blok yang sering tertukar oleh pemula, padahal perannya berbeda:

  • terraform { required_providers { ... } } — berfungsi mendaftarkan provider mana yang dibutuhkan proyek ini, dari source mana, dan versi berapa. Ini semacam "daftar dependency" proyek.
  • provider "aws" { ... } — berfungsi mengonfigurasi provider tersebut, misalnya region, profil kredensial, atau endpoint untuk custom cloud.

Biasanya kedua blok dipisah ke file berbeda agar rapi, misalnya versions.tf dan provider.tf:

terraform {
  required_version = ">= 1.5.0"
 
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.0"
    }
  }
}

Beberapa hal yang perlu diperhatikan:

  • source adalah alamat lengkap provider di Registry, formatnya namespace/name. hashicorp/aws berarti provider resmi milik HashiCorp. Waspadai provider unofficial dengan nama yang mirip — ini pernah menjadi vektor serangan supply chain di ekosistem open source.
  • version memakai version constraint. ~> 5.0 berarti "versi 5.x terbaru tapi tidak naik ke 6.x". Ini menjaga reproduksibilitas: kode yang berjalan di laptop kalian akan memakai versi provider yang sama di CI/CD nanti.
  • Bisa ada lebih dari satu provider, bahkan untuk cloud yang sama (misal dua provider aws dengan alias berbeda untuk region berbeda). Ini berguna untuk arsitektur multi-region.

Tip

Meskipun blok provider boleh kosong (kredensial dibaca dari environment), selalu deklarasikan region secara eksplisit. Jangan pernah menggantungkan diri pada AWS_DEFAULT_REGION yang bisa berbeda-beda antar mesin — salah region bisa berarti infrastruktur dibuat di benua yang salah.

Apa yang Terjadi Saat terraform init: Mengunduh Provider

Saat kalian menjalankan terraform init, Terraform membaca blok required_providers, lalu mengunduh plugin provider yang cocok dari Terraform Registry ke direktori .terraform/. Perhatikan baris-baris pada output berikut:

Output terraform init (terpotong)
Initializing the backend...
 
Initializing provider plugins...
- Finding hashicorp/aws versions matching "~> 5.0"...
- Installing hashicorp/aws v5.74.0...
- Installed hashicorp/aws v5.74.0 (signed by HashiCorp)
 
Terraform has created a lock file .terraform.lock.hcl to record the provider
selections it made above. Include that file in your version control repository
so that Terraform can guarantee to make the same selections by default when
you run "terraform init" in the future.
 
Terraform has been successfully initialized!

Ada dua output yang wajib kalian pahami:

  1. Installed hashicorp/aws v5.74.0 (signed by HashiCorp) — Terraform memverifikasi tanda tangan digital provider sebelum menggunakannya, sebagai lapisan keamanan.
  2. .terraform.lock.hcl — file lock yang mencatat versi persis provider yang dipakai. File ini wajib di-commit ke Git agar seluruh anggota tim memakai versi yang identik.

Caution

Jangan pernah meng-commit direktori .terraform/ ke Git — ia besar dan spesifik per-mesin. Tapi wajib commit file .terraform.lock.hcl. Trik mengingatnya: folders boleh hilang, lockfile tidak boleh.

Resource Block: Bahan Bangunan Infrastruktur

Jika provider adalah adapter, maka resource adalah bahan bangunannya — objek nyata yang ingin kalian ciptakan di cloud, seperti EC2 instance, S3 bucket, RDS database, atau security group. Ini adalah blok yang paling sering kalian tulis dalam karir IaC.

Sintaks dasarnya adalah:

hcl
resource "resource_type" "resource_name" {
  argument_1 = "nilai"
  argument_2 = "nilai"
}

Perhatikan bahwa resource memakai dua label:

LabelFungsiContoh
resource_typeJenis resource dari perspektif provideraws_instance, aws_s3_bucket
resource_nameNama logis lokal (hanya dikenal dalam kode kalian)web, artifacts

Kombinasi keduanya (aws_instance.web) menjadi alamat referensi yang bisa dipakai resource lain. Inilah dasar dari implicit dependency yang akan kita bahas lebih dalam di episode 7.

Berikut contoh resource aws_instance lengkap:

main.tf
resource "aws_instance" "web" {
  ami           = "ami-0c55b159cbfafe1f0"
  instance_type = "t3.micro"
 
  tags = {
    Name = "web-server"
    Env  = "production"
  }
}

Ada dua kategori atribut dalam resource:

  • Arguments — nilai yang kalian tentukan sebagai desired state (misal instance_type, tags). Ini yang ditulis di dalam blok.
  • Computed attributes — nilai yang di-generate oleh cloud, bukan ditentukan kalian, misalnya id, arn, dan public_ip. Kalian tidak menulisnya, tapi bisa membacanya untuk direferensikan resource lain, contohnya aws_instance.web.public_ip.

Note

Penulisan atribut yang salah eja di dalam resource sering kali tidak menghasilkan error sintaks — Terraform hanya akan menganggapnya argumen tambahan dan mengeluh saat terraform plan. Selalu jalankan terraform validate setelah menulis resource untuk menangkap masalah ini lebih awal.

Mengenal Ragam Provider Populer

Untuk memberi gambaran luasnya ekosistem Terraform, berikut beberapa provider yang paling sering ditemui di dunia kerja:

ProviderSource (Registry)Digunakan untuk
AWShashicorp/awsEC2, S3, VPC, RDS, IAM, EKS
Azurehashicorp/azurermVM, Blob Storage, AKS, Virtual Network
Google Cloudhashicorp/googleCompute Engine, GKE, Cloud Storage, VPC
Kuberneteshashicorp/kubernetesMengelola workload di cluster K8s (deployment, service)
Dockerkreuzwerker/dockerContainer, image, network di Docker daemon
Cloudflarecloudflare/cloudflareDNS, CDN, WAF, Zero Trust

Tip

Kalian bisa menjalankan lebih dari satu provider dalam satu proyek — misalnya menyiapkan DNS record di Cloudflare untuk domain yang menunjuk ke load balancer AWS. Terraform akan membangun dependency graph lintas provider secara otomatis.

Data Sources: Membaca, Bukan Membuat

Ada kalanya kalian tidak perlu membuat resource karena objeknya sudah ada — dibuat manual oleh tim lain, atau memang infrastruktur yang tidak boleh diduplikasi (VPC perusahaan, AMI bawaan, subnet yang sudah dipartisi). Di sinilah data source bekerja.

Data source adalah blok yang hanya membaca (read-only) informasi dari cloud tanpa membuat atau mengubah apa pun. Bayangkan perbedaannya seperti ini: resource adalah kita yang membangun rumah dari nol, sedangkan data source adalah kita yang mengecek database alamat rumah yang sudah terdaftar di kelurahan.

Sintaksnya mirip resource, hanya kata kuncinya data:

hcl
data "data_source_type" "data_source_name" {
  filter = "kriteria"
}

Contoh paling klasik adalah mencari AMI Ubuntu terbaru untuk dipakai instance kita:

data.tf
data "aws_ami" "ubuntu" {
  most_recent = true
  owners      = ["099720109477"]
 
  filter {
    name   = "name"
    values = ["ubuntu/images/hvm-ssd/ubuntu-jammy-22.04-amd64-server-*"]
  }
}

owners berisi ID akun AWS resmi Canonical (pembuat Ubuntu), dan filter mempersempit hasil pencarian. Dengan most_recent = true, Terraform memilih AMI terbaru yang cocok — sehingga kalian tidak perlu mengecek AMI ID secara manual di console setiap kali rilis baru keluar.

Selanjutnya, hasil data source bisa direferensikan dengan alamat data.<type>.<name>.<attribute>:

main.tf
resource "aws_instance" "web" {
          ami           = data.aws_ami.ubuntu.id
  instance_type = "t3.micro"
}

Perhatikan referensi data.aws_ami.ubuntu.id — kata kunci data di depannya adalah penanda bahwa ia milik data source, bukan resource.

Important

Perbedaan paling penting: resource membuat dan mengelola siklus hidup objek (bisa di-update dan di-destroy), sedangkan data source hanya membaca dan tidak akan pernah dihapus oleh Terraform. Memakai data untuk sesuatu yang seharusnya resource (atau sebaliknya) adalah salah satu kesalahan arsitektur tersering pada kode Terraform.

Contoh Gabungan: Data Source + Resource + Output

Sebagai penutup pembahasan, mari kita rangkai semuanya: data source untuk mencari AMI, resource untuk membuat instance, dan satu referensi lintas blok:

main.tf
terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.0"
    }
  }
}
 
provider "aws" {
  region = "ap-southeast-1"
}
 
data "aws_ami" "ubuntu" {
  most_recent = true
  owners      = ["099720109477"]
 
  filter {
    name   = "name"
    values = ["ubuntu/images/hvm-ssd/ubuntu-jammy-22.04-amd64-server-*"]
  }
}
 
resource "aws_instance" "web" {
  ami           = data.aws_ami.ubuntu.id
  instance_type = "t3.micro"
 
  tags = {
    Name = "web-server"
  }
}
 
output "web_public_ip" {
  value = aws_instance.web.public_ip
}

Alur eksekusinya: terraform init mengunduh provider AWS → terraform plan menunjukkan bahwa satu AMI akan dibaca (data source) dan satu instance akan dibuat (resource) → terraform apply membuat instance sungguhan di AWS dan menampilkan IP publiknya.

Kesalahan Umum dalam Provider, Resource & Data Source

KesalahanGejalaSolusi
Lupa required_providersPeringatan deprecated & provider ter-resolve ambiguSelalu deklarasikan source dan version
Tidak menjalankan terraform init setelah menambah providerError provider.aws: no suitable version installedJalankan terraform init ulang
Salah menulis nama atribut resourceError saat terraform plan, bukan validateGunakan terraform validate + ekstensi editor
Hardcode AMI ID yang jarang di-refreshInstance memakai OS versi lamaPakai data source aws_ami
Data source menghasilkan banyak hasil tanpa filterError Your query returned more than one resultTambahkan most_recent = true atau filter yang lebih spesifik
Lupa alias saat memakai provider gandaResource dibuat di region yang salahDeklarasikan provider ber-alias dan referensikan lewat provider = aws.west

Penutup

Pada episode 3 ini kita telah membahas tiga pilar fundamental Terraform: provider sebagai jembatan HCL menuju cloud API beserta mekanisme required_providers dan terraform init yang mengunduhnya; resource sebagai bahan bangunan infrastruktur dengan sintaks resource "type" "name"; serta data source untuk membaca infrastruktur yang sudah ada tanpa membuatnya ulang.

Inti dari episode ini adalah pemahaman akan siapa yang berbicara dengan cloud (provider), apa yang diciptakan (resource), dan apa yang dibaca (data source). Dengan fondasi ini, kalian sudah bisa membuat konfigurasi Terraform pertama yang benar-benar menghasilkan infrastruktur nyata di cloud.

Di episode 4 selanjutnya, kita akan membuat konfigurasi ini jauh lebih fleksibel dan reusable dengan Input Variables, Local Values & Output Values — sehingga satu set kode yang sama bisa dipakai untuk environment staging maupun production. Pastikan tetap semangat!

Belajar Terraform - Providers, Resources & Data Sources | Belajar Terraform