شبكات Kubernetes والتخزين

نموذج شبكات كوبرنيتيس

18 دقيقة الدرس 1 من 31

نموذج شبكات كوبرنيتيس

قبل أن تتمكن من فهم الخدمات (Services) أو Ingress أو سياسات الشبكة (NetworkPolicies)، يجب أن تستوعب العقد الأساسي الذي يضمنه كوبرنيتيس فيما يخص الشبكات — وهو نموذج شبكات كوبرنيتيس. كل مفهوم شبكي متقدم في هذا الدرس يُبنى على هذا الأساس، وكل حادثة إنتاج ستقوم بتشخيصها تعود في النهاية إلى مدى التزام الكلستر بهذا النموذج.

الضمانات الثلاث الأساسية

تُلزم مواصفات كوبرنيتيس بثلاثة ضمانات شبكية يجب أن يفي بها أي كلستر متوافق، بصرف النظر عن مزود الخدمة السحابية أو إضافة CNI أو البنية التحتية:

  1. كل Pod يحصل على عنوان IP فريد خاص به. لا يتشارك أي بودَّان قيد التشغيل في الكلستر — حتى على عقد مختلفة — في نفس العنوان. الـPod هو أصغر وحدة يمكن عنونتها، وليس الحاوية.
  2. يمكن للـPods على أي عقدة التواصل مباشرةً مع أي Pod على أي عقدة أخرى، دون NAT. حزمة مُرسَلة من Pod A (10.244.1.5) إلى Pod B (10.244.3.8) تصل إلى Pod B وعنوان المصدر لا يزال 10.244.1.5. لا يوجد تمويه للعناوين، ولا تعيين للمنافذ، ولا ترجمة بواسطة وسيط.
  3. الوكلاء على العقدة (مثل kubelet، والشياطين النظامية) يمكنهم التواصل مع كل Pod على تلك العقدة.

ما لا يُلزم به النموذج عمداً: آلية التنفيذ. التنفيذ مُفوَّض إلى إضافة واجهة شبكة الحاوية (CNI) المثبتة في كلسترك. هذا الفصل بين العقد والتنفيذ هو السبب الجوهري في أن نفس ملفات YAML تعمل على AWS وGCP والأجهزة المادية والحاسوب المحلي — العقد قابلة للنقل حتى لو كانت الأسلاك تحتها مختلفة تماماً.

لماذا بدون NAT؟ في مراكز البيانات التقليدية القائمة على الأجهزة الافتراضية، تتواصل الأجهزة عبر بوابات NAT ويُعاد كتابة عنوان المصدر عند الحدود. في كوبرنيتيس، تحتاج الـPods إلى معرفة عنوان IP الحقيقي للمُرسِل — لضبط التحكم في الوصول، وللتسجيل، وللتتبع. NAT سيجعل ذلك مستحيلاً دون حلول بديلة على مستوى التطبيق. نموذج الشبكة المسطحة بدون NAT هو قرار تصميمي مقصود يجعل الأنظمة الموزعة أسهل في الفهم.

ما يعنيه "الشبكة المسطحة" عملياً

يأتي كل عنوان IP للـPod من نطاق Pod CIDR للكلستر كاملاً. في كلستر kubeadm نموذجي يكون هذا 10.244.0.0/16؛ وفي GKE قد يكون 10.4.0.0/14. تُخصص مستوى التحكم شبكة فرعية من هذا النطاق لكل عقدة — لنقل 10.244.1.0/24 للعقدة الأولى و10.244.2.0/24 للعقدة الثانية. يحصل الـPods المجدولة على تلك العقدة على عناوين IP من شبكتها الفرعية.

حتى يتمكن بودَّان على عقدتين مختلفتين من التواصل بدون NAT، يجب أن تضمن إضافة CNI أن حزمة مُوجَّهة إلى 10.244.2.5 — الموجودة على العقدة الثانية — تصل فعلاً إلى العقدة الثانية حتى لو أنشئت على العقدة الأولى. للـCNI عدة استراتيجيات لتحقيق ذلك: شبكات التراكب (أنفاق VXLAN)، أو الإعلان عن المسارات عبر BGP، أو حقن مسارات المضيف، أو واجهات برمجة تطبيقات توجيه VPC لمزود الخدمة السحابية. النتيجة دائماً هي نفس فضاء العناوين المسطح؛ فقط الأنابيب تختلف.

Kubernetes flat Pod network: every Pod has a unique routable IP across all nodes Cluster Pod CIDR: 10.244.0.0/16 Node 1 Subnet: 10.244.1.0/24 Pod A 10.244.1.4 Pod B 10.244.1.5 veth pairs → cni0 bridge → eth0 (node NIC) Node 2 Subnet: 10.244.2.0/24 Pod C 10.244.2.3 Pod D 10.244.2.7 veth pairs → cni0 bridge → eth0 (node NIC) Node 3 Subnet: 10.244.3.0/24 Pod E 10.244.3.2 Pod F 10.244.3.9 veth pairs → cni0 bridge → eth0 (node NIC) no NAT no NAT All Pod IPs are unique and directly routable across all nodes — implemented by the CNI plugin
الشبكة المسطحة للـPod في كوبرنيتيس: تحتل كل عقدة شبكة فرعية من CIDR الكلستر، ويتواصل الـPods عبر العقد بدون NAT.

إضافات CNI: منفذو العقد

واجهة شبكة الحاوية (CNI) هي مواصفة وليست منتجاً. عند جدولة Pod على عقدة، تستدعي kubelet ملف إضافة CNI الثنائي — مُمررةً مسار مساحة اسم الشبكة للحاوية والإعداد — وتقوم الإضافة بتوصيل الشبكة. عند حذف الـPod تُستدعى مجدداً للتنظيف. يجب أن تفي الإضافة بضمانات النموذج؛ وكيفية القيام بذلك متروكة كلياً لها.

أبرز إضافات CNI في الكلسترات الإنتاجية، وكيفية تنفيذها للشبكة المسطحة:

  • Flannel — الخيار الأبسط. تُنشئ شبكة تراكب VXLAN: يُغلَّف الحركة بين العقد في حزم UDP تُنقل عبر الشبكة الفيزيائية. تعقيد تشغيلي منخفض، مع عقوبة أداء معتدلة بسبب التغليف. شائع في المختبرات المحلية والكلسترات الصغيرة.
  • Calico — يستخدم BGP للإعلان عن مسارات الشبكة الفرعية للـPod بين العقد. لا تغليف في الوضع الافتراضي — توجيه IP خالص. أداء أعلى بكثير من شبكات التراكب. الأكثر انتشاراً لتطبيق NetworkPolicy في بيئات المؤسسات.
  • Cilium — يستخدم برامج eBPF في النواة لتنفيذ التوجيه وموازنة التحميل وتطبيق الأمان. يستبدل kube-proxy كلياً. أفضل رؤية مراقبة (Hubble)، أفضل أداء على نطاق واسع، دعم أصلي لسياسات الشبكة L7. هذا ما تشغّله Google وMeta داخلياً.
  • AWS VPC CNI — على EKS، يحصل كل Pod على عنوان IP ثانوي حقيقي من AWS VPC ENI. لا تغليف: عناوين IP للـPod قابلة للتوجيه أصلاً داخل VPC. يبقى حركة Pod-to-pod في بنية VPC بسرعة خط. التنازل: استنفاد عناوين IP — لكل عقدة حد صارم من ENIs وعناوين IP لكل ENI.
  • Azure CNI / GKE Dataplane V2 — مكافئات خاصة بالسحابة لـAWS VPC CNI، تستخدم بنى VPC الخاصة بها.
الافتراضي في الإنتاج: في الكلسترات السحابية المُدارة (EKS, GKE, AKS) تكون إضافة CNI السحابية هي الافتراضية والاختيار الصحيح — إذ توفر توجيه VPC الأصلي بدون تكاليف إضافية. على الأجهزة المادية أو المحلية، Calico مع BGP هو الافتراضي الهندسي السليم للكلسترات التي تتجاوز 50 عقدة. Flannel أداة مختبر وليست للإنتاج.

فحص نموذج الشبكة من داخل الكلستر

عند الانضمام إلى كلستر جديد أو تشخيص مشكلة شبكية، تتمثل الخطوة الأولى في التحقق من أن النموذج يعمل بشكل صحيح. هذه الأوامر تُؤكد الأساسيات:

# 1. تأكيد CIDR الـPod المخصص لكل عقدة kubectl get nodes -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.spec.podCIDR}{"\n"}{end}' # الناتج المتوقع: # node-1 10.244.1.0/24 # node-2 10.244.2.0/24 # node-3 10.244.3.0/24 # 2. رؤية جميع عناوين IP للـPod والعقدة التي توجد عليها kubectl get pods -A -o wide # 3. تحديد إضافة CNI المثبتة kubectl -n kube-system get pods | grep -E 'calico|cilium|flannel|weave|aws-node' ls /etc/cni/net.d/ # ملفات إعداد CNI على أي عقدة (يتطلب وصولاً للعقدة) # 4. التحقق من الاتصال بين الـPods عبر العقد مباشرةً # نشر بود للتشخيص ثم إرسال ping لبود على عقدة مختلفة: kubectl run netcheck --image=nicolaka/netshoot --restart=Never -- sleep 3600 kubectl exec netcheck -- ping -c 3 <pod-ip-on-another-node> # التأكد من عدم وجود NAT: يجب أن يكون عنوان IP المصدر المُرى في البود الهدف هو IP بود المُرسِل kubectl exec <target-pod> -- tcpdump -n -i eth0 icmp

مساحة اسم شبكة الـPod

لكل Pod مساحة اسم شبكة Linux خاصة به: رؤية معزولة تماماً من واجهات الشبكة وجداول التوجيه وقواعد الجدار الناري. تُنشئ إضافة CNI زوج veth — كابل Ethernet افتراضي — حيث يعيش أحد طرفيه (eth0) داخل مساحة اسم الـPod والطرف الآخر على المضيف، مُوصَّلاً بجسر (عادةً cni0) أو مُبرمَج مباشرةً في جدول التوجيه. الحاويات داخل نفس الـPod تشارك تلك المساحة، وهذا هو سبب تواصلها عبر localhost وإمكانية تعارضها على المنافذ — إذ تشترك فعلاً في مكدس شبكة واحد.

Pod network namespace, veth pair, and bridge wiring on a single node Node (Host Network Namespace) Pod A Namespace Container 1 Container 2 eth0 (10.244.1.4) veth pair Pod B Namespace Container 1 Container 2 eth0 (10.244.1.5) veth pair cni0 bridge (host) eth0 (node NIC) → Physical Network ← shared via localhost → * حاوية "pause" تحمل مساحة اسم الشبكة. حاويات التطبيق تنضم إليها.
الحاويات داخل الـPod تشترك في مساحة اسم شبكة واحدة (IP واحد، جدول توجيه واحد). تقوم إضافة CNI بتوصيل زوج veth من eth0 داخل مساحة الاسم إلى الجسر على المضيف ثم إلى الشبكة الفيزيائية.

فحص الأسلاك على العقدة

عندما يعطل شبكة Pod، تحتاج إلى النزول إلى العقدة للتحقق من الأسلاك. الأوامر التالية تمنحك رؤية كاملة لما وصّلته إضافة CNI:

# فتح جلسة تشخيص ذات امتيازات على عقدة (استبدل node-name) kubectl debug node/node-1 -it --image=nicolaka/netshoot # داخل بود التشخيص — نظام الملفات الجذري للعقدة في /host # عرض إعداد CNI الذي مُنح للإضافة: cat /host/etc/cni/net.d/10-flannel.conflist # سرد كل أزواج veth: كل Pod قيد التشغيل يجب أن يملك واحداً ip link show type veth # فحص الجسر bridge link show # رؤية جدول التوجيه الكامل — يجب أن يكون لكل شبكة Pod فرعية مسار ip route # التأكد من إمكانية الوصول لعنوان IP للـPod من العقدة ping -c 2 10.244.1.4 # الحصول على مساحة اسم الشبكة لحاوية معينة (تُشغَّل على العقدة) # أولاً ابحث عن معرف الحاوية: crictl ps | grep <pod-name> # ثم افحص مساحة اسم شبكتها: crictl inspect <container-id> | grep -i netns # ادخل مساحة اسم الشبكة للـPod: nsenter --net=/var/run/netns/<ns-id> ip addr
حالة فشل في الإنتاج — نفاد عناوين IP: على AWS EKS مع VPC CNI، كل Pod يستهلك عنوان IP حقيقياً من VPC من ENI الخاص بالعقدة. لأنواع الأجهزة حدود صارمة (مثلاً m5.large تدعم 3 ENIs × 10 عناوين IP = 30 عنوان Pod IP كحد أقصى، مطروحاً منها عنوان IP للعقدة نفسها). سيفشل الجدولة بصمت مع الرسالة 0/3 nodes available: 3 Insufficient pods عند الوصول لهذا الحد. راقب kubectl describe nodeAllocatable.pods مقابل Non-terminated Pods. الحل: استخدام أنواع أجهزة أكبر، تفعيل prefix delegation (ENABLE_PREFIX_DELEGATION=true على VPC CNI)، أو الانتقال لإضافة CNI تدعم CIDRs الثانوية.

لماذا يهم هذا لكل ما يليه

كل بنية شبكية رفيعة المستوى في كوبرنيتيس تفترض وجود النموذج المسطح. ClusterIP للخدمة هو عنوان IP افتراضي يستخدمه kube-proxy لتحويل الحزم إلى عناوين IP حقيقية للـPod — يعمل فقط لأن عناوين IP للـPod قابلة للتوجيه مباشرةً. تُطبَّق سياسات NetworkPolicy بواسطة إضافة CNI على مستوى Pod-to-pod — توجد فقط لأن هناك طبقة pod-to-pod لتطبيق القواعد عليها. وحدات التحكم في Ingress توجه الحركة إلى نقاط نهاية الـPod — مباشرةً، بدون NAT. اكتشاف الخدمة المستند إلى DNS يُعيد عناوين IP للـPod — وهي ذات معنى فقط لأن تلك العناوين يمكن الوصول إليها عالمياً.

عند مواجهة خدمة معطوبة، أو سياسة NetworkPolicy لا تُطبَّق، أو Ingress يُعيد 502، السؤال الأول دائماً هو: هل يمكن للـPod A الوصول إلى Pod B مباشرةً؟ إذا كانت الإجابة لا، فإن CNI معطوب ولن يعمل أي شيء فوقه. ابدأ من أسفل المكدس.

ES
Edrees Salih
منذ ساعة

We are still cooking the magic in the way!