SSD Nodes Learn 🎉 VPS mulai $5.50/bln
Panduan Matt ConnorOleh Matt Connor · Diperbarui 2026-08-07

Ansible vs Terraform: Mana yang Anda Butuhkan?

Terraform membuat VPS, sedangkan Ansible mengonfigurasinya. Pahami perbedaan keduanya, risiko provisioner, perintah serah terima, dan kapan cukup memakai Ansible.

Ansible vs Terraform dalam satu kalimat

Ansible vs Terraform bukan pilihan antara dua tool yang melakukan pekerjaan yang sama. Terraform mendeklarasikan infrastruktur yang tersedia: server, disk, jaringan, dan record DNS. Ansible mendeklarasikan kondisi di dalam mesin yang sudah tersedia: paket, pengguna, file konfigurasi, dan service yang berjalan. Terraform membuat VPS. Ansible mengubah VPS tersebut menjadi web server.

Keduanya bersifat deklaratif, dan keduanya disebut infrastructure as code (IaC). Perbedaan sebenarnya terletak pada hal yang diingat oleh masing-masing tool. Terraform menulis file state yang memetakan setiap resource dalam kode Anda ke objek nyata yang dibuatnya melalui API. Dengan demikian, Terraform dapat mengetahui bahwa penghapusan lima baris berarti satu server harus dihancurkan. Ansible tidak menyimpan apa pun di antara eksekusi. Ansible terhubung melalui SSH, memeriksa mesin, lalu hanya mengubah hal-hal yang belum sesuai dengan playbook.

Satu perbedaan ini menjelaskan bagian lain dalam panduan ini, termasuk alasan mencampurkan kedua pekerjaan tersebut ke dalam satu tool dapat menimbulkan masalah.

Yang sebenarnya dilakukan Terraform

Terraform berkomunikasi dengan API melalui plugin provider. Halaman registry provider Anda menentukan jenis resource yang dapat ditulis. Karena itu, server pada satu host dan server pada host lain memiliki nama resource yang berbeda, dengan argumen yang berbeda.

resource "cloud_server" "web" {
  name  = "web1"
  image = "ubuntu-24.04"
  type  = "small"
}

output "web_ip" {
  value = cloud_server.web.ipv4_address
}

Ganti cloud_server dengan jenis resource yang didokumentasikan oleh provider Anda. Blok output adalah bagian penting dalam panduan ini karena blok tersebut menentukan cara alamat keluar dari Terraform.

terraform init
terraform fmt -check
terraform validate
terraform plan -out=tfplan
terraform apply tfplan

terraform init mengunduh provider dan menulis file lock. terraform plan menampilkan perbedaan antara kode Anda dan file state, lalu mengakhirinya dengan baris seperti Plan: 1 to add, 0 to change, 0 to destroy.. Baca baris tersebut setiap kali. Beberapa argumen tidak dapat diubah secara langsung. Plan menandainya dengan # forces replacement di samping atribut, diikuti 1 to add, 0 to change, 1 to destroy. Jika plan tersebut diterapkan, server akan dihapus dan server kosong baru akan dibuat. Akibatnya, data yang dianggap aman dapat hilang.

Menyimpan plan ke file lalu menerapkan file tersebut, alih-alih menjalankan terraform apply tanpa argumen, memastikan bahwa konfigurasi yang Anda tinjau adalah konfigurasi yang dijalankan. Di antara kedua perintah tersebut, orang lain mungkin telah mengubah infrastruktur.

terraform.tfstate adalah penyimpan informasi Terraform. Jika informasi tersebut hilang, Terraform tidak lagi mengetahui bahwa server-server tersebut adalah milik Anda. Apply berikutnya akan mencoba membuat duplikat. Simpan informasi tersebut di backend jarak jauh segera setelah lebih dari satu orang menjalankan perintah, karena dua orang yang melakukan apply secara bersamaan akan menghasilkan kondisi berikut:

Error: Error acquiring the state lock

OpenTofu adalah fork Terraform yang menggunakan perintah dan format file yang sama. Per Juli 2026, semua hal dalam panduan ini berfungsi jika Anda mengetik tofu sebagai pengganti terraform.

Yang sebenarnya dilakukan Ansible

Ansible tidak memerlukan agent atau API. Ansible membuka koneksi SSH, menyalin modul Python kecil ke target, menjalankannya, lalu menghapusnya. Apa pun yang dapat Anda akses melalui SSH dan password sudo dapat dikonfigurasi oleh Ansible.

- name: Base web server
  hosts: web
  become: true
  tasks:
    - name: Install nginx
      ansible.builtin.apt:
        name: nginx
        state: present
        update_cache: true

    - name: Ensure nginx is running at boot
      ansible.builtin.service:
        name: nginx
        state: started
        enabled: true
ansible -i inventory.ini web -m ansible.builtin.ping
ansible-playbook -i inventory.ini site.yml --check --diff
ansible-playbook -i inventory.ini site.yml

Modul ping memverifikasi SSH, Python, dan sudo sebelum Anda mulai men-debug playbook. Hasil yang sehat adalah web1 | SUCCESS => {"ping": "pong"}. Perintah --check --diff adalah hal yang paling mendekati rencana dalam Ansible: perintah ini melaporkan perubahan yang akan dilakukan tanpa menerapkannya. Namun, task yang bergantung pada task sebelumnya dapat melaporkan hasil yang salah dalam check mode karena perubahan sebelumnya tidak pernah benar-benar terjadi.

Setiap eksekusi berakhir dengan ringkasan seperti ok=6 changed=2 unreachable=0 failed=0. Jalankan playbook yang sama dua kali. Eksekusi kedua seharusnya melaporkan changed=0. Task yang melaporkan changed pada setiap eksekusi tidak bersifat idempoten. Biasanya, task tersebut berupa task command atau shell yang seharusnya menggunakan modul sebenarnya. Jika ini merupakan hal baru bagi Anda, mulai dengan playbook Ansible pertama pada satu VPS lalu kembangkan dari sana.

Di mana kedua alat ini tumpang tindih dan di mana keduanya saling mengganggu

Terraform dapat menjalankan perintah pada server baru dengan provisioner remote-exec. Dokumentasi HashiCorp sendiri menyebut provisioner sebagai pilihan terakhir. Ada alasan yang kuat untuk itu.

Provisioner hanya berjalan saat resource dibuat. Jika skrip diedit, tidak ada perubahan pada server yang sudah ada karena menurut Terraform, resource tersebut sudah sesuai dengan kode. Langkah provisioner tidak pernah muncul dalam terraform plan, sehingga hasil review tidak menunjukkan keberadaannya. Jika skrip gagal, Terraform menandai resource sebagai tainted. Pada apply berikutnya, Terraform akan menghapus dan membuat ulang server yang kemungkinan sebenarnya masih baik.

Waktu terjadinya kegagalan juga tidak tepat. Provider melaporkan server telah dibuat segera setelah API menyatakan demikian, sementara sistem operasi masih melakukan boot dan sshd belum listening.

Error: remote-exec provisioner error
timeout - last error: dial tcp 203.0.113.10:22: connect: connection refused

Ansible memiliki godaan yang berlawanan. Modul cloud dapat membuat server, dan pendekatan ini dapat bekerja untuk beberapa mesin. Namun, Anda kehilangan dependency graph dan state file. Ansible akan membuat resource tanpa masalah, tetapi jika task tersebut dihapus dari playbook, resource itu tetap berjalan dan biaya tetap dibebankan karena tidak ada catatan bahwa resource tersebut pernah dibuat oleh Ansible.

Aturan yang dapat diterapkan adalah: biarkan Terraform mengelola objek yang dibuat dan dihapus oleh API, dan biarkan Ansible mengelola segala sesuatu di dalam sistem operasi yang sudah selesai boot.

Serah terima yang berhasil

Serah terima adalah batas antartahap, bukan integrasi. Terraform selesai, menerbitkan sebuah alamat, lalu berhenti. Ansible dimulai dari alamat tersebut.

terraform apply -auto-approve
terraform output -raw web_ip
printf '[web]\n%s ansible_user=root\n' "$(terraform output -raw web_ip)" > inventory.ini
ansible -i inventory.ini web -m ansible.builtin.ping
ansible-playbook -i inventory.ini site.yml

terraform output -raw mencetak satu nilai tanpa tanda kutip dan tanpa pembungkus JSON. Format ini sesuai untuk digunakan dalam substitusi shell. Untuk beberapa server, gunakan terraform output -json lalu buat inventory dari hasilnya, karena -raw hanya menangani satu string, angka, atau boolean.

Langkah ping di antara kedua alat tersebut tetap perlu dipertahankan. Langkah ini membedakan "Terraform memberikan alamat yang salah kepada saya" dari "playbook saya memiliki bug". Kedua masalah tersebut terlihat sama jika playbook menjadi hal pertama yang menyentuh server baru.

Membaca state Terraform sebagai inventory Ansible

Jika Anda tidak ingin menulis file inventory sama sekali, koleksi cloud.terraform membaca state secara langsung.

ansible-galaxy collection install cloud.terraform

Tulis terraform.yml di samping playbook Anda:

plugin: cloud.terraform.terraform_provider
project_path: /home/deploy/infra
ansible-inventory -i terraform.yml --graph
ansible-playbook -i terraform.yml site.yml

Ada dua hal yang perlu diketahui sebelum Anda mengandalkannya. Plugin ini menjalankan terraform show terhadap project_path, sehingga direktori tersebut harus sudah diinisialisasi. Jika tidak, plugin akan gagal. Plugin ini juga tidak membuat host dari resource server Anda. Plugin membaca resource ansible_host dan ansible_group, yang Anda deklarasikan dalam kode Terraform menggunakan provider Ansible. Tidak ada apa pun yang muncul di ansible-inventory --graph sampai Anda menambahkannya.

File inventory hasil generate biasa lebih mudah di-debug dan berfungsi dengan provider apa pun. Plugin ini mulai bermanfaat setelah inventory berkembang melampaui beberapa mesin dan pengeditan manual mulai menimbulkan salah ketik. Pada titik yang sama, mengelola beberapa server Linux dari satu mesin kontrol berubah menjadi alur kerja nyata, bukan sekadar kebiasaan.

Apakah Anda benar-benar membutuhkan Terraform?

Sebagian besar pembaca tidak membutuhkannya, setidaknya belum. Terraform sepadan dengan biaya dan kompleksitasnya ketika pembuatan dan penghapusan infrastruktur menjadi tugas yang berulang. Jika Anda memesan satu VPS melalui panel kontrol dan berencana menggunakannya selama dua tahun, Terraform hanya mendeskripsikan sesuatu yang terjadi sekali. Selain itu, Terraform menambahkan state file yang tidak boleh hilang.

Gunakan Terraform ketika Anda sering membangun ulang environment, ketika staging harus sama persis dengan production, ketika beberapa orang mengubah infrastruktur dan Anda menginginkan plan yang dapat ditinjau sebelum sesuatu dihapus, atau ketika hal yang Anda kelola mencakup lebih dari sekadar server, seperti DNS record, load balancer, dan firewall rule yang berada dalam provider API.

Gunakan Ansible saja ketika server berumur panjang dan jumlahnya sedikit, serta pertanyaan sehari-hari adalah "apakah server ini telah dikonfigurasi dengan benar", bukan "apakah server ini ada". Satu playbook untuk memperkuat konfigurasi server baru mencakup hal yang sama seperti sepuluh menit pertama pada VPS baru, dengan kelebihan bahwa playbook tersebut dapat dijalankan dengan cara yang sama pada server berikutnya.

Urutan pembelajaran mengikuti pertimbangan tersebut. Ansible mulai memberikan manfaat sejak server pertama yang Anda miliki. Terraform mulai memberikan manfaat ketika Anda membangun ulang environment yang ketiga.

Masalah pada serah terima

Server belum siap. Terraform berhasil, tetapi Ansible langsung gagal.

fatal: [web1]: UNREACHABLE! => {"changed": false, "msg": "Failed to connect to the host via ssh: ssh: connect to host 203.0.113.10 port 22: Connection refused", "unreachable": true}

API mengembalikan alamat sebelum sshd mulai listening. Tunggu port tersebut, bukan menambahkan jeda tetap. Ansible menyediakan ansible.builtin.wait_for_connection khusus untuk keperluan ini. Jalankan sebagai task pertama dalam play.

Host key berubah. Anda menghapus dan membuat ulang server. Server baru merespons pada alamat yang sama dengan key baru.

Host key verification failed.

Hapus entri lama dengan ssh-keygen -R 203.0.113.10. Hal ini sering terjadi setelah Terraform menangani pembuatan ulang server. Karena itu, sebaiknya pembuatan ulang jarang dilakukan pada mesin yang menyimpan data.

Sudo gagal. fatal: [web1]: FAILED! => {"msg": "Missing sudo password"} berarti become: true memerlukan password pada host tersebut. Konfigurasikan sudo tanpa password untuk user deploy, atau teruskan --ask-become-pass.

Terraform ingin menghancurkan sesuatu yang tidak Anda ubah. Plan menampilkan perubahan yang tidak pernah Anda tulis. Ini berarti infrastruktur aktual telah menyimpang dari kode, biasanya karena seseorang mengubah pengaturan pada panel web provider. Jalankan terraform plan -refresh-only untuk melihat perbedaan tersebut saja, lalu tentukan apakah kode atau resource aktif yang salah. Jangan pernah menerapkan plan destruktif yang tidak dapat Anda jelaskan baris demi baris.

Ansible melaporkan changed pada setiap eksekusi. Task shell tanpa guard creates atau when selalu dijalankan. Ini bukan sekadar masalah tampilan, karena Anda tidak lagi dapat menggunakan changed=0 sebagai indikator bahwa server berada dalam kondisi yang diminta.

FAQ

Dapatkah Terraform menggantikan Ansible?

Tidak untuk konfigurasi di dalam server. Terraform dapat menjalankan skrip dengan provisioner remote-exec, tetapi skrip tersebut hanya dijalankan saat resource dibuat, tidak pernah muncul di terraform plan, dan menandai resource sebagai tainted jika gagal. Kondisi ini menjadwalkan penghapusan dan pembuatan ulang pada apply berikutnya. Terraform tidak memiliki padanan modul yang memeriksa apakah nginx sudah terpasang dan tidak melakukan apa pun jika memang sudah terpasang. Gunakan Terraform untuk membuat mesin, lalu serahkan pengelolaannya.

Dapatkah Ansible menggantikan Terraform?

Untuk sejumlah kecil server yang digunakan dalam jangka panjang, ya. Ansible memiliki modul cloud untuk membuat server. Jika Anda memesan dua instance VPS dan mempertahankannya, itu sudah cukup. Namun, Anda kehilangan state file dan dependency graph. Jika Anda menghapus task dari playbook, resource tersebut tetap berjalan dan tetap menimbulkan biaya karena Ansible tidak pernah mencatat bahwa resource itu dibuat olehnya. Terraform seharusnya akan merencanakan destroy.

Mana yang harus saya pelajari terlebih dahulu?

Ansible, jika saat ini Anda memiliki server. Ansible memberikan manfaat sejak mesin pertama, hanya memerlukan SSH, dan keterampilannya dapat diterapkan pada server yang Anda pesan secara manual. Terraform memberikan manfaat kemudian, saat Anda berulang kali membuat ulang environment atau mengelola resource provider selain server, seperti DNS record dan firewall rule.

Bagaimana cara meneruskan IP server baru dari Terraform ke Ansible?

Deklarasikan output dalam kode Terraform Anda, lalu baca nilainya setelah apply. terraform output -raw web_ip mencetak nilai mentah untuk substitusi shell, sedangkan terraform output -json memberikan semua output sekaligus jika terdapat beberapa host. Tulis nilai tersebut ke dalam file inventory, atau instal collection cloud.terraform dan arahkan ansible-inventory -i terraform.yml --graph ke direktori project.

Mengapa playbook saya gagal tepat setelah Terraform selesai?

Provider melaporkan server sebagai telah dibuat segera setelah API-nya menyatakan demikian, sementara sistem operasi masih melakukan boot. Akibatnya, koneksi SSH ditolak selama beberapa detik pertama. Error tersebut adalah UNREACHABLE! dengan Connection refused. Jadikan ansible.builtin.wait_for_connection sebagai task pertama dalam play, alih-alih menebak durasi sleep, karena waktu boot berbeda-beda bergantung pada image dan plan.