۳۰ اردیبهشت ۲۵۸۵
سه تا Peering و ۱۰ دلار در ماه: کِی VPC Peering از Transit Gateway میبَره
ما یه AWS Organization کوچیک داریم. یه اکانت ops/internal چندتا سرویس داخلی مشترک رو نگه میداره. سهتا workload account (dev، staging، prod) هر کدوم VPC خودشون رو دارن و باید به این سرویسها برسن. یه ریجن (us-east-1)، هر VPC با ۳ تا AZ. تمام معماریهای مرجع AWS به Transit Gateway اشاره میکنن. من قیمتش رو در برابر ترافیک واقعیمون حساب کردم و به جاش VPC Peering رو انتخاب کردم. اینجا منطق و اعدادش رو میگم.
مسئله
چهارتا اکانت AWS زیر یه Organization:
- ops-internal: VPC سرویسهای مشترک،
172.16.0.0/16. یه مجموعه کوچیک از ابزارهای داخلی روش — observability، مدیریت secret، control plane برای connectivity داخلی. در مجموع سهتا سرویس. - dev:
172.17.0.0/16 - staging:
172.18.0.0/16 - prod:
172.19.0.0/16
VPCهای workload باید به VPC ops برسن. لازم نیست با همدیگه ارتباط داشته باشن — dev نباید prod رو ببینه، prod هم نباید dev رو. ساختار hub-and-spoke با ops در مرکز.
محدودیتها:
- تیم کوچیکیم. هرچی انتخاب کنم، خودم باید نگهش دارم.
- یه ریجن، حداقل تا یه سال دیگه برنامهای برای گسترش نداریم.
- هزینه برامون مهمه. ما یه استارتآپیم؛ هر آیتم تکراری روی صورتحساب AWS باید توجیه داشته باشه.
- هر چهارتا اکانت از قبل تو AWS Organizations هستن، پس IAM بین اکانتها سادهست.
این کل setup ـه. تصمیم جالب، لایهی connectivity ـه.
گزینههایی که بررسی کردم
| گزینه | چی هست | کاربرد ایدهآل | مدل هزینه |
|---|---|---|---|
| VPC Peering | لینک مستقیم ۱:۱ بین دو VPC | چندتا VPC، بدون نیاز به routing گذرا | 0$/ساعت، فقط هزینهی data transfer |
| Transit Gateway | روتر منطقهای، hub-and-spoke | تعداد زیاد VPC، routing گذرا، inspection مرکزی | $0.05/ساعت برای هر attachment + $0.02/GB |
| Site-to-Site VPN | تونل IPSec | هیبریدی (on-prem ↔ AWS) | $0.05/ساعت برای هر connection + data out |
| PrivateLink | endpoint های سرویس مبتنی بر NLB | افشای سرویسهای مشخص بین اکانتها | $0.01/ساعت برای هر endpoint در هر AZ + $0.01/GB |
| VPC Lattice | service mesh در لایهی اپلیکیشن | تعداد زیاد سرویس، احراز هویت مبتنی بر identity | $0.025/ساعت برای هر سرویس + $0.025/GB |
| Overlay در فضای کاربر (مدل Tailscale) | mesh وایرگارد روی هر underlay | connectivity در لایهی app برای هاستهای شرکتکننده | رایگان / self-hosted |
گزینهی overlay یه نکتهی جدا داره. یه mesh وایرگارد جایگزین VPC Peering نمیشه؛ روی هر چی که زیرش داری میشینه و فقط هاستهایی که به mesh متصل بشن میتونن ازش استفاده کنن. برای ترافیک ماشین به ماشین بین EC2 هایی که agent اجرا نمیکنن — مثل scrape های Prometheus یا API call های داخلی — هنوز به connectivity در سطح VPC نیاز داری. حذفش بهعنوان تنها لایهی connectivity راحت بود: خیلی چیزها باید mesh-aware میشدن.
Site-to-Site VPN برای هیبریدیه (دیتاسنترت به AWS). برای استفادهی داخل AWS، گرون و بدشکله — برای حل مسئلهای که AWS با Peering حلش کرده، باید هزینهی تونل و عملیات customer gateway بدی. صرفاً برای کامل بودن لیست آوردمش.
میمونه چهارتا گزینهی جدی: Peering، TGW، PrivateLink، Lattice.
چرا VPC Peering رو انتخاب کردم
چهارتا VPC در hub-and-spoke یعنی سهتا peering connection. همین. هشدار اسکیلینگ n*(n-1)/2 که همه تکرار میکنن فقط وقتی گاز میگیره که هر VPC با هر VPC دیگهای باید حرف بزنه. در hub-and-spoke با یه hub، فقط n-1 ـه.
Tradeoff هایی که آگاهانه قبول کردم:
- بدون routing گذرا. اگه یه روزی dev بخواد به staging برسه، باید یه peering چهارم اضافه کنم یا کلاً بازنگری کنم. الان نیاز نیست، و مسئلهی امروز تنها مسئلهایه که دارم حل میکنم.
- ورودی دستی route table از هر دو طرف. هر دو VPC تو یه peering به route صریح روی
pcx-*نیاز دارن. یه طرف یادت بره و ترافیک بیسروصدا تو black-hole گیر میکنه (پایینتر بیشتر). - CIDRها نباید همپوشانی داشته باشن. فضای آدرس رو از قبل برنامهریزی کردم — /16 های مجاور زیر یه supernet با /14 — پس فقط یهبار هزینهی ذهنی داشت.
- بدون egress مرکزی، بدون inspection، بدون firewall hop. برامون قابل قبوله؛ تیم SecOps نداریم که نقطهی inspection روی transit رو الزامی کنه.
نکتهی تعیینکننده: تو چهارتا VPC، فقط هزینهی attachment ـه TGW در ماه حدود ۱۴۶ دلاره، قبل از این که حتی یه بایت رد بشه. Peering در حالت بدون ترافیک ۰ دلار/ماهه. این که «TGW بهتر اسکیل میشه» درسته، ولی رایگان نیست — و ما در مقیاسی نیستیم که سادگی عملیاتیش ۱۴۶ دلار در ماه بیارزه.
مرور setup
سه نکتهی برجسته در Terraform. الگو برای هر spoke تکرار میشه.
Provider alias برای cross-account. خود peering connection سمت requester (ops) ـه؛ resource ـه accepter سمت workload ـه. هر دو provider صریح میخوان — تو نسخهی اولم، aws_vpc_peering_connection_accepter به اشتباه با provider ـه requester اجرا میشد. Terragrunt بدون مشکل apply کرد؛ accepter هیچوقت نرفت بالا:
provider "aws" {
alias = "ops"
region = "us-east-1"
assume_role { role_arn = "arn:aws:iam::${var.ops_account_id}:role/TerragruntExec" }
}
provider "aws" {
alias = "workload"
region = "us-east-1"
assume_role { role_arn = "arn:aws:iam::${var.workload_account_id}:role/TerragruntExec" }
}
سمت requester (اکانت ops). برای peering تو یه ریجن، peer_region ست نکن — این آرگومان فقط برای inter-region ـه و ست کردنش AWS رو به حالت cross-region میبره (هزینهگذاری متفاوت، قوانین option block متفاوت). فلگ auto_accept اینجا فقط وقتی معنا داره که هر دو VPC تو یه اکانت باشن؛ برای cross-account باید یه resource ـه aws_vpc_peering_connection_accepter جدا با provider ـه accepter تعریف کنی:
resource "aws_vpc_peering_connection" "ops_to_workload" {
provider = aws.ops
vpc_id = aws_vpc.ops.id
peer_vpc_id = var.workload_vpc_id
peer_owner_id = var.workload_account_id
auto_accept = false
# peer_region نداره — same-region
tags = { Name = "ops-to-${var.workload_env}" }
}
سمت accepter (اکانت workload):
resource "aws_vpc_peering_connection_accepter" "workload_from_ops" {
provider = aws.workload
vpc_peering_connection_id = aws_vpc_peering_connection.ops_to_workload.id
auto_accept = true
tags = { Name = "from-ops" }
}
ورودیهای route table — هر دو طرف:
resource "aws_route" "ops_to_workload" {
provider = aws.ops
route_table_id = aws_route_table.ops_private.id
destination_cidr_block = var.workload_vpc_cidr
vpc_peering_connection_id = aws_vpc_peering_connection.ops_to_workload.id
}
resource "aws_route" "workload_to_ops" {
provider = aws.workload
route_table_id = var.workload_private_rt_id
destination_cidr_block = aws_vpc.ops.cidr_block
vpc_peering_connection_id = aws_vpc_peering_connection.ops_to_workload.id
}
اون gotcha ای که ۳۰ دقیقه از عمرم رو خورد. اولین peering رفت روی ACTIVE. security group ها درست تنظیم شده بودن. ترافیک تو black-hole گیر کرد. بدون خطا، بدون ICMP unreachable، فقط دراپ خاموش بستهها. ورودی route table رو سمت accepter یادم رفته بود. وضعیت peering و وضعیت routing مستقل از هماند؛ AWS با کمال خوشحالی peering رو سالم گزارش میده، در حالی که ترافیک واقعی هیچجا نمیتونه بره.
gotcha دوم: DNS. هاستنیمهای داخلی از سمت اکانتهای workload به IP عمومی resolve میشدن تا وقتی که remote DNS resolution رو فعال کردم. برای peering های cross-account، این گزینه باید از هر طرف در اکانت خودش ست بشه — requester نمیتونه فلگ accepter رو ست کنه و برعکس. یعنی دو resource جدا، هر کدوم با provider درست و ID درست (resource ـه accepter باید به ID خود accepter اشاره کنه نه به requester):
resource "aws_vpc_peering_connection_options" "requester" {
provider = aws.ops
vpc_peering_connection_id = aws_vpc_peering_connection.ops_to_workload.id
requester { allow_remote_vpc_dns_resolution = true }
}
resource "aws_vpc_peering_connection_options" "accepter" {
provider = aws.workload
vpc_peering_connection_id = aws_vpc_peering_connection_accepter.workload_from_ops.id
accepter { allow_remote_vpc_dns_resolution = true }
}
با نگاه به عقب، باید روز اول یه ماژول peering-pair میساختم — requester، accepter، هر دو route، هر دو option block ـه DNS، همگی پشت یه مجموعه ورودی. اولی رو inline نوشتم چون «خب فقط یه peering ـه»، برای دومی و سومی copy-paste کردم، و الان سه تا peering جلوتر با همون تکرار نشستهم. refactor یعنی رقص state-move ـه Terraform که اولویتش نکردم. کلاسیک.
مقایسهی هزینه با اعداد واقعی
سناریو: ۳ تا VPC ـه workload ↔ ۱ VPC ـه shared services، us-east-1، حدود ۵۰۰ گیگابایت در ماه ترافیک cross-VPC، ۳ تا AZ. همهی قیمتها به صفحات pricing ـه AWS لینک شدن تا وقتی (نه اگر) عوض شدن، بتونی دوباره حساب کنی.
VPC Peering. ۰ دلار/ساعت برای خود connection. data transfer تنها آیتم هزینهست. AWS هزینهی cross-AZ رو دوبار حساب میکنه — $0.01/GB روی اکانت فرستنده (out) بهعلاوهی $0.01/GB روی اکانت گیرنده (in)، یعنی مجموعاً $0.02/GB به ازای هر گیگ منتقلشده. در حدود ۵۰۰ گیگابایت/ماه روی هر سهتا peering: حدود ۱۰ دلار در ماه. اگه سرویسها رو به AZ خاصی pin کنی کمتره، ولی برای صداقت همون بدترین حالت رو نگه میدارم. (قیمت VPC)
Transit Gateway. ۴ تا attachment × $0.05/ساعت × ۷۳۰ ساعت = ۱۴۶ دلار/ماه فقط برای attachment ها. بهعلاوه $0.02/GB processed × ۵۰۰ گیگابایت = ۱۰ دلار. حدود ۱۵۶ دلار در ماه، قبل از هر چیز دیگه. همون حدود ۱۰ دلار data transfer ـه cross-AZ روی TGW هم میاد — تفاوت اصلی، اون ۱۴۶ دلار attachment fee ـه، نه لایهی داده. (قیمت TGW)
Site-to-Site VPN. $0.05/ساعت برای هر connection × ۷۳۰ ساعت × ۳ تا connection = ۱۰۹.۵ دلار/ماه، بهعلاوهی data transfer out و بار عملیاتی customer gateway. حدود ۱۱۰ دلار در ماه و ابزار غلط برای intra-AWS. (قیمت VPN)
PrivateLink. هزینهی per-endpoint وقتی چندتا سرویس داری سریع بالا میره. ۳ سرویس × ۳ AZ × $0.01/ساعت × ۷۳۰ = ۶۵.۷ دلار/ماه به ازای هر VPC مصرفکننده. ۳ تا VPC ـه workload مصرفکننده = ۱۹۷ دلار/ماه فقط برای endpoint ها، بهعلاوه $0.01/GB × ۵۰۰ گیگ = ۵ دلار. حدود ۲۰۲ دلار در ماه. (قیمت PrivateLink)
VPC Lattice. $0.025/ساعت برای هر سرویس × ۳ سرویس × ۷۳۰ = ۵۴.۷۵ دلار/ماه، بهعلاوه $0.025/GB × ۵۰۰ گیگ = ۱۲.۵ دلار. حدود ۶۷ دلار در ماه. (قیمت Lattice)
| گزینه | هزینهی ماهانه (این سناریو) |
|---|---|
| VPC Peering | حدود ۱۰ دلار |
| VPC Lattice | حدود ۶۷ دلار |
| Site-to-Site VPN | حدود ۱۱۰ دلار |
| Transit Gateway | حدود ۱۵۶ دلار |
| PrivateLink | حدود ۲۰۲ دلار |
نقطهی break-even با TGW. هزینهی data transfer بهازای هر گیگ تقریباً یکیه (حدود $0.02/GB). تصمیم کاملاً روی attachment fee در برابر سختی عملیاتی n-1 تا peering (در hub-and-spoke) یا n*(n-1)/2 (در full mesh) میچرخه. قاعدهی سرانگشتی من: بالای ~۵ تا VPC در hub-and-spoke یا هر سناریوی full-mesh، برو سراغ TGW. پایینتر از اون، peering در هزینه با اختلاف یه مرتبهی بزرگی برندهست و فاصلهی عملیاتیش میشه «دو تا ورودی route table بیشتر».
کجاها نباید سراغ peering بری
- بیش از ~۵ تا VPC. منحنی
n*(n-1)/2حتی در hub-and-spoke هم مدیریت رو دردناک میکنه، اگه قرار باشه یه spoke به spoke دیگه برسه. - routing گذرا. peering ها ترانزیت نمیکنن. اگه A↔B و B↔C باشه، A بدون A↔C به C نمیرسه. TGW این رو ذاتی حل میکنه.
- تغییرات مکرر CIDR. هر تغییر یه رویداد هماهنگی بین اکانتهاست.
- egress یا inspection مرکزی. اگه compliance یه VPC ـه inspection یا NAT مرکزی بخواد، باید سراغ TGW یا الگوی transit VPC بری.
- cross-region در مقیاس بزرگ. peering بین ریجنها کار میکنه، ولی هزینهی داده و بار عملیاتی سریع بالا میره. peering ـه TGW بین ریجنها شکل بهتریه.
- کنترل دسترسی در لایهی سرویس به جای لایهی شبکه. اون قلمرو PrivateLink یا Lattice ـه.
نکات نهایی
- پیشفرض سراغ TGW رفتن، برای تیمهای کوچیک یه تصمیم cargo-cult ـه. معماریهای مرجع AWS برای شرکتهایی نوشته شدن که دهها اکانت و تیم شبکهی اختصاصی دارن. تو (احتمالاً) اونها نیستی.
- هشدار «peering اسکیل نمیشه» درسته، ولی بد بیان شده. بالای ~۵ تا VPC در full mesh اسکیل نمیشه. تو ۴ تا VPC در hub-and-spoke، میشه سهتا connection — کسلکننده، ارزون، تموم.
- همیشه هزینهی connectivity رو روی پروفایل ترافیک واقعی خودت حساب کن. نقطهی break-even رو attachment hour ها تعیین میکنن نه داده — و پیشفرضهای AWS calculator تو رو سمت TGW میبرن، حتی وقتی با peering ماهی ۱۴۰ دلار صرفهجویی میکردی.
- ماژول peering-pair رو روز اول بهصورت Terraform ـه قابل استفادهی مجدد بساز. اولی رو inline ننویس چون «فقط یکیه». من دقیقاً همین کارو کردم و هنوز با copy-paste هزینهاش رو میدم.
- حالتهای شکست خاموش، هزینهی واقعیاند. peering بهعلاوهی ورودی فراموششدهی route table بهعلاوهی فلگهای گمشدهی DNS option، یه بعدازظهر رو میخوره. تو ماژول بذارشون و دیگه بهشون فکر نکن.