अंतिम समीक्षा: मई 2026
साधारण Terraform के साथ 004 परीक्षा के AWS संसाधनों को बनाएं — एक समय में एक ब्लॉक, प्रत्येक परीक्षा डोमेन से जुड़ा हुआ। यही कोड OpenTofu पर भी काम करता है।
इस लैब के अंत तक, आप बिना किसी क्लाउड खाते या एक भी पैसा खर्च किए, संपूर्ण कोर टेराफ़ॉर्म वर्कफ़्लो को शुरू से अंत तक चला चुके होंगे और हर एसोसिएट परीक्षा डोमेन को छू चुके होंगे। हम random और local प्रोवाइडर का उपयोग करते हैं, जिन्हें किसी क्रेडेंशियल की आवश्यकता नहीं होती है, इसलिए ध्यान उस चीज़ पर केंद्रित रहता है जिसकी परीक्षा वास्तव में जाँच करती है: टेराफ़ॉर्म स्वयं कैसे व्यवहार करता है।
आप अपना पहला रिसोर्स लिखेंगे, इसे वैरिएबल और आउटपुट के साथ पैरामीटराइज़ करेंगे, for_each के साथ कई रिसोर्स जेनरेट करेंगे, दोहराव को एक पुनः प्रयोज्य मॉड्यूल में रीफ़ैक्टर करेंगे, स्टेट का निरीक्षण और माइग्रेट करेंगे, और अंत में रिमोट रन के लिए कॉन्फ़िगरेशन को एचसीपी टेराफ़ॉर्म पर इंगित करेंगे। हर स्निपेट सामान्य टेराफ़ॉर्म है — वही कोड OpenTofu पर अपरिवर्तित काम करता है। ब्लॉक को एक ही main.tf में डालें (हम उन कुछ को इंगित करेंगे जो अपनी फ़ाइलों में रहते हैं), terraform init एक बार चलाएँ, फिर terraform apply कदम दर कदम चलाएँ।
>= 1.5 या OpenTofu >= 1.6 (terraform version)। हम चरण 6 में कॉन्फ़िग-ड्रिवेन import ब्लॉक का उपयोग करते हैं, जिसके लिए 1.5+ की आवश्यकता होती है।random और local प्रोवाइडर पूरी तरह से आपकी मशीन पर चलते हैं।mkdir tf-associate-lab && cd tf-associate-lab)।यह लैब पूरी तरह से मुफ़्त है। random और local प्रोवाइडर कोई क्लाउड रिसोर्स नहीं बनाते हैं — केवल आपकी अपनी डिस्क पर कुछ छोटी फ़ाइलें और एक स्थानीय terraform.tfstate में एंट्रीज़। चरण 7 (एचसीपी टेराफ़ॉर्म) मुक्त टियर का उपयोग करता है, जो एक एकल लैब वर्कस्पेस के लिए पर्याप्त है। यहां ऐसा कुछ भी नहीं है जो निष्क्रिय रहते हुए बिल बनाता हो।
कुछ भी चलाने से पहले, हम यह घोषित करते हैं कि हम किस टेराफ़ॉर्म संस्करण की अपेक्षा करते हैं और हम किन प्रोवाइडर पर निर्भर करते हैं। पिनिंग परीक्षा का पसंदीदा है — टेराफ़ॉर्म बेसिक्स और कोर वर्कफ़्लो डोमेन दोनों यह परीक्षण करते हैं कि आप required_version, required_providers ब्लॉक, और .terraform/ में प्रोवाइडर प्लगइन्स डाउनलोड करने में terraform init की भूमिका को समझते हैं।
हम जानबूझकर random और local चुनते हैं। किसी को भी क्लाउड लॉगिन की आवश्यकता नहीं होती है, इसलिए पूरी लैब मुफ़्त और रिप्रोड्यूसिबल रहती है, और वैसे भी परीक्षा कभी किसी विशिष्ट क्लाउड के बारे में नहीं पूछती — यह टेराफ़ॉर्म के बारे में पूछती है। इसे एक नई main.tf में डालें और terraform init चलाएँ; आप देखेंगे कि टेराफ़ॉर्म दोनों प्रोवाइडर को .terraform.lock.hcl फ़ाइल में रिज़ॉल्व और लॉक करता है, जो स्वयं एक बेसिक्स-डोमेन चर्चा बिंदु है (लॉक फ़ाइल को कमिट करें ताकि हर रन समान प्लगइन संस्करणों का उपयोग करे)।
terraform {
required_version = ">= 1.5"
required_providers {
random = {
source = "hashicorp/random"
version = "~> 3.6"
}
local = {
source = "hashicorp/local"
version = "~> 2.5"
}
}
}
# Both providers run locally and need no "provider" configuration
# block at all - a useful reminder that providers are just plugins.अब हम कोर टेराफ़ॉर्म वर्कफ़्लो का उपयोग करें डोमेन (परीक्षा का 18%) के मुख्य भाग का अभ्यास करते हैं। हम एक random_pet घोषित करते हैं जो एक दोस्ताना नाम बनाता है, फिर एक local_file जो उस नाम को डिस्क पर लिखता है। local_file.greeting रिसोर्स random_pet.name.id को संदर्भित करता है, और यही संदर्भ टेराफ़ॉर्म को बताता है कि फ़ाइल पेट पर निर्भर करती है — अंतर्निहित निर्भरता क्रम, depends_on की आवश्यकता नहीं है।
वर्कफ़्लो को क्रम में चलाएँ: terraform plan आपको दिखाता है कि कुछ भी होने से पहले क्या बदलेगा, और terraform apply इसे वास्तविक बनाता है और परिणाम को terraform.tfstate में रिकॉर्ड करता है। बिना कुछ बदले terraform apply को दूसरी बार चलाएँ और आपको कोई बदलाव नहीं दिखेगा — यह आइडेंपोटेंसी है, और परीक्षा यह पूछना पसंद करती है कि दूसरा अप्लाई नो-ऑप क्यों है। एक कार्यशील रिसोर्स और एक नई स्टेट फ़ाइल के साथ, हम कॉन्फ़िगरेशन को लचीला बनाना शुरू कर सकते हैं।
resource "random_pet" "name" {
length = 2
separator = "-"
}
resource "local_file" "greeting" {
filename = "${path.module}/hello.txt"
content = "Hello from ${random_pet.name.id}!\n"
}डेमो के लिए हार्ड-कोडेड मान ठीक हैं, लेकिन कॉन्फ़िगरेशन पढ़ें, जेनरेट करें और संशोधित करें डोमेन (19%) आपसे पैरामीटराइज़ करने की अपेक्षा करता है। हम type, default, और एक validation ब्लॉक के साथ एक इनपुट variable जोड़ते हैं जो हमारे अनुमत वातावरण के बाहर किसी भी चीज़ को अस्वीकार करता है — सत्यापन योजना समय पर चलता है और एक अक्सर पूछा जाने वाला परीक्षा प्रश्न है। हम एक locals मैप की गणना एक बार करते हैं और उसे पुनः उपयोग करते हैं, और हम परिणामों को output ब्लॉक के साथ उजागर करते हैं ताकि अन्य कॉन्फ़िगरेशन (और terraform output) उन्हें पढ़ सकें।
परीक्षा द्वारा परीक्षण किए गए लेयरिंग पर ध्यान दें: variable इनपुट है, locals एक व्युत्पन्न/मध्यवर्ती मान है, और output प्रकाशित परिणाम है। फिर से अप्लाई करें और एक मान पढ़ने के लिए terraform output pet_name आज़माएँ, या इसके विरुद्ध स्क्रिप्ट करने के लिए terraform output -json आज़माएँ। इनपुट और आउटपुट के साथ, हम एक-एक करके रिसोर्स लिखना बंद करने और एक पूरा सेट जेनरेट करने के लिए तैयार हैं।
variable "environment" {
description = "Deployment environment label."
type = string
default = "dev"
validation {
condition = contains(["dev", "staging", "prod"], var.environment)
error_message = "environment must be one of: dev, staging, prod."
}
}
locals {
common_tags = {
environment = var.environment
managed_by = "terraform"
}
}
output "pet_name" {
description = "The generated pet name."
value = random_pet.name.id
}
output "tags" {
value = local.common_tags
}वास्तविक कॉन्फ़िगरेशन शायद ही कभी हर चीज़ में से एक घोषित करते हैं। यहां हम एक संग्रह से रिसोर्स निर्माण को चलाकर कॉन्फ़िगरेशन पढ़ें, जेनरेट करें और संशोधित करें डोमेन में और गहराई तक जाते हैं। एक set(string) वैरिएबल लॉजिकल सेवाओं को सूचीबद्ध करता है; for_each फिर प्रति सेवा एक random_string और एक local_file बनाता है, जिसे random_string.suffix["api"] और इसी तरह संबोधित किया जा सकता है।
यह चरण उन एक्सप्रेशन और बिल्ट-इन फ़ंशन्स को भी प्रदर्शित करता है जिन्हें परीक्षा आपको पहचानने की अपेक्षा करती है: वर्तमान तत्व के लिए each.key, प्रति-सेवा बकेट नाम बनाने के लिए स्ट्रिंग इंटरपोलेशन, और डिस्क पर एक HCL ऑब्जेक्ट को JSON फ़ाइल में बदलने के लिए jsonencode()। हम चरण 3 से var.environment और local.common_tags का पुनः उपयोग करते हैं ताकि हर जेनरेट की गई फ़ाइल में सुसंगत मेटाडेटा हो। अगला स्पष्ट प्रश्न — यह दोहराव वाला हो रहा है, मैं इसे कैसे पैकेज करूं? — ठीक वही है जिसका उत्तर मॉड्यूल देते हैं।
variable "services" {
description = "Logical services to generate a config file for."
type = set(string)
default = ["api", "web", "worker"]
}
resource "random_string" "suffix" {
for_each = var.services
length = 6
special = false
upper = false
}
resource "local_file" "service_config" {
for_each = var.services
filename = "${path.module}/config/${each.key}.json"
content = jsonencode({
service = each.key
environment = var.environment
bucket = "${each.key}-${random_string.suffix[each.key].result}"
tags = local.common_tags
})
}टेराफ़ॉर्म मॉड्यूल के साथ इंटरैक्ट करें डोमेन चाहता है कि आप एक मॉड्यूल लिखें, उसे कॉल करें, और मानों को अंदर और बाहर पास करें। हम प्रति-सेवा तर्क को ./modules/service के तहत एक चाइल्ड मॉड्यूल में ले जाते हैं, इसे अपने स्वयं के variable इनपुट और एक output देते हैं, फिर इसे for_each के साथ रूट से कॉल करते हैं — प्रति सेवा एक मॉड्यूल इंस्टेंस।
नीचे दी गई दो फ़ाइलें सीमा को स्पष्ट रूप से दिखाती हैं: चाइल्ड मॉड्यूल को यह नहीं पता होता है कि कौन सी सेवाएँ मौजूद हैं (यह var.name के माध्यम से कॉलर का काम है), और रूट को यह नहीं पता होता है कि एक सेवा कैसे बनाई जाती है (यह मॉड्यूल में समाहित है)। एक मॉड्यूल जोड़ने के बाद terraform init को फिर से चलाएँ — परीक्षा यह परीक्षण करती है कि नए मॉड्यूल स्रोतों को स्थापित करने के लिए एक री-इनिट की आवश्यकता होती है। हमारे कॉन्फ़िगरेशन के अब मॉड्यूलर होने के साथ, अंतिम बड़ा एसोसिएट विषय वह है जिसे टेराफ़ॉर्म पूरे समय चुपचाप ट्रैक कर रहा है: स्टेट।
# modules/service/main.tf
variable "name" {
type = string
}
variable "environment" {
type = string
}
resource "random_string" "suffix" {
length = 6
special = false
upper = false
}
resource "local_file" "config" {
filename = "${path.root}/config/${var.name}.json"
content = jsonencode({
service = var.name
environment = var.environment
bucket = "${var.name}-${random_string.suffix.result}"
})
}
output "bucket_name" {
value = "${var.name}-${random_string.suffix.result}"
}
# main.tf (root) - call the module once per service
module "service" {
source = "./modules/service"
for_each = var.services
name = each.key
environment = var.environment
}
output "service_buckets" {
value = { for k, m in module.service : k => m.bucket_name }
}स्टेट को लागू करें और बनाए रखें (19%) और कोर वर्कफ़्लो के बाहर टेराफ़ॉर्म का उपयोग करें (9%) डोमेन दोनों यहीं रहते हैं। स्टेट वह JSON लेजर है जो आपके कॉन्फ़िग पतों को वास्तविक वस्तुओं से मैप करता है; terraform state list इसे सूचीबद्ध करता है और terraform state show <addr> एक एंट्री प्रिंट करता है। परीक्षा आपसे यह जानने की अपेक्षा करती है कि कॉन्फ़िग में किसी रिसोर्स का नाम बदलने से सामान्यतः उसे नष्ट और पुनः निर्मित किया जाएगा — जब तक कि आप टेराफ़ॉर्म को यह न बताएँ कि पता स्थानांतरित हो गया है।
एक moved ब्लॉक बिल्कुल यही घोषणात्मक रूप से करता है: local_file.greeting (चरण 2 से) का नाम बदलकर local_file.welcome करें और moved ब्लॉक स्टेट को यथास्थान माइग्रेट करता है, इसलिए plan एक चाल दिखाता है, न कि नष्ट और पुनः निर्माण। (अनिवार्य समकक्ष terraform state mv local_file.greeting local_file.welcome है।) हम एक कॉन्फ़िग-ड्रिवेन import ब्लॉक भी दिखाते हैं — पुराने terraform import CLI कमांड के बिना एक पूर्व-मौजूदा ऑब्जेक्ट को स्टेट में अपनाने का 1.5+ तरीका। स्टेट नियंत्रण में होने के साथ, एक क्षमता बाकी है जिसे पूरा करना है: यह सब दूरस्थ रूप से चलाना।
# Renaming a resource? A "moved" block migrates state in place
# instead of destroying and recreating the object. Replace the
# Step 2 "greeting" resource with this renamed "welcome" one.
moved {
from = local_file.greeting
to = local_file.welcome
}
resource "local_file" "welcome" {
filename = "${path.module}/hello.txt"
content = "Hello from ${random_pet.name.id}!\n"
}
# Config-driven import (Terraform 1.5+): adopt an object that
# already exists into state, no "terraform import" CLI command.
# terraform_data is a built-in resource - nothing to provision.
import {
to = terraform_data.tracked
id = "existing-id"
}
resource "terraform_data" "tracked" {}अंतिम डोमेन, एचसीपी टेराफ़ॉर्म क्षमताओं को समझें (5%), परीक्षा को पूरा करता है। terraform {} के अंदर एक अकेला cloud ब्लॉक स्थानीय निष्पादन को एचसीपी टेराफ़ॉर्म से बदल देता है: स्टेट दूरस्थ रूप से रहता है और रन के दौरान लॉक रहता है, terraform plan/apply हैशिकोर्प के रनर्स पर निष्पादित होते हैं, और रन आउटपुट (प्लस एक संग्रहीत योजना) वेब यूआई में दिखाई देता है। यहीं पर परीक्षा एचसीपी टेराफ़ॉर्म सुविधाओं — रिमोट स्टेट, रन हिस्ट्री, सेंटिनल/ओपीए के साथ पॉलिसी एनफोर्समेंट, और एक निजी मॉड्यूल रजिस्ट्री — को उस विशुद्ध रूप से स्थानीय वर्कफ़्लो के विपरीत दिखाती है जिसका हमने चरण 1-6 में उपयोग किया था।
my-org को अपने संगठन से बदलें, एक एपीआई टोकन संग्रहीत करने के लिए terraform login एक बार चलाएँ, फिर स्टेट को रिमोट वर्कस्पेस में माइग्रेट करने के लिए terraform init करें। इस लैब में आपने जो कुछ भी लिखा है वह अब अपरिवर्तित चलता है — केवल कहां चलता है वह बदल गया है। वह राउंड-ट्रिप, एक साधारण main.tf से रिमोट-बैकड वर्कस्पेस तक, एक ही बैठक में पूरा एसोसिएट आर्क है।
terraform {
cloud {
organization = "my-org"
workspaces {
name = "terraform-associate-lab"
}
}
}
# Run once to authenticate, then re-init to migrate state:
# terraform login
# terraform initसब कुछ आपकी मशीन पर रहता है, इसलिए सफाई जल्दी होती है:
terraform destroy चलाएँ।terraform-associate-lab वर्कस्पेस को हटा दें (या पहले इसके विरुद्ध terraform destroy चलाएँ), फिर cloud ब्लॉक को हटा दें।cd .. && rm -rf tf-associate-lab। स्थानीय .terraform/ प्लगइन कैश, .terraform.lock.hcl, और terraform.tfstate भी इसके साथ चले जाएंगे।एसोसिएट परीक्षा टेराफ़ॉर्म उपकरण के बारे में है, न कि किसी एक क्लाउड के बारे में, इसलिए यह लैब जानबूझकर कोई क्लाउड इन्फ्रास्ट्रक्चर प्रदान नहीं करती है। हम जानबूझकर AWS / Azure / GCP रिसोर्स को छोड़ देते हैं: उन्हें क्रेडेंशियल की आवश्यकता होती है, लागत लग सकती है, और वे उन यांत्रिकी से ध्यान भटकाते हैं जिनकी परीक्षा वास्तव में जाँच करती है — वर्कफ़्लो, स्टेट, कॉन्फ़िगरेशन भाषा और मॉड्यूल।
कुछ एसोसिएट विषयों के बारे में चलाने के बजाय पढ़ना सबसे अच्छा है: एचसीपी टेराफ़ॉर्म (S3, Azure Blob, GCS, Consul) के अलावा बैकएंड, remote-exec जैसे प्रोविज़नर (जिसे हैशिकोर्प अंतिम उपाय के रूप में सूचीबद्ध करता है), और कई स्टेट इंस्टेंस को प्रबंधित करने के लिए वर्कस्पेस। उनके लिए, इस प्रमाणन पृष्ठ के ब्राउज़ और मार्गदर्शिका अनुभागों में वैचारिक कवरेज है। यहां का हैंड्स-ऑन मूल्य init → plan → apply की मांसपेशी स्मृति, एक स्टेट फ़ाइल पढ़ना, और moved के साथ सुरक्षित रूप से रीफ़ैक्टर करना है।