رفتن به محتوای اصلی

Pedram Sarani

یادداشت‌های SRE و DevOps

بازگشت به مسیرها

مسیر یادگیری

مسیر ترافیک در Kubernetes؛ از Pod تا Service و Gateway

در این مسیر یاد می‌گیریم ترافیک در کوبرنتیز واقعاً از کجا عبور می‌کند؛ از ارتباط Pod و Service تا Gateway API، و لایه‌هایی مثل DNS، EndpointSlice، kube-proxy، NAT، conntrack و NetworkPolicy.

این مسیر یادگیری (Learning Path) برای زمانی است که می‌خواهیم تقریبا کل استک شبکه کوبرنتیز را فقط از روی YAML و manifest نفهمیم. چون واقعیت این است که مسیر traffic در کلاستر همیشه به آن سادگی که در manifest دیده می‌شود نیست.

گاهی یک پاد به پاد دیگر وصل می‌شود. گاهی یک پاد اسم یک Service را صدا می‌زند. گاهی هم یک کلاینت مثلا یک کاربرنهایی از بیرون کلاستر از طریق NodePort، LoadBalancer، Ingress یا جدیدتر Gateway API وارد می‌شود. در همه این حالت‌ها، پشت صحنه چند لایه با هم کار می‌کنند؛ از DNS و route تا Service Discovery و NAT، از انتخاب backend تا conntrack و NetworkPolicy، و در نهایت CNI.

هدف این Learning Path این است که این لایه‌ها را جداگانه باز کنیم، بعد آرام‌آرام آن‌ها را کنار هم بگذاریم. طوری که وقتی در production مشکلی پیش آمد، فقط به manifest نگاه نکنیم و حدس نزنیم؛ بتوانیم واقعاً مسیر request را دنبال کنیم.

در هر بخش سعی می‌کنیم فقط به تئوری بسنده نکنیم. سناریوی عملی، مسیر troubleshooting، خطاهای رایج و نکاتی که در محیط واقعی اهمیت پیدا می‌کنند هم هستند. این صفحه بیشتر نقش نقشه راه را دارد؛ یعنی نشان می‌دهد هر بخش کجای داستان Kubernetes networking قرار می‌گیرد.

این مسیر برای چه کسی مناسب است؟

این مسیر برای کسی مناسب است که با مفاهیم پایه Kubernetes آشناست؛ می‌داند Pod چیست، Service چه کاری می‌کند، Deployment چه نقشی دارد و Node یعنی چه.

اما اگر هنوزسؤال است که وقتی یک request داخل کلاستر حرکت می‌کند دقیقاً از کجا رد می‌شود، این مسیر به همین ساختار میپردازد. شاید Service را می‌شناسیم، ولی ندانیم ClusterIP واقعاً کجاست. شاید بدانیم DNS اسم Service را resolve می‌کند، اما ندانیم بعد از resolve شدن چه اتفاقی برای packet می‌افتد. یا شاید درگیر خطایی شده باشیم که همه‌چیز در YAML درست به نظر می‌رسد، ولی ارتباط برقرار نمی‌شود.

اینجاست که باید مسیر را لایه‌به‌لایه دید.

چرا این مسیر مهم است؟

در کوبرنتیز چیزی که می‌بینیم همیشه همان چیزی نیست که در مسیر packet اتفاق می‌افتد.

مثلاً وقتی یک Pod به ClusterIP یک Service وصل می‌شود، آن IP معمولاً یک process واقعی یا interface جداگانه نیست. جایی در کلاستر یک سرویس فیزیکی با آن IP ننشسته که request را بگیرد. پشت صحنه، EndpointSliceها backendهای واقعی را نگه می‌دارند، kube-proxy روی nodeها rule می‌سازد، kernel کار NAT را انجام می‌دهد و conntrack وضعیت connection را حفظ می‌کند.

ممکن است DNS درست جواب بدهد، ولی Service هیچ endpoint فعالی نداشته باشد. شاید endpoint وجود داشته باشد، ولی NetworkPolicy اجازه عبور traffic را ندهد. گاهی kube-proxy رول ها را ساخته باشد، اما conntrack باعث شود connection قدیمی هنوز به backend قبلی برود. یا مشکل اصلاً داخل cluster نباشد و در مسیر ورود از LoadBalancer یا Gateway باشد.

برای همین troubleshooting شبکه در کوبرنتیز فقط با kubectl get svc یا نگاه کردن به YAML کامل نمی‌شود. باید بدانیم request از کدام namespace شبکه خارج می‌شود، اسم DNS چطور resolve می‌شود، Service چطور به EndpointSlice وصل می‌شود، Service VIP در چه مرحله‌ای به ای پی پاد تبدیل می‌شود، backend چطور انتخاب می‌شود و response از چه مسیری برمی‌گردد.

پیش‌نیازهای این مسیر

برای دنبال کردن این مسیر لازم نیست متخصص کوبرنتیز یا شبکه باشیم، ولی بهتر است این مفاهیم را در حد پایه بشناسیم:

  • Pod چیست و چطور اجرا می‌شود
  • Service چه مشکلی را حل می‌کند
  • Deployment و نقش آن در مدیریت Podها
  • Node و نقش آن در کلاستر
  • Namespace در Kubernetes
  • ClusterIP به‌عنوان نوعی از Service
  • kubelet و نقش آن روی node
  • اینکه CNI چیست و چرا کلاستر به آن نیاز دارد
  • اینکه DNS در Kubernetes برای چه کاری است

تفاوت این‌ها با آنچه در این مسیر یاد می‌گیریم این است: پیش‌نیازها را باید قبلاً دیده باشیم. اما نقش هر کدام در مسیر واقعی traffic — مثلاً اینکه CNI دقیقاً کجای مسیر packet وارد می‌شود، یا DNS چطور اسم Service را resolve می‌کند — همان چیزی است که اینجا باز می‌کنیم.

نقشهٔ Learning Path

کل این مسیر را به چند بخش تقسیم کرده‌ام. اول یک مدل ذهنی کلی می‌سازیم، بعد لایه‌به‌لایه جلو می‌رویم.

بخشموضوعوضعیت
۱مدل ذهنی Kubernetes networking✅ منتشرشده
۲DNS و Service Discovery در Kubernetes✅ منتشرشده
۳شبکه Podها، CNI، route، overlay و MTU🔜 به‌زودی
۴مسیر Pod to Pod🔜 به‌زودی
۵مسیر Pod to Service و EndpointSlice🔜 به‌زودی
۶kube-proxy، Service VIP، iptables، nftables و IPVS🔜 به‌زودی
۷conntrack، NAT، connection reuse و مسیر برگشت🔜 به‌زودی
۸NetworkPolicy، segmentation و failure modeهای CNI🔜 به‌زودی
۹مسیر external traffic با NodePort و LoadBalancer🔜 به‌زودی
۱۰مسیر L7 با Ingress و Gateway API🔜 به‌زودی
۱۱Observability و ابزارهای troubleshooting شبکه🔜 به‌زودی
۱۲سناریوهای واقعی troubleshooting مرحله‌به‌مرحله🔜 به‌زودی

بخش اول: مدل ذهنی Kubernetes networking

در بخش اول، قرار نیست مستقیم برویم سراغ iptables یا Gateway. اول باید تصویر کلی را درست کنیم.

در کوبرنتیز چند نوع IP داریم که هرکدام نقش متفاوتی دارند: Pod IP، Service IP، Node IP و external IP. اگر این‌ها را با هم قاطی کنیم، خیلی از رفتارهای شبکه گیج‌کننده می‌شود. مثلاً ممکن است فکر کنیم ClusterIP خودش یک مقصد واقعی است، در حالی که بیشتر شبیه یک آدرس مجازی برای رسیدن به backendها عمل می‌کند.

در این بخش جایگاه اجزای اصلی را مشخص می‌کنیم:

  • نقش DNS برای پیدا کردن نام‌ها
  • نقش Service برای تعریف یک ورودی پایدار
  • نقش EndpointSlice برای نگه داشتن backendهای واقعی
  • نقش kube-proxy برای آماده کردن ruleهای لازم روی nodeها
  • نقش CNI برای اتصال شبکه‌ای Podها
  • نقش route برای هدایت packet بین nodeها
  • نقش NetworkPolicy برای محدود کردن traffic
  • نقش conntrack برای نگه داشتن وضعیت connectionها

بعد از این بخش، وقتی یک request را تصور می‌کنیم، فقط یک فلش ساده از Pod به Service نمی‌بینیم؛ می‌دانیم پشت آن فلش چند مرحله واقعی وجود دارد.

بخش دوم: DNS و Service Discovery در کوبرنتیز

در بخش دوم، همان جمله ساده بخش اول را باز می‌کنیم: وقتی یک پاد اسم یک سرویس را صدا می‌زند، قبل از هر چیز باید بفهمیم این اسم چطور به یک مقصد قابل استفاده تبدیل می‌شود.

اینجا هنوز به kube-proxy، NAT و conntrack نرسیده‌ایم. فعلاً با لایه‌ای طرفیم که معمولاً بی‌صدا کار می‌کند، اما وقتی خراب شود خودش را با timeout، کندی‌های عجیب یا خطاهای مبهم نشان می‌دهد.

در این بخش مسیر DNS را از داخل پاد دنبال می‌کنیم؛ از فایل resolv.conf و رفتار resolver تا CoreDNS، رکوردهای سرویس، headless service، search domain، ndots، cache و NodeLocal DNSCache.
هدف این است که موقع خطایابی، قبل از اینکه سریع سراغ سرویس، endpoint یا ruleهای شبکه برویم، بدانیم آیا نام اصلاً درست و به‌موقع resolve شده یا نه.

بعد از پایان این مسیر چه یاد می‌گیری؟

در پایان این Learning Path باید بتوانیم با دید واقعی‌تر و نزدیک‌تر به production به این سؤال‌ها جواب بدهیم:

  • وقتی یک Pod به Pod دیگر وصل می‌شود، packet دقیقاً از کجا عبور می‌کند؟
  • وقتی یک Pod نام یک Service را resolve می‌کند، DNS دقیقاً چه کاری انجام می‌دهد؟
  • وقتی request به Service می‌رسد، backend چطور انتخاب می‌شود؟
  • چرا ClusterIP خودش endpoint واقعی نیست؟
  • kube-proxy دقیقاً چه چیزی را روی node تغییر می‌دهد؟
  • تفاوت iptables، nftables و IPVS در kube-proxy چیست؟
  • conntrack چه نقشی در NAT و Service traffic دارد؟
  • چرا یک connection قدیمی ممکن است همچنان به backend قبلی برود؟
  • NetworkPolicy دقیقاً کجا traffic را محدود می‌کند؟
  • مسیر traffic از بیرون cluster تا workload داخلی چطور است؟
  • source IP در کدام مسیرها حفظ می‌شود و کجا از بین می‌رود؟
  • Gateway API، Ingress، NodePort و LoadBalancer از نظر مسیر واقعی traffic چه تفاوتی دارند؟
  • موقع troubleshooting از کدام لایه باید شروع کرد و مرحله‌به‌مرحله چه چیزهایی را باید چک کرد؟

نتیجه

Kubernetes networking از آن موضوع‌هایی است که اگر فقط در حد manifest یاد گرفته شود، خیلی زود دردسرساز می‌شود.

تا وقتی همه‌چیز درست کار می‌کند، شاید لازم نباشد بدانیم packet از کجا عبور کرده. اما وقتی یک Service جواب نمی‌دهد، یک backend اشتباه انتخاب می‌شود، DNS درست resolve می‌شود ولی connection برقرار نمی‌شود، یا traffic ورودی از Gateway به workload نمی‌رسد، آن‌وقت همین جزئیات تعیین‌کننده می‌شوند.

این Learning Path قرار است همین فاصله را پر کند؛ فاصله بین «من Service ساختم» تا «می‌دانم packet واقعاً چه مسیری را طی کرده است».