Ansible বনাম Terraform: আপনার কোনটি দরকার?
Terraform VPS তৈরি করে, Ansible সেটি configure করে। দুই tool-এর আসল পার্থক্য, provisioner কেন সমস্যা করে, handoff commands এবং কখন শুধু Ansible যথেষ্ট জানুন।
এক বাক্যে Ansible বনাম Terraform
Ansible বনাম Terraform একই কাজ করা দুটি টুলের মধ্যে পছন্দ নয়। Terraform ঘোষণা করে কোন infrastructure থাকবে: server, disk, network, DNS record। Ansible ঘোষণা করে আগে থেকে থাকা কোনো machine-এর ভেতরে কী অবস্থা সত্য হবে: package, user, config file, চলমান service। Terraform VPS তৈরি করে। Ansible সেই VPS-কে web server-এ রূপ দেয়।
দুটিই declarative, এবং দুটিকেই infrastructure as code (IaC) বলা হয়। আসল পার্থক্য হলো, এগুলো কী মনে রাখে। Terraform একটি state file লেখে, যেখানে আপনার code-এর প্রতিটি resource-কে API-এর মাধ্যমে তৈরি করা বাস্তব object-এর সঙ্গে মেলানো থাকে। তাই পাঁচটি line মুছে ফেললে একটি server ধ্বংস করতে হবে—এটি Terraform বুঝতে পারে। Ansible run-এর মধ্যে কোনো state মনে রাখে না। এটি SSH-এর মাধ্যমে সংযোগ করে, machine পরীক্ষা করে এবং playbook-এর সঙ্গে যা মেলে না শুধু সেটিই পরিবর্তন করে।
এই একটি পার্থক্যই এই guide-এর বাকি বিষয়গুলো ব্যাখ্যা করে। একই tool দিয়ে দুটি কাজ একত্রে করার চেষ্টা কেন ব্যর্থ হয়, সেটিও এর মধ্যে রয়েছে।
Terraform আসলে কী করে
Terraform একটি provider plugin-এর মাধ্যমে API-তে যোগাযোগ করে। আপনি যে provider ব্যবহার করেন, তার registry page-এ আপনি লিখতে পারবেন এমন resource type-গুলো নির্ধারিত থাকে। তাই একটি host-এ server এবং অন্য host-এ server-এর জন্য ভিন্ন argument-সহ ভিন্ন resource name থাকে।
resource "cloud_server" "web" {
name = "web1"
image = "ubuntu-24.04"
type = "small"
}
output "web_ip" {
value = cloud_server.web.ipv4_address
}cloud_server-এর জায়গায় আপনার provider-এর documentation-এ উল্লেখ করা resource type বসান। এই গাইডের জন্য output block-টিই গুরুত্বপূর্ণ, কারণ এর মাধ্যমেই address Terraform-এর বাইরে যায়।
terraform init
terraform fmt -check
terraform validate
terraform plan -out=tfplan
terraform apply tfplanterraform init provider download করে এবং একটি lock file লেখে। terraform plan আপনার code এবং state file-এর মধ্যে পার্থক্য দেখায়। এর শেষে Plan: 1 to add, 0 to change, 0 to destroy.-এর মতো একটি line থাকে। প্রতিবার ওই line পড়ুন। কিছু argument সরাসরি পরিবর্তন করা যায় না। Plan-এ attribute-এর পাশে # forces replacement লেখা থাকে এবং তার পরে 1 to add, 0 to change, 1 to destroy থাকে। এই plan apply করলে server মুছে একটি নতুন খালি server তৈরি হয়। নিরাপদ আছে বলে মনে করা data এভাবেই হারিয়ে যেতে পারে।
Plan একটি file-এ save করে সেই file apply করুন। সরাসরি terraform apply চালানোর বদলে এভাবে চালালে আপনি যে plan review করেছেন, সেটিই run হবে। এই দুই command-এর মাঝের সময়ে অন্য কেউ infrastructure পরিবর্তন করে থাকতে পারে।
terraform.tfstate হলো Terraform-এর স্মৃতি। এটি হারালে Terraform আর জানবে না যে ওই server-গুলো আপনার। ফলে পরের apply duplicate server তৈরি করার চেষ্টা করবে। একাধিক ব্যক্তি command চালালেই এটি remote backend-এ রাখুন। কারণ একই সময়ে দুই ব্যক্তি apply করলে এমন ফল দেখা যায়:
Error: Error acquiring the state lockOpenTofu হলো Terraform-এর একটি fork। এতে একই command এবং একই file format ব্যবহার করা হয়। July 2026 অনুযায়ী, terraform-এর বদলে tofu লিখলে এই গাইডের সবকিছু কাজ করবে।
Ansible আসলে যা করে
Ansible-এর কোনো agent বা API প্রয়োজন হয় না। এটি একটি SSH connection খোলে, target-এ একটি ছোট Python module কপি করে, সেটি চালায় এবং পরে মুছে দেয়। SSH এবং sudo password দিয়ে যে target-এ পৌঁছানো যায়, 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.ymlআপনি playbook debug করা শুরু করার আগে ping module SSH, Python এবং sudo কাজ করছে কি না যাচাই করে। সুস্থ ফলাফল হলো web1 | SUCCESS => {"ping": "pong"}। --check --diff run-কে Ansible-এর plan-এর সবচেয়ে কাছাকাছি ধরা যায়: এটি কী কী পরিবর্তন হতো তা জানায়, কিন্তু কোনো পরিবর্তন করে না। তবে কোনো task আগের task-এর ওপর নির্ভর করলে check mode-এ ভুল ফলাফল দেখাতে পারে, কারণ আগের পরিবর্তনটি আসলে কার্যকর হয়নি।
প্রতিটি run ok=6 changed=2 unreachable=0 failed=0-এর মতো একটি recap দিয়ে শেষ হয়। একই playbook দুবার চালান। দ্বিতীয় run-এ changed=0 দেখানো উচিত। কোনো task প্রতিবার changed দেখালে সেটি idempotent নয়। সাধারণত এটি একটি command বা shell task, যেটি একটি প্রকৃত module ব্যবহার করে লেখা উচিত ছিল। এই বিষয়টি নতুন হলে একটি VPS-এ প্রথম Ansible playbook দিয়ে শুরু করে ধীরে ধীরে সেটি সম্প্রসারিত করুন।
যেখানে দুটি টুলের কাজের ক্ষেত্র মেলে এবং যেখানে তারা পরস্পরের সঙ্গে সংঘাতে জড়ায়
Terraform `remote-exec` provisioner ব্যবহার করে নতুন সার্ভারে command চালাতে পারে। HashiCorp-এর নিজস্ব documentation-এ provisioner-কে শেষ অবলম্বন হিসেবে উল্লেখ করা হয়েছে। এর যথেষ্ট কারণ আছে।
Provisioner শুধু resource তৈরির সময় একবার চলে। Script সম্পাদনা করলেও বিদ্যমান সার্ভারে কিছু ঘটে না, কারণ Terraform-এর দৃষ্টিতে resource-টি ইতিমধ্যেই code-এর সঙ্গে মিলে আছে। Provisioner-এর ধাপগুলো `terraform plan`-এ কখনো দেখা যায় না, তাই আপনার review-তে সেগুলোর কোনো চিহ্ন থাকে না। Script ব্যর্থ হলে Terraform resource-টিকে tainted হিসেবে চিহ্নিত করে। পরবর্তী apply এমন একটি সার্ভার ধ্বংস করে পুনরায় তৈরি করে, যেটি সম্ভবত ঠিকই ছিল।
ব্যর্থতার সময়টিও সমস্যাজনক। API সার্ভার তৈরির কথা জানালেই provider সার্ভারটিকে created হিসেবে দেখায়। কিন্তু তখনও operating system boot হচ্ছে এবং `sshd` এখনো listening করছে না।
Error: remote-exec provisioner error
timeout - last error: dial tcp 203.0.113.10:22: connect: connection refusedAnsible-এর ক্ষেত্রে বিপরীত প্রলোভন থাকে। Cloud module ব্যবহার করে server তৈরি করা যায়, এবং অল্প কয়েকটি machine-এর ক্ষেত্রে এটি কাজও করে। তবে এতে dependency graph এবং state file আর থাকে না। Ansible resource তৈরি করে দিতে পারে, কিন্তু playbook থেকে task মুছে ফেললেও resource চালু থাকে এবং তার জন্য billing চলতে থাকে। কারণ resource-টি কখনো আপনার ছিল—এমন কোনো তথ্য record করা হয়নি।
এ থেকে যে নিয়মটি পাওয়া যায় তা হলো: API যে object তৈরি ও ধ্বংস করে, তার দায়িত্ব Terraform-কে দিন। আর boot করা operating system-এর ভেতরের সবকিছুর দায়িত্ব Ansible-কে দিন।
Handoff, যা কাজ করেছে
Handoff একটি boundary, integration নয়। Terraform কাজ শেষ করে, একটি address প্রকাশ করে এবং থেমে যায়। Ansible সেই address থেকে শুরু হয়।
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 কোনো quote বা JSON wrapper ছাড়াই একটি value print করে। Shell substitution-এর ভিতরে এটিই প্রয়োজন। একাধিক server-এর জন্য terraform output -json ব্যবহার করে সেটি থেকে inventory তৈরি করুন, কারণ -raw শুধু একটি string, number বা boolean পরিচালনা করে।
দুটি tool-এর মাঝের ping ধাপটি রাখা উপযোগী। এতে "Terraform আমাকে ভুল address দিয়েছে" এবং "আমার playbook-এ bug আছে"—এই দুটি সমস্যা আলাদা করা যায়। Playbook-ই যদি নতুন box-এ প্রথম কাজ করা উপাদান হয়, তাহলে উভয় সমস্যাই একই রকম দেখায়।
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টি project_path-এর বিরুদ্ধে terraform show চালায়, তাই ওই directory আগে থেকেই initialized থাকতে হবে; তা না হলে plugin ব্যর্থ হবে। এটি আপনার server resource থেকে নিজে host তৈরি করে না। এটি ansible_host এবং ansible_group resource পড়ে, যেগুলো আপনি Ansible provider ব্যবহার করে Terraform code-এ declare করেন। এগুলো যোগ না করা পর্যন্ত ansible-inventory --graph-তে কিছুই দেখা যাবে না।
সাধারণ generated inventory file debug করা সহজ এবং যেকোনো provider-এর সঙ্গে কাজ করে। Inventory কয়েকটি machine-এর সীমা ছাড়িয়ে গেলে এবং হাতে edit করতে গিয়ে typo হতে শুরু করলে pluginটি কার্যকর হয়। এই পর্যায়েই একটি control machine থেকে একাধিক Linux server পরিচালনা করা অভ্যাসের বদলে বাস্তব workflow হয়ে ওঠে।
আপনার কি আসলেই Terraform প্রয়োজন?
এটি পড়ছেন এমন অধিকাংশ মানুষের ক্ষেত্রে এখনো Terraform প্রয়োজন হয় না। Infrastructure তৈরি ও ধ্বংস করা নিজেই যখন বারবার করতে হয়, তখন Terraform-এর খরচ সার্থক হয়। আপনি যদি একটি control panel-এর মাধ্যমে একটি VPS নিয়ে দুই বছর সেটি চালিয়ে যাওয়ার পরিকল্পনা করেন, তাহলে Terraform এমন একটি কাজ বর্ণনা করবে যা একবারই ঘটবে। এর সঙ্গে একটি state file যোগ হবে, যা হারানো যাবে না।
বারবার environment পুনর্নির্মাণ করলে Terraform ব্যবহার করুন। staging-কে production-এর সঙ্গে হুবহু মিলিয়ে রাখতে হলে এটি ব্যবহার করুন। একাধিক ব্যক্তি infrastructure পরিবর্তন করলে এবং কিছু মুছে ফেলার আগে review করা যায় এমন plan চাইলে Terraform ব্যবহার করুন। DNS record, load balancer এবং provider API-তে থাকা firewall rule-সহ server-এর বাইরের resource পরিচালনা করতে হলে Terraform ব্যবহার করুন।
server দীর্ঘস্থায়ী এবং সংখ্যা কম হলে Ansible একাই ব্যবহার করুন। দৈনন্দিন প্রশ্ন যদি হয় “এই box কি সঠিকভাবে configured আছে?”—“এই box কি বিদ্যমান?” নয়—তাহলে Ansible যথেষ্ট। একটি playbook নতুন server-কে সুরক্ষিত ও সঠিকভাবে configured করার একই কাজ করে, যেমন নতুন VPS-এ প্রথম দশ মিনিটে করা কাজ, এবং পরের server-এও একইভাবে চালানো যায়।
এ থেকেই শেখার ক্রম নির্ধারিত হয়। আপনার নিজের প্রথম server-এই Ansible-এর উপকার পাওয়া শুরু হবে। তৃতীয় environment পুনর্নির্মাণের সময় Terraform-এর উপকার স্পষ্ট হবে।
হস্তান্তরের সময় কী কী সমস্যা হয়
সার্ভার প্রস্তুত নয়। 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}sshd listening শুরু করার আগে API একটি address ফেরত দিয়েছে। নির্দিষ্ট সময়ের জন্য sleep যোগ না করে port-এর জন্য অপেক্ষা করুন। Ansible-এ এর জন্য ঠিক ansible.builtin.wait_for_connection রয়েছে; এটিকে play-এর প্রথম task হিসেবে চালান।
host key পরিবর্তিত হয়েছে। আপনি সার্ভারটি ধ্বংস করে আবার তৈরি করেছেন, এবং নতুন সার্ভারটি একই address-এ নতুন key নিয়ে সাড়া দিচ্ছে।
Host key verification failed.ssh-keygen -R 203.0.113.10 দিয়ে পুরোনো entry সরান। Terraform যখন নিয়মিত server rebuild করছে, তখন এটি বারবার ঘটে। তাই data সংরক্ষণকারী মেশিনে rebuild যতটা সম্ভব কম করা ভালো।
Sudo ব্যর্থ হয়। fatal: [web1]: FAILED! => {"msg": "Missing sudo password"}-এর অর্থ হলো, ওই host-এ become: true চালাতে password প্রয়োজন। হয় deploy user-এর জন্য passwordless sudo configure করুন, অথবা --ask-become-pass দিন।
আপনি পরিবর্তন না করলেও Terraform কোনো resource ধ্বংস করতে চায়। plan-এ এমন পরিবর্তন দেখা যাচ্ছে যা আপনি code-এ লেখেননি। এর অর্থ হলো, বাস্তব infrastructure code থেকে সরে গেছে। সাধারণত provider-এর web panel-এ কেউ কোনো setting পরিবর্তন করলে এটি ঘটে। শুধু ওই পার্থক্যটি দেখতে terraform plan -refresh-only চালান। এরপর code নাকি live resource ভুল, তা নির্ধারণ করুন। যে destructive plan-এর প্রতিটি line ব্যাখ্যা করতে পারবেন না, তা কখনো apply করবেন না।
প্রতিটি run-এ Ansible changed দেখায়। কোনো creates বা when guard ছাড়া shell task সব সময় অনিয়ন্ত্রিতভাবে চলে। এটি শুধু দেখানোর সমস্যা নয়। এর ফলে server আপনার নির্ধারিত অবস্থায় আছে কি না বোঝার সংকেত হিসেবে changed=0 আর ব্যবহার করা যায় না।
FAQ
Terraform কি Ansible-কে প্রতিস্থাপন করতে পারে?
সার্ভারের ভেতরের configuration-এর ক্ষেত্রে নয়। Terraform remote-exec provisioner ব্যবহার করে script চালাতে পারে, কিন্তু সেগুলো শুধু resource তৈরির সময় চলে, কখনো terraform plan-এ দেখা যায় না, এবং ব্যর্থ হলে resource-কে tainted করে। এর ফলে পরবর্তী apply-এ destroy ও rebuild নির্ধারিত হয়। Terraform-এ এমন কোনো module নেই, যা পরীক্ষা করে nginx আগে থেকেই ইনস্টল করা আছে কি না এবং থাকলে কোনো কাজ না করে। মেশিন তৈরির জন্য Terraform ব্যবহার করুন, তারপর দায়িত্ব হস্তান্তর করুন।
Ansible কি Terraform-কে প্রতিস্থাপন করতে পারে?
অল্পসংখ্যক দীর্ঘমেয়াদি server-এর ক্ষেত্রে পারে। Ansible-এ server তৈরির জন্য cloud module আছে। আপনি যদি 2টি VPS instance order করে চালু রাখেন, সেটিই যথেষ্ট। তবে state file ও dependency graph থাকবে না। Playbook থেকে কোনো task সরালেও resource চলতে থাকবে এবং billing চলবে, কারণ Ansible কখনো record করেনি যে resource-টি সে তৈরি করেছিল। Terraform হলে destroy করার পরিকল্পনা তৈরি করত।
প্রথমে কোনটি শেখা উচিত?
আপনি যদি বর্তমানে server পরিচালনা করেন, তাহলে Ansible। প্রথম মেশিনেই এর সুফল পাওয়া যায়, SSH ছাড়া আর কিছু প্রয়োজন হয় না, এবং হাতে order করা server-এও এই দক্ষতা কাজে লাগে। Terraform-এর সুফল পরে পাওয়া যায়, যখন environment বারবার rebuild করেন বা server-এর বাইরে DNS record ও firewall rule-এর মতো provider resource পরিচালনা করেন।
Terraform থেকে নতুন server-এর IP Ansible-এ কীভাবে পাঠাব?
Terraform code-এ একটি output declare করুন, তারপর apply-এর পরে সেটি পড়ুন। Shell substitution-এর জন্য terraform output -raw web_ip শুধু value দেখায়, আর একাধিক host থাকলে terraform output -json একসঙ্গে সব output দেয়। সেই output inventory file-এ লিখুন, অথবা cloud.terraform collection ইনস্টল করে ansible-inventory -i terraform.yml --graph-কে project directory দেখান।
Terraform শেষ হওয়ার পরপরই আমার playbook ব্যর্থ হয় কেন?
Provider-এর API server তৈরি হয়েছে জানালেই provider server-টিকে created হিসেবে report করে। তখন operating system এখনও boot হচ্ছে, তাই প্রথম কয়েক সেকেন্ড SSH প্রত্যাখ্যাত হয়। UNREACHABLE!-এর সঙ্গে Connection refused error দেখা যায়। অনুমান করে sleep duration নির্ধারণ না করে play-এর প্রথম task হিসেবে ansible.builtin.wait_for_connection ব্যবহার করুন, কারণ image ও plan অনুযায়ী boot time পরিবর্তিত হয়।