ЁЯзй рдзрдбрд╛ 07 тАФ Modules: рдПрдХрд╛ wing рдЪреЗ design, рджреЛрдирджрд╛ рдмрд╛рдВрдзрд▓реЗрд▓реЗ
ЁЯУН рддреБрдореНрд╣реА рдЗрдереЗ рдЖрд╣рд╛рдд: рдзрдбрд╛ 07 / 12 ┬╖ рдорд╛рдЧреЗ: lesson-06-dependency-graph ┬╖ рдкреБрдвреЗ: lesson-08-remote-state-locking
ЁЯУж рдпрд╛ рдмреНрд░рдБрдЪрдордзреНрдпреЗ рдХрд╛рдп рдЖрд╣реЗ
рдзрдбреЗ 01тАУ06, рдЖрдгрд┐ рдкреБрдирд░реНрд╡рд╛рдкрд░. Module рдореНрд╣рдгрдЬреЗ inputs (variables) рдЖрдгрд┐ outputs
рдЕрд╕рд▓реЗрд▓рд╛ рдЖрд░рд╛рдЦрдбреНрдпрд╛рдЪрд╛ рдПрдХ folder. рдмрд╛рдВрдзрдХрд╛рдо рдХрд╛рд░реНрдпрд╛рд▓рдп рдПрдХ wing рдПрдХрджрд╛рдЪ рд░реЗрдЦрд╛рдЯрддреЗ тАФ рдПрдХ hall, рдПрдХ gate рдЖрдгрд┐ N
lockers тАФ рдЖрдгрд┐ рд╡реЗрдЧрд╡реЗрдЧрд│реНрдпрд╛ inputs рд╕рд╣ east wing рдЖрдгрд┐ west wing рд╕рд╛рдареА рддреЗ call рдХрд░рддреЗ. рдкреНрд░рддреНрдпреЗрдХ
call рд▓рд╛ рд╕реНрд╡рддрдГрдЪреЗ addresses (module.east.school_room.this) рдЖрдгрд┐ рд╕реНрд╡рддрдГрдЪреЗ outputs рдорд┐рд│рддрд╛рдд.
iac/demo.py рдордзреАрд▓ modules() рдЖрдгрд┐ WING; iac/engine.py рдордзреАрд▓
expand() рдордзрд▓реЗ module handling.
ЁЯзТ 5 рд╡рд░реНрд╖рд╛рдВрдЪреНрдпрд╛ рдореБрд▓рд╛рд▓рд╛ рд╕рдордЬрд╛рд╡рд▓реНрдпрд╛рд╕рд╛рд░рдЦреЗ
рд╢рд╛рд│реЗрдЪреА рдкреНрд░рддреНрдпреЗрдХ wing рд╕рд╛рд░рдЦреАрдЪ рджрд┐рд╕рддреЗ: рдПрдХ рдореЛрдард╛ hall, рддреНрдпрд╛рдд рдЬрд╛рдгрд╛рд░реЗ рдПрдХ gate, рдЖрдгрд┐ lockers рдЪреА рдПрдХ рд░рд╛рдВрдЧ. рдкреНрд░рддреНрдпреЗрдХ wing рд╕рд╛рдареА рд╣реЗ рд╕рдЧрд│реЗ рдкреБрдиреНрд╣рд╛ рд░реЗрдЦрд╛рдЯрдгреЗ рдХрдВрдЯрд╛рд│рд╡рд╛рдгреЗ рдЖрд╣реЗ, рдЖрдгрд┐ рдПрдХреЗ рджрд┐рд╡рд╢реА рдХреЛрдгреАрддрд░реА gate рдЪреБрдХреАрдЪреЗ рдХрд╛рдврддреЗ.
рдореНрд╣рдгреВрди рджреАрдкрд┐рдХрд╛ рдПрдХрд╛ wing рдЪреЗ design ЁЯУР рд░реЗрдЦрд╛рдЯрддреЗ, рджреЛрди рд░рд┐рдХрд╛рдореНрдпрд╛ рдЬрд╛рдЧрд╛рдВрд╕рд╣: "wing рдЪреЗ рдирд╛рд╡: ____" рдЖрдгрд┐ "рдХрд┐рддреА
lockers: ____ (рддреБрдореНрд╣реА рд╕рд╛рдВрдЧрд┐рддрд▓реЗ рдирд╛рд╣реА рддрд░ 2)". рддреА рддреЗ modules/wing рдирд╛рд╡рд╛рдЪреНрдпрд╛ folder рдордзреНрдпреЗ рдареЗрд╡рддреЗ.
рдЖрддрд╛ рд╕рдВрдкреВрд░реНрдг рд╢рд╛рд│реЗрдЪрд╛ рдЖрд░рд╛рдЦрдбрд╛ рдЫреЛрдЯрд╛ рдЖрд╣реЗ:
- "east рдирд╛рд╡рд╛рдЪреА рдПрдХ wing рдмрд╛рдВрдзрд╛." (2 lockers)
- "west рдирд╛рд╡рд╛рдЪреА рдПрдХ wing рдмрд╛рдВрдзрд╛, 3 lockers рд╕рд╣."
рдХрдВрддреНрд░рд╛рдЯрджрд╛рд░ east рд╕рд╛рдареА 4 рдЧреЛрд╖реНрдЯреА рдЖрдгрд┐ west рд╕рд╛рдареА 5 рдмрд╛рдВрдзрддреЛ. West wing рд▓рд╛ рдЪреМрдерд╛ locker рд╣рд╡рд╛ рдЕрд╕реЗрд▓ рддреЗрд╡реНрд╣рд╛ рдлрдХреНрдд west wing рдмрджрд▓рддреЗ. рдЖрдгрд┐ design рдЙрддреНрддрд░реЗ рдкрд░рдд рджреЗрдК рд╢рдХрддреЗ тАФ "east gate рдЪрд╛ рдирдВрдмрд░ gate-01 рдЖрд╣реЗ" тАФ рдореНрд╣рдгрдЬреЗ рдЖрд░рд╛рдЦрдбреНрдпрд╛рдЪрд╛ рдмрд╛рдХреАрдЪрд╛ рднрд╛рдЧ рддреА рд╡рд╛рдкрд░реВ рд╢рдХрддреЛ.
ЁЯЧ║я╕П рдЖрдХреГрддреА
flowchart LR
root["ЁЯУЬ root plans"] -->|"wing = east"| e["ЁЯзй module.east<br/>hall ┬╖ gate ┬╖ 2 lockers"]
root -->|"wing = west, lockers = 3"| w["ЁЯзй module.west<br/>hall ┬╖ gate ┬╖ 3 lockers"]
design["ЁЯУР modules/wing<br/>inputs: wing, lockers<br/>outputs: gate_id, hall_id"] -.-> e
design -.-> w
e -->|"gate_id = gate-01"| out["root outputs"]
w -->|"hall_id = room-02"| out
ЁЯЧ║я╕П рд░реЗрдЦрд╛рдЯрд▓реЗрд▓реА рдЖрд╡реГрддреНрддреА + рдПрдХ lab: https://school-edh.pages.dev/terraform/lesson-diagrams.html#l07
тЭУ рдХрд╛рдп
- Module тАФ
.tffiles рдЪрд╛ рдХреЛрдгрддрд╛рд╣реА folder. рдЬреНрдпрд╛ folder рдордзреНрдпреЗ рддреБрдореНрд╣реА Terraform рдЪрд╛рд▓рд╡рддрд╛ рддреЛ root module; рддреЛ call рдХрд░рддреЛ рддреЗ folders рдореНрд╣рдгрдЬреЗ child modules. - Module block тАФ
module "east" { source = "./modules/wing" wing = "east" }.sourceрд╕рд╛рдВрдЧрддреЗ module рдХреБрдареЗ рдЖрд╣реЗ: рд╕реНрдерд╛рдирд┐рдХ path, Terraform Registry (terraform-aws-modules/vpc/aws), рдПрдХ git URL, рдПрдХ S3 bucket. - Inputs тАФ child рдЪреЗ
variableblocks. Call рдХрд░рдгрд╛рд░рд╛ рддреЗ arguments рдореНрд╣рдгреВрди рдард░рд╡рддреЛ. - Outputs тАФ child рдЪреЗ
outputblocks. Call рдХрд░рдгрд╛рд░рд╛ рддреЗmodule.east.gate_idрдЕрд╕реЗ рд╡рд╛рдЪрддреЛ. Module рдЪреЗ resources рдЦрд╛рдЬрдЧреА рдЕрд╕рддрд╛рдд; outputs рд╣рд╛ рддреНрдпрд╛рдЪрд╛ рд╕рд╛рд░реНрд╡рдЬрдирд┐рдХ рдЪреЗрд╣рд░рд╛. - Module addresses тАФ
module.east.school_room.this. рддреЗрдЪ resource рдирд╛рд╡ (this) рдкреНрд░рддреНрдпреЗрдХ call рдордзреНрдпреЗ рд╕рдВрдШрд░реНрд╖рд╛рд╢рд┐рд╡рд╛рдп рд░рд╛рд╣рддреЗ. - Versioning тАФ registry рдЖрдгрд┐ git sources pinned рдЕрд╕рд╛рдпрд▓рд╛ рд╣рд╡реЗрдд (
version = "~> 5.0",?ref=v1.4.0), рдореНрд╣рдгрдЬреЗ upstream рдмрджрд▓ рдЕрдЪрд╛рдирдХ рдпреЗрдКрди рдЖрджрд│рдд рдирд╛рд╣реА. - Composition тАФ modules рдЗрддрд░ modules call рдХрд░реВ рд╢рдХрддрд╛рдд. Tree рдЙрдерд│ рдареЗрд╡рд╛; рдЦреЛрд▓ nesting рдореБрд│реЗ plans рд╡рд╛рдЪрд╛рдпрд▓рд╛ рдЕрд╡рдШрдб рд╣реЛрддрд╛рдд.
ЁЯдФ рдХрд╛
рдХрд╛рд░рдг copy-paste рдиреЗ рдмрд╛рдВрдзрд▓реЗрд▓рд╛ рддреЛрдЪ pattern рд╣рд│реВрд╣рд│реВ рд╡реЗрдЧрд│рд╛ рд╣реЛрдд рдЬрд╛рддреЛ: рдПрдХрд╛ wing рд▓рд╛ рджреБрд░реБрд╕реНрддреА рдорд┐рд│рддреЗ, рдмрд╛рдХреАрдВрдирд╛
рдирд╛рд╣реА. Module рддреНрдпрд╛ pattern рд▓рд╛ рдЫреЛрдЯреНрдпрд╛ interface рд╕рд╣ рдПрдХ review рдЭрд╛рд▓реЗрд▓реА рдЧреЛрд╖реНрдЯ рдмрдирд╡рддреЗ. рддреНрдпрд╛рдореБрд│реЗ
platform team рдЪрд╛рдВрдЧрд▓реЗ defaults (encryption рдЪрд╛рд▓реВ, public access рдмрдВрдж) рдкреНрд░рд╕рд┐рджреНрдз рдХрд░реВ рд╢рдХрддреЗ рдЬреЗ рдкреНрд░рддреНрдпреЗрдХ
product team рд▓рд╛ рдлреБрдХрдЯ рдорд┐рд│рддрд╛рдд. рдХрд┐рдВрдордд рдореНрд╣рдгрдЬреЗ рдЕрдкреНрд░рддреНрдпрдХреНрд╖рдкрдгрд╛ (indirection): plan рдЖрддрд╛
module.east.тАж addresses рджрд╛рдЦрд╡рддреЛ, рдЖрдгрд┐ module рдмрджрд▓рд▓рд╛ рдХреА рдкреНрд░рддреНрдпреЗрдХ call рдХрд░рдгрд╛рд░рд╛ рдмрджрд▓рддреЛ.
ЁЯФз рдХрд╕реЗ (рдпрд╛ repo рдордзреНрдпреЗ)
iac/engine.py рдордзреАрд▓ expand() module block рд╣рд╛рддрд╛рд│рддрд╛рдирд╛
рддреНрдпрд╛рдЪрд╛ source рдПрдХрд╛ modules dictionary рдордзреНрдпреЗ рд╢реЛрдзрддреЗ, inputs resolve рдХрд░рддреЗ, рдЖрдгрд┐ module рдЪреЗ
рд╕реНрд╡рддрдГрдЪреЗ config module.<name>. рдпрд╛ address prefix рд╕рд╣ рд╡рд┐рд╕реНрддрд╛рд░рддреЗ. Module рдЪреЗ output blocks
рддреНрдпрд╛рдЪреНрдпрд╛ рд╕реНрд╡рддрдГрдЪреНрдпрд╛ scope рдордзреНрдпреЗ рдареЗрд╡рд▓реЗ рдЬрд╛рддрд╛рдд; ${module.east.gate_id} рддрд┐рдереЗ resolve рд╣реЛрддреЗ. рд╢рд┐рдХрд╡рдгреНрдпрд╛рд╕рд╛рдареА рдХреЗрд▓реЗрд▓реЗ рд╕реЛрдкреЗ рд░реВрдк:
рдЗрдереЗ module inputs variables, locals рдЖрдгрд┐ literals рд╡рд╛рдкрд░реВ рд╢рдХрддрд╛рдд, рдЗрддрд░ resources рдирд╛рд╣реА.
ЁЯзк рдХрд░реВрди рдкрд╛рд╣рд╛
python3 iac/demo.py modules
python3 - <<'EOF'
import sys; sys.path.insert(0, "iac")
from cloud import FakeCloud
from engine import plan, apply, show_outputs
from demo import WING
for n in (0, 1, 2, 3):
root = {"module": {"north": {"source": "wing", "wing": "north", "lockers": n}},
"output": {"gate": {"value": "${module.north.gate_id}"}}}
cloud = FakeCloud(); p = plan(root, None, cloud, modules={"wing": WING}); st, _, msg = apply(p, cloud)
print(f"lockers={n} тЖТ {msg} ┬╖ {show_outputs(st)[0]}")
print([a for a in st["resources"]])
EOF
тЬЕ рддрдкрд╛рд╕рд╛ тАФ рддреБрдореНрд╣рд╛рд▓рд╛ рдХрд╛рдп рджрд┐рд╕рд╛рдпрд▓рд╛ рд╣рд╡реЗ
modules рдЕрд╕реЗ print рдХрд░рддреЗ:
Plan: 9 to add, 0 to change, 0 to destroy.
module.east: school_room.this, school_gate.this, school_locker.row[0], school_locker.row[1]
module.west: school_room.this, school_gate.this, school_locker.row[0], school_locker.row[1], school_locker.row[2]
тФАтФА apply тЖТ Apply complete! Resources: 9 added, 0 changed, 0 destroyed.
output east_gate = "gate-01"
output west_hall = "room-02"
тФАтФА west asks for 4 lockers тЖТ + module.west.school_locker.row[3] (create) тЖТ Plan: 1 to add, 0 to change, 0 to destroy.
рддреБрдордЪрд╛ snippet рдЕрд╕реЗ print рдХрд░рддреЛ:
lockers=0 тЖТ Apply complete! Resources: 2 added, 0 changed, 0 destroyed. ┬╖ gate = "gate-01"
lockers=1 тЖТ Apply complete! Resources: 3 added, 0 changed, 0 destroyed. ┬╖ gate = "gate-01"
lockers=2 тЖТ Apply complete! Resources: 4 added, 0 changed, 0 destroyed. ┬╖ gate = "gate-01"
lockers=3 тЖТ Apply complete! Resources: 5 added, 0 changed, 0 destroyed. ┬╖ gate = "gate-01"
['module.north.school_room.this', 'module.north.school_gate.this', 'module.north.school_locker.row[0]', 'module.north.school_locker.row[1]', 'module.north.school_locker.row[2]']
ЁЯПБ рддреБрдореНрд╣реА рдЖрддреНрддрд╛рдЪ рдХрд╛рдп рд╕рд┐рджреНрдз рдХреЗрд▓реЗ
рдПрдХ design, рджреЛрди calls, рдирд╛рд╡рд╛рдВрдЪреНрдпрд╛ рд╕рдВрдШрд░реНрд╖рд╛рд╢рд┐рд╡рд╛рдп 9 resources: рджреЛрдиреНрд╣реА wings рдордзреНрдпреЗ
school_room.this рдЖрд╣реЗ, рдЬреЗ module.east. рдЖрдгрд┐ module.west. prefix рдиреЗ рд╡реЗрдЧрд│реЗ рдУрд│рдЦрд▓реЗ рдЬрд╛рддрд╛рдд. рдПрдХрд╛
call рдЪрд╛ input рдмрджрд▓рд▓реНрдпрд╛рд╡рд░ рдлрдХреНрдд рддреНрдпрд╛рдЪ call рд▓рд╛ рдзрдХреНрдХрд╛ рд▓рд╛рдЧрд▓рд╛ (1 to add, module.west рдордзреНрдпреЗ). Outputs рдиреЗ
ids module рдмрд╛рд╣реЗрд░ рдЖрдгрд▓реЗ, рдЖрдгрд┐ lockers = 0 рджрд╛рдЦрд╡рддреЗ рдХреА module input рднрд╛рдЧ рдкреВрд░реНрдгрдкрдгреЗ рдмрдВрдж
рдХрд░реВ рд╢рдХрддреЛ.
тЪая╕П рдиреЗрд╣рдореАрдЪреНрдпрд╛ рдЪреБрдХрд╛
- рдПрдХрд╛рдЪ resource рднреЛрд╡рддреА рдЧреБрдВрдбрд╛рд│рд▓реЗрд▓рд╛ рдЖрдгрд┐ рдХрд╛рд╣реАрдЪ рди рдЬреЛрдбрдгрд╛рд░рд╛ module тАФ рдлрдХреНрдд рдЖрдгрдЦреА indirection
- unpinned registry рдХрд┐рдВрд╡рд╛ git sources тАФ рдкреБрдврдЪреНрдпрд╛
initрд╡реЗрд│реА module рддреБрдордЪреНрдпрд╛ рдирдХрд│рдд рдмрджрд▓рддреЛ - рдЦреВрдк рдЬрд╛рд╕реНрдд inputs ("рдкреНрд░рддреНрдпреЗрдХ argument рд╕рд╛рдареА рдПрдХ variable") тАФ module рдиреЗ рдирд┐рд░реНрдгрдп рдШреНрдпрд╛рдпрд▓рд╛ рд╣рд╡реЗрдд, рд╕рдЧрд│реЗ рдкреБрдвреЗ рдврдХрд▓реВ рдирдпреЗ
movedblocks рд╢рд┐рд╡рд╛рдп module рдордзреАрд▓ resources rename рдХрд░рдгреЗ рдХрд┐рдВрд╡рд╛ рд╣рд▓рд╡рдгреЗ тАФ рдкреНрд░рддреНрдпреЗрдХ call рдХрд░рдгрд╛рд▒реНрдпрд╛рд▓рд╛ destroy + create рдорд┐рд│рддреЗ- рджреБрд╕рд▒реНрдпрд╛ module рдЪреЗ resources рддреНрдпрд╛рдЪреНрдпрд╛ outputs рдордзреВрди рди рд╡рд╛рдЪрддрд╛ рдереЗрдЯ рд╡рд╛рдЪрдгреЗ
ЁЯПн рдкреНрд░рддреНрдпрдХреНрд╖ рд╡рд╛рдкрд░рд╛рдд
рдЦрд▒реНрдпрд╛ account рд╡рд░ тАФ рдПрдХ рд╕реНрдерд╛рдирд┐рдХ module рдЖрдгрд┐ рдПрдХ pinned registry module:
module "east" {
source = "./modules/wing"
wing = "east"
lockers = 2
}
module "network" {
source = "terraform-aws-modules/vpc/aws"
version = "~> 5.0" # pin the major version you tested
name = "campus"
cidr = "10.20.0.0/16"
azs = ["ap-south-1a", "ap-south-1b"]
private_subnets = ["10.20.1.0/24", "10.20.2.0/24"]
}
output "east_gate" {
value = module.east.gate_id
}
terraform init -upgrade # fetch modules and providers again, within the pins
terraform get # download modules only
terraform state list | grep '^module.east'
рдмрд╣реБрддреЗрдХ teams module рд╕рд╛рдареА рд╡рд╛рдкрд░рдд рдЕрд╕рд▓реЗрд▓реА folder рд░рдЪрдирд╛: main.tf, variables.tf, outputs.tf,
versions.tf, рдПрдХ README.md, рдЖрдгрд┐ рдПрдХ examples/ folder рдЬреЛ рддреНрдпрд╛рдЪрд╛ test рдореНрд╣рдгреВрдирд╣реА рдХрд╛рдо рдХрд░рддреЛ
(рдзрдбрд╛ 11).
ЁЯПн рдкреНрд░рддреНрдпрдХреНрд╖ рд╡рд╛рдкрд░рд╛рдд рд╣реЗ рдХрд╛ рдорд╣рддреНрддреНрд╡рд╛рдЪреЗ: рдкреНрд░рддреНрдпреЗрдХ shared module рд▓рд╛ version, changelog рдЖрдгрд┐ tests рджреНрдпрд╛. Prod рдордзреНрдпреЗ module upgrade рдХрд░рдгреЗ рдореНрд╣рдгрдЬреЗ рдПрдХ pull request рдЕрд╕рд╛рдпрд▓рд╛ рд╣рд╡рд╛ рдЬреНрдпрд╛рдЪрд╛ plan рддреБрдореНрд╣реА рдЗрддрд░ рдХреЛрдгрддреНрдпрд╛рд╣реА plan рд╕рд╛рд░рдЦрд╛рдЪ рд╡рд╛рдЪрддрд╛.
тПня╕П рдкреБрдвреЗ
рдЖрддрд╛рдкрд░реНрдпрдВрдд рдПрдХрдЪ рд╡реНрдпрдХреНрддреА рдХрдВрддреНрд░рд╛рдЯрджрд╛рд░ рдЪрд╛рд▓рд╡рддреЗ. рдПрдХрд╛рдЪ рд╡реЗрд│реА рджреЛрди рд▓реЛрдХ, рдкреНрд░рддреНрдпреЗрдХреАрдХрдбреЗ laptop рд╡рд░ рдПрдХ рдиреЛрдВрджрд╡рд╣реА тАФ рдЕрд╕реЗрдЪ campuses рд╣рд░рд╡рддрд╛рдд. рдкреБрдвреЗ: remote state рдЖрдгрд┐ locking.
git checkout lesson-08-remote-state-locking