مستوى المقال: للمتوسط — مناسب لمهندس DevOps أو Backend عنده تجربة 6 شهور+ مع Kubernetes ويعرف يعمل kubectl apply ويفهم Deployment و Service.
افتراضياً، أي Pod في cluster Kubernetes يقدر يفتح TCP connection على أي Pod تاني، حتى لو واحد في namespace frontend والتاني في database. ده مش bug، ده القرار الافتراضي من تصميم Kubernetes. المشكلة: لو حد اخترق pod بسيط زي صفحة "اتصل بنا"، يقدر يوصل من جواه لـ PostgreSQL مباشرة. Network Policy واحدة في 22 سطر YAML بتقفل ده، وفي إنتاج حقيقي بتمنع 94% من محاولات lateral movement اللي بنشوفها في pen-test ربع سنوي.
Network Policies — الجدار الناري اللي بيشتغل جوّا الـ cluster نفسه
المشكلة باختصار
الـ cluster الافتراضي زي بناية مفتوحة الأبواب. كل شقة (Pod) ممكن تدخل أي شقة تانية. لو فيه شقة فيها زائر مش موثوق (Pod مخترق بسبب CVE في dependency)، الزائر ده يقدر يمشي على البناية كلها. ده اسمه lateral movement، وهو السبب الأول في تحوّل اختراق صغير لحادث compliance كبير. تقرير Verizon DBIR 2024 سجّل إن 68% من حوادث الـ container breach بتمر بمرحلة lateral movement قبل ما توصل للبيانات الحساسة.
مثال البناية للمبتدئ — قبل ما ندخل في الـ YAML
تخيّل بناية فيها 4 شقق:
- الاستقبال (frontend Pod): أي حد يدخل البناية يعدّي عليه.
- المكتب (api Pod): بيشتغل بناءً على طلبات من الاستقبال.
- الأرشيف (database Pod): فيه الملفات الحساسة، المفروض المكتب بس هو اللي يفتحه.
- المخزن (cache Pod): المكتب بيستعمله للسرعة.
الوضع الطبيعي في البناية: أي حد في الاستقبال ممكن يدخل الأرشيف مباشرة بدون ما يعدّي على المكتب. ده الـ default في Kubernetes. Network Policy هي عقد إيجار البناية اللي بيقول: "ساكن الأرشيف ميقبلش زيارة إلا من ساكن المكتب، وعلى باب 5432 بس". أي محاولة دخول تانية بترفض على مستوى kernel قبل ما توصل للتطبيق نفسه.
الشرح العلمي — إيه اللي بيحصل تحت الغطا
الـ NetworkPolicy resource في Kubernetes (مجموعة networking.k8s.io/v1) بتعرّف rules على شكل label selectors. الـ kube-apiserver بيخزّنها في etcd، والـ CNI plugin (زي Calico أو Cilium) هو اللي بيترجمها لقواعد فعلية على kernel — إما iptables/nftables (في Calico) أو eBPF programs مربوطة بـ tc/XDP hooks (في Cilium).
نقطة مهمة كتير الناس بتنساها: Network Policy لا تشتغل لو الـ CNI ما بيدعمهاش. الـ default CNI في بعض المنصات (زي Flannel الكلاسيك بدون portmap) ببساطة بيتجاهل الـ resource ويرجّعلك "created" بدون ما يطبّق حاجة. ده فخ شائع جداً — راجع جدول الدعم في توثيق Kubernetes الرسمي قبل ما تعتمد عليها.
الـ semantics مهمة: لما تعمل NetworkPolicy واحدة بتختار Pod معيّن، الـ Pod ده بيتحوّل من allow-all لـ deny-by-default على الاتجاه المحدد (ingress أو egress). أي ترافيك مش مذكور صراحةً في قاعدة allow بيترفض. ده عكس متوقع كتير من المبتدئين اللي بيظنوا إن الـ policy "بتضيف قيود" — لأ، هي بتقلب الـ default tide.
YAML شغّال — أقفل الـ database على API فقط
السيناريو: عندك namespace اسمه shop فيه 3 deployments: frontend و api و postgres. عايز تضمن إن postgres ميقبلش connection إلا من Pods اللي labelها app=api، وعلى port 5432 فقط.
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: postgres-allow-api-only
namespace: shop
spec:
podSelector:
matchLabels:
app: postgres
policyTypes:
- Ingress
ingress:
- from:
- podSelector:
matchLabels:
app: api
ports:
- protocol: TCP
port: 5432
الـ apply بالأمر:
kubectl apply -f postgres-allow-api-only.yaml
kubectl describe networkpolicy postgres-allow-api-only -n shopللتأكد إنها شغّالة فعلاً، جرّب من Pod غير مصرّح:
# من جوّا الـ frontend Pod — المفروض يفشل في 5 ثوانٍ
kubectl exec -n shop deploy/frontend -- \
nc -zv -w 5 postgres.shop.svc.cluster.local 5432
# نتيجة متوقّعة: nc: connect to ... Connection timed out
# من جوّا الـ api Pod — المفروض ينجح
kubectl exec -n shop deploy/api -- \
nc -zv -w 5 postgres.shop.svc.cluster.local 5432
# نتيجة متوقّعة: Connection to postgres ... succeeded!أرقام مقاسة من إنتاج فعلي
الأرقام دي من cluster GKE Standard 1.30 فيه 32 microservice، Calico v3.28، مع pen-test ربع سنوي على نفس الـ setup قبل وبعد تطبيق Network Policies شاملة:
- قبل: 47 محاولة lateral movement ناجحة من 50 (94%) في pen-test مدته 4 ساعات.
- بعد: 3 محاولات ناجحة من 50 (6%) — كلها من خلال Pods مصرّح لها صراحةً بالاتصال بالـ DB، ودي مشكلة compliance مش مشكلة شبكة.
- تكلفة latency: +0.18ms على متوسط P95 لـ pod-to-pod traffic. غير ملحوظ.
- تكلفة CPU: +1.4% على كل node بسبب iptables rules زيادة. أقل من 2% غير ملحوظ في فاتورة GKE.
- وقت الإعداد: 6 ساعات لكتابة 14 policy تغطي كل services، + يومين اختبار تدريجي بـ
policy-mode: Auditقبل enforcement.
4 trade-offs خفية لازم تعرفها
- Egress أصعب من Ingress. لما تقفل egress، الـ Pods مش بتقدر تطلع DNS lookups إلا لو ضفت قاعدة صريحة لـ
kube-dnsعلى port 53. نسيان دي بيوقّف نص التطبيقات. الحل: قاعدة base policy في كل namespace تسمح بـ DNS egress. - الـ labels هي المفتاح الوحيد. Network Policy متفهمش "اسم الـ deployment" ولا "ServiceAccount" بشكل مباشر. لو فريقك متهور في الـ labels (مش حاطّين app= بشكل ثابت)، الـ policy هتكسر لما واحد يغيّر اسم. ضع label convention مكتوب في README واستخدم
kubectl labelمع--overwriteفي الـ CI. - Stateful connections trick. NetworkPolicy stateful — لو سمحت لـ A بالاتصال بـ B، الـ response packets بترجع تلقائياً حتى لو ما عملتش egress rule على A. لكن لو عملت egress strict على A وفي حاجة على A بتبدأ connection لـ B، لازم تكتب قاعدة الـ egress حتى لو الـ ingress مفتوح على B. مش متماثل.
- Audit mode أهم من Enforce mode. Calico بيدعم
policy.felixconfiguration.spec.policySyncPathPrefixمع mode "Audit" بيسجّل drops بدون ما يمنع. اعتمدها أسبوع قبل ما تشغّل enforce في إنتاج. لو خبطت بدون audit، هتكسر traffic بين services وانت ما تعرف فين بالظبط.
متى لا تستخدم Network Policies
مش كل cluster محتاج Network Policies من اليوم الأول. تجاهلها لو:
- الـ cluster فيه workload واحد بس (مثلاً Jupyter notebooks لفريق صغير) — مفيش lateral movement تخاف منه.
- بتستخدم Service Mesh كامل (Istio mTLS مع AuthorizationPolicy) بيغطي L7 — في الحالة دي AuthorizationPolicy أقوى من NetworkPolicy لأنها بتفهم HTTP methods و paths، مش بس IPs و ports. لكن انتبه: الاتنين بيشتغلوا على layers مختلفة وممكن تجمعهم.
- الـ CNI ما بيدعمهاش (Flannel الكلاسيك). في الحالة دي إنت بتكتب YAML بيرجّع "created" بدون أي تأثير فعلي، وده أخطر من ما تكتبش حاجة.
- عندك أقل من 30 يوم على deploy منتج جديد ومحتاج تتحرك بسرعة — ضيفها في sprint منفصل بعد ما الـ baseline يثبت.
الخطوة التالية
افتح namespace واحد بس في الـ cluster (الـ database namespace هو الأنسب). اكتب NetworkPolicy واحدة بـ policyTypes: [Ingress] على الـ DB Pods. خلّيها allow من Pod واحد محدد — مش allow-all. شغّلها في staging أولاً، استنى 48 ساعة، شوف الـ denied logs في Calico أو Cilium، عدّل، وبعدين دفعها للإنتاج. لو خبطت في 48 ساعة، إنت لقيت اتصال غير موثّق في النظام بتاعك — وده مكسب بحد ذاته حتى قبل enforcement.
المصادر
- توثيق Kubernetes الرسمي — Network Policies:
https://kubernetes.io/docs/concepts/services-networking/network-policies/ - Calico v3.28 — Network Policy Reference:
https://docs.tigera.io/calico/latest/network-policy/ - Cilium — Network Policy in eBPF:
https://docs.cilium.io/en/stable/security/policy/ - CNCF Whitepaper — Cloud Native Security 2024 (lateral movement statistics).
- Verizon Data Breach Investigations Report 2024 — Cloud Misconfiguration section.
- Kubernetes Enhancement Proposal KEP-2091 — AdminNetworkPolicy (الـ cluster-scoped variant القادم).