10.10-bob: Infrastructure as Code — Terraform asoslari
10-QISM — DevOps va Deploy · 10-mavzu
1. Kirish va motivatsiya
10-QISM'da biz infratuzilmani bosqichma-bosqich qurdik: Linux server va SSH 10.1-bob, Nginx 10.2-bob, Docker (10.3-10.4), CI/CD 10.5-bob, AWS cloud xizmatlari 10.6-bob, deploy strategiyalari 10.7-bob, Kubernetes 10.8-bob va monitoring 10.9-bob. Lekin 10.6 da AWS resurslarini (EC2, S3, RDS, Security Group) qanday yaratdik? Qo'lda — AWS Console'da sichqoncha bilan tugmalarni bosib, maydonlarni to'ldirib. Bu — ClickOps (klik bilan operatsiya) deb ataladi va u jiddiy muammolarga olib keladi: bir oydan keyin "men buni qanday sozlagandim?" deb eslay olmaysiz; ikkinchi serverni xuddi shunday qilib yaratish — yana 30 daqiqa qo'l mehnati va albatta biror joyda xato; "production va staging bir xilmi?" degan savolga ishonch bilan javob bera olmaysiz; xodim ketsa — bilim ham u bilan ketadi.
Yechim — Infrastructure as Code (IaC — infratuzilma kod sifatida): serverni, tarmoqni, ma'lumotlar bazasini qo'lda emas, matnli kod fayllar orqali ta'riflash. Bu kod Git'da versiyalanadi (4-QISM), code review'dan o'tadi 15.2-bob, bir buyruq bilan takrorlanadi va istalgan paytda aynan o'sha holatga qaytariladi. Va IaC'ning de-fakto standarti — Terraform (HashiCorp). Siz HCL tilida "menga t3.micro EC2 + S3 bucket + Security Group kerak" deb yozasiz, terraform apply deb bosasiz — Terraform AWS API orqali hammasini yaratib beradi. O'chirmoqchi bo'lsangiz terraform destroy — hammasi izsiz yo'qoladi. Bu — "men serverni qo'lda sozlayman" deydigan junior bilan, "butun infratuzilmani kodda ta'riflab, bir buyruq bilan ko'tarib-tushiraman" deydigan senior o'rtasidagi farq.
Bu bob: IaC nima (imperative vs declarative, ClickOps muammosi), Terraform nima (multi-cloud, declarative engine), HCL til (block, resource, argument), provider (aws/gcp/azure), resource (yaratiladigan obyekt), declarative model (kerakli holat — Terraform farqni hisoblaydi), state (terraform.tfstate — real holat xaritasi, drift), workflow (init/plan/apply/destroy), variable va output (parametrlash), data source (mavjud resursni o'qish), module (qayta ishlatish), remote state/backend (S3 lock — jamoa), workspace (dev/prod), Terraform'ni boshqa vositalar bilan taqqoslash, hamda ko'p resurs (count/for_each, dynamic, lifecycle), local/depends_on/provisioner/provider alias/import va CI/CD bilan integratsiya. Bu bob 10.6 (AWS) ni avtomatlashtiradi, 10.5 (CI/CD) bilan birlashadi va 10.11 (secrets) ga ko'prik bo'ladi.
O'xshatish: IaC — retsept kitobi va IKEA yig'ish chizmasi. Qo'lda server yaratish — oshpaz oshxonada o'z xotirasidan, "ko'z bilan" osh damlashi: bir marta zo'r chiqadi, lekin ikkinchisi boshqacha, va boshqa odam takrorlay olmaydi (hujjatsiz). IaC esa — aniq yozilgan retsept: har bir masalliq (resource), miqdori (argument), tartibi (dependency) qog'ozda. Istalgan oshpaz (jamoadagi har kim) bir xil natijani qaytaradi. Terraform — IKEA yig'ish ustasi: siz unga chizmani (HCL kod) berasiz, u qutidagi qismlarni (AWS resurslar) to'g'ri tartibda yig'ib beradi. Eng muhimi — chizmada "menga 3 ta javon kerak" deb yozasiz (declarative — kerakli holat), "avval bu vintni bur, keyin u taxtani qo'y" deb emas (imperative — qadamlar). Hozir 2 ta javon bo'lsa — Terraform o'zi farqni ko'rib, faqat 1 tasini qo'shadi. State fayli — yig'ilgan mebel ro'yxati: nima yig'ilgani, qayerda turgani yozilgan daftar (Terraform shu daftarga qarab keyingi safar nima qilishni biladi).
Nega muhim?
- Takrorlanuvchanlik — bitta buyruq bilan dev/staging/prod'ni bir xil yaratasiz (qo'l xatosi yo'q).
- Versiyalash — infratuzilma Git'da, har o'zgarish review/rollback qilinadi (10.6'dagi ClickOps'da bu yo'q).
- Hujjat — kod o'zi hujjat: "nima bor?" degan savolga
.tffayllar javob beradi. - Intervyu/ish — "Terraform bilan ishlaganmisan? state nima?" — DevOps/SRE intervyularining markaziy savoli.
2. Nazariya — chuqur tushuntirish
2.1. IaC nima: imperative vs declarative, ClickOps muammosi
INFRASTRUCTURE AS CODE (IaC) — infratuzilmani QO'LDA emas, KOD bilan boshqarish:
server, tarmoq, DB, IP — hammasi matnli faylda ta'riflanadi (versiyalanadi)
3 XIL YONDASHUV (infratuzilma qanday yaratiladi):
1. ClickOps (QO'LDA) — AWS Console'da sichqoncha bilan 10.6-bob:
takrorlab bo'lmaydi (har safar boshqacha)
hujjatsiz ("qanday sozlagandim?" — eslab bo'lmaydi)
xato ko'p (inson qo'li), audit yo'q
2. IMPERATIVE (qadamlar bilan) — skript yoziladi (bash, AWS CLI — 10.6):
"avval EC2 yarat, keyin SG yarat, keyin biriktir..." (HOW — qanday)
holat o'zgarsa — skript buziladi (allaqachon bor bo'lsa xato beradi)
3. DECLARATIVE (kerakli holat) — Terraform:
"menga 1 EC2 + 1 S3 + 1 SG KERAK" (WHAT — nima, tartibni o'zi hal qiladi)
Terraform real holatni tekshirib, FARQNI hisoblaydi (yo'qni yaratadi)
ikki marta ishlatsang ham — natija bir xil (idempotent)Infrastructure as Code (IaC) — infratuzilmani qo'lda (sichqoncha bilan) emas, matnli kod fayllar orqali ta'riflash va boshqarish. Uch xil yondashuv bor. ClickOps — AWS Console'da qo'lda bosish (10.6'da shunday qildik): takrorlab bo'lmaydi, hujjatsiz, xato ko'p. Imperative (buyruqli) — qadamlarni skript bilan yozasiz (bash + AWS CLI): "avval bu, keyin u" — ya'ni qanday (HOW) qilishni aytasiz; muammosi — resurs allaqachon mavjud bo'lsa, skript buziladi. Declarative (e'lon qiluvchi) — Terraform yondashuvi: nima (WHAT) kerakligini ta'riflaysiz ("1 ta EC2 kerak"), tartibni va qadamlarni Terraform o'zi hal qiladi. Eng muhim afzallik — idempotentlik: bir xil kodni ikki, o'n marta ishlatsangiz ham natija bir xil bo'ladi (Terraform real holatni tekshirib, faqat yetishmagan qismni yaratadi). Bu ClickOps'da mutlaqo yo'q.
2.2. Terraform nima va nega (multi-cloud, declarative engine)
TERRAFORM — IaC vositasi (HashiCorp), infratuzilmani kod bilan quradi:
"Terraform lets you build, change, and version cloud and on-prem resources
safely and efficiently" (rasmiy ta'rif)
ASOSIY XUSUSIYATLAR:
DECLARATIVE — kerakli holatni ta'riflaysan 2.1-bob, Terraform amalga oshiradi
MULTI-CLOUD — bitta til (HCL) bilan AWS, GCP, Azure, K8s, GitHub... 2.3-bob
STATE-BASED — real holatni state faylda kuzatadi 2.7-bob
PLAN — o'zgarishni OLDINDAN ko'rsatadi (xavfsizlik — 2.6, 2.8)
TERRAFORM QANDAY ISHLAYDI (yuqori daraja):
┌──────────────┐ o'qiydi ┌─────────────┐ API ┌──────────────┐
│ .tf fayllar │ ────────── │ TERRAFORM │ ─────── │ AWS / GCP │
│ (HCL kod) │ │ (engine + │ │ (haqiqiy │
│ kerakli │ │ provider) │ ─────── │ resurslar) │
│ holat │ └──────┬──────┘ holat └──────────────┘
└──────────────┘ │
┌────────▼────────┐
│ terraform.tfstate│ real holat xaritasi
└─────────────────┘Terraform — HashiCorp'ning IaC vositasi: cloud va on-prem (o'z data-markazingdagi) resurslarni kod bilan quradi, o'zgartiradi va versiyalaydi. Asosiy xususiyatlari: declarative (kerakli holatni ta'riflaysiz — 2.1); multi-cloud — bitta til (HCL) bilan AWS, GCP, Azure, Kubernetes, GitHub va minglab boshqa platformalarni boshqarasiz (har biri uchun alohida CLI o'rganmaysiz — 2.3); state-based — real holatni
terraform.tfstatefaylda kuzatadi 2.7-bob; plan — har o'zgarishni amalga oshirishdan oldin ko'rsatadi 2.6-bob. Ishlash mexanizmi: siz.tffayllarda kerakli holatni yozasiz Terraform engine ularni o'qiydi, provider orqali 2.4-bob cloud API'siga murojaat qiladi resurslarni yaratadi/o'zgartiradi natijani state faylga yozadi. Keyingi safar Terraform avval state'ni o'qiydi, real holat bilan kerakli holatni solishtiradi va faqat farqni qo'llaydi. Terraform — IaC bozorining eng keng tarqalgan vositasi (Pulumi, OpenTofu — muqobillar, 2.13).
2.3. HCL til: block, argument, expression
HCL (HashiCorp Configuration Language) — Terraform'ning tili:
matnli, o'qilishi oson, ikki asosiy qurilma: ARGUMENT va BLOCK
ARGUMENT — nomga qiymat beradi (ism = qiymat):
┌─────────────────────────────────┐
│ instance_type = "t3.micro" │
│ └────┬─────┘ │ └────┬─────┘ │
│ IDENTIFIER = QIYMAT │
│ (nom) (expression) │
└─────────────────────────────────┘
BLOCK — boshqa mazmun saqlovchi konteyner (TUR + LABEL'lar + tana {}):
┌──────────────────────────────────────────────┐
│ resource "aws_instance" "web" { │
│ └───┬───┘ └──────┬──────┘ └─┬─┘ │ │
│ TUR 1-LABEL 2-LABEL tana │
│ (block type) (resurs turi)(nom) │
│ │
│ ami = "ami-0abc123" argument │
│ instance_type = "t3.micro" argument │
│ } │
└──────────────────────────────────────────────┘
IZOH: # bir qatorli (asosiy) // ham mumkin /* ko'p qatorli */
Fayl UTF-8, kengaytma .tf ; identifier harf/_ bilan boshlanadiHCL (HashiCorp Configuration Language) — Terraform yoziladigan til (matnli, inson o'qishi uchun qulay). Ikki asosiy qurilma bor (rasmiy hujjat). Argument — nomga qiymat beradi:
instance_type = "t3.micro"(chap tomonda identifier — nom, teng belgidan keyin expression — qiymat/ifoda). Block — boshqa mazmunni saqlovchi konteyner: tur (block type —resource,variable,provider...), keyin label'lar (0 yoki undan ko'p —resourceikki label oladi: resurs turi"aws_instance"va nom"web"), va{ }ichidagi tana (body — argumentlar va ichki bloklar). Sintaksis qoidalari (rasmiy): fayl UTF-8 kodlangan, kengaytmasi.tf; izohlar —#(asosiy, idiomatik),//yoki/* */; identifier harf yoki_bilan boshlanadi (raqam bilan emas), faqat harf/raqam/_/-bo'ladi. HCL JSON emas — ancha o'qilishi oson, lekin Terraform JSON formatini ham qabul qiladi (mashina generatsiyasi uchun).
2.4. Provider — cloud bilan ko'prik (aws/gcp/azure)
PROVIDER — Terraform'ni biror platformaga ulaydigan PLAGIN:
har resurs turi bitta provider tomonidan amalga oshiriladi
providersiz Terraform HECH NARSA boshqara olmaydi (rasmiy)
MASHHUR PROVIDER'LAR (Terraform Registry'da minglab bor):
- hashicorp/aws AWS (EC2, S3, RDS — 10.6)
- hashicorp/google Google Cloud (GCP)
- hashicorp/azurerm Microsoft Azure
- hashicorp/kubernetes K8s 10.8-bob ; cloudflare, github, docker...
E'LON QILISH (har modul qaysi provider kerakligini AYTADI):
terraform {
required_providers {
aws = {
source = "hashicorp/aws" # Registry'dagi manba
version = "~> 5.0" # versiya cheklovi (2.12 — muhim!)
}
}
}
provider "aws" { # provider'ni sozlash
region = "eu-central-1" # qaysi region (10.6: 2.2)
}Provider — Terraform'ni biror platforma (AWS, GCP, Azure...) bilan bog'laydigan plagin. Har bir resurs turi (
aws_instance,aws_s3_bucket) aniq bir provider tomonidan amalga oshiriladi — provider o'sha platformaning API'sini biladi. Rasmiy: providersiz Terraform hech qanday infratuzilmani boshqara olmaydi — u Terraform'ning "qo'llari". Mashhur provider'lar Terraform Registry'da:hashicorp/aws(AWS — 10.6),hashicorp/google(GCP),hashicorp/azurerm(Azure),hashicorp/kubernetes(K8s — 10.8), shuningdekcloudflare,github,dockerva minglab boshqalar. Har modul qaysi provider kerakliginirequired_providersblokida e'lon qiladi (source— Registry manbasi,version— versiya cheklovi). Keyinprovider "aws" { region = ... }bilan sozlanadi (qaysi region, ixtiyoriy autentifikatsiya).terraform init2.6-bob shu e'londan kelib chiqib provider'larni avtomatik yuklab oladi.
2.5. Resource va data source
RESOURCE — Terraform YARATADIGAN/boshqaradigan obyekt (eng muhim element):
"Resources are the most important element in the Terraform language" (rasmiy)
bitta resource bloki = bitta (yoki ko'p) infratuzilma obyekti
resource "aws_instance" "web" { # YARATILADI (Terraform boshqaradi)
ami = "ami-0abc123"
instance_type = "t3.micro"
}
ichki murojaat: aws_instance.web.id (boshqa joyda shu resursga havola)
DATA SOURCE — MAVJUD resursni faqat O'QIYDI (yaratmaydi):
Terraform tashqarida yaratilgan narsani "ko'radi" (faqat o'qish)
data "aws_ami" "ubuntu" { # MAVJUD AMI'ni IZLAYDI (yaratmaydi)
most_recent = true
owners = ["099720109477"] # Canonical (Ubuntu)
filter { name = "name" values = ["ubuntu/images/*-24.04-*"] }
}
ishlatish: ami = data.aws_ami.ubuntu.id (topilgan AMI'ni resource'ga ber)
resource = MEN yarataman/boshqaraman ; data = MAVJUD narsani o'qiymanResource — Terraform yaratadigan va boshqaradigan infratuzilma obyekti, eng muhim element (rasmiy: "Resources are the most important element in the Terraform language"). Bitta
resourcebloki bitta (yoki bir nechta) obyektni ta'riflaydi:resource "aws_instance" "web" { ... }— Terraform shu EC2 instance'ni yaratadi, o'zgartiradi vadestroy'da o'chiradi. Resursga boshqa joyda havola qilish —aws_instance.web.id(Terraform o'zi to'g'ri tartibni — dependency graph'ni — quradi, 2.8). Data source esa — mavjud (Terraform tashqarisida yaratilgan) resursni faqat o'qiydi (yaratmaydi):data "aws_ami" "ubuntu" { ... }AWS'dagi eng so'nggi Ubuntu AMI'sini topadi, siz unidata.aws_ami.ubuntu.idorqali ishlatasiz. Asosiy farq:resource— men yarataman/boshqaraman;data— mavjud narsani o'qiyman (masalan, default VPC ID'sini olish, eng yangi AMI'ni topish). Bu — kodni qattiq qiymatlardan (hardcode) xalos qiladi.
2.6. Terraform workflow: init / plan / apply / destroy
TERRAFORM ASOSIY ISH JARAYONI (4 buyruq — eng muhim):
1. terraform init TAYYORLASH (har loyihada birinchi marta):
provider'larni yuklab oladi 2.4-bob, backend'ni sozlaydi 2.10-bob
.terraform/ papka + .terraform.lock.hcl yaratiladi
2. terraform plan OLDINDAN KO'RISH (nima o'zgaradi — XAVFSIZLIK):
real holat (state) bilan kerakli holatni solishtiradi
+ create (yashil) ~ update - destroy (qizil) ko'rsatadi
HECH NARSA o'zgartirmaydi (faqat reja — quruq yugurish)
3. terraform apply QO'LLASH (haqiqatan yaratadi/o'zgartiradi):
plan'ni ko'rsatadi "yes" deb tasdiqlaysan bajaradi
state faylni yangilaydi (real holat yoziladi)
4. terraform destroy O'CHIRISH (boshqarilgan hamma resursni o'chiradi):
faqat Terraform yaratganini o'chiradi (ehtiyot — qaytmaydi!)
YORDAMCHI: terraform fmt (formatla) | validate (tekshir) | show (holatni ko'r)Terraform workflow — to'rt asosiy buyruq (rasmiy: write plan apply).
terraform init— loyihani tayyorlaydi (har yangi loyihada birinchi marta):required_providers'dan provider'larni yuklab oladi, backend'ni 2.10-bob sozlaydi,.terraform/papka va.terraform.lock.hcl(versiya qulflari) yaratadi.terraform plan— o'zgarishni oldindan ko'rsatadi: real holatni (state) kerakli holat bilan solishtirib, nima yaratilishi (+), o'zgarishi (~) yoki o'chishi (-) ni chiqaradi — lekin hech narsa qilmaydi (xavfsiz "quruq yugurish").terraform apply— rejani qo'llaydi: avval plan'ni ko'rsatib,yesso'rab, keyin haqiqatan resurslarni yaratadi/o'zgartiradi va state'ni yangilaydi.terraform destroy— Terraform boshqargan hamma resursni o'chiradi (faqat o'zi yaratganini — qaytmaydi, ehtiyot bo'l). Yordamchi buyruqlar:terraform fmt(kodni standart formatlaydi),validate(sintaksisni tekshiradi),show(joriy state'ni ko'rsatadi). Doimoplan'ni ko'rib, keyinapplyqil 2.8-bob.
2.7. State nima va nega muhim (tfstate, drift)
STATE — Terraform boshqargan REAL holatning XARITASI:
default: terraform.tfstate (JSON fayl, lokal)
"source of truth" — qaysi kod qaysi haqiqiy resursga mos kelishi
NEGA KERAK (Terraform'siz bilolmaydi):
- kod: aws_instance.web haqiqat: i-0abc123 (qaysi EC2 — state'da yozilgan)
- state bo'lmasa — Terraform "men nimani yaratganman?" deb bilolmaydi
- plan tezligi: state'dagi holatni asos qilib farqni hisoblaydi
DRIFT — kod bilan haqiqat ORASIDAGI farq (kimdir QO'LDA o'zgartirsa):
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ KOD (.tf) │ =?= │ STATE │ =?= │ HAQIQAT(AWS)│
│ t3.micro │ │ t3.micro │ │ t3.LARGE │ kimdir
└──────────────┘ └──────────────┘ └──────────────┘ qo'lda
terraform plan drift'ni ko'rsatadi (qaytib kodga moslashtiradi — refresh) o'zgartirgan
STATE FAYLI — JIDDIY: secret'larni OCHIQ saqlashi mumkin (parol, kalit — 2.11)
tfstate'ni Git'ga commit QILMA (xavf!) — remote backend ishlat (2.10)State — Terraform boshqargan real infratuzilmaning xaritasi (rasmiy: "source of truth for your environment"). Default holatda lokal
terraform.tfstatefayl (JSON). Nega kerak: Terraform kodingizdagiaws_instance.webqaysi haqiqiy EC2 instance'ga (i-0abc123) mos kelishini state'dan biladi — state bo'lmasa, Terraform "men nimani yaratganman?" deb bilolmaydi (resurslarni qayta yaratib yuboradi yoki o'chira olmaydi). Drift (siljish) — kod/state bilan haqiqat orasidagi farq: kimdir AWS Console'da qo'lda instance turinit3.micro'dant3.large'ga o'zgartirsa, kod bilan haqiqat mos kelmay qoladi.terraform planbu drift'ni aniqlaydi va kodga qaytib moslashtirishni taklif qiladi (refresh). Eng muhim xavfsizlik ogohlantirishi: state fayli secret'larni ochiq matnda saqlashi mumkin (DB paroli, kalitlar — 2.11). Shuning uchunterraform.tfstate'ni hech qachon Git'ga commit qilma va lokal saqlama — remote backend 2.10-bob ishlat. Bu IaC'dagi eng keng tarqalgan jiddiy xato.
2.8. Plan: oldindan ko'rish va dependency graph
PLAN — apply'dan OLDIN nima bo'lishini ko'rsatadi (review qilinadi — xavfsizlik):
$ terraform plan
Terraform will perform the following actions:
# aws_instance.web will be created
+ resource "aws_instance" "web" {
+ ami = "ami-0abc123" + yangi qiymat
+ instance_type = "t3.micro"
+ id = (known after apply) yaratilgach ma'lum bo'ladi
}
Plan: 1 to add, 0 to change, 0 to destroy. XULOSA (eng muhim qator!)
BELGILAR: + create ~ update (joyida) -/+ replace (o'chir+yarat) - destroy
DEPENDENCY GRAPH — Terraform tartibni O'ZI hisoblaydi:
aws_instance ami = data.aws_ami.ubuntu.id AVVAL data, KEYIN instance
bog'liq bo'lmaganlarni PARALLEL yaratadi (tez)
plan'ni DOIM o'qi: "X to destroy" ko'rsatsa — nima o'chayotganini tekshir!Plan — Terraform'ning eng muhim xavfsizlik xususiyati:
apply'dan oldin aynan nima o'zgarishini ko'rsatadi, siz review qilasiz. Chiqishda har resurs uchun belgi:+(create — yaratiladi),~(update — joyida o'zgartiriladi),-/+(replace — o'chirib qaytadan yaratiladi, masalan o'zgartirib bo'lmaydigan maydon o'zgarsa),-(destroy — o'chiriladi). Eng muhim qator — oxirgi xulosa:Plan: 1 to add, 0 to change, 0 to destroy. Dependency graph (bog'liqlik grafi): Terraform resurslar orasidagi havolalardan (data.aws_ami.ubuntu.id'ni ishlatgan instance — avval AMI o'qiladi, keyin instance) to'g'ri tartibni o'zi hisoblaydi — siz tartibni yozmaysiz (declarative — 2.1). Bog'liq bo'lmagan resurslarni parallel yaratadi (tez). Oltin qoida: plan chiqishini doimo o'qib chiq — agar "X to destroy" ko'rsatsa, nima o'chayotganini tekshir (production DB tasodifan o'chmasin). CI/CD'da plan'ni PR'ga qo'shish — eng yaxshi amaliyot (2.13, 10.5).
2.9. Variable va output: parametrlash
VARIABLE — kodga TASHQARIDAN kiritiladigan qiymat (parametrlash):
variable "instance_type" {
type = string
default = "t3.micro" # berilmasa — shu (ixtiyoriy)
description = "EC2 instance o'lchami"
}
ishlatish: instance_type = var.instance_type
QIYMAT BERISH (bir necha usul, prioritet ortib boradi):
- default (kodda) < terraform.tfvars fayl < -var CLI < TF_VAR_ env
OUTPUT — apply'dan KEYIN chiqariladigan qiymat (natija):
output "public_ip" {
value = aws_instance.web.public_ip # yaratilgan IP'ni ko'rsat
}
terraform apply oxirida: public_ip = "203.0.113.5"
SENSITIVE — maxfiy qiymatni yashirish (parol, IP — 2.11):
output "db_password" {
value = aws_db_instance.main.password
sensitive = true # plan/output'da "(sensitive)" deb yashiradi
}Variable — kodga tashqaridan kiritiladigan qiymat (kodni parametrlaydi — bir kodni dev/prod uchun turli qiymat bilan ishlatasiz).
variable "instance_type" { type = string; default = "t3.micro" }—type(turi),default(berilmasa ishlatiladigan qiymat — ixtiyoriy),description(izoh). Ishlatish —var.instance_type. Qiymat berish usullari (prioritet pastdan yuqoriga): kodadagidefault<terraform.tfvarsfayl <-varCLI bayrog'i <TF_VAR_muhit o'zgaruvchisi. Output —apply'dan keyin chiqariladigan qiymat (natija — masalan yaratilgan EC2'ning public IP'si):output "public_ip" { value = aws_instance.web.public_ip }. Bu — boshqa modulga qiymat uzatish yoki sodda ravishda foydalanuvchiga ko'rsatish uchun.sensitive = true— maxfiy qiymatni (DB paroli) plan va output chiqishida(sensitive value)deb yashiradi (terminalga yoki log'ga oshkor bo'lmaydi). Lekin diqqat: u state faylda baribir ochiq saqlanadi (2.7, 2.11) — shuning uchun secret'larni alohida boshqarish kerak 10.11-bob.
2.10. Remote state va backend (S3 lock — jamoa)
BACKEND — state QAYERDA saqlanishini belgilaydi:
- LOCAL (default) — terraform.tfstate lokal faylda (faqat o'zing — yomon jamoa uchun)
- REMOTE — markaziy joyda (S3, HCP Terraform, GCS, Azure Blob...) — JAMOA uchun
NEGA REMOTE (jamoada lokal state YOMON):
lokal: har kimda o'z nusxasi (bir-biriga zid — konflikt)
lokal: kompyuter buzilsa — state yo'qoladi (resurslar "yetim" qoladi)
remote: bitta markaziy state (hamma bir manbadan o'qiydi)
remote: shifrlash + versiyalash + LOCK
STATE LOCKING — ikki kishi BIR VAQTDA apply qilmasligi uchun qulf:
A apply qilayotganda — B kutadi (state buzilmaydi — race condition yo'q)
S3 BACKEND (AWS — eng keng tarqalgan):
terraform {
backend "s3" {
bucket = "mening-tfstate-2026" # state saqlanadigan S3 (10.6: 2.6)
key = "prod/terraform.tfstate" # bucket ichidagi yo'l
region = "eu-central-1"
encrypt = true # state shifrlanadi (2.7 — secret!)
use_lockfile = true # NATIVE S3 lock (2026 — yangi usul)
}
}
ESKI: DynamoDB jadval bilan lock (endi deprecated — use_lockfile afzal — rasmiy)Backend — state qayerda saqlanishini belgilaydi. Local (default) —
terraform.tfstatelokal faylda (faqat o'zingiz ishlasangiz yetadi, lekin jamoa uchun yomon). Remote — markaziy joyda (AWS S3, HCP Terraform, GCS, Azure Blob). Nega remote: lokal state'da har kishida o'z nusxasi bo'lib, bir-biriga zid bo'ladi (konflikt); kompyuter buzilsa state yo'qoladi va resurslar "yetim" qoladi (Terraform ularni boshqara olmaydi). Remote — bitta markaziy manba, shifrlangan, versiyalangan. State locking (qulflash) — ikki kishi bir vaqtdaapplyqilib state'ni buzmasligi uchun: A apply qilayotganda B kutadi (race condition yo'q — 10.1 jamoa muammosiga o'xshash). S3 backend (eng keng tarqalgan):bucket,key(yo'l),region,encrypt = true(state shifrlanadi — 2.7 secret xavfi), vause_lockfile = true— S3'ning native lock mexanizmi. 2026 muhim yangilik (rasmiy): ilgari lock uchun alohida DynamoDB jadval kerak edi, endi u deprecated (eskirgan) —use_lockfilebilan S3'ning o'zi qulflaydi (DynamoDB shart emas). Eski loyihalar migratsiya uchun ikkalasini birga ishlatishi mumkin.
2.11. Module: qayta ishlatish
MODULE — birga boshqariladigan resurslar TO'PLAMI (qayta ishlatiladigan paket):
"A module is a collection of resources that Terraform manages together" (rasmiy)
ROOT MODULE — sen turgan asosiy papka (terraform shu yerda ishga tushadi)
CHILD MODULE — root chaqiradigan boshqa modul (module bloki orqali)
CHAQIRISH (module bloki):
module "vpc" {
source = "terraform-aws-modules/vpc/aws" # Registry'dan (yoki ./local-yo'l)
version = "5.0.0" # versiya (qulflash — 2.12)
name = "mening-vpc" # modulga kirish (variable)
cidr = "10.0.0.0/16"
}
natija: module.vpc.vpc_id (modul output'iga murojaat)
MANBA (source) TURLARI:
- ./modules/network lokal papka (o'z modullaring)
- terraform-aws-modules/vpc/aws Terraform Registry (ommaviy, tayyor)
- github.com/org/repo Git repozitoriy
MODULE = funksiya (5.6'dagi funksiyaga o'xshash): input (var) resurslar outputModule — birga boshqariladigan resurslar to'plami (rasmiy ta'rif), qayta ishlatiladigan paket. Har Terraform loyihasida root module bor — siz turgan asosiy papka (Terraform shu yerda ishlaydi). Child module — root chaqiradigan boshqa modul (
modulebloki orqali). Chaqirish:module "vpc" { source = "..."; version = "..."; name = "..." }—sourcemodulni qayerdan olishni, qolgan argumentlar modulga kirish (input — variable) qiymatlarini beradi. Modul natijasiga murojaat —module.vpc.vpc_id. Source turlari: lokal papka (./modules/network— o'z modullaring), Terraform Registry (terraform-aws-modules/vpc/aws— tayyor, ommaviy modullar), yoki Git repozitoriy (github.com/...). Modulni funksiya deb tasavvur qil (5.6'dagi funksiyaga o'xshash): kirish (variable) qabul qiladi ichida resurslar yaratadi chiqish (output) qaytaradi. Bir marta yozasiz — dev/staging/prod'da, hatto turli loyihalarda qayta ishlatasiz (DRY — takrorlanishni kamaytirish). Bu — IaC'ning eng kuchli tomoni.
2.12. Workspace, versiya cheklovi va sensitive
WORKSPACE — bir kod, ko'p ALOHIDA state (dev/staging/prod):
terraform workspace new dev # yangi workspace
terraform workspace new prod
terraform workspace select prod # prod'ga o'tish
har workspace'da AYRIM state (dev resurslari prod'dan ajralgan)
ko'pincha katta loyihalarda alohida PAPKA/backend afzal (workspace o'rniga)
VERSIYA CHEKLOVI (juda muhim — kutilmagan buzilishdan himoya):
required_version = ">= 1.5" # Terraform o'zining versiyasi
version = "~> 5.0" 5.x ruxsat, 6.0 EMAS (pessimistik operator)
version = ">= 5.0, < 6.0" # aniq diapazon
.terraform.lock.hcl provider'ni AYNAN qulflaydi (jamoa bir versiya)
SENSITIVE / SECRET (10.11 bilan bog'liq):
- sensitive = true terminal/log'da yashiradi 2.9-bob
- LEKIN state'da OCHIQ 2.7-bob remote+encrypt MAJBURIY 2.10-bob
- secret'larni kodga YOZMA tfvars (gitignore) yoki Vault/SSM (10.11)Workspace — bitta kod bilan bir nechta alohida state boshqarish (dev/staging/prod):
terraform workspace new dev,select prod. Har workspace'ning ayrim state'i bor (dev resurslari prod'dan ajralgan, lekin kod bir xil). Amalda katta loyihalarda ko'pincha alohida papka/backend afzal ko'riladi (workspace o'rniga) — chunki workspace'lar bir backend'da turib chalkashtirishi mumkin. Versiya cheklovi (juda muhim — kutilmagan buzilishdan himoya):required_version = ">= 1.5"(Terraform CLI versiyasi), provider uchunversion = "~> 5.0"— pessimistik operator (5.xruxsat, lekin6.0emas — katta versiya buzuvchi o'zgarish keltirishi mumkin)..terraform.lock.hclfayli provider versiyasini aynan qulflaydi (Git'ga commit qilinadi — jamoaning hammasi bir xil versiya ishlatadi, 4-QISM). Sensitive/secret 10.11-bob:sensitive = trueterminal/log'da yashiradi 2.9-bob, lekin state'da ochiq qoladi 2.7-bob — shuning uchun remote backend +encryptmajburiy 2.10-bob, va secret'larni kodga yozma —.tfvars(gitignore) yoki Vault/AWS SSM Parameter Store ishlat 10.11-bob.
2.13. Terraform vs Ansible/CloudFormation/Pulumi/OpenTofu
IaC VOSITALARI — qachon qaysi biri:
┌──────────────┬─────────────┬──────────────────────────────────────┐
│ Vosita │ Tur │ Farqi │
├──────────────┼─────────────┼──────────────────────────────────────┤
│ Terraform │ provisioning│ declarative, multi-cloud, state, HCL │
│ Ansible │ config mgmt │ server ICHINI sozlash (paket, fayl) │
│ │ │ ko'pincha Terraform BILAN birga │
│ CloudFormation│ provisioning│ faqat AWS (HCL emas, YAML/JSON) │
│ Pulumi │ provisioning│ Terraform'ga o'xshash, lekin TS/Py/Go│
│ OpenTofu │ provisioning│ Terraform'ning ochiq forki (2023+) │
└──────────────┴─────────────┴──────────────────────────────────────┘
XULOSA:
- infratuzilma YARATISH (server, tarmoq, DB) Terraform (provisioning)
- server ICHINI sozlash (Node o'rnatish, config) Ansible yoki Docker 10.3-bob
ko'p loyiha: Terraform (resurs) + Ansible/Docker (sozlash) — birgaIaC vositalari va ularning farqi. Terraform — provisioning (resurs yaratish): declarative, multi-cloud, state-li, HCL. Ansible — configuration management (server ichini sozlash — paket o'rnatish, config fayl yozish — 10.1'dagi qo'l ishini avtomatlashtiradi); ko'pincha Terraform bilan birga ishlatiladi (Terraform serverni yaratadi Ansible uni sozlaydi). CloudFormation — AWS'ning o'z IaC vositasi (faqat AWS, HCL emas — YAML/JSON; Terraform ko'p platformali). Pulumi — Terraform'ga o'xshash, lekin HCL o'rniga haqiqiy dasturlash tili (TypeScript/Python/Go — 7-QISM). OpenTofu — Terraform'ning litsenziya o'zgarishidan keyin paydo bo'lgan ochiq forki (2023+, deyarli mos). Qaror: infratuzilma yaratish (server, tarmoq, DB) Terraform; server ichini sozlash (Node o'rnatish, deploy) Ansible yoki Docker (10.3-10.4). Ko'p production loyihada ikkalasi birga ishlatiladi. Terraform — provisioning sohasida de-fakto standart, shuning uchun avval shuni o'rgan.
2.14. Ko'p resurs: count va for_each, dynamic block, lifecycle
KO'P RESURS YARATISH — bir blok, ko'p nusxa (qo'lda takrorlamaslik — DRY):
count — SON bo'yicha (0, 1, 2... nusxa):
resource "aws_instance" "web" {
count = 3 # 3 ta bir xil EC2
instance_type = "t3.micro"
tags = { Name = "web-${count.index}" } # count.index: 0,1,2
}
murojaat: aws_instance.web[0].id (indeks bilan — ro'yxat)
MUAMMO: o'rtadan bittasi o'chsa — indekslar SILJIYDI (keyingilar qayta yaratiladi)
for_each — TO'PLAM (map/set) bo'yicha — TURG'UN kalit (afzalroq):
resource "aws_instance" "web" {
for_each = toset(["web", "api", "worker"]) # 3 ta NOMLI
instance_type = "t3.micro"
tags = { Name = each.key } # each.key / each.value
}
murojaat: aws_instance.web["api"].id (kalit bilan — o'chsa boshqasi tegmaydi)
QOIDA: bir xil nusxa + tartib muhim count ; nomli/turg'un for_each (afzal)
dynamic — takrorlanuvchi ICHKI BLOK generatsiyasi (SG qoidalari kabi):
dynamic "ingress" {
for_each = var.ports # [80, 443, 8080] uchun
content { # har biriga bitta ingress bloki
from_port = ingress.value to_port = ingress.value protocol = "tcp"
}
}
lifecycle — resurs HAYOT SIKLINI boshqarish (meta-argument):
lifecycle {
create_before_destroy = true # AVVAL yangi yarat, KEYIN eskini o'chir (uzilishsiz)
prevent_destroy = true # bu resursni O'CHIRISHNI bloklaydi (prod DB himoyasi)
ignore_changes = [tags] # bu maydon drift'ini E'TIBORSIZ qoldir (tashqi o'zgarish)
}count va for_each — bitta resurs blokidan ko'p nusxa yaratish (kodni takrorlamaslik).
count = 3— son bo'yicha 3 ta bir xil nusxa;count.index(0, 1, 2) bilan farqlash, murojaataws_instance.web[0]. Muammosi: o'rtadagi nusxa o'chsa, indekslar siljiydi va keyingilar keraksiz qayta yaratiladi.for_each— map yoki set bo'yicha nusxalash, har biriga turg'un kalit beradi (each.key,each.value), murojaataws_instance.web["api"]. Amaliy qoida: nusxalar bir xil va tartib muhim bo'lsa —count; nomli/turg'un identifikatsiya kerak bo'lsa —for_eachafzal (bitta element o'chsa, qolganlariga tegmaydi).dynamicblock — takrorlanuvchi ichki bloklarni (masalan Security Group'ning ko'pingressqoidasi) ro'yxatdan avtomatik generatsiya qiladi (for_each+contentbilan) — qo'lda o'nlab bir xil blok yozmaysiz.lifecycle— resurs hayot siklini boshqaradigan meta-argument:create_before_destroy = true(avval yangisini yaratib, keyin eskisini o'chiradi — almashtirishda uzilish bo'lmaydi);prevent_destroy = true(resursni o'chirishni butunlay bloklaydi — production ma'lumotlar bazasi uchun himoya);ignore_changes = [tags](ko'rsatilgan maydondagi drift'ni e'tiborsiz qoldiradi — masalan tashqi tizim o'zgartiradigan teg).
2.15. Local values, depends_on, provisioner, provider alias, import
LOCAL VALUES — kod ichidagi TAKRORLANUVCHI ifodaga nom (var emas — ichki):
locals {
project = "mening-loyiham"
common_tags = { Project = local.project, ManagedBy = "Terraform" }
}
ishlatish: tags = local.common_tags (bir marta yoz, hamma joyda ishlat — DRY)
variable = TASHQARIDAN kiritiladi ; local = ICHKARIDA hisoblanadi
BOG'LIQLIK (dependency) — Terraform tartibni O'ZI biladi:
- IMPLICIT (yashirin) — havola orqali AVTOMATIK (afzal):
vpc_security_group_ids = [aws_security_group.web.id] avval SG, keyin EC2
- EXPLICIT — depends_on (havola YO'Q, lekin tartib kerak — kamdan-kam):
resource "aws_instance" "web" {
depends_on = [aws_s3_bucket.data] # IAM/yon-effekt bog'liqligi
}
PROVISIONER — OXIRGI CHORA (resurs yaratilgach buyruq bajarish):
provisioner "remote-exec" { inline = ["sudo apt install -y nginx"] }
RASMIY: provisioner — SO'NGGI chora. Afzal: user_data / Ansible / Docker 2.13-bob
PROVIDER ALIAS — bir provider'ning bir NECHTA sozlamasi (ko'p region):
provider "aws" { region = "eu-central-1" } # asosiy (default)
provider "aws" { alias = "us" region = "us-east-1" } # ikkinchi region
ishlatish: resource "aws_instance" "x" { provider = aws.us ... }
IMPORT — MAVJUD (qo'lda yaratilgan) resursni Terraform boshqaruviga olish:
terraform import aws_instance.web i-0abc123 # eski usul (CLI)
import { to = aws_instance.web id = "i-0abc123" } # yangi: import bloki (kodda)
import faqat STATE'ga qo'shadi — resource blokini QO'LDA yozish kerak (plan tekshiradi)Local values (
locals) — kod ichida takrorlanuvchi ifodaga nom berish (local.common_tags). Farqi: variable tashqaridan kiritiladi (parametr), local ichkarida hisoblanadi (yordamchi ifoda — bir marta yoziladi, hamma joyda ishlatiladi, DRY). Bog'liqlik (dependency): Terraform resurslar tartibini o'zi aniqlaydi 2.8-bob. Implicit (yashirin) — bir resurs boshqasining atributiga havola qilsa (aws_security_group.web.id), Terraform avtomatik "avval SG, keyin EC2" tartibini quradi (bu — afzal usul). Explicit —depends_on = [...]bilan qo'lda ko'rsatiladi: havola yo'q, lekin yashirin bog'liqlik bor bo'lganda (masalan IAM ruxsati resurs yaratilishidan oldin tayyor bo'lishi kerak) — kamdan-kam ishlatiladi. Provisioner — resurs yaratilgach unda buyruq bajarish (remote-exec— SSH orqali skript). Rasmiy hujjat buni so'nggi chora (last resort) deb ataydi: undan oldinuser_data, Ansible yoki Docker'ni ko'rib chiqing 2.13-bob — provisioner Terraform state'iga to'liq kirmaydi va mo'rt bo'ladi. Provider alias — bitta provider'ning bir nechta sozlamasi (masalan ikki AWS region): default provider'dan tashqarialias = "us"bilan ikkinchisi e'lon qilinadi, resursdaprovider = aws.usbilan tanlanadi (ko'p regionli deploy). Import — Terraform tashqarisida (qo'lda) yaratilgan mavjud resursni Terraform boshqaruviga olib kirish: eski usulterraform importCLI buyrug'i, yangi usul — koddagiimport { to = ... id = ... }bloki. Import faqat resursni state'ga qo'shadi — mosresourceblokini qo'lda yozish kerak (keyinplankod bilan haqiqat mos kelishini tekshiradi). Bu — ClickOps bilan yaratilgan eski infratuzilmani IaC'ga ko'chirishning asosiy yo'li.
3. Sintaksis — tez ma'lumotnoma
WORKFLOW 2.6-bob: terraform init | plan | apply | destroy | fmt | validate | show
terraform apply -auto-approve (tasdiqsiz — CI/CD'da ehtiyot)
BLOCK 2.3-bob: resource "<TUR>" "<NOM>" { argument = qiymat }
PROVIDER 2.4-bob: terraform { required_providers { aws = { source="hashicorp/aws" } } }
provider "aws" { region = "eu-central-1" }
RESOURCE 2.5-bob: resource "aws_instance" "web" { ami = "..." instance_type = "..." }
DATA 2.5-bob: data "aws_ami" "x" {...} data.aws_ami.x.id
VARIABLE 2.9-bob: variable "name" { type=string default="..." } var.name
OUTPUT 2.9-bob: output "ip" { value = aws_instance.web.public_ip }
HAVOLA: aws_instance.web.id | module.vpc.vpc_id | data.x.y.z
BACKEND 2.10-bob: terraform { backend "s3" { bucket=".." key=".." use_lockfile=true } }
MODULE 2.11-bob: module "vpc" { source="./modules/vpc" cidr="10.0.0.0/16" }
WORKSPACE2.12-bob:terraform workspace new|select|list dev|prod
STATE 2.7-bob: terraform state list | show <addr> | rm <addr> (ehtiyotkorona!)
COUNT 2.14-bob: resource "..." "x" { count = 3 ... } ...x[0].id (count.index)
FOR_EACH2.14-bob: resource "..." "x" { for_each = toset([...]) } ...x["k"] (each.key)
DYNAMIC 2.14-bob: dynamic "ingress" { for_each = ... content { ... } }
LIFECYCLE2.14-bob:lifecycle { create_before_destroy | prevent_destroy | ignore_changes }
LOCAL 2.15-bob: locals { common_tags = {...} } local.common_tags
DEPENDS 2.15-bob: depends_on = [aws_s3_bucket.data] (yashirin bog'liqlik)
ALIAS 2.15-bob: provider "aws" { alias = "us" ... } provider = aws.us
IMPORT 2.15-bob: import { to = aws_instance.web id = "i-0abc123" }4. Batafsil kod namunalari
Misol 1 — Terraform o'rnatish va birinchi loyiha (init)
# Terraform o'rnatish (rasmiy — HashiCorp repozitoriysidan, Ubuntu — 10.1)
wget -O- https://apt.releases.hashicorp.com/gpg | sudo gpg --dearmor \
-o /usr/share/keyrings/hashicorp-archive-keyring.gpg
echo "deb [signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg] \
https://apt.releases.hashicorp.com $(lsb_release -cs) main" | \
sudo tee /etc/apt/sources.list.d/hashicorp.list
sudo apt update && sudo apt install terraform # o'rnatish (10.1: 2.5)
terraform version # tekshirish: Terraform v1.x.x
# Yangi loyiha papkasi
mkdir mening-infra && cd mening-infra # bo'sh papka (root module — 2.11)
# main.tf faylini yozamiz (Misol 2), keyin:
terraform init # provider yuklab oladi (2.6)
# "Terraform has been successfully initialized!" (.terraform/ paydo bo'ladi)Misol 2 — Provider va birinchi resurs (EC2 — 2.4, 2.5)
# main.tf — eng oddiy to'liq misol (AWS EC2 yaratish)
terraform {
required_version = ">= 1.5" # Terraform CLI versiyasi (2.12)
required_providers {
aws = {
source = "hashicorp/aws" # Registry'dagi provider (2.4)
version = "~> 5.0" # 5.x ruxsat, 6.0 emas (2.12)
}
}
}
provider "aws" { # provider sozlash
region = "eu-central-1" # Frankfurt (10.6: 2.2)
} # kalitlar bu yerda EMAS — env/IAM role (10.6: 2.9)
resource "aws_instance" "web" { # YARATILADIGAN EC2 (2.5)
ami = "ami-0abc1234567890" # Ubuntu AMI (region'ga xos — Misol 5'da data bilan)
instance_type = "t3.micro" # arzon, free tier (10.6: 2.11)
tags = {
Name = "web-server" # AWS Console'da ko'rinadigan nom
}
}terraform plan # nima yaratilishini ko'rsatadi 2.8-bob — "1 to add"
terraform apply # "yes" so'raydi haqiqatan EC2 yaratiladi (2.6)Misol 3 — Variable bilan parametrlash (2.9)
# variables.tf — kiritiladigan qiymatlar (kodni dev/prod uchun moslaydi)
variable "instance_type" {
type = string
default = "t3.micro" # berilmasa shu (2.9)
description = "EC2 instance o'lchami"
}
variable "environment" {
type = string
description = "Muhit nomi (dev/staging/prod)"
# default yo'q MAJBURIY (apply paytida so'raydi yoki tfvars'dan oladi)
validation { # qiymatni tekshirish (faqat ruxsat etilgan)
condition = contains(["dev", "staging", "prod"], var.environment)
error_message = "environment faqat dev/staging/prod bo'lishi mumkin."
}
}# main.tf — variable'larni ishlatish
resource "aws_instance" "web" {
ami = "ami-0abc1234567890"
instance_type = var.instance_type # var.<nom> orqali (2.9)
tags = {
Name = "web-${var.environment}" # interpolatsiya: web-prod
Environment = var.environment
}
}Misol 4 — terraform.tfvars bilan qiymat berish (2.9)
# prod.tfvars — production qiymatlari (alohida fayl)
environment = "prod"
instance_type = "t3.large" # prod kuchliroq
# dev.tfvars — development qiymatlari
# environment = "dev"
# instance_type = "t3.micro"# Qaysi muhit uchun apply qilayotganimizni TANLAYMIZ (bir kod, har xil qiymat)
terraform plan -var-file="prod.tfvars" # prod rejasini ko'r
terraform apply -var-file="prod.tfvars" # prod'ni qo'lla
# *.tfvars'da secret bo'lsa — .gitignore'ga qo'sh (10.11, 2.11)Misol 5 — Data source (mavjud AMI'ni topish — 2.5)
# AMI ID'sini QO'LDA yozmaslik — eng yangi Ubuntu'ni AVTOMATIK topamiz (2.5)
data "aws_ami" "ubuntu" {
most_recent = true # eng so'nggisi
owners = ["099720109477"] # Canonical (Ubuntu rasmiy egasi)
filter {
name = "name"
values = ["ubuntu/images/hvm-ssd/ubuntu-noble-24.04-amd64-server-*"]
}
}
resource "aws_instance" "web" {
ami = data.aws_ami.ubuntu.id # topilgan AMI'ni ishlatamiz (2.5)
instance_type = var.instance_type
# endi AMI ID'sini har region uchun qo'lda izlamaymiz — Terraform topadi
}Misol 6 — Security Group resursi (10.6: 2.5 ni kodda)
# Security Group — virtual firewall (10.6: 2.5 — qo'lda emas, kodda)
resource "aws_security_group" "web_sg" {
name = "web-sg"
description = "Web server firewall (Terraform boshqaradi)"
ingress { # KIRUVCHI: SSH — faqat o'z IP'ngga
from_port = 22
to_port = 22
protocol = "tcp"
cidr_blocks = ["203.0.113.10/32"] # 0.0.0.0/0 EMAS (10.6: 2.5 xavfsizlik)
description = "SSH faqat ofis IP"
}
ingress { # KIRUVCHI: HTTP/HTTPS — hammaga
from_port = 80
to_port = 443 # 80-443 oralig'i
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"] # web ochiq
}
egress { # CHIQUVCHI: hammasi ochiq (default)
from_port = 0
to_port = 0
protocol = "-1" # barcha protokol
cidr_blocks = ["0.0.0.0/0"]
}
}
resource "aws_instance" "web" {
ami = data.aws_ami.ubuntu.id
instance_type = var.instance_type
vpc_security_group_ids = [aws_security_group.web_sg.id] # SG'ni biriktiramiz (2.8 havola)
}Misol 7 — S3 bucket resursi (10.6: 2.6 ni kodda)
# S3 bucket — kodda (10.6: 2.6 — qo'lda Console'da emas)
resource "aws_s3_bucket" "uploads" {
bucket = "mening-loyiham-uploads-2026" # GLOBAL noyob (10.6: 2.6)
tags = { Name = "Foydalanuvchi rasmlari" }
}
# Public kirishni BLOKLASH (default xavfsiz — 10.6: 2.6)
resource "aws_s3_bucket_public_access_block" "uploads" {
bucket = aws_s3_bucket.uploads.id # yuqoridagi bucket'ga havola
block_public_acls = true
block_public_policy = true
ignore_public_acls = true
restrict_public_buckets = true # to'liq private (sizmasin)
}
# Versiyalash (tasodifan o'chgan faylni qaytarish — backup)
resource "aws_s3_bucket_versioning" "uploads" {
bucket = aws_s3_bucket.uploads.id
versioning_configuration { status = "Enabled" }
}Misol 8 — Output bilan natija chiqarish (2.9)
# outputs.tf — apply'dan keyin ko'rsatiladigan qiymatlar (2.9)
output "instance_public_ip" {
value = aws_instance.web.public_ip # yaratilgan EC2 IP'si
description = "Web server public IP (SSH/brauzer uchun)"
}
output "bucket_name" {
value = aws_s3_bucket.uploads.bucket
}
output "ssh_command" { # tayyor SSH buyrug'i (qulay)
value = "ssh ubuntu@${aws_instance.web.public_ip}" # 10.1: 2.8
}terraform apply
# Apply complete! Resources: 3 added, 0 changed, 0 destroyed.
# Outputs:
# instance_public_ip = "203.0.113.5"
# ssh_command = "ssh ubuntu@203.0.113.5"
terraform output instance_public_ip # bitta output'ni alohida olishMisol 9 — Remote backend (S3 + native lock — 2.10)
# backend.tf — state'ni S3'da saqlash (jamoa uchun — 2.10)
terraform {
backend "s3" {
bucket = "mening-tfstate-2026" # state saqlanadigan S3 (avval yaratilgan)
key = "prod/terraform.tfstate" # bucket ichidagi yo'l
region = "eu-central-1"
encrypt = true # state SHIFRLANADI (2.7 — secret xavfi!)
use_lockfile = true # NATIVE S3 lock (2026 — DynamoDB shart emas)
}
}# Lokal state'dan remote'ga ko'chirish (init backend'ni o'rnatadi)
terraform init -migrate-state # "yes" state S3'ga ko'chadi
# Endi jamoa bir state'dan ishlaydi, ikki kishi bir vaqtda apply qilolmaydi (lock — 2.10)
# tfstate'ni Git'ga commit QILMA — .gitignore: *.tfstate, *.tfstate.*, .terraform/Misol 10 — Module ishlatish (qayta foydalanish — 2.11)
# main.tf — tayyor VPC modulini Registry'dan chaqiramiz (2.11)
module "vpc" {
source = "terraform-aws-modules/vpc/aws" # Terraform Registry (ommaviy)
version = "5.0.0" # versiya qulflanadi (2.12)
name = "mening-vpc"
cidr = "10.0.0.0/16" # tarmoq diapazoni (10.6: 2.10)
azs = ["eu-central-1a", "eu-central-1b"] # 2 AZ (10.6: 2.2)
public_subnets = ["10.0.1.0/24", "10.0.2.0/24"] # public (EC2)
private_subnets = ["10.0.11.0/24", "10.0.12.0/24"] # private (RDS — 10.6: 2.10)
}
# Modul OUTPUT'iga murojaat (2.11)
resource "aws_instance" "web" {
ami = data.aws_ami.ubuntu.id
instance_type = var.instance_type
subnet_id = module.vpc.public_subnets[0] # modul yaratgan public subnet'ga qo'y
}
output "vpc_id" {
value = module.vpc.vpc_id # modul qaytargan VPC ID (2.11)
}Misol 11 — count va for_each: ko'p resurs (2.14)
# count — bir xil 3 ta EC2 (indeks bilan farqlanadi)
resource "aws_instance" "worker" {
count = 3 # 3 nusxa (2.14)
ami = data.aws_ami.ubuntu.id
instance_type = "t3.micro"
tags = { Name = "worker-${count.index}" } # worker-0, worker-1, worker-2
}
# murojaat: aws_instance.worker[0].id (ro'yxat — indeks bilan)
# for_each — NOMLI resurslar (turg'un kalit — o'chsa boshqasi tegmaydi — afzal)
resource "aws_instance" "service" {
for_each = toset(["web", "api", "worker"]) # 3 ta nomli (2.14)
ami = data.aws_ami.ubuntu.id
instance_type = var.instance_type
tags = { Name = each.key } # each.key: "web"/"api"/"worker"
}
# murojaat: aws_instance.service["api"].public_ip (kalit bilan)Misol 12 — dynamic block + local values (2.14, 2.15)
# local — takrorlanuvchi qiymatlarga nom (bir marta yoz, hamma joyda ishlat — 2.15)
locals {
project = "mening-loyiham"
common_tags = { Project = local.project, ManagedBy = "Terraform" }
web_ports = [80, 443, 8080] # ochiladigan portlar ro'yxati
}
# dynamic — takrorlanuvchi ingress bloklarini ro'yxatdan generatsiya (2.14)
resource "aws_security_group" "web_sg" {
name = "web-sg"
tags = local.common_tags # local'ni ishlatamiz (DRY)
dynamic "ingress" { # local.web_ports uchun har biriga blok
for_each = local.web_ports
content {
from_port = ingress.value # ingress.value: 80, 443, 8080
to_port = ingress.value
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
}
}Misol 13 — lifecycle va explicit depends_on (2.14, 2.15)
resource "aws_instance" "web" {
ami = data.aws_ami.ubuntu.id
instance_type = var.instance_type
depends_on = [aws_s3_bucket.uploads] # yashirin bog'liqlik (2.15)
lifecycle {
create_before_destroy = true # avval yangi, keyin eski (uzilishsiz — 2.14)
ignore_changes = [tags["LastScanned"]] # tashqi tizim tegini e'tiborsiz qoldir
}
}
# Production ma'lumotlar bazasi — tasodifan o'chmasin (2.14)
resource "aws_db_instance" "main" {
identifier = "prod-db"
# ...
lifecycle {
prevent_destroy = true # destroy'ni bloklaydi (himoya)
}
}Misol 14 — Provider alias va import (2.15)
# Bir provider — ikki region (alias bilan — 2.15)
provider "aws" {
region = "eu-central-1" # asosiy (default) — Frankfurt
}
provider "aws" {
alias = "us" # ikkinchi sozlama
region = "us-east-1" # Virginia (masalan CloudFront/ACM uchun)
}
resource "aws_instance" "us_web" {
provider = aws.us # AYNAN us region provider'i (2.15)
ami = "ami-0abc1234567890"
instance_type = "t3.micro"
}
# Mavjud (qo'lda yaratilgan) resursni Terraform boshqaruviga olish (2.15)
import {
to = aws_instance.legacy # koddagi manzil
id = "i-0abc123def456" # AWS'dagi haqiqiy ID
}
# Mos "resource aws_instance legacy {...}" blokini QO'LDA yozib, keyin:
# terraform plan kod bilan haqiqat mos kelishini tekshiradi (farq bo'lsa ko'rsatadi)Misol 15 — CI/CD: GitHub Actions'da plan (PR) va apply (merge) — 10.5
# .github/workflows/terraform.yml — infratuzilmani avtomatik qo'llash (10.5)
name: Terraform
on:
pull_request: # PR'da faqat PLAN (o'zgarish ko'rinadi, review qilinadi — 2.8)
push:
branches: [main] # main'ga merge bo'lganda APPLY (2.6)
jobs:
terraform:
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: write # plan natijasini PR izohiga yozish uchun
steps:
- uses: actions/checkout@v4
- uses: hashicorp/setup-terraform@v3
- run: terraform init
- run: terraform fmt -check # format buzilgan bo'lsa — fail (2.6, 8-bo'lim)
- run: terraform validate # sintaksis tekshiruvi (2.6)
- run: terraform plan -no-color # PR'da: nima o'zgarishini ko'rsatadi (2.8)
- name: Apply (faqat main)
if: github.ref == 'refs/heads/main' # PR'da EMAS — faqat merge'dan keyin
run: terraform apply -auto-approve # tasdiqlangan o'zgarishni qo'llaydi (2.6)
env: # AWS kalitlari — GitHub Secrets (kodda EMAS — 10.11)
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}5. To'g'ri va noto'g'ri holatlar
1) Infratuzilma yaratish usuli
AWS Console'da qo'lda (ClickOps — takrorlab/hujjatlab bo'lmaydi — 2.1)
Terraform kod — versiyalanadi, takrorlanadi, review qilinadi2) State saqlash
terraform.tfstate'ni Git'ga commit qilish (secret sizadi, konflikt — 2.7)
Remote backend (S3 + encrypt + lock); tfstate'ni .gitignore'ga (2.10)3) Apply qilish tartibi
Ko'rmasdan to'g'ridan apply (yoki -auto-approve hamma yerda)
Avval terraform plan'ni o'qi, KEYIN apply (nima o'chayotganini tekshir — 2.8)4) AMI / qiymatlar
ami = "ami-0abc..." qo'lda (har region boshqacha, eskiradi — 2.5)
data "aws_ami" bilan avtomatik topish (har region'da ishlaydi — 2.5)5) Secret boshqaruvi
DB parolini main.tf'ga yozish (kodda ochiq, git'ga ketadi — 2.12)
tfvars (gitignore) yoki Vault/SSM; sensitive=true; encrypt (10.11, 2.11)6) Provider versiyasi
version berilmagan (har init turli versiya — kutilmagan buzilish)
version = "~> 5.0" + .terraform.lock.hcl commit (jamoa bir xil — 2.12)6. Keng tarqalgan xatolar va yechimlari
Xato 1 — State qo'lda o'zgartirilgan (drift)
Sababi: kimdir AWS Console'da resursni qo'lda o'zgartirgan (instance turi, SG qoidasi) — kod/state bilan haqiqat mos kelmaydi 2.7-bob. Yechimi: terraform plan drift'ni ko'rsatadi terraform apply kodga qaytib moslashtiradi (yoki kodni haqiqatga moslab yozasiz). Oldini olish: resurslarni faqat Terraform orqali o'zgartir (qo'lda tegma — 2.1).
Xato 2 — Error acquiring the state lock
Sababi: boshqa apply hali tugamagan (lock ushlab turibdi), yoki avvalgi apply yarim qolib lock "osilib" qolgan 2.10-bob. Yechimi: boshqa apply tugashini kut; haqiqatan osilib qolgan bo'lsa terraform force-unlock <LOCK_ID> (ehtiyotkorona — faqat ishonch bo'lsa).
Xato 3 — tfstate'da secret ochiq qolgan
Sababi: DB paroli/kalit state faylda ochiq matnda saqlanadi 2.7-bob, tfstate Git'ga ketgan. Yechimi: tfstate'ni Git tarixidan o'chir (sizib ketgan parolni almashtir — kech), remote backend + encrypt=true o'rnat 2.10-bob, tfstate'ni .gitignore'ga qo'sh 14.5-bob.
Xato 4 — Plan'siz apply, resurs kutilmaganda o'chgan
Sababi: o'zgartirib bo'lmaydigan maydon (masalan ami) o'zgargan Terraform resursni replace qiladi (o'chir+yarat — 2.8), plan'ni o'qimasdan apply qilingan. Yechimi: doim plan'ni o'qi (-/+ replace belgisiga e'tibor); production'da prevent_destroy lifecycle qo'y. Oldini olish: CI/CD'da plan'ni PR'ga chiqar (2.13, 10.5).
Xato 5 — No valid credential sources found (autentifikatsiya)
Sababi: AWS kalitlari topilmadi (provider sozlanmagan). Yechimi: aws configure (10.6: Misol 1) yoki AWS_ACCESS_KEY_ID/AWS_SECRET_ACCESS_KEY env, yoki EC2'da IAM role (10.6: 2.9 — eng xavfsiz). Kalitni provider blokiga yozma (git'ga ketadi).
Xato 6 — Provider versiyasi mos kelmadi / kutilmagan buzilish
Sababi: version berilmagan, yangi major versiya 6.0-bob buzuvchi o'zgarish keltirgan 2.12-bob. Yechimi: version = "~> 5.0" qo'y, .terraform.lock.hcl'ni commit qil (jamoa bir versiya); terraform init -upgrade bilan ataylab yangila.
Xato 7 — terraform destroy kerakli resursni o'chirdi
Sababi: destroy Terraform boshqargan hammasini o'chiradi (production DB ham — 2.6). Yechimi: muhim resursga lifecycle { prevent_destroy = true } qo'y; destroy oldidan terraform plan -destroy bilan ro'yxatni ko'r. Eslatma: o'chgan ma'lumot qaytmaydi — backup shart (10.6: 2.7 RDS backup).
7. Integratsiya — bu mavzu stack'ning qayerida uchraydi
- AWS cloud 10.6-bob: Terraform aynan shu EC2/S3/RDS/SG resurslarini qo'lda emas, kodda yaratadi (bu bobning markaziy bog'lanishi).
- CI/CD 10.5-bob: GitHub Actions'da
terraform plan(PR'da) +apply(merge'da) — infratuzilma avtomatik qo'llanadi. - Linux/SSH 10.1-bob: Terraform serverni yaratadi, keyin
user_datayoki Ansible uni sozlaydi (paket, deploy). - Docker/K8s (10.3, 10.8):
kubernetes/helmprovider bilan klaster va deploy'larni ham Terraform boshqaradi. - Secrets 10.11-bob: state'dagi secret xavfi
sensitive, encrypt, Vault/SSM — keyingi bob. - Git (4-QISM):
.tffayllar versiyalanadi,.terraform.lock.hclcommit, tfstate.gitignore. - Xavfsizlik 14.5-bob: kalit/parol kodga yozilmaydi, state shifrlangan remote'da.
8. Eng yaxshi amaliyotlar (best practices)
- Hammasi kodda — ClickOps o'rniga Terraform; har o'zgarish Git'da (2.1, review — 15.2).
- Remote backend + lock — S3 +
encrypt+use_lockfile(jamoa, xavfsiz — 2.10). - State'ni hech qachon Git'ga qo'yma —
.gitignore:*.tfstate,.terraform/2.7-bob. - Doim
plan'ni o'qi — apply'dan oldin, ayniqsadestroy/replace'ga e'tibor 2.8-bob. - Versiyani qulfla —
required_version+ providerversion+ lock fayl commit 2.12-bob. - Parametrlash —
variable/tfvarsbilan (kodni hardcode qilma — dev/prod — 2.9). fmtvavalidate— har commit oldidan (toza kod, CI'da tekshir — 15.3).- Modul bilan DRY — takrorlanuvchi qismni modulga (qayta ishlat — 2.11).
- Least privilege — Terraform IAM huquqi minimal; secret kodda emas (10.6: 2.9, 10.11).
- Kichik, fokuslangan state — butun infrani bitta state'ga tiqma (xavf/sekinlik kamayadi).
9. Amaliy loyiha: "Infratuzilmani noldan kodda ko'tarish"
10.6 da qo'lda yaratgan AWS infratuzilmani butunlay Terraform kodiga ko'chir — bir buyruq bilan ko'tarib-tushiriladigan, versiyalangan infratuzilma.
Maqsad
Bo'sh papkadan boshlab, HCL kod bilan to'liq web infratuzilma yarat: VPC (yoki default), Security Group, EC2 instance (eng yangi Ubuntu AMI), S3 bucket — hammasi terraform apply bilan ko'tarilsin, terraform destroy bilan izsiz o'chsin. State remote (S3) backend'da, parametrlangan (dev/prod), modul bilan tartibli.
Talablar (requirements)
- Provider:
awsprovider,required_versionvaversionqulflangan (Misol 2, 2.12). - Variable:
environment(dev/prod, validation bilan) vainstance_type(Misol 3, 2.9). - Data source: eng yangi Ubuntu 24.04 AMI'ni avtomatik top (Misol 5, 2.5).
- Security Group: SSH faqat o'z IP'ngga, HTTP/HTTPS hammaga (Misol 6, 10.6: 2.5).
- EC2:
dataAMI + variable type + SG biriktirilgan (Misol 2, 6). - S3: bucket + public access block + versioning (Misol 7, 10.6: 2.6).
- Output: EC2 public IP va tayyor
sshbuyrug'i (Misol 8, 2.9). - Remote backend: state S3'da,
encrypt+use_lockfile(Misol 9, 2.10). - Parametrlash:
dev.tfvarsvaprod.tfvars— bir kod, ikki muhit (Misol 4, 2.9). - Hujjat:
.gitignore(tfstate, .terraform), kichik README — qanday ishga tushirish.
Maslahatlar (hint)
- Avval lokal state bilan ishla, ishlagach
backendqo'shibinit -migrate-stateqil (Misol 9). - Har
apply'dan oldin albattaplan'ni o'qi — nima yaratilayotganini ko'r 2.8-bob. - AMI'ni qo'lda yozma —
data "aws_ami"ishlat (har region'da ishlaydi — 2.5). - Kalitni kodga yozma —
aws configureyoki env (10.6: Misol 1, Xato 5). - Tugatgach
terraform destroyqil — keraksiz AWS hisobi kelmasin (10.6: 2.11 billing). - Kodni
fmtbilan formatla,validatebilan tekshir (8-bo'lim).
"Tayyor" mezonlari (acceptance criteria)
-
terraform initprovider'larni muvaffaqiyatli yuklab oladi. -
terraform plananiq nima yaratilishini ko'rsatadi (xulosa qatori bilan). -
terraform applyEC2 + SG + S3'ni haqiqatan yaratadi, output'da IP chiqadi. - Brauzer/SSH orqali EC2'ga ulanish ishlaydi (output'dagi buyruq bilan).
- State S3 backend'da (lokal
terraform.tfstateyo'q),encryptyoqilgan. -
dev.tfvars/prod.tfvarsbilan har xil instance turi qo'llanadi. -
.gitignore'da tfstate va.terraform/bor (Git'ga ketmaydi). -
terraform destroyhamma resursni izsiz o'chiradi.
Yechim kodi ataylab berilmagan — bu loyihani o'zingiz yozib ko'ring.
10. Xulosa va keyingi bobga ko'prik
Bu bobda Infrastructure as Code va Terraform'ni chuqur o'rgandik:
- IaC (qo'lda ClickOps muammosi, imperative vs declarative — 2.1); Terraform (multi-cloud, declarative engine — 2.2); HCL (block, argument, expression — 2.3).
- Provider (cloud ko'prigi — 2.4); resource va data source (yaratish vs o'qish — 2.5); workflow (
init/plan/apply/destroy— 2.6). - State (
tfstate, drift, secret xavfi — 2.7); plan (oldindan ko'rish, dependency graph — 2.8); variable/output (parametrlash — 2.9). - Remote backend (S3 + native lock — 2.10); module (qayta ishlatish — 2.11); workspace/versiya/sensitive 2.12-bob; vositalar taqqosi 2.13-bob.
- Ko'p resurs (
count/for_each,dynamicblock,lifecycle— 2.14); local values,depends_on, provisioner, provider alias, import 2.15-bob; CI/CD integratsiyasi (plan PR'da, apply merge'da — Misol 15, 10.5).
Endi siz infratuzilmani qo'lda emas, kodda quray olasiz — versiyalangan, takrorlanadigan, jamoada ishonchli. Bu — 10.6'dagi ClickOps'ni professional, qaytariladigan jarayonga aylantiradi. "Serverni qo'lda sozlayman" chegarasidan o'tildi — endi infratuzilma ham dastur kabi boshqariladi.
Keyingi bob — 10.11-bob: Environment va secrets boshqaruvi. Terraform state'da secret'lar ochiq saqlanishini ko'rdik (2.7, 2.11) — bu jiddiy muammoning bir qismi. Endi to'liq savol: ilova va infratuzilma uchun maxfiy ma'lumotlarni (DB parol, API kalit, JWT secret) qayerda va qanday saqlash kerak? .env fayllar, environment o'zgaruvchilari, va professional yechimlar — HashiCorp Vault, AWS Secrets Manager/SSM Parameter Store. Bu — 10-QISM'ning so'nggi va xavfsizlik uchun eng muhim mavzularidan biri.
Foydalanilgan rasmiy/ishonchli manbalar
- HashiCorp Developer — "What is Terraform?" va IaC tushunchasi (declarative vs imperative), 2026
- Terraform Language — Configuration Syntax (HCL): block, argument, expression; izohlar, 2026
- Terraform Language — Providers (
required_providers, provider konfiguratsiyasi,alias), 2026 - Terraform Language — Resources va meta-argumentlar:
count,for_each,depends_on,lifecycle(create_before_destroy,prevent_destroy,ignore_changes),provider, 2026 - Terraform Language — Data Sources; Variables (
type,default,validation,sensitive), Outputs, Local Values, 2026 - Terraform Language — Modules (root/child,
source, input/output); Dynamic Blocks; Provisioners (last resort), 2026 - Terraform Language — Import (import bloki va
terraform importCLI), 2026 - Terraform State — Purpose, Remote State, State Locking; Backend Type: s3 (
use_lockfile, DynamoDB locking deprecated), 2026 - Terraform CLI —
init,plan,apply,destroy,fmt,validate,workspace,state,force-unlockbuyruqlari, 2026 - Terraform Registry — provider va modullar (
hashicorp/aws,terraform-aws-modules/vpc), 2026 - HashiCorp/GitHub —
setup-terraformaction (CI/CD integratsiyasi), 2026
Izohlar (0)
Izoh yozish uchun kiring.
- Hozircha izoh yo'q. Birinchi bo'ling!