Ansible बनाम Terraform: आपके लिए क्या सही है?
Terraform इंफ्रास्ट्रक्चर बनाता है और Ansible उसे कॉन्फ़िगर करता है। जानें कि कब केवल Ansible का उपयोग करना है और क्यों इन दोनों टूल्स को आपस में मिलाना एक बड़ी गलती हो सकती है।
Ansible और Terraform की तुलना एक वाक्य में
Ansible और Terraform एक ही काम करने वाले दो टूल्स के बीच का विकल्प नहीं हैं। Terraform यह घोषित करता है कि कौन सा इंफ्रास्ट्रक्चर मौजूद है: सर्वर्स, डिस्क, नेटवर्क्स, DNS रिकॉर्ड्स। Ansible यह घोषित करता है कि पहले से मौजूद मशीन के अंदर क्या स्थिति होनी चाहिए: पैकेजेस, यूजर्स, कॉन्फ़िगरेशन फाइल्स, रनिंग सर्विसेज। Terraform VPS बनाता है। Ansible उस VPS को वेब सर्वर में बदलता है।
दोनों ही डिक्लेरेटिव हैं और दोनों को इंफ्रास्ट्रक्चर एज़ कोड (IaC) कहा जाता है। वास्तविक अंतर यह है कि वे क्या याद रखते हैं। Terraform एक स्टेट फाइल लिखता है जो आपके कोड के हर रिसोर्स को उसके द्वारा API के माध्यम से बनाए गए वास्तविक ऑब्जेक्ट से मैप करती है, ताकि वह यह बता सके कि पांच लाइनों को हटाने का मतलब है कि एक सर्वर को नष्ट किया जाना चाहिए। Ansible रन के बीच कुछ भी याद नहीं रखता है। यह SSH के माध्यम से कनेक्ट होता है, मशीन का निरीक्षण करता है, और केवल उसी को बदलता है जो पहले से प्लेबुक से मेल नहीं खाता है।
यह एक अंतर इस गाइड के बाकी हिस्सों की व्याख्या करता है, जिसमें यह भी शामिल है कि दोनों कार्यों को एक टूल में मिलाने से चीजें गलत क्यों हो जाती हैं।
Terraform वास्तव में क्या करता है
Terraform एक provider plugin के माध्यम से API से बात करता है। आपके provider का registry page उन resource types को परिभाषित करता है जिन्हें आप लिख सकते हैं, इसलिए एक host पर सर्वर और दूसरे host पर सर्वर अलग-अलग resource names और अलग-अलग arguments वाले होते हैं।
resource "cloud_server" "web" {
name = "web1"
image = "ubuntu-24.04"
type = "small"
}
output "web_ip" {
value = cloud_server.web.ipv4_address
}cloud_server को उस resource type से बदलें जिसे आपका provider document करता है। इस गाइड के लिए output ब्लॉक महत्वपूर्ण हिस्सा है, क्योंकि इसी तरह address Terraform से बाहर जाता है।
terraform init
terraform fmt -check
terraform validate
terraform plan -out=tfplan
terraform apply tfplanterraform init provider को डाउनलोड करता है और एक lock file लिखता है। terraform plan आपके कोड और state file के बीच का अंतर प्रिंट करता है, जो Plan: 1 to add, 0 to change, 0 to destroy. जैसी लाइन पर समाप्त होता है। हर बार उस लाइन को पढ़ें। कुछ arguments को सीधे (in-place) बदला नहीं जा सकता है, और plan में attribute के बगल में # forces replacement के साथ यह लिखा होता है, जिसके बाद 1 to add, 0 to change, 1 to destroy आता है। उस plan को apply करने से सर्वर डिलीट हो जाता है और एक नया खाली सर्वर बन जाता है, और इसी तरह लोग अपना वह डेटा खो देते हैं जिसे वे सुरक्षित समझते थे।
सीधे terraform apply चलाने के बजाय plan को एक फाइल में सेव करना और उस फाइल को apply करना यह सुनिश्चित करता है कि जो आपने review किया है, वही run हो। इन दो commands के बीच, किसी और ने infrastructure में बदलाव किया हो सकता है।
terraform.tfstate मेमोरी है। इसे खोने पर Terraform को यह पता नहीं रहता कि वे सर्वर आपके हैं, इसलिए अगला apply डुप्लिकेट बनाने की कोशिश करता है। जैसे ही एक से अधिक व्यक्ति commands run करने लगें, इसे remote backend में रखें, क्योंकि दो लोगों के एक साथ apply करने पर यह परिणाम मिलता है:
Error: Error acquiring the state lockOpenTofu, Terraform का एक fork है जिसमें समान commands और समान file format है। जुलाई 2026 तक, यदि आप terraform के बजाय tofu टाइप करते हैं, तो इस गाइड की हर चीज़ काम करती है।
Ansible वास्तव में क्या करता है
Ansible को किसी agent या API की आवश्यकता नहीं होती है। यह एक SSH connection खोलता है, एक छोटा Python module target पर copy करता है, उसे चलाता है, और फिर उसे delete कर देता है। जिस भी चीज़ तक आप SSH और sudo password के साथ पहुँच सकते हैं, उसे Ansible configure कर सकता है।
- 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 module यह सिद्ध करता है कि playbook debug करना शुरू करने से पहले SSH, Python और sudo सही ढंग से काम कर रहे हैं। एक सफल परिणाम web1 | SUCCESS => {"ping": "pong"} होता है। --check --diff run, Ansible की योजना के सबसे करीब है: यह रिपोर्ट करता है कि क्या बदलाव किए जाएंगे, बिना उन्हें वास्तव में लागू किए। हालाँकि, जो tasks पहले के tasks पर निर्भर होते हैं, वे check mode में गलत रिपोर्ट दे सकते हैं, क्योंकि पिछला बदलाव वास्तव में कभी हुआ ही नहीं होता है।
हर run एक recap के साथ समाप्त होता है, जैसे कि ok=6 changed=2 unreachable=0 failed=0। एक ही playbook को दो बार चलाएँ। दूसरी run को changed=0 रिपोर्ट करना चाहिए। जो task हर run पर changed रिपोर्ट करता है, वह idempotent नहीं है, और यह आमतौर पर एक command या shell task होता है जिसे एक वास्तविक module होना चाहिए था। यदि यह आपके लिए नया है, तो एक single VPS पर पहली Ansible playbook से शुरुआत करें और धीरे-धीरे आगे बढ़ें।
जहाँ ये दो टूल्स एक-दूसरे के काम में आते हैं, और जहाँ इनमें टकराव होता है
Terraform, remote-exec provisioner के साथ नए सर्वर पर commands चला सकता है। HashiCorp का अपना documentation provisioners को अंतिम विकल्प (last resort) मानता है। इसके पीछे ठोस कारण हैं।
एक provisioner केवल तभी चलता है जब resource बनाई जाती है। यदि आप script में बदलाव करते हैं, तो मौजूदा सर्वर पर कुछ नहीं होता, क्योंकि Terraform के नजरिए से resource पहले से ही code के अनुरूप है। Provisioner के steps कभी भी terraform plan में दिखाई नहीं देते, इसलिए आपके review में इनका कोई संकेत नहीं मिलता। यदि script विफल हो जाती है, तो Terraform resource को tainted चिह्नित कर देता है, और अगली apply प्रक्रिया उस सर्वर को नष्ट करके फिर से बनाती है जो शायद पूरी तरह ठीक था।
यह विफलता गलत समय पर भी होती है। Provider सर्वर को उसी क्षण 'created' रिपोर्ट कर देता है जैसे ही API ऐसा कहती है, जबकि operating system अभी भी boot हो रहा होता है और sshd अभी listen नहीं कर रहा होता है।
Error: remote-exec provisioner error
timeout - last error: dial tcp 203.0.113.10:22: connect: connection refusedAnsible के साथ विपरीत समस्या है। Cloud modules सर्वर बना सकते हैं, और कुछ मशीनों के लिए यह काम करता है। लेकिन आप dependency graph और state file का लाभ खो देते हैं। Ansible खुशी-खुशी resource बना देगा, लेकिन यदि आप अपने playbook से task हटा देते हैं, तो भी वह resource चलती रहेगी और उसका बिल आता रहेगा, क्योंकि कहीं भी यह दर्ज नहीं हुआ कि वह आपकी थी।
इससे यह नियम निकलता है: Terraform को उन objects का स्वामित्व दें जिन्हें API बनाती और नष्ट करती है, और Ansible को एक booted operating system के अंदर की हर चीज़ का स्वामित्व दें।
हैंडऑफ, सफल रहा
हैंडऑफ एक सीमा है, एकीकरण नहीं। Terraform अपना काम पूरा करता है, एक पता (address) प्रकाशित करता है और रुक जाता है। Ansible उस पते से अपना काम शुरू करता है।
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 बिना किसी कोट्स और JSON रैपर के एक मान प्रिंट करता है, जो कि शेल सब्स्टीट्यूशन के भीतर आपको चाहिए होता है। कई सर्वरों के लिए, terraform output -json का उपयोग करें और उससे इन्वेंट्री बनाएं, क्योंकि -raw केवल एक स्ट्रिंग, नंबर या बूलियन को ही संभालता है।
दोनों टूल्स के बीच ping चरण को बनाए रखना उपयोगी है। यह "Terraform ने मुझे गलत पता दिया" और "मेरे प्लेबुक में कोई बग है" के बीच अंतर स्पष्ट करता है, और जब प्लेबुक पहली ऐसी चीज़ होती है जो नए बॉक्स को छूती है, तो ये दोनों समस्याएं एक जैसी ही दिखाई देती हैं।
Terraform state को Ansible inventory के रूप में पढ़ना
यदि आप inventory file बिल्कुल नहीं लिखना चाहते हैं, तो cloud.terraform collection सीधे state को पढ़ लेती है।
ansible-galaxy collection install cloud.terraformअपने playbook के बगल में terraform.yml लिखें:
plugin: cloud.terraform.terraform_provider
project_path: /home/deploy/infraansible-inventory -i terraform.yml --graph
ansible-playbook -i terraform.yml site.ymlइस पर निर्भर होने से पहले दो बातें जान लें। यह plugin terraform show को project_path के विरुद्ध चलाता है, इसलिए वह directory पहले से initialized होनी चाहिए अन्यथा plugin विफल हो जाएगा। यह आपके server resources से hosts का निर्माण भी नहीं करता है: यह ansible_host और ansible_group resources को पढ़ता है, जिन्हें आप Ansible provider का उपयोग करके अपने Terraform code में घोषित करते हैं। जब तक आप उन्हें जोड़ते नहीं हैं, तब तक ansible-inventory --graph में कुछ भी दिखाई नहीं देता है।
एक साधारण generated inventory file को debug करना आसान होता है और यह किसी भी provider के साथ काम करती है। यह plugin तब उपयोगी साबित होता है जब inventory कुछ मशीनों से बढ़ जाती है और manual editing से typos होने लगते हैं, जो कि वही बिंदु है जहाँ एक control machine से कई Linux servers को manage करना एक आदत के बजाय एक वास्तविक workflow बन जाता है।
क्या आपको वास्तव में Terraform की आवश्यकता है?
इसे पढ़ने वाले अधिकांश लोगों को, कम से कम अभी तो, इसकी आवश्यकता नहीं है। Terraform अपनी लागत तब वसूल करता है जब infrastructure को बनाना और नष्ट करना स्वयं एक दोहराया जाने वाला कार्य हो। यदि आपने control panel के माध्यम से एक VPS ऑर्डर किया है और उसे दो साल तक रखने का इरादा रखते हैं, तो Terraform एक ऐसी प्रक्रिया का वर्णन करता है जो केवल एक बार होती है, और यह एक state file जोड़ देता है जिसे आपको खोना नहीं चाहिए।
Terraform का उपयोग तब करें जब आप अक्सर environments को फिर से बनाते हैं, जब staging को production से बिल्कुल मेल खाना होता है, जब कई लोग infrastructure में बदलाव करते हैं और आप चाहते हैं कि कुछ भी delete होने से पहले एक reviewable plan हो, या जब आप जो manage करते हैं वह servers से आगे बढ़कर DNS records, load balancers और firewall rules तक पहुँच जाता है जो एक provider API में रहते हैं।
जब servers लंबे समय तक चलते हैं और संख्या में कम होते हैं, और जब दैनिक प्रश्न यह होता है कि "क्या यह box सही ढंग से configured है" न कि "क्या यह box मौजूद है", तब केवल Ansible के साथ बने रहें। एक single playbook जो एक नए server को harden करती है, वह एक नए VPS पर पहले दस मिनट के समान ही काम करती है, जिसका लाभ यह है कि यह अगले server पर भी उसी तरह चलती है।
सीखने का क्रम इसी से तय होता है। Ansible आपके पास मौजूद पहले server पर ही लाभ देना शुरू कर देता है। Terraform आपके द्वारा फिर से बनाए गए तीसरे environment पर लाभ देता है।
हैंडऑफ के दौरान क्या खराब होता है
सर्वर तैयार नहीं है। Terraform सफल होता है, लेकिन Ansible तुरंत विफल हो जाता है।
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 के listening मोड में आने से पहले ही एक पता (address) लौटा दिया। एक निश्चित sleep जोड़ने के बजाय port के तैयार होने की प्रतीक्षा करें। Ansible में इसके लिए ansible.builtin.wait_for_connection मौजूद है, इसे play के पहले task के रूप में चलाएं।
होस्ट की (host key) बदल गई है। आपने सर्वर को नष्ट करके फिर से बनाया है, और नया सर्वर उसी पते पर एक नई की (key) के साथ प्रतिक्रिया दे रहा है।
Host key verification failed.ssh-keygen -R 203.0.113.10 का उपयोग करके पुरानी एंट्री को हटा दें। जब Terraform रीबिल्डिंग कर रहा हो तो ऐसा लगातार होता है, जो डेटा रखने वाली मशीनों पर रीबिल्ड को कम रखने का एक अच्छा कारण है।
Sudo विफल हो जाता है। fatal: [web1]: FAILED! => {"msg": "Missing sudo password"} का मतलब है कि उस होस्ट पर become: true को पासवर्ड की आवश्यकता है। या तो डिप्लॉय यूजर के लिए पासवर्ड-रहित sudo कॉन्फ़िगर करें, या --ask-become-pass पास करें।
Terraform ऐसी चीज़ को नष्ट करना चाहता है जिसे आपने नहीं छुआ। प्लान उन बदलावों को दिखाता है जिन्हें आपने कभी नहीं लिखा, जिसका अर्थ है कि वास्तविक इंफ्रास्ट्रक्चर कोड से अलग हो गया है (drift), आमतौर पर इसलिए क्योंकि किसी ने प्रोवाइडर के वेब पैनल में कोई सेटिंग बदल दी है। उस अंतर को देखने के लिए terraform plan -refresh-only चलाएं, फिर तय करें कि कोड गलत है या लाइव रिसोर्स। कभी भी ऐसे विनाशकारी प्लान को लागू (apply) न करें जिसे आप लाइन-दर-लाइन समझा न सकें।
Ansible हर रन पर 'changed' रिपोर्ट करता है। बिना creates या when गार्ड वाला shell टास्क बिना शर्त चलता है। यह केवल कॉस्मेटिक समस्या नहीं है, क्योंकि इसका मतलब है कि आप अब changed=0 का उपयोग उस संकेत के रूप में नहीं कर सकते कि सर्वर आपकी इच्छित स्थिति में है।
FAQ
क्या Terraform, Ansible की जगह ले सकता है?
सर्वर के अंदर कॉन्फ़िगरेशन के लिए नहीं। Terraform, remote-exec प्रोविज़नर के साथ स्क्रिप्ट्स को कॉल कर सकता है, लेकिन वे केवल रिसोर्स निर्माण के समय चलती हैं, कभी भी terraform plan में दिखाई नहीं देतीं, और विफल होने पर रिसोर्स को 'taint' कर देती हैं, जिससे अगले 'apply' पर उसे नष्ट (destroy) और पुनः निर्मित (rebuild) करने का शेड्यूल बन जाता है। Terraform में ऐसा कोई मॉड्यूल नहीं है जो यह जांच सके कि nginx पहले से इंस्टॉल है या नहीं और यदि है, तो कुछ न करे। मशीन बनाने के लिए Terraform का उपयोग करें, फिर काम Ansible को सौंप दें।
क्या Ansible, Terraform की जगह ले सकता है?
कम संख्या में लंबे समय तक चलने वाले सर्वरों के लिए, हाँ। Ansible में क्लाउड मॉड्यूल हैं जो सर्वर बनाते हैं, और यदि आप दो VPS इंस्टेंस ऑर्डर करते हैं और उन्हें बनाए रखते हैं, तो यह पर्याप्त है। आप जो खोते हैं वह है स्टेट फाइल और डिपेंडेंसी ग्राफ: प्लेबुक से कोई टास्क हटाने पर भी रिसोर्स चलता रहता है और बिलिंग जारी रहती है, क्योंकि Ansible ने कभी रिकॉर्ड नहीं किया कि उसने इसे बनाया था। Terraform ने इसे नष्ट करने की योजना (plan) बनाई होती।
मुझे पहले क्या सीखना चाहिए?
Ansible, यदि आपके पास आज सर्वर हैं। यह पहली मशीन पर ही लाभ देना शुरू कर देता है, इसे केवल SSH की आवश्यकता होती है, और यह कौशल उस सर्वर पर भी लागू होता है जिसे आपने मैन्युअल रूप से ऑर्डर किया है। Terraform का लाभ बाद में मिलता है, जब आप बार-बार एनवायरनमेंट को फिर से बनाते हैं या सर्वर के अलावा अन्य प्रोवाइडर रिसोर्स, जैसे DNS रिकॉर्ड और फायरवॉल नियमों को मैनेज करते हैं।
मैं Terraform से नए सर्वर का IP, Ansible में कैसे पास करूँ?
अपने Terraform कोड में एक output घोषित करें, फिर 'apply' के बाद उसे पढ़ें। terraform output -raw web_ip शेल सब्स्टीट्यूशन के लिए केवल वैल्यू प्रिंट करता है, और जब कई होस्ट हों तो terraform output -json आपको एक साथ सभी आउटपुट देता है। इसे एक इन्वेंट्री फाइल में लिखें, या cloud.terraform कलेक्शन इंस्टॉल करें और ansible-inventory -i terraform.yml --graph को प्रोजेक्ट डायरेक्टरी पर पॉइंट करें।
Terraform के समाप्त होते ही मेरी प्लेबुक विफल क्यों हो जाती है?
प्रोवाइडर सर्वर को तभी 'created' रिपोर्ट कर देता है जैसे ही उसका API ऐसा कहता है, जबकि ऑपरेटिंग सिस्टम अभी भी बूट हो रहा होता है, इसलिए शुरुआती कुछ सेकंड के लिए SSH कनेक्शन अस्वीकार कर दिया जाता है। त्रुटि UNREACHABLE! होती है जिसमें Connection refused दिखाई देता है। स्लीप ड्यूरेशन का अनुमान लगाने के बजाय ansible.builtin.wait_for_connection को प्ले का पहला टास्क बनाएं, क्योंकि बूट का समय इमेज और प्लान के अनुसार अलग-अलग होता है।