Provider #
Provider adalah komponen yang membuat Terraform bisa berbicara dengan dunia luar. Tanpa provider, Terraform hanya tahu cara membaca file HCL — ia tidak tahu cara membuat EC2 instance, membuat DNS record, atau mengkonfigurasi Kubernetes cluster. Provider-lah yang menerjemahkan instruksi di file .tf-mu menjadi panggilan API ke layanan yang sebenarnya. Memahami bagaimana provider bekerja di balik layar, cara mengkonfigurasinya dengan benar, dan pola penggunaan multi-provider akan membantu kamu membangun konfigurasi Terraform yang robust dan maintainable.
Apa itu Provider #
Provider adalah plugin binary yang memperluas kemampuan Terraform agar bisa berinteraksi dengan layanan eksternal tertentu. Setiap provider menyediakan sekumpulan resource type dan data source yang bisa kamu gunakan dalam konfigurasi. Ketika kamu menulis resource "aws_instance" "web", prefix aws di situ merujuk ke provider AWS — provider inilah yang tahu cara memanggil AWS EC2 API untuk membuat, mengubah, dan menghapus instance.
flowchart TD
A["File Konfigurasi (.tf)"] --> B["Terraform Core"]
B --> C["Provider Plugin\n(AWS / GCP / Azure / Cloudflare)"]
C --> D["API Layanan Eksternal"]
D --> E["Resource dibuat\ndiubah / dihapus"]
F["terraform init"] -->|"Download & install"| C
G[".terraform.lock.hcl"] -->|"Pin versi"| C
style A fill:#e3f2fd,stroke:#1565c0
style B fill:#f3e5f5,stroke:#7b1fa2
style C fill:#e8f5e9,stroke:#2e7d32
style D fill:#fff3e0,stroke:#e65100
style E fill:#fff3e0,stroke:#e65100Provider tidak hanya untuk cloud. Ada provider untuk DNS (Cloudflare, Route53), monitoring (Datadog, Grafana), SaaS (GitHub, PagerDuty), database (PostgreSQL, MySQL), dan bahkan untuk utilitas lokal (null, local, random). Setiap layanan yang punya API bisa punya provider Terraform.
Mengkonfigurasi Provider #
Setiap provider perlu dideklarasikan di blok required_providers dan dikonfigurasi di blok provider. Deklarasi memberitahu Terraform provider apa yang dibutuhkan dan dari mana mengunduhnya. Konfigurasi memberikan credential dan parameter yang dibutuhkan provider untuk terhubung ke layanan.
# Langkah 1: Deklarasikan provider yang dibutuhkan di terraform block
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
cloudflare = {
source = "cloudflare/cloudflare"
version = "~> 4.0"
}
}
}
# Langkah 2: Konfigurasi provider
# Credential diambil dari environment variable, bukan hardcode
provider "aws" {
region = "ap-southeast-1"
}
provider "cloudflare" {
api_token = var.cloudflare_api_token
}
# Langkah 3: Download provider (hanya perlu sekali atau saat versi berubah)
$ terraform init
Initializing the backend...
Initializing provider plugins...
- Finding cloudflare/cloudflare versions matching "~> 4.0"...
- Finding hashicorp/aws versions matching "~> 5.0"...
- Installing hashicorp/aws v5.31.0...
- Installing cloudflare/cloudflare v4.22.0...
Terraform has been successfully initialized!
Jangan pernah hardcode credential (access key, secret, token) langsung di dalam blokprovider. File konfigurasi Terraform masuk ke version control — credential yang hardcode akan bocor ke repository. Gunakan environment variable,.tfvarsfile yang di-gitignore, atau secrets manager.
Urutan Deklarasi dan Konfigurasi #
Terraform tidak peduli urutan blok di dalam file .tf. Kamu bisa menulis provider sebelum terraform {} atau sesudahnya — hasilnya sama. Yang penting adalah keduanya ada dan benar secara sintaks.
# Urutan apapun valid — tulis dalam urutan yang paling readable
# Opsi 1: terraform block dulu (lebih umum)
terraform {
required_providers {
aws = { source = "hashicorp/aws", version = "~> 5.0" }
}
}
provider "aws" {
region = "ap-southeast-1"
}
# Opsi 2: provider block dulu (juga valid)
provider "aws" {
region = "ap-southeast-1"
}
terraform {
required_providers {
aws = { source = "hashicorp/aws", version = "~> 5.0" }
}
}
Versi Provider dan Kenapa Penting #
Pinning versi provider adalah praktik wajib, bukan opsional. Provider bisa release breaking change yang merusak konfigurasi yang sudah berjalan. Tanpa version constraint, terraform init akan mengunduh versi terbaru — yang mungkin saja tidak kompatibel dengan konfigurasimu.
Operator Version Constraint #
HCL menyediakan beberapa operator untuk version constraint:
| Operator | Arti | Contoh | Yang cocok |
|---|---|---|---|
= 5.31.0 | Persis versi ini | version = "= 5.31.0" | Jarang dipakai, terlalu ketat |
>= 5.0 | Lebih besar atau sama | version = ">= 5.0" | Terlalu longgar, tidak aman |
~> 5.31 | >= 5.31.0, < 6.0.0 | version = "~> 5.31" | Paling umum dan direkomendasikan |
>= 5.0, < 6.0 | Range eksplisit | version = ">= 5.0, < 6.0" | Sama dengan ~> 5.0 |
Operator ~> (pessimistic constraint) adalah yang paling umum digunakan. Ia memungkinkan patch update tapi mencegah major version upgrade yang berpotensi breaking.
# ANTI-PATTERN: Tidak pin versi
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
# Tanpa version constraint
# → terraform init download versi terbaru
# → Provider v6 bisa breaking change dari v5
# → Konfigurasi yang sudah berjalan bisa rusak
}
}
}
# ANTI-PATTERN: Pin terlalu ketat
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "= 5.31.0" # Hanya versi persis ini
# → Tidak bisa patch update
# → Security fix di 5.31.1 tidak masuk
# → Tim lain harus pin versi yang sama persis
}
}
}
# BENAR: Pin ke range versi yang aman
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.31"
# → >= 5.31.0 dan < 6.0.0
# → Patch update (5.31.1, 5.32.0) diterima
# → Major update (6.0.0) ditolak
}
}
}
Lock File #
Setelah terraform init, Terraform membuat file .terraform.lock.hcl yang mencatat versi provider yang diinstall beserta hash-nya. File ini harus di-commit ke version control.
# .terraform.lock.hcl — commit file ini!
provider "registry.terraform.io/hashicorp/aws" {
version = "5.31.0"
constraints = "~> 5.31"
hashes = [
"h1:abcdef1234567890...",
]
}
provider "registry.terraform.io/cloudflare/cloudflare" {
version = "4.22.0"
constraints = "~> 4.0"
hashes = [
"h1:fedcba0987654321...",
]
}
Lock file menjamin bahwa semua anggota tim menggunakan versi provider yang identik, bahkan jika ada rilis baru di antara waktu developer A dan developer B menjalankan terraform init.
# Update provider ke versi terbaru dalam constraint
$ terraform init -upgrade
# Update hanya provider tertentu
$ terraform init -upgrade=hashicorp/aws
flowchart TD
A["terraform init"] --> B{"Ada\n.terraform.lock.hcl?"}
B -->|"Ya"| C["Gunakan versi di lock file"]
B -->|"Tidak"| D["Download versi terbaru\n(dalam constraint)"]
C --> E["Lock file di-commit\nke version control"]
D --> E
E --> F["Semua tim menggunakan\nversi provider yang sama"]
style C fill:#e8f5e9,stroke:#2e7d32
style D fill:#e3f2fd,stroke:#1565c0
style F fill:#e8f5e9,stroke:#2e7d32Multi-Provider #
Terraform bisa menggunakan lebih dari satu provider sekaligus. Ini sangat umum digunakan untuk mengelola resource di beberapa region, beberapa cloud, atau beberapa layanan berbeda dari satu konfigurasi.
Multi-Region dengan Alias #
Ketika kamu butuh menggunakan provider yang sama dengan konfigurasi berbeda (misalnya AWS di region berbeda), gunakan alias.
# Provider default — tanpa alias
provider "aws" {
region = "ap-southeast-1" # Singapore
}
# Provider dengan alias — untuk region lain
provider "aws" {
alias = "us_east"
region = "us-east-1" # Virginia
}
provider "aws" {
alias = "eu_west"
region = "eu-west-1" # Ireland
profile = "production" # Bisa pakai profile berbeda
}
# Resource menggunakan provider default (tanpa provider argument)
resource "aws_s3_bucket" "asia" {
bucket = "app-assets-asia"
}
# Resource menggunakan provider dengan alias (eksplisit)
resource "aws_s3_bucket" "us" {
provider = aws.us_east
bucket = "app-assets-us"
}
resource "aws_s3_bucket" "eu" {
provider = aws.eu_west
bucket = "app-assets-eu"
}
Multi-Cloud #
Terraform bisa mengelola resource dari beberapa cloud provider sekaligus. Ini berguna untuk arsitektur multi-cloud atau ketika kamu menggunakan layanan dari vendor berbeda.
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
google = {
source = "hashicorp/google"
version = "~> 5.0"
}
cloudflare = {
source = "cloudflare/cloudflare"
version = "~> 4.0"
}
}
}
# Masing-masing provider dikonfigurasi terpisah
provider "aws" {
region = "ap-southeast-1"
}
provider "google" {
project = var.gcp_project
region = "asia-southeast1"
}
provider "cloudflare" {
api_token = var.cloudflare_token
}
# Resource dari berbagai provider dalam satu konfigurasi
resource "aws_instance" "app" {
ami = "ami-0abcdef1234567890"
instance_type = "t3.medium"
}
resource "google_dns_managed_zone" "main" {
name = "example-zone"
dns_name = "example.com."
}
resource "cloudflare_record" "app" {
zone_id = var.cloudflare_zone_id
name = "app"
value = aws_instance.app.public_ip
type = "A"
proxied = true
}
default_tags dan Konfigurasi Provider Tambahan
#
Provider AWS mendukung default_tags yang otomatis menambahkan tag ke semua resource yang dikelolanya. Ini sangat berguna untuk cost allocation dan resource tracking.
provider "aws" {
region = "ap-southeast-1"
default_tags {
tags = {
Environment = var.environment
Project = var.project_name
ManagedBy = "terraform"
Team = "platform-engineering"
}
}
}
# Semua resource di bawah ini otomatis mendapat tag di atas
resource "aws_instance" "web" {
ami = "ami-0abcdef1234567890"
instance_type = "t3.micro"
tags = {
Name = "web-server"
# Tag di atas ditambahkan ke default_tags
# Hasil: Name, Environment, Project, ManagedBy, Team
}
}
Mencari dan Memilih Provider #
Semua provider tersedia di Terraform Registry di registry.terraform.io. Format source address selalu mengikuti pola namespace/name.
| Namespace | Tipe | Contoh |
|---|---|---|
hashicorp/ | Provider resmi HashiCorp | hashicorp/aws, hashicorp/google |
integrations/ | Provider resmi vendor | integrations/github, integrations/gitlab |
| Vendor langsung | Provider dari vendor | cloudflare/cloudflare, datadog/datadog |
| Komunitas | Provider dari komunitas | cyrilgdn/postgresql, aidan-melen/eksa |
terraform {
required_providers {
# Provider resmi HashiCorp
aws = { source = "hashicorp/aws", version = "~> 5.0" }
azurerm = { source = "hashicorp/azurerm", version = "~> 3.0" }
google = { source = "hashicorp/google", version = "~> 5.0" }
kubernetes = { source = "hashicorp/kubernetes", version = "~> 2.0" }
# Provider dari vendor
cloudflare = { source = "cloudflare/cloudflare", version = "~> 4.0" }
datadog = { source = "datadog/datadog", version = "~> 3.0" }
github = { source = "integrations/github", version = "~> 6.0" }
# Provider utilitas (built-in, tidak perlu download)
null = { source = "hashicorp/null" }
local = { source = "hashicorp/local" }
random = { source = "hashicorp/random" }
}
}
Provider Utilitas #
Beberapa provider tidak menghubungkan Terraform ke layanan eksternal — mereka menyediakan utilitas lokal yang berguna dalam konfigurasi.
# null_resource — untuk menjalankan provisioner atau trigger
resource "null_resource" "setup" {
triggers = {
always_run = timestamp() # Selalu run
}
provisioner "local-exec" {
command = "echo 'Setup complete'"
}
}
# random_string — untuk menghasilkan nilai random
resource "random_string" "suffix" {
length = 8
special = false
upper = false
}
resource "aws_s3_bucket" "logs" {
bucket = "app-logs-${random_string.suffix.result}"
# Hasil: app-logs-a1b2c3d4
}
# local_file — untuk membuat file lokal
resource "local_file" "config" {
content = jsonencode({ endpoint = aws_instance.web.public_ip })
filename = "${path.module}/generated/config.json"
}
Authentication Patterns #
Provider membutuhkan credential untuk terhubung ke layanan. Ada beberapa pola authentication yang bisa digunakan, masing-masing dengan kelebihan dan trade-off.
Environment Variable (Paling Umum) #
# Set environment variable sebelum terraform plan/apply
export AWS_ACCESS_KEY_ID="AKIAIOSFODNN7EXAMPLE"
export AWS_SECRET_ACCESS_KEY="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"
export AWS_DEFAULT_REGION="ap-southeast-1"
# Untuk provider lain
export CLOUDFLARE_API_TOKEN="your-api-token"
export DATADOG_API_KEY="your-api-key"
export DATADOG_APP_KEY="your-app-key"
AWS Profile #
# Menggunakan AWS profile dari ~/.aws/credentials
provider "aws" {
region = "ap-southeast-1"
profile = "production" # Nama profile
}
Assume Role (AWS) #
# Assume role di account lain
provider "aws" {
region = "ap-southeast-1"
assume_role {
role_arn = "arn:aws:iam::123456789012:role/TerraformRole"
session_name = "terraform-session"
}
}
OIDC Token (CI/CD Modern) #
# GitHub Actions OIDC — tidak perlu simpan AWS key
provider "aws" {
region = "ap-southeast-1"
assume_role_with_web_identity {
role_arn = var.github_actions_role_arn
web_identity_token_file = "/tmp/oidc-token"
}
}
flowchart TD
A["Pilih Authentication"] --> B{"Running di mana?"}
B -->|"Lokal (development)"| C["AWS Profile\n~/.aws/credentials"]
B -->|"CI/CD Pipeline"| D{"Cloud Provider CI?"}
D -->|"GitHub Actions"| E["OIDC Token\n(tanpa stored credentials)"]
D -->|"GitLab CI"| F["CI/CD Variables\n(environment variable)"]
D -->|"Jenkins / Self-hosted"| G["Secrets Manager\n(Vault, AWS SM)"]
B -->|"Production Server"| H["IAM Role\n(instance profile)"]
style C fill:#e3f2fd,stroke:#1565c0
style E fill:#e8f5e9,stroke:#2e7d32
style F fill:#e3f2fd,stroke:#1565c0
style G fill:#fff3e0,stroke:#e65100
style H fill:#e8f5e9,stroke:#2e7d32Troubleshooting Provider #
Masalah provider adalah salah satu issue yang paling umum di Terraform. Berikut beberapa masalah dan solusinya.
Provider Not Found #
# Error: provider registry.terraform.io/hashicorp/xyz not found
# Penyebab: typo di source address atau provider tidak ada di registry
# Solusi: cek nama provider di registry.terraform.io
Version Conflict #
# Error: provider constraints conflict
# Module A butuh aws ~> 5.0, module B butuh aws ~> 4.0
# Solusi: update module B agar kompatibel dengan v5
# atau gunakan satu versi constraint di root module
Authentication Failed #
# Error: InvalidClientTokenId: The security token included is invalid
# Penyebab: credential salah atau expired
# Solusi: cek credential
$ aws sts get-caller-identity # Untuk AWS
$ terraform providers mirror ./mirror # Cache provider secara lokal
Ringkasan #
- Provider adalah plugin yang menghubungkan Terraform dengan API layanan eksternal — tanpa provider, Terraform tidak bisa membuat resource apapun.
- Provider diinstall otomatis saat
terraform init— kamu hanya perlu mendeklarasikannya di blokrequired_providersdengansourcedanversion.- Selalu pin versi provider dengan
version = "~> X.Y"untuk mencegah breaking change yang tidak terduga dari major version upgrade.- Commit
.terraform.lock.hclke version control agar semua anggota tim menggunakan versi provider yang identik.- Multi-provider dengan alias memungkinkan kamu mengelola resource di region, account, atau cloud yang berbeda dari satu konfigurasi Terraform.
- Jangan hardcode credential — gunakan environment variable, AWS profile, assume role, atau OIDC token tergantung environment.
default_tagsdi provider AWS menambahkan tag otomatis ke semua resource — sangat berguna untuk cost allocation.