IP کلاینت VPN در Kubernetes: حفظش کنیم یا SNAT کنیم؟
بین حفظ آدرس واقعی کلاینت VPN و NAT مبدأ در Kubernetes بر اساس سه شرط انتخاب کنید، سپس مسیر بازگشت و جابهجایی podها را بررسی کنید.
جایی بین تونل و backend، آدرس کلاینت یا زنده میماند یا جایگزین میشود، و هر دو نتیجه قابل دفاع است. انتخاب متعلق به صاحب سرویس گیرنده است، نه کسی که CNI را نصب کرده. وقتی مجوزدهی برای هر کلاینت، سهمیهها یا سوابق ممیزی مهم است، آدرس باید از هر گام جان سالم به در ببرد. وقتی انتساب مشترک پذیرفتنی است، NAT مبدأ مشکلی در مسیریابی را حذف میکند که در غیر این صورت همیشه نگهداری میکردید.
کجا آدرس کلاینت واقعاً ناپدید میشود
بسته یک کلاینت راه دور با مبدأ داخلی در محدوده تونل، مثلاً 10.90.0.42، به pod مربوط به VPN میرسد. وقتی pod آن بسته را به سمت یک ClusterIP یا IP مربوط به pod هدایت میکند، سه سازوکار مختلف میتوانند مبدأ را بازنویسی کنند. قاعده masquerade در CNI روی گره شامل ترافیکی است که pod بیرون از CIDR خوشه میفرستد. ورودی conntrack در kube-proxy روی گره مقصد شامل خود پرش Service است. پراکسی که اتصال را پایان میدهد اصلاً بسته را هدایت نمیکند، پس مبدأیی که در پایان میبینید متعلق به پراکسی است.
هر کدام در لایهای متفاوت زندگی میکند، و به همین دلیل یک فیلد Service تقریباً هرگز کل مسیر را درست نمیکند.
externalTrafficPolicy روی Service عمومی VPN فقط درباره اتصال بیرونی تصمیم میگیرد: Local آدرس دور را روی گرهی دریافتکننده نگه میدارد، در حالی که Cluster به kube-proxy اجازه میدهد بسته را به گرهی دیگر بدهد و همانجا masquerade کند. آن تنظیم شنوندهیی را کنترل میکند که کلاینتهای شما به آن وصل میشوند. درباره بسته رمزگشاییشدهیی که فرآیند VPN شما بعداً به خوشه مسیریابی میکند هیچ نمیگوید.
سه شرط که بحث را فیصله میدهند
من هر بار که این موضوع پیش میآید همان سه پرسش را به همان ترتیب میپرسم، چون اولی معمولاً بحث را تمام میکند. برای همان بار کاری مشخص پاسخ دهید، نه برای کل خوشه. دو خوشه در یک شرکت میتوانند به پاسخهای متفاوت برسند و هر دو درست باشند.
| Question | Preserve | SNAT |
|---|---|---|
| Does the backend enforce policy per client? | Yes, the address is the identity | Only if a trusted proxy supplies identity |
| Can the cluster route 10.90.0.0/24 back to a stable gateway? | Required | Not needed |
| Is the workload a forwarder or a proxy? | Forwarder | Proxy is fine |
اگر backend به پرسش اول بله و به دومی نه بگوید، کار شبکه دارید نه فایل manifest برای ویرایش. اگر سطر سوم بگوید پراکسی، آدرس هرگز زنده نمیماند، و ادعای خلافش یک هفته گرفتن بسته هزینه دارد.
حالت preserve چه چیزی از شبکه میخواهد
حفظ مبدأ یعنی گره مقصد باید ترافیک را از طریق یک دروازه VPN فعال به 10.90.0.42 برگرداند. استخر VPN یک CIDR خوشه نیست، پس هیچ CNI آن را بهطور پیشفرض برای شما مسیریابی نمیکند. مسیر را خودتان اضافه میکنید و سپس مطمئن میشوید نقطه پایانی دروازهیی که به آن اشاره میکند از برنامهریزی مجدد جان سالم به در میبرد.
ip route add 10.90.0.0/24 via 10.244.3.17 dev eth0
sysctl -w net.ipv4.conf.eth0.rp_filter=2
آن پرش بعدی یک آدرس pod است، و آدرسهای pod جابهجا میشوند. مسیر را به یک VIP مربوط به Service یا آدرسی از گره که سر جایش میماند نشانه بگیرید، یا بپذیرید که بعد از هر اخراج دنبال دروازه خواهید دوید. فیلتر مسیر معکوس تله دیگر است: حالت سختگیرانه بستههایی را میاندازد که مسیر بازگشتشان با رابطی که از آن آمدهاند نمیخواند، و این دقیقاً شکل یک جریان VPN حفظشده است.
اعتبارسنجی سهلانگارانه غالباً تفاوت میان مسیر بازگشت درستکار و پاسخهایی است که پس از ترک backend ناپدید میشوند. قواعد masquerade روی گره VPN هم باید محدوده تونل را استثنا کنند، وگرنه بسته هدایتشده با آدرس pod خارج میشود، فارغ از مسیری که ساختهاید. بهتر است این استثنا را در پیکربندی خود CNI بیان کنید نه ویرایش دستی iptables، چون عامل در راهاندازی مجدد زنجیرههایش را بازنویسی میکند و قاعده دستنویس شما دقیقاً تا ارتقای بعدی زنده میماند.
NetworkPolicy کنترل دسترسی است نه مسیریابی. سختتر کردن یک سیاست هرگز آدرسی را که masquerade قبلاً جایگزین کرده برنمیگرداند.
SNAT چه هزینهیی دارد و چگونه آن را بنویسیم
NAT مبدأ به سمت خوشه طرح ارزانتر است و اشتباه نیست. backend آدرس pod یا گره VPN را میبیند، گزارشها با هم میخوانند و لازم نیست مسیر بازگشتی وجود داشته باشد. چیزی که از دست میدهید توانایی تشخیص دو کلاینت در لایه شبکه است، پس سهمیهها، مسدودسازیها و ردهای ممیزی باید از جای دیگری بیایند.
معمولاً آن جای دیگر برنامه است: توکن نشست، سرآیند امضاشده یا خطی از پروتکل PROXY که پراکسی تحت کنترل شما مینویسد. اینها به گیرنده هویتی میدهند که تنها زمانی میتواند به آن اعتماد کند که پراکسی در مسیر باشد و سرآیند از سمت کلاینت قابل تنظیم نباشد. در runbook صریح بگویید کدام اعمال میشود، چون مهندس بعدی فرض میکند آدرس داخل گزارش همان کلاینت است. اینطور نیست، و یک حادثه برای گران کردن آن فرض کافی است.
معامله تا زمانی که نوشته شود صادق میماند.
بررسیهایی که مسیر کارآمد را از مسیر خوششانس جدا میکنند
با اتصال تازه آزمایش کنید نه اتصال کششده، و در هر دو جهت آزمایش کنید. چند خطا فقط به این دلیل متناوب به نظر میرسند که جریانهای جدید مسیر بازنویسیشده را میگیرند.
tuple را در سه نقطه در طول یک درخواست مجاز بگیرید: درست پس از رمزگشایی، روی رابط خروجی pod مربوط به VPN، و روی backend. اگر مبدأ بین برداشت دوم و سوم تغییر کند، علت پایینتر از pod است. اگر پیش از دومی تغییر کند، خود pod ترجمه میکند.
سپس pod مربوط به VPN را حذف کنید و آزمایش را هنگام برنامهریزی مجددش تکرار کنید. مسیر حفظشدهیی که در اخراج میشکند ناتمام است، و همچنین قاعده NAT که به آدرسی دیگر موجود نیست سنجاق شده. در پایان یک درخواست از مبدأیی بفرستید که انتظار رد شدنش را دارید و تأیید کنید که رد از سیاست میآید نه از مسیر گمشده.