ЁЯПл The SchoolтА║ЁЯПл VPCтА║ЁЯЪМ рдзрдбрд╛ 10 тАФ Transit Gateway: рдЬрд┐рд▓реНрд╣реНрдпрд╛рдЪреЗ bus station
ЁЯЦ╝я╕П See the drawing + lab ЁЯПа Course home ЁЯМ┐ Branch on GitHub тЬПя╕П View source
ЁЯЦ╝я╕П рдЖрдХреГрддреА рдЖрдгрд┐ labThe drawing + lab рдкреВрд░реНрдг рдкрд╛рдирд╛рд╡рд░ рдЙрдШрдбрд╛ тЖЧOpen full page тЖЧ

ЁЯЪМ рдзрдбрд╛ 10 тАФ Transit Gateway: рдЬрд┐рд▓реНрд╣реНрдпрд╛рдЪреЗ bus station

ЁЯУН рддреБрдореНрд╣реА рдЗрдереЗ рдЖрд╣рд╛рдд: 12 рдкреИрдХреА рдзрдбрд╛ 10 ┬╖ рдорд╛рдЧрдЪрд╛: lesson-09-peering ┬╖ рдкреБрдврдЪрд╛: lesson-11-troubleshooting


ЁЯУж рдпрд╛ рдмреНрд░рдБрдЪрдордзреНрдпреЗ рдХрд╛рдп рдЖрд╣реЗ

рдзрдбреЗ 01тАУ09, рдЖрдгрд┐ hub: vpc/demo.py рдордзрд▓реЗ tgw() prod, dev, shared рдЖрдгрд┐ office-vpn рдпрд╛рдВрдирд╛ рдПрдХрд╛рдЪ Transit Gateway рд▓рд╛ attach рдХрд░рддреЗ, рдЖрдгрд┐ рдПрдХ TGW route table рдХреЛрдг рдХреЛрдгрд╛рдкрд░реНрдпрдВрдд рдкреЛрд╣реЛрдЪреВ рд╢рдХреЗрд▓ рддреЗ рдард░рд╡рддреЗ тАФ vpc/network.py рдордзрд▓реНрдпрд╛ tgw_path() рд╕рд╣.

ЁЯзТ 5 рд╡рд░реНрд╖рд╛рдВрдЪреНрдпрд╛ рдореБрд▓рд╛рд▓рд╛ рд╕рдордЬрд╛рд╡рд▓реНрдпрд╛рд╕рд╛рд░рдЦреЗ

рдЬрд┐рд▓реНрд╣реНрдпрд╛рдд рдЕрдиреЗрдХ рд╢рд╛рд│рд╛ рдЖрдгрд┐ рдПрдХ рдХрд╛рд░реНрдпрд╛рд▓рдп рдЖрд╣реЗ. рдкреНрд░рддреНрдпреЗрдХ рдЬреЛрдбреАрдордзреНрдпреЗ corridor рдмрд╛рдВрдзрд╛рдпрдЪрд╛ рдореНрд╣рдгрдЬреЗ рдЦреВрдкрдЪ рдЬрд╛рд╕реНрдд corridors. рдореНрд╣рдгреВрди рдЬрд┐рд▓реНрд╣рд╛ рдордзреЛрдордз рдПрдХ bus station ЁЯЪМ рдмрд╛рдВрдзрддреЛ.

рдкреНрд░рддреНрдпреЗрдХ campus station рдкрд░реНрдпрдВрдд рдПрдХрдЪ рд░рд╕реНрддрд╛ рдмрд╛рдВрдзрддреЛ тАФ рдПрдХ attachment. рдХрд╛рд░реНрдпрд╛рд▓рдпрд╣реА рдПрдХрд╛ VPN рд░рд╕реНрддреНрдпрд╛рдиреЗ рдЬреЛрдбрд▓реЗ рдЬрд╛рддреЗ.

Station рд╡рд░ рдкреНрд░рддреНрдпреЗрдХ рд░рд╕реНрддреНрдпрд╛рдЪреЗ рд╕реНрд╡рддрдГрдЪреЗ рд╡реЗрд│рд╛рдкрддреНрд░рдХ рдЕрд╕рддреЗ тАФ TGW route table. Prod рд╢рд╛рд│реЗрдЪреНрдпрд╛ рд╡реЗрд│рд╛рдкрддреНрд░рдХрд╛рдд shared рдХрдбреЗ рдЖрдгрд┐ рдХрд╛рд░реНрдпрд╛рд▓рдпрд╛рдХрдбреЗ buses рдЖрд╣реЗрдд. Dev рд╢рд╛рд│реЗрдЪреНрдпрд╛ рд╡реЗрд│рд╛рдкрддреНрд░рдХрд╛рдд рдлрдХреНрдд shared рдХрдбреЗ bus рдЖрд╣реЗ. рддреНрдпрд╛рдореБрд│реЗ dev рдЪреНрдпрд╛ рд╡рд┐рджреНрдпрд╛рд░реНрдерд┐рдиреА shared рдЧреНрд░рдВрдерд╛рд▓рдпрд╛рдкрд░реНрдпрдВрдд рдкреЛрд╣реЛрдЪреВ рд╢рдХрддрд╛рдд, рдкрдг prod рд╢рд╛рд│реЗрдкрд░реНрдпрдВрдд рдХрдзреАрдЪ рдирд╛рд╣реА тАФ рддрд┐рдереЗ bus рдЪ рдирд╛рд╣реА.

Bus рдПрдХрд╛рдЪ рджрд┐рд╢реЗрдиреЗ рдЬрд╛рддреЗ. рдЙрддреНрддрд░ рдкрд░рдд рдпрд╛рдпрдЪреЗ рдЕрд╕реЗрд▓ рддрд░ рджреБрд╕рд▒реНрдпрд╛ рд╢рд╛рд│реЗрдЪреНрдпрд╛ рд╡реЗрд│рд╛рдкрддреНрд░рдХрд╛рддрд╣реА рдкрд░рддреАрдЪреА bus рд╣рд╡реА.

ЁЯЧ║я╕П рдЖрдХреГрддреА

flowchart TB
    tgw["ЁЯЪМ Transit Gateway"]
    prod["ЁЯПл prod"] --- tgw
    dev["ЁЯПл dev"] --- tgw
    shared["ЁЯУЪ shared"] --- tgw
    vpn["ЁЯПв office-vpn"] --- tgw
    t1["timetable prod: shared ┬╖ office-vpn"]
    t2["timetable dev: shared"]
    tgw -.-> t1
    tgw -.-> t2
    dev -.->|"ЁЯЪл no bus"| prod

ЁЯЧ║я╕П рд░реЗрдЦрд╛рдЯрд▓реЗрд▓реА рдЖрд╡реГрддреНрддреА + рдПрдХ lab: https://school-edh.pages.dev/vpc/lesson-diagrams.html#l10

тЭУ рдХрд╛рдп

ЁЯдФ рдХрд╛

рдХрд╛рд░рдг рдЦрд▒реНрдпрд╛ рдХрдВрдкрдиреНрдпрд╛рдВрдХрдбреЗ рдЕрдиреЗрдХ VPCs рдЕрд╕рддрд╛рдд тАФ рдкреНрд░рддреНрдпреЗрдХ team рд╕рд╛рдареА, рдкреНрд░рддреНрдпреЗрдХ environment рд╕рд╛рдареА, рдкреНрд░рддреНрдпреЗрдХ account рд╕рд╛рдареА тАФ рд╢рд┐рд╡рд╛рдп offices рдЖрдгрд┐ data centres. рд╡реЗрд│рд╛рдкрддреНрд░рдХреЗ рдЕрд╕рд▓реЗрд▓рд╛ hub рдореНрд╣рдгрдЬреЗ рдХреЛрдг рдмреЛрд▓реВ рд╢рдХреЗрд▓ рд╣реЗ рд╕рд╛рдВрдЧрдгреНрдпрд╛рдЪреА рдПрдХ рдЬрд╛рдЧрд╛, рдЖрдгрд┐ office рдЬреЛрдбрдгреНрдпрд╛рдЪреА рдПрдХ рдЬрд╛рдЧрд╛.

ЁЯФз рдХрд╕реЗ (рдпрд╛ repo рдордзреНрдпреЗ)

vpc/network.py рдордзрд▓реЗ tgw_path(attachments, route_table, a, c) рдлрдХреНрдд рддреЗрд╡реНрд╣рд╛рдЪ true рдЕрд╕рддреЗ рдЬреЗрд╡реНрд╣рд╛ рджреЛрдШреЗрд╣реА attached рдЕрд╕рддрд╛рдд рдЖрдгрд┐ c рд╣рд╛ a рдЪреНрдпрд╛ route table рдордзреНрдпреЗ рдЕрд╕рддреЛ. vpc/demo.py рдордзрд▓реЗ tgw() рдЪрд╛рд░ рдкреНрд░рд╢реНрди рд╡рд┐рдЪрд╛рд░рддреЗ рдЖрдгрд┐ peerings рд╡рд┐рд░реБрджреНрдз attachments рдореЛрдЬрддреЗ. рдпрд╛ model рдордзреНрдпреЗ рдкреНрд░рддреНрдпреЗрдХ attachment рд▓рд╛ рдПрдХ table рдЖрд╣реЗ рдЖрдгрд┐ рддреЗ рдПрдХрдЪ рджрд┐рд╢рд╛ рддрдкрд╛рд╕рддреЗ; рдкрд░рддреАрдЪреА рджрд┐рд╢рд╛ рдХрд╛ рдорд╣рддреНрддреНрд╡рд╛рдЪреА рд╣реЗ snippet рджрд╛рдЦрд╡рддреЛ.

ЁЯзк рдХрд░реВрди рдкрд╛рд╣рд╛

python3 vpc/demo.py tgw
python3 - <<'EOF'
import sys; sys.path.insert(0, "vpc"); from network import tgw_path
att = {"prod", "dev", "shared", "office-vpn"}
rt = {"prod": ["shared", "office-vpn"], "dev": ["shared"], "shared": ["prod", "dev"], "office-vpn": ["prod"]}
print("dev тЖТ prod:", tgw_path(att, rt, "dev", "prod"))
rt["dev"].append("prod")                                     # someone widens dev's TGW route table
print("dev тЖТ prod after the change:", tgw_path(att, rt, "dev", "prod"), "┬╖ prod тЖТ dev:", tgw_path(att, rt, "prod", "dev"))
print("not attached:", tgw_path(att, {"sandbox": ["shared"]}, "sandbox", "shared"))
for n in (4, 10, 20):
    print(f"{n} VPCs: peering {n*(n-1)//2} links ┬╖ TGW {n} attachments")
EOF

тЬЕ рддрдкрд╛рд╕рд╛ тАФ рддреБрдореНрд╣рд╛рд▓рд╛ рдХрд╛рдп рджрд┐рд╕рд╛рдпрд▓рд╛ рд╣рд╡реЗ

tgw рд╣реЗ рдЫрд╛рдкрддреЗ:

   prod       тЖТ shared     тЬЕ
   dev        тЖТ shared     тЬЕ
   dev        тЖТ prod       ЁЯЪл kept apart by the TGW route table
   office-vpn тЖТ prod       тЬЕ
   4 VPCs with peering need 6 corridors (n┬╖(nтИТ1)/2); with a TGW, 4 attachments

рддреБрдордЪрд╛ snippet рдЖрдзреА dev тЖТ prod: False рдЫрд╛рдкрддреЛ, рдордЧ dev тЖТ prod after the change: True ┬╖ prod тЖТ dev: False тАФ request рд▓рд╛ bus рдЖрд╣реЗ, рдЙрддреНрддрд░рд╛рд▓рд╛ рдирд╛рд╣реА, рддреНрдпрд╛рдореБрд│реЗ AWS рдордзреНрдпреЗ connection рддрд░реАрд╣реА рдЕрдкрдпрд╢реА рдард░реЗрд▓. рддреНрдпрд╛рдирдВрддрд░ not attached: False, рдЖрдгрд┐ 4 VPCs: peering 6 links ┬╖ TGW 4 attachments, 10 VPCs: peering 45 links ┬╖ TGW 10 attachments, 20 VPCs: peering 190 links ┬╖ TGW 20 attachments.

ЁЯПБ рддреБрдореНрд╣реА рдЖрддреНрддрд╛рдЪ рдХрд╛рдп рд╕рд┐рджреНрдз рдХреЗрд▓реЗ

Hub n┬╖(nтИТ1)/2 corridors рдЪреЗ n рд░рд╕реНрддреЗ рдХрд░рддреЛ, рдЖрдгрд┐ рддреНрдпрд╛рдЪреНрдпрд╛ route tables тАФ рджреЛрдиреНрд╣реА рджрд┐рд╢рд╛рдВрдиреА тАФ рдкреНрд░рддреНрдпрдХреНрд╖рд╛рдд рдХреЛрдг рдмреЛрд▓реВ рд╢рдХреЗрд▓ рддреЗ рдард░рд╡рддрд╛рдд.

тЪая╕П рдиреЗрд╣рдореАрдЪреНрдпрд╛ рдЪреБрдХрд╛

ЁЯПн рдкреНрд░рддреНрдпрдХреНрд╖ рд╡рд╛рдкрд░рд╛рдд

рдПрдХ рд╕рд╛рдорд╛рдиреНрдп рд░рдЪрдирд╛: рдкреНрд░рддреНрдпреЗрдХ Region рдордзреНрдпреЗ рдПрдХ TGW, AWS RAM рдиреЗ accounts рдордзреНрдпреЗ share рдХреЗрд▓реЗрд▓рд╛; рдПрдХ prod table, рдПрдХ nonprod table рдЖрдгрд┐ рдПрдХ shared table; office VPN рдХрд┐рдВрд╡рд╛ Direct Connect рд╡рд░; firewalls рд╕рд╛рдареА inspection VPCs.

рдЦрд▒реНрдпрд╛ account рд╡рд░ (AWS CLI рдЖрдгрд┐ credentials рд▓рд╛рдЧрддрд╛рдд; IDs рдЙрджрд╛рд╣рд░рдгрд╛рджрд╛рдЦрд▓ рдЖрд╣реЗрдд):

aws ec2 create-transit-gateway --description school-hub \
    --options DefaultRouteTableAssociation=disable,DefaultRouteTablePropagation=disable
aws ec2 create-transit-gateway-vpc-attachment --transit-gateway-id tgw-0123456789abcdef0 \
    --vpc-id vpc-0dev000000000000a --subnet-ids subnet-0a subnet-0b subnet-0c
aws ec2 create-transit-gateway-route-table --transit-gateway-id tgw-0123456789abcdef0
aws ec2 associate-transit-gateway-route-table --transit-gateway-route-table-id tgw-rtb-0dev00000000000a \
    --transit-gateway-attachment-id tgw-attach-0dev0000000000a
aws ec2 enable-transit-gateway-route-table-propagation --transit-gateway-route-table-id tgw-rtb-0dev00000000000a \
    --transit-gateway-attachment-id tgw-attach-0shared00000000a
aws ec2 create-route --route-table-id rtb-0dev000000000000a --destination-cidr-block 10.0.0.0/8 \
    --transit-gateway-id tgw-0123456789abcdef0

тПня╕П рдкреБрдвреЗ

Campus рдЖрддрд╛ рдЕрдиреЗрдХ рдкреНрд░рдХрд╛рд░реЗ рдЬреЛрдбрд▓реЗрд▓рд╛ рдЖрд╣реЗ тАФ рдореНрд╣рдгрдЬреЗ packet рд╣рд░рд╡рдгреНрдпрд╛рдЪреНрдпрд╛ рдЕрдиреЗрдХ рдЬрд╛рдЧрд╛. Flow logs рдЖрдгрд┐ Reachability Analyzer: A рд▓рд╛ B рдкрд░реНрдпрдВрдд рдХрд╛ рдкреЛрд╣реЛрдЪрддрд╛ рдпреЗрдд рдирд╛рд╣реА?

git checkout lesson-11-troubleshooting

ЁЯЪМ Lesson 10 тАФ Transit Gateway: the district bus station

ЁЯУН You are here: Lesson 10 of 12 ┬╖ Previous: lesson-09-peering ┬╖ Next: lesson-11-troubleshooting


ЁЯУж What's in this branch

Lessons 01тАУ09, plus the hub: tgw() in vpc/demo.py attaches prod, dev, shared and office-vpn to one Transit Gateway, and a TGW route table decides who may reach whom тАФ with tgw_path() in vpc/network.py.

ЁЯзТ Explain like I'm 5

The district has many schools and one office. Building a corridor between every pair is too many corridors. So the district builds a bus station ЁЯЪМ in the middle.

Every campus builds one road to the station тАФ an attachment. The office joins too, by a VPN road.

At the station, each road has its own timetable тАФ the TGW route table. The prod school's timetable has buses to shared and to the office. The dev school's timetable has a bus to shared only. So dev pupils can reach the shared library, but never the prod school тАФ there is simply no bus.

A bus goes one way. For an answer to come back, the other school's timetable needs a bus back too.

ЁЯЧ║я╕П Diagram

flowchart TB
    tgw["ЁЯЪМ Transit Gateway"]
    prod["ЁЯПл prod"] --- tgw
    dev["ЁЯПл dev"] --- tgw
    shared["ЁЯУЪ shared"] --- tgw
    vpn["ЁЯПв office-vpn"] --- tgw
    t1["timetable prod: shared ┬╖ office-vpn"]
    t2["timetable dev: shared"]
    tgw -.-> t1
    tgw -.-> t2
    dev -.->|"ЁЯЪл no bus"| prod

ЁЯЧ║я╕П Drawn version + a lab: https://school-edh.pages.dev/vpc/lesson-diagrams.html#l10

тЭУ What

ЁЯдФ Why

Because real companies have many VPCs тАФ per team, per environment, per account тАФ plus offices and data centres. A hub with timetables is one place to say who may talk, and one place to connect the office.

ЁЯФз How (in this repo)

tgw_path(attachments, route_table, a, c) in vpc/network.py is true only if both are attached and c is in a's route table. tgw() in vpc/demo.py asks four questions and counts peerings vs attachments. The model has one table per attachment and checks one direction; the snippet shows why the return direction matters.

ЁЯзк Try it

python3 vpc/demo.py tgw
python3 - <<'EOF'
import sys; sys.path.insert(0, "vpc"); from network import tgw_path
att = {"prod", "dev", "shared", "office-vpn"}
rt = {"prod": ["shared", "office-vpn"], "dev": ["shared"], "shared": ["prod", "dev"], "office-vpn": ["prod"]}
print("dev тЖТ prod:", tgw_path(att, rt, "dev", "prod"))
rt["dev"].append("prod")                                     # someone widens dev's TGW route table
print("dev тЖТ prod after the change:", tgw_path(att, rt, "dev", "prod"), "┬╖ prod тЖТ dev:", tgw_path(att, rt, "prod", "dev"))
print("not attached:", tgw_path(att, {"sandbox": ["shared"]}, "sandbox", "shared"))
for n in (4, 10, 20):
    print(f"{n} VPCs: peering {n*(n-1)//2} links ┬╖ TGW {n} attachments")
EOF

тЬЕ Verify тАФ what you should see

tgw prints:

   prod       тЖТ shared     тЬЕ
   dev        тЖТ shared     тЬЕ
   dev        тЖТ prod       ЁЯЪл kept apart by the TGW route table
   office-vpn тЖТ prod       тЬЕ
   4 VPCs with peering need 6 corridors (n┬╖(nтИТ1)/2); with a TGW, 4 attachments

Your snippet prints dev тЖТ prod: False, then dev тЖТ prod after the change: True ┬╖ prod тЖТ dev: False тАФ the request has a bus, the reply does not, so in AWS the connection would still fail. Then not attached: False, and 4 VPCs: peering 6 links ┬╖ TGW 4 attachments, 10 VPCs: peering 45 links ┬╖ TGW 10 attachments, 20 VPCs: peering 190 links ┬╖ TGW 20 attachments.

ЁЯПБ What you just proved

A hub turns n┬╖(nтИТ1)/2 corridors into n roads, and its route tables тАФ in both directions тАФ decide who may actually talk.

тЪая╕П Common mistakes

ЁЯПн In production

A common shape: one TGW per Region, shared across accounts with AWS RAM; a prod table, a nonprod table and a shared table; the office on VPN or Direct Connect; inspection VPCs for firewalls.

On a real account (needs the AWS CLI and credentials; IDs are examples):

aws ec2 create-transit-gateway --description school-hub \
    --options DefaultRouteTableAssociation=disable,DefaultRouteTablePropagation=disable
aws ec2 create-transit-gateway-vpc-attachment --transit-gateway-id tgw-0123456789abcdef0 \
    --vpc-id vpc-0dev000000000000a --subnet-ids subnet-0a subnet-0b subnet-0c
aws ec2 create-transit-gateway-route-table --transit-gateway-id tgw-0123456789abcdef0
aws ec2 associate-transit-gateway-route-table --transit-gateway-route-table-id tgw-rtb-0dev00000000000a \
    --transit-gateway-attachment-id tgw-attach-0dev0000000000a
aws ec2 enable-transit-gateway-route-table-propagation --transit-gateway-route-table-id tgw-rtb-0dev00000000000a \
    --transit-gateway-attachment-id tgw-attach-0shared00000000a
aws ec2 create-route --route-table-id rtb-0dev000000000000a --destination-cidr-block 10.0.0.0/8 \
    --transit-gateway-id tgw-0123456789abcdef0

тПня╕П Next

The campus is connected in many ways now тАФ which means many places for a packet to get lost. Flow logs and Reachability Analyzer: why can't A reach B?

git checkout lesson-11-troubleshooting
тЖР PreviouspeeringNext тЖТtroubleshooting

This page is the lesson's README from the lesson-10-transit-gateway branch, shown here so the whole School stays on one site. Code files open on GitHub at the same branch.