Ansible ve Terraform Arasındaki Fark Nedir?
Terraform altyapı oluştururken Ansible sunucu yapılandırması yapar. Hangi aracın ne zaman kullanılacağını, durum dosyası mantığını ve iki aracın entegrasyonunu öğrenin.
Ansible ve Terraform tek cümleyle
Ansible ve Terraform aynı işi yapan iki araç arasında bir seçim değildir. Terraform mevcut altyapıyı (sunucular, diskler, ağlar, DNS kayıtları) tanımlar. Ansible ise halihazırda var olan bir makinenin içindeki durumu (paketler, kullanıcılar, yapılandırma dosyaları, çalışan servisler) tanımlar. Terraform VPS'i oluşturur; Ansible ise bu VPS'i bir web sunucusuna dönüştürür.
Her ikisi de bildirimseldir ve her ikisi de kod olarak altyapı (IaC) olarak adlandırılır. Aralarındaki temel fark, neyi hatırladıklarıdır. Terraform, kodunuzdaki her kaynağı API aracılığıyla oluşturduğu gerçek bir nesneyle eşleyen bir durum dosyası (state file) yazar; böylece koddan beş satır silmenin bir sunucunun yok edilmesi gerektiği anlamına geldiğini anlayabilir. Ansible ise çalıştırmalar arasında hiçbir şeyi hatırlamaz. SSH üzerinden bağlanır, makineyi inceler ve yalnızca playbook ile eşleşmeyen kısımları değiştirir.
Bu tek fark, rehberin geri kalanını ve iki işin tek bir araçta birleştirilmesinin neden hatalı sonuçlar doğurduğunu açıklar.
Terraform gerçekte ne yapar
Terraform, bir sağlayıcı eklentisi aracılığıyla API ile iletişim kurar. Sağlayıcınızın kayıt sayfası, yazabileceğiniz kaynak türlerini tanımlar; bu nedenle bir ana bilgisayardaki sunucu ile diğerindeki sunucu, farklı argümanlara sahip farklı kaynak isimleridir.
resource "cloud_server" "web" {
name = "web1"
image = "ubuntu-24.04"
type = "small"
}
output "web_ip" {
value = cloud_server.web.ipv4_address
}cloud_server kısmını, sağlayıcınızın dokümante ettiği kaynak türüyle değiştirin. output bloğu, bu rehber için önemli olan kısımdır çünkü adresin Terraform'dan çıkış yolu budur.
terraform init
terraform fmt -check
terraform validate
terraform plan -out=tfplan
terraform apply tfplanterraform init, sağlayıcıyı indirir ve bir kilit dosyası oluşturur. terraform plan, kodunuz ile durum dosyası arasındaki farkı yazdırır ve Plan: 1 to add, 0 to change, 0 to destroy. gibi bir satırla biter. Bu satırı her seferinde okuyun. Bazı argümanlar yerinde değiştirilemez; plan, özniteliğin yanında # forces replacement ifadesiyle bunu belirtir ve ardından 1 to add, 0 to change, 1 to destroy gelir. Bu planı uygulamak, sunucuyu silip yerine yeni ve boş bir tane oluşturur; insanlar güvende olduğunu düşündükleri verileri bu şekilde kaybederler.
Planı bir dosyaya kaydedip o dosyayı uygulamak, doğrudan terraform apply çalıştırmaktan daha güvenlidir; çünkü incelediğiniz şeyin çalıştırılmasını sağlar. İki komut arasında başka biri altyapıyı değiştirmiş olabilir.
terraform.tfstate, hafızadır. Bunu kaybederseniz Terraform artık o sunucuların size ait olduğunu bilmez ve bir sonraki uygulama işlemi kopyalarını oluşturmaya çalışır. Komutları birden fazla kişi çalıştırdığında, bunu hemen uzak bir backend üzerinde tutun; çünkü aynı anda iki kişinin uygulama yapması şu sonucu doğurur:
Error: Error acquiring the state lockOpenTofu, aynı komutlara ve aynı dosya biçimine sahip bir Terraform çatalıdır (fork). Temmuz 2026 itibarıyla, terraform yerine tofu yazarsanız bu rehberdeki her şey çalışır.
Ansible'ın gerçek işlevi
Ansible, herhangi bir aracı (agent) veya API gerektirmez. Hedef sunucuya bir SSH bağlantısı açar, küçük bir Python modülünü kopyalar, çalıştırır ve ardından siler. SSH ve sudo parolası ile erişebildiğiniz her şeyi Ansible ile yapılandırabilirsiniz.
- 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: trueansible -i inventory.ini web -m ansible.builtin.ping
ansible-playbook -i inventory.ini site.yml --check --diff
ansible-playbook -i inventory.ini site.ymlping modülü, bir playbook üzerinde hata ayıklamaya başlamadan önce SSH, Python ve sudo erişimini doğrular. Sağlıklı bir sonuç web1 | SUCCESS => {"ping": "pong"} çıktısını verir. --check --diff çalıştırması, Ansible'ın bir plana en yakın halidir: herhangi bir değişiklik yapmadan nelerin değişeceğini raporlar. Ancak önceki görevlere bağlı olan görevler, önceki değişiklikler aslında gerçekleşmediği için kontrol modunda hatalı rapor verebilir.
Her çalıştırma, ok=6 changed=2 unreachable=0 failed=0 gibi bir özetle sona erer. Aynı playbook'u iki kez çalıştırın. İkinci çalıştırma changed=0 raporunu vermelidir. Her çalıştırmada "changed" (değişti) raporu veren bir görev idempotent (eşgüçlü) değildir; bu genellikle gerçek bir modül olması gerekirken command veya shell olarak yazılmış bir görevdir. Eğer bu konuda yeniyseniz, tek bir VPS üzerinde ilk Ansible playbook'unuzu oluşturma rehberi ile başlayıp buradan ilerleyebilirsiniz.
İki aracın çakıştığı ve çatıştığı noktalar
Terraform, remote-exec provisioner kullanarak yeni bir sunucuda komutlar çalıştırabilir. HashiCorp'un kendi dokümantasyonu, provisioner'ları son çare olarak tanımlar. Bunun geçerli nedenleri vardır.
Bir provisioner yalnızca kaynak oluşturulduğunda çalışır. Betiği düzenlediğinizde mevcut sunucuda hiçbir şey değişmez; çünkü Terraform açısından kaynak zaten kodla uyumludur. Provisioner adımları terraform plan içinde asla görünmez, bu nedenle incelemenizde bunlara dair hiçbir iz bulunmaz. Betik başarısız olursa Terraform kaynağı tainted olarak işaretler ve bir sonraki apply işlemi, muhtemelen sorunsuz olan bir sunucuyu yok edip yeniden oluşturur.
Hata zamanlaması da oldukça kötüdür. Sağlayıcı, API onay verdiği anda sunucunun oluşturulduğunu raporlar; ancak işletim sistemi henüz açılmaktadır ve sshd henüz dinleme yapmamaktadır.
Error: remote-exec provisioner error
timeout - last error: dial tcp 203.0.113.10:22: connect: connection refusedAnsible'da ise tam tersi bir cazibe söz konusudur. Bulut modülleri sunucu oluşturabilir ve az sayıda makine için bu yöntem işe yarar. Ancak bu durumda bağımlılık grafiğinden ve durum dosyasından (state file) feragat etmiş olursunuz. Ansible bir kaynağı memnuniyetle oluşturur, ancak görevi playbook dosyanızdan sildiğinizde kaynak çalışmaya ve faturalandırılmaya devam eder; çünkü hiçbir kayıt o kaynağın size ait olduğunu tutmamaktadır.
Buradan çıkan kural şudur: API ile oluşturulan ve yok edilen nesnelerin yönetimini Terraform'a, açılmış bir işletim sisteminin içindeki her şeyin yönetimini ise Ansible'a bırakın.
Devir teslim işlemi, başarıyla tamamlandı
Devir teslim bir entegrasyon değil, bir sınırdır. Terraform işini bitirir, bir adres yayınlar ve durur. Ansible ise bu adresten itibaren devreye girer.
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.ymlterraform output -raw, kabuk (shell) yerleştirmesi içinde ihtiyaç duyduğunuz şekilde, tırnak işareti veya JSON sarmalayıcısı olmadan tek bir değer yazdırır. Birden fazla sunucu için terraform output -json kullanın ve envanteri bunun üzerinden oluşturun; çünkü -raw yalnızca tek bir dizge, sayı veya boole değeri ile çalışır.
İki araç arasındaki ping adımını korumakta fayda vardır. Bu adım, "Terraform bana yanlış adresi verdi" sorunu ile "playbook dosyamda bir hata var" sorununu birbirinden ayırır. Playbook, yeni sunucuya dokunan ilk işlem olduğunda bu iki sorun birbirinin aynısı gibi görünür.
Terraform durumunu Ansible envanteri olarak okuma
Envanter dosyası yazmak istemiyorsanız, cloud.terraform koleksiyonu durumu doğrudan okur.
ansible-galaxy collection install cloud.terraformPlaybook'unuzun yanına terraform.yml dosyasını oluşturun:
plugin: cloud.terraform.terraform_provider
project_path: /home/deploy/infraansible-inventory -i terraform.yml --graph
ansible-playbook -i terraform.yml site.ymlBuna güvenmeden önce bilmeniz gereken iki husus vardır. Eklenti, terraform show komutunu project_path dizinine karşı çalıştırır; bu nedenle ilgili dizinin önceden başlatılmış olması gerekir, aksi takdirde eklenti başarısız olur. Ayrıca, sunucu kaynaklarınızdan otomatik olarak ana bilgisayar (host) oluşturmaz; Terraform kodunuzda Ansible sağlayıcısını kullanarak tanımladığınız ansible_host ve ansible_group kaynaklarını okur. Siz ekleyene kadar ansible-inventory --graph içinde hiçbir şey görünmez.
Düz bir şekilde oluşturulmuş envanter dosyasında hata ayıklamak daha kolaydır ve her sağlayıcıyla çalışır. Eklenti, envanter birkaç makinenin üzerine çıktığında ve elle düzenleme yazım hatalarına yol açmaya başladığında faydalı olur; bu nokta, tek bir kontrol makinesinden birden fazla Linux sunucusu yönetmenin bir alışkanlıktan ziyade gerçek bir iş akışına dönüştüğü noktadır.
Terraform kullanmanız gerçekten gerekli mi?
Bunu okuyan çoğu kişi için, en azından henüz değil. Terraform, altyapı oluşturma ve yok etme işlemleri tekrarlanan bir görev haline geldiğinde maliyetini karşılar. Eğer bir kontrol paneli üzerinden tek bir VPS sipariş ettiyseniz ve onu iki yıl boyunca tutmayı planlıyorsanız, Terraform yalnızca bir kez gerçekleşecek bir süreci tanımlar ve kaybetmemeniz gereken bir durum dosyası (state file) ekler.
Ortamları sık sık yeniden oluşturduğunuzda, staging ortamının production ile birebir aynı olması gerektiğinde, birden fazla kişi altyapı üzerinde değişiklik yaptığında ve herhangi bir şey silinmeden önce gözden geçirilebilir bir plana ihtiyaç duyduğunuzda veya yönettikleriniz sunucuların ötesine geçip DNS kayıtları, yük dengeleyiciler ve sağlayıcı API'sinde yaşayan güvenlik duvarı kurallarına ulaştığında Terraform'a yönelin.
Sunucular uzun ömürlü ve az sayıda olduğunda, günlük soru "bu kutu var mı" yerine "bu kutu doğru yapılandırılmış mı" olduğunda yalnızca Ansible ile devam edin. Yeni bir sunucuyu güvenli hale getiren tek bir playbook, yeni bir VPS'teki ilk on dakika ile aynı işi görür; üstelik bir sonraki sunucuda da aynı şekilde çalışma avantajına sahiptir.
Öğrenme sırası da buna göre belirlenir. Ansible, sahip olduğunuz ilk sunucuda karşılığını verir. Terraform ise yeniden oluşturduğunuz üçüncü ortamda karşılığını verir.
Handoff sırasında ne bozulur
Sunucu hazır değil. Terraform başarılı olur, ancak Ansible hemen hata verir.
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, sshd henüz dinlemeye başlamadan önce bir adres döndürdü. Sabit bir bekleme süresi eklemek yerine portun açılmasını bekleyin. Ansible'ın tam olarak bu iş için ansible.builtin.wait_for_connection modülü vardır; bunu play'in ilk görevi olarak çalıştırın. Aynı playbook tek bir yeni sunucu yerine bir gruba yönlendirildiğinde, bir sunucu ulaşılamaz durumda kaldığında ne yapılması gerektiğine önceden karar verin; çünkü Ansible o sunucuyu işlemin geri kalanından çıkarır ve bunu size yalnızca özet satırında bildirir.
Host anahtarı değişti. Sunucuyu yok edip yeniden oluşturdunuz; yeni sunucu aynı adreste yeni bir anahtarla yanıt veriyor.
Host key verification failed.Eski girişi ssh-keygen -R 203.0.113.10 ile kaldırın. Terraform yeniden oluşturma işlemleri yapmaya başladığında bu durum sürekli yaşanır; bu, veri barındıran makinelerde yeniden oluşturma işlemlerini nadir tutmak için iyi bir nedendir.
Sudo başarısız oluyor. fatal: [web1]: FAILED! => {"msg": "Missing sudo password"} hatası, become: true komutunun o sunucuda parola gerektirdiği anlamına gelir. Dağıtım kullanıcısı için parolasız sudo yapılandırın ya da --ask-become-pass bayrağını kullanın.
Terraform dokunmadığınız bir şeyi yok etmek istiyor. Plan, yazmadığınız değişiklikleri gösteriyorsa, gerçek altyapı koddan sapmış demektir; bu genellikle birinin sağlayıcının web panelinden bir ayarı değiştirmesinden kaynaklanır. Farkı tek başına görmek için terraform plan -refresh-only komutunu çalıştırın, ardından kodun mu yoksa canlı kaynağın mı hatalı olduğuna karar verin. Satır satır açıklayamadığınız yıkıcı bir planı asla uygulamayın.
Ansible her çalıştırmada değişiklik raporluyor. creates veya when koruması olmayan bir shell görevi koşulsuz olarak çalışır. Bu sadece kozmetik bir sorun değildir; çünkü artık changed=0 çıktısını, sunucunun istediğiniz durumda olduğunun bir göstergesi olarak kullanamazsınız.
FAQ
Terraform, Ansible'ın yerini alabilir mi?
Sunucu içindeki yapılandırma işlemleri için hayır. Terraform, remote-exec provisioner'ı ile betikleri çalıştırabilir ancak bunlar yalnızca kaynak oluşturulurken tetiklenir, terraform plan içinde görünmezler ve başarısız olduklarında kaynağı "taint" (kirli) durumuna düşürürler; bu da bir sonraki apply işleminde kaynağın silinip yeniden oluşturulmasını tetikler. Terraform'da, nginx'in zaten kurulu olup olmadığını kontrol eden ve kuruluysa hiçbir işlem yapmayan bir modül eşdeğeri yoktur. Makineyi oluşturmak için Terraform'u, ardından yapılandırma için Ansible'ı kullanın.
Ansible, Terraform'un yerini alabilir mi?
Az sayıda ve uzun ömürlü sunucu için evet. Ansible, sunucu oluşturan bulut modüllerine sahiptir; iki adet VPS örneği kiralayıp bunları uzun süre tutacaksanız bu yeterlidir. Ancak bu durumda state dosyasını ve bağımlılık grafiğini kaybedersiniz: playbook'tan bir görevi kaldırırsanız, kaynak çalışmaya ve faturalandırılmaya devam eder çünkü Ansible onu oluşturduğunu kayıt altına almamıştır. Terraform ise bu durumda bir silme (destroy) planı oluştururdu.
Hangisini önce öğrenmeliyim?
Hâlihazırda sunucularınız varsa Ansible. İlk makinede bile verim sağlar, SSH dışında hiçbir şeye ihtiyaç duymaz ve edindiğiniz beceri manuel olarak kurduğunuz sunucularda da geçerlidir. Terraform, ortamları sürekli yeniden oluşturduğunuzda veya DNS kayıtları ve güvenlik duvarı kuralları gibi sunucu dışındaki sağlayıcı kaynaklarını yönettiğinizde daha fazla verim sağlar.
Yeni sunucunun IP adresini Terraform'dan Ansible'a nasıl aktarırım?
Terraform kodunuzda bir output tanımlayın ve apply işleminden sonra bunu okuyun. terraform output -raw web_ip, kabuk (shell) yerine koyma işlemi için ham değeri yazdırır; terraform output -json ise birden fazla sunucu olduğunda tüm çıktıları aynı anda verir. Bu değeri bir envanter dosyasına yazın veya cloud.terraform koleksiyonunu yükleyip ansible-inventory -i terraform.yml --graph parametresini proje dizinine yönlendirin.
Neden playbook'um Terraform biter bitmez hata veriyor?
Sağlayıcı, API yanıt verir vermez sunucuyu oluşturulmuş olarak raporlar; ancak işletim sistemi henüz açılış aşamasında olduğu için ilk birkaç saniye SSH bağlantısı reddedilir. Hata, Connection refused ile birlikte UNREACHABLE! olarak döner. Rastgele bir bekleme süresi tahmin etmek yerine, ansible.builtin.wait_for_connection işlemini playbook'taki ilk görev yapın; çünkü açılış süresi imaja ve plana göre değişiklik gösterir.