अंतिम समीक्षा: मई 2026
साधारण Terraform के साथ TF-PRO परीक्षा के AWS संसाधनों को बनाएं — एक समय में एक ब्लॉक, प्रत्येक परीक्षा डोमेन से जुड़ा हुआ। यही कोड OpenTofu पर भी काम करता है।
इस लैब के अंत तक आप उन चार डोमेन का अभ्यास कर चुके होंगे, जिन्हें Terraform Pro परीक्षा सबसे अधिक महत्व देती है: उन्नत एचसीएल (HCL) लिखना, मॉड्यूल बनाना और संयोजित करना, स्टेट सर्जरी करना और एचसीपी टेराफ़ॉर्म (HCP Terraform) के विरुद्ध संचालन करना — यह सब क्रेडेंशियल-मुक्त random और local प्रोवाइडर के साथ, इसलिए भुगतान करने और एक फोल्डर के अलावा कुछ भी साफ करने की आवश्यकता नहीं है।
आप समृद्ध प्रकार की बाधाओं और सत्यापन के साथ इनपुट को मॉडल करेंगे, परीक्षा पर निर्भर एक्सप्रेशन और फंक्शन के साथ संग्रहों को बदलेंगे, एक पुन: प्रयोज्य मॉड्यूल लिखेंगे और इसे for_each के साथ फैलाएंगे, फिर import, moved और removed ब्लॉकों के साथ लाइव स्टेट को रिफैक्टर करेंगे। अंतिम चरण पूरे सिस्टम को रिमोट एक्सेक्यूशन के लिए एचसीपी टेराफ़ॉर्म से जोड़ता है। हर स्निपेट प्लेन टेराफ़ॉर्म है — ओपनटोफू (OpenTofu) पर समान। इसे एक ही वर्किंग डायरेक्टरी में बनाएं; हम उन फ़ाइलों को इंगित करते हैं जो ./modules के अंतर्गत रहती हैं।
>= 1.9 या ओपनटोफू >= 1.8 (terraform version)। हम removed ब्लॉक (1.7+) और import ब्लॉक (1.5+) का उपयोग करते हैं, इसलिए एसोसिएट लैब की तुलना में यहां वर्तमान रिलीज़ अधिक महत्वपूर्ण है।random और local पूरी तरह से आपकी मशीन पर चलते हैं।mkdir tf-pro-lab && cd tf-pro-lab)।terraform fmt और terraform validate चलाने की आदत डालें — प्रो परीक्षा मानती है कि आप उन्हें लिखने के हिस्से के रूप में मानते हैं, न कि बाद के विचार के रूप में।यह लैब पूरी तरह से निःशुल्क है। random और local प्रोवाइडर आपकी अपनी डिस्क पर केवल छोटी फ़ाइलें और एक स्थानीय terraform.tfstate बनाते हैं; किसी भी क्लाउड में कुछ भी प्रावधान नहीं किया जाता है और निष्क्रिय होने पर कोई बिलिंग नहीं होती है। चरण 7 (HCP Terraform) फ्री टियर पर चलता है, जिसमें एक ही लैब वर्कस्पेस और परीक्षा द्वारा पूछे गए परिचालन सुविधाएँ शामिल हैं।
हम हाल के टेराफ़ॉर्म को पिन करके एचसीएल (HCL) और कॉन्फ़िगरेशन डोमेन शुरू करते हैं — प्रो परीक्षा उन भाषा सुविधाओं को मानती है जो केवल नए रिलीज़ में मौजूद हैं (optional() ऑब्जेक्ट विशेषताएँ, removed ब्लॉक)। required_providers ब्लॉक random और local को लॉक करता है, और terraform init एक .terraform.lock.hcl लिखता है जिसे आपको कमिट करना चाहिए ताकि प्लान एक टीम में रिप्रोड्यूस करने योग्य हों।
अब बनाने वाली दो आदतें पूरे लैब में चलती हैं: terraform fmt स्पेसिंग और अलाइनमेंट को कैनोनिकल बनाता है (परीक्षा यह परीक्षण करती है कि यह फ़ाइलों को यथास्थान फिर से लिखता है और -check मोड में गैर-शून्य से बाहर निकलता है), और terraform validate यह जांचता है कि किसी भी प्रोवाइडर से संपर्क करने से पहले आपका कॉन्फ़िगरेशन आंतरिक रूप से सुसंगत है। टूलचेन पिन होने और आपकी उंगलियों पर उन दो कमांड के साथ, हम एचसीएल (HCL) लिख सकते हैं जो सत्यापन के लायक है।
terraform {
required_version = ">= 1.9"
required_providers {
random = {
source = "hashicorp/random"
version = "~> 3.6"
}
local = {
source = "hashicorp/local"
version = "~> 2.5"
}
}
}
# Build the muscle memory:
# terraform fmt # rewrite files to canonical style
# terraform validate # check internal consistency, offlineप्रो परीक्षा type = string से काफी आगे जाती है। यहां हम optional() विशेषताओं के साथ एक object प्रकार घोषित करते हैं जो एक कॉलर द्वारा छोड़े जाने पर डिफ़ॉल्ट प्रदान करती हैं, फिर कई validation ब्लॉक संलग्न करते हैं — परीक्षा यह परीक्षण करती है कि एक वेरिएबल एक से अधिक ले जा सकता है, प्रत्येक अपनी स्वयं की condition और error_message के साथ।
locals में try() अन्य प्रो-लेवल चाल है: यह पहला एक्सप्रेशन लौटाता है जो बिना त्रुटि के मूल्यांकन करता है, इसलिए शायद-अनुपस्थित विशेषता को पढ़ने से योजना को रोकने के बजाय धीरे-धीरे खराब हो जाता है। इसका सिबलिंग can() (जो एक बूल लौटाता है) चरण 4 के सत्यापन में बाद में दिखाई देता है। यह platform वेरिएबल बाकी लैब के लिए सत्य का एकल स्रोत बन जाता है — हर बाद का चरण इससे पढ़ता है, इसलिए यहां प्रकार और उसकी गारंटी सही होने से डाउनस्ट्रीम में फायदा होता है।
variable "platform" {
description = "Platform configuration."
type = object({
name = string
replicas = optional(number, 2)
features = optional(set(string), [])
owners = list(string)
})
validation {
condition = var.platform.replicas >= 1 && var.platform.replicas <= 10
error_message = "replicas must be between 1 and 10."
}
validation {
condition = length(var.platform.owners) > 0
error_message = "At least one owner is required."
}
default = {
name = "lab"
owners = ["platform@example.com"]
}
}
locals {
# try() returns the first error-free expression - here it shields
# against features being unset and classifies the tier.
tier = length(try(var.platform.features, [])) > 0 ? "enhanced" : "standard"
}संग्रह जिम्नास्टिक्स एचसीएल (HCL) और कॉन्फ़िगरेशन डोमेन का सबसे सघन हिस्सा है। हम प्रत्येक क्षेत्र/सेवा युग्म बनाने के लिए setproduct() का उपयोग करते हैं, फिर उन युग्मों को एक कीड मैप में फिर से आकार देने के लिए एक for एक्सप्रेशन का उपयोग करते हैं — वही सटीक पैटर्न जो बाद में for_each को फीड करता है। इसके साथ ही, flatten() + distinct() मालिकों की सूचियों की सूची को एक साफ अद्वितीय सेट में बदल देती है।
ये वे फ़ंक्शन हैं जिन पर प्रो प्रश्न बार-बार लौटते हैं: एक मैप बनाने के लिए => के साथ for, क्रॉस-प्रोडक्ट्स के लिए setproduct, नेस्टिंग के एक स्तर को गिराने के लिए flatten, मैप्स को संयोजित करने के लिए merge, और परिणाम को क्रमबद्ध करने के लिए jsonencode। हम गणना किए गए deployments मैप को एक फ़ाइल में प्रस्तुत करते हैं ताकि आप cat out/deployments.json कर सकें और अपनी एक्सप्रेशन द्वारा उत्पादित आकार देख सकें। वह कीड मैप ठीक उसी प्रकार का मान है जिसे हम अगले मॉड्यूल के for_each को सौंपेंगे।
locals {
regions = ["us-east-1", "eu-west-1"]
services = ["api", "web"]
# setproduct builds every (region, service) pair; the for
# expression reshapes the pairs into a keyed map.
deployments = {
for pair in setproduct(local.regions, local.services) :
"${pair[0]}/${pair[1]}" => {
region = pair[0]
service = pair[1]
}
}
# flatten + distinct collapse nested owner lists into a unique set.
all_owners = distinct(flatten([
for owner in var.platform.owners : split(",", owner)
]))
}
resource "local_file" "matrix" {
filename = "${path.module}/out/deployments.json"
content = jsonencode(local.deployments)
}अब मॉड्यूल डोमेन (25%)। हम ./modules/workload के तहत एक workload चाइल्ड मॉड्यूल निकालते हैं, जिसमें इसके अपने required_providers, मान्य इनपुट और प्रकाशित आउटपुट होते हैं। नाम सत्यापन में can(regex(...)) प्रो मुहावरा है: regex गैर-मिलान पर एक त्रुटि देगा, और can उस त्रुटि को false में बदल देता है जिसका उपयोग condition कर सकता है।
एक अच्छी तरह से बनाया गया मॉड्यूल अपने आंतरिक भागों को छुपाता है और एक स्थिर अनुबंध को उजागर करता है — कॉलर्स name और replicas पास करते हैं, और एक id और एक manifest_path वापस प्राप्त करते हैं, कभी भी अंदर के random_string को नहीं छूते हैं। मॉड्यूल द्वारा अपनी स्वयं की प्रोवाइडर आवश्यकताओं को घोषित करना एक जानबूझकर प्रो बिंदु है: प्रोवाइडर कॉन्फ़िगरेशन डिफ़ॉल्ट रूप से रूट से विरासत में मिलता है, लेकिन प्रोवाइडर आवश्यकताएँ प्रति मॉड्यूल घोषित की जाती हैं। हाथ में एक साफ मॉड्यूल के साथ, दिलचस्प सवाल यह है कि इसे कितनी बार इंस्टेंटिएट किया जाए और इंस्टेंस को एक साथ कैसे जोड़ा जाए।
# modules/workload/main.tf
terraform {
required_providers {
random = {
source = "hashicorp/random"
version = "~> 3.6"
}
local = {
source = "hashicorp/local"
version = "~> 2.5"
}
}
}
variable "name" {
type = string
validation {
# can() turns regex's raise-on-no-match into a usable bool.
condition = can(regex("^[a-z][a-z0-9-]{1,30}$", var.name))
error_message = "name must be 2-31 chars: lowercase letter, then letters/digits/hyphens."
}
}
variable "replicas" {
type = number
default = 1
}
resource "random_string" "suffix" {
length = 6
special = false
upper = false
}
resource "local_file" "manifest" {
filename = "${path.root}/out/${var.name}.json"
content = jsonencode({
name = var.name
replicas = var.replicas
id = "${var.name}-${random_string.suffix.result}"
})
}
output "id" {
description = "Stable identifier for this workload."
value = "${var.name}-${random_string.suffix.result}"
}
output "manifest_path" {
value = local_file.manifest.filename
}अभी भी मॉड्यूल डोमेन में, अब हम एक सेट पर for_each के साथ प्रति वर्कलोड एक बार module.workload को कॉल करते हैं, प्रति कुंजी सशर्त रूप से replicas सेट करते हैं, और फिर प्रत्येक इंस्टेंस के id आउटपुट को एक ही एग्रीगेट registry.json में उपभोग करते हैं। एक for एक्सप्रेशन के साथ module.workload पर इटरेट करना वह कैनोनिकल तरीका है जिससे परीक्षा एक मॉड्यूल के आउटपुट को दूसरे संसाधन के इनपुट में जोड़ती है।
एग्रीगेट फ़ाइल पर स्पष्ट depends_on एक शिक्षण बिंदु है: module.workload संदर्भ से निहित निर्भरताएँ पहले से ही चीजों को सही ढंग से व्यवस्थित करती हैं, लेकिन depends_on इरादे को अचूक बनाता है और कभी-कभी आवश्यक होता है जब डेटा के माध्यम से निर्भरता व्यक्त नहीं की जाती है। मॉड्यूल स्रोत जोड़ने के बाद terraform init चलाएँ, फिर apply करें। कई मॉड्यूल इंस्टेंस लाइव होने और उनके आउटपुट एग्रीगेट होने के साथ, हमारे पास वास्तविक स्टेट है जिस पर संचालन करना योग्य है — जो अगला डोमेन है।
# main.tf (root) - fan the module out, then aggregate its outputs
module "workload" {
source = "./modules/workload"
for_each = toset(["api", "web", "worker"])
name = each.key
replicas = each.key == "api" ? 3 : 1
}
resource "local_file" "registry" {
filename = "${path.module}/out/registry.json"
content = jsonencode({
for k, m in module.workload : k => m.id
})
depends_on = [module.workload]
}
output "workload_ids" {
value = { for k, m in module.workload : k => m.id }
}सीएलआई (CLI) और स्टेट मैनेजमेंट डोमेन (25%) वह जगह है जहाँ प्रो परीक्षा एसोसिएट से खुद को अलग करती है। हम तीन कॉन्फ़िग-चालित स्टेट ऑपरेशन का उपयोग करते हैं। एक import ब्लॉक एक ऐसी वस्तु को स्टेट में अपनाता है जो पहले से मौजूद है — हम एक बिल्ट-इन terraform_data को लक्षित करते हैं ताकि उदाहरण क्रेडेंशियल-मुक्त रहे। एक removed ब्लॉक वास्तविक वस्तु को नष्ट किए बिना स्टेट से एक संसाधन हटाता है — बिल्कुल वही जिसके लिए आप पहुँचते हैं जब किसी अन्य कॉन्फ़िगरेशन को स्वामित्व सौंपते हैं। और replace_triggered_by के साथ terraform_data जब भी चरण 5 से रजिस्ट्री बदलती है, तो डाउनस्ट्रीम प्रतिस्थापन को मजबूर करता है, जिसमें कोई प्रोवाइडर शामिल नहीं होता है।
अनिवार्य सीएलआई (CLI) समकक्षों को भी जानें जिनका परीक्षा अभी भी परीक्षण करती है: निरीक्षण करने के लिए terraform state list और state show, नाम बदलने के लिए terraform state mv, भूलने के लिए terraform state rm, एक रन को संकुचित करने के लिए terraform plan -target=ADDR, और एक संसाधन को फिर से बनाने के लिए terraform apply -replace=ADDR। स्टेट को स्थानीय रूप से आपके नियंत्रण में मजबूती से रखने के साथ, अंतिम डोमेन यह सब एचसीपी टेराफ़ॉर्म (HCP Terraform) पर कर रहा है।
# 1) Adopt an existing object into state (Terraform 1.5+),
# replacing the older imperative "terraform import" command.
import {
to = terraform_data.legacy
id = "existing-id"
}
resource "terraform_data" "legacy" {}
# 2) Stop managing a resource WITHOUT destroying it (Terraform 1.7+).
removed {
from = random_string.deprecated
lifecycle {
destroy = false
}
}
# 3) terraform_data + replace_triggered_by recreates a marker
# whenever the registry file content changes.
resource "terraform_data" "deploy_marker" {
input = local_file.registry.content
lifecycle {
replace_triggered_by = [local_file.registry]
}
}एचसीपी टेराफ़ॉर्म (HCP Terraform) ऑपरेशंस डोमेन (20%) परीक्षा को समाप्त करता है। एक cloud ब्लॉक — यहां workspaces { tags = [...] } का उपयोग कर रहा है ताकि एक कॉन्फ़िगरेशन कई टैग-मिलान वाले वर्कस्पेस पर मैप हो सके — आपके लैपटॉप से निष्पादन को हटाता है। रन एचसीपी टेराफ़ॉर्म (HCP Terraform) पर रिमोट, लॉक किए गए स्टेट के साथ होते हैं; परीक्षा रिमोट, स्थानीय, और एजेंट निष्पादन मोड और वीसीएस (VCS)-चालित, सीएलआई (CLI)-चालित, और एपीआई (API)-चालित रन वर्कफ़्लो के बीच अंतर करती है।
यह वह जगह भी है जहाँ प्रो परीक्षा द्वारा नाम दी गई परिचालन सुविधाएँ एक साथ आती हैं: वर्कस्पेस में इनपुट साझा करने के लिए वेरिएबल सेट, एक वर्कस्पेस के अप्लाई को दूसरे की योजना में जोड़ने के लिए रन ट्रिगर, बाहरी एकीकरण के लिए रन टास्क, अप्लाई को गेट करने के लिए पॉलिसी सेट (सेंटिनल या ओपा), और चरण 4 में आपके द्वारा बनाए गए मॉड्यूल के प्रकार को प्रकाशित करने के लिए एक निजी मॉड्यूल रजिस्ट्री। my-org को अपने संगठन से बदलें, terraform login चलाएँ, फिर स्टेट को माइग्रेट करने के लिए terraform init चलाएँ। चरण 1-6 में आपके द्वारा लिखा गया कॉन्फ़िगरेशन अपरिवर्तित चलता है — केवल स्थान और उसके आसपास की सुरक्षा रेलें ऊपर उठ गई हैं, जो पूरी प्रो कहानी है।
terraform {
cloud {
organization = "my-org"
workspaces {
tags = ["terraform-pro-lab"]
}
}
}
# Authenticate once, then migrate state to the remote workspace:
# terraform login
# terraform initसब कुछ स्थानीय है, इसलिए हटाना तेज़ है:
terraform destroy चलाएँ। चरण 6 में removed ब्लॉक के कारण, random_string.deprecated (यदि यह कभी मौजूद था) को नष्ट करने के बजाय भुला दिया जाता है — यह इरादा है।terraform destroy चलाएँ, फिर यूआई (UI) में terraform-pro-lab वर्कस्पेस को हटा दें और cloud ब्लॉक को हटा दें।cd .. && rm -rf tf-pro-lab। .terraform/ कैश, .terraform.lock.hcl, और कोई भी स्थानीय स्टेट इसके साथ चले जाते हैं।प्रो परीक्षा टेराफ़ॉर्म के लेखन और संचालन का परीक्षण करती है, न कि किसी विशेष क्लाउड का, इसलिए यह लैब जानबूझकर कोई क्लाउड इन्फ्रास्ट्रक्चर प्रदान नहीं करती है — यह इसे क्रेडेंशियल-मुक्त रखती है और हर चरण को एचसीएल (HCL), मॉड्यूल, स्टेट और एचसीपी टेराफ़ॉर्म (HCP Terraform) पर ध्यान केंद्रित करने देती है।
प्रो-प्रासंगिक विषयों का एक समूह यहां प्रावधान करने के बजाय बेहतर ढंग से अध्ययन किया जाता है: dynamic ब्लॉक (जिनके सार्थक होने के लिए दोहराने योग्य नेस्टेड ब्लॉकों वाले संसाधन प्रकार — एक क्लाउड संसाधन — की आवश्यकता होती है), प्रोवाइडर configuration_aliases और मॉड्यूल में उपनामित प्रोवाइडर पास करना, सेंटिनल / ओपा (Sentinel / OPA) नीति लेखन, और निजी मॉड्यूल रजिस्ट्री प्रकाशन प्रवाह। इस प्रमाणन पृष्ठ के ब्राउज़ और मार्गदर्शिका अनुभाग उन अवधारणाओं को कवर करते हैं। यहां हैंड्स-ऑन मूल्य लेखन और संचालन लूप है जिसके चारों ओर परीक्षा बनाई गई है: मान्य जटिल इनपुट, संयोजित मॉड्यूल, निडर स्टेट सर्जरी और रिमोट रन।