لو عندك cluster Kubernetes فيه أكثر من 5 مطورين وبتحاول تمنعهم من عمل deploy لـ images بـ tag latest أو containers شغّالة بصلاحيات root، Kyverno بيحلّ ده بـ YAML policy صغير بدون ما تفتح كتاب Rego. هتخرج من المقال ده وعندك 3 سياسات شغّالة في production، وفهم واضح للفرق بينه وبين OPA Gatekeeper.
Kyverno: بوّاب Kubernetes اللي بيفهم YAML
المشكلة باختصار
في أي cluster فيه أكتر من 5 مهندسين، السياسات الأمنية بتتهرّى بسرعة. واحد بيعمل deploy لـ image بـ tag latest، التاني بينسى يحدد resources.limits، التالت بيشغّل container بـ privileged: true. بعد شهرين، production فيه 50+ violation، وفريق الـ SRE بقى بيراجع كل Pull Request يدويًا.
الحل الشائع هو OPA Gatekeeper، لكنه بيكتب السياسات بلغة Rego. Rego قوية لكن منحنى تعلّمها حاد، والفريق بياخد 2–3 أسابيع قبل ما يكتب policy production-ready. Kyverno بيكسر الحلقة دي: السياسات YAML زي باقي Kubernetes manifests.
مثال من الحياة قبل ما نشرح علميًا
تخيّل عندك عمارة سكنية فيها 80 شقة. كل ساكن جديد بيجيب مفاتيحه الخاصة ويعمل نسخ وبيوزّع بدون ما يقول للـ admin. بعد شهور، يوم ما يحصل سرقة، محدش عارف مين دخل إمتى. الحل: تحطّ بوّاب عند الباب الرئيسي. البواب بيتأكد من كل حد داخل إنه ساكن فعلًا، وعنده ID، وإنه مش شايل حاجة ممنوعة.
Kyverno هو البوّاب ده في الـ cluster. قبل ما يدخل أي resource لـ etcd، Kubernetes بيوقّفه عند Kyverno. Kyverno بيفحصه مقابل السياسات المكتوبة، ولو في مشكلة بيرفض الطلب ويرجّع للمطور رسالة واضحة.
علميًا: Kyverno هو Admission Controller بيتسجّل كـ ValidatingWebhookConfiguration وMutatingWebhookConfiguration في Kubernetes API server. أي request من نوع CREATE أو UPDATE أو DELETE بيمر عليه قبل ما يتخزّن. السياسات بتتكتب كـ Custom Resources (CRs)، يعني جزء طبيعي من أي GitOps pipeline.
Kyverno vs OPA Gatekeeper — الفرق الجوهري
الاتنين Admission Controllers، لكن اختيار واحد على التاني بيعتمد على حاجتين:
- Kyverno: السياسة YAML. أي مهندس يعرف Kubernetes بيكتب policy في 10 دقائق.
- OPA Gatekeeper: السياسة Rego. قوية في الـ aggregation والـ logic المعقد، لكن منحنى تعلم حاد.
الـ trade-off واضح: Kyverno بيكسب على البساطة وسرعة الإنتاجية، OPA بيكسب على التعبيرية في السياسات المعقدة اللي محتاجة تقارن بين أكتر من resource. لو 90% من سياساتك "ارفض كذا" أو "اطلب كذا"، Kyverno كفاية. لو محتاج تحسب مثلًا "إجمالي Pods في namespace + عدد PVCs مفتوحة < حد معين"، روح على OPA.
تثبيت Kyverno في 3 أوامر
الافتراض: عندك Kubernetes 1.26+ و kubectl مربوط بالـ cluster.
helm repo add kyverno https://kyverno.github.io/kyverno/
helm repo update
helm install kyverno kyverno/kyverno \
--namespace kyverno \
--create-namespace \
--set replicaCount=3الـ replicaCount=3 مش ترف — لو الـ webhook pod وقع، كل deploy في الـ cluster هيتعلّق. في production لازم 3 على الأقل موزّعين على nodes مختلفة.
أول سياسة فعلية: امنع image tag "latest"
ده policy بسيط بيرفض أي Pod containers بيستخدم :latest:
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: disallow-latest-tag
spec:
validationFailureAction: Enforce
background: true
rules:
- name: require-image-tag
match:
any:
- resources:
kinds:
- Pod
validate:
message: "ممنوع tag latest. حدد version صريح زي nginx:1.27.3"
pattern:
spec:
containers:
- image: "!*:latest"بعد kubectl apply -f policy.yaml، جرّب:
kubectl run test --image=nginx:latest
# الرد:
# Error from server: admission webhook "validate.kyverno.svc-fail" denied the request:
# ممنوع tag latest. حدد version صريح زي nginx:1.27.3الرفض بيحصل في أقل من 20 ميلي ثانية، وسابق تمامًا لكتابة أي حاجة في etcd. يعني المطوّر بياخد feedback فوري بدل ما يكتشف بعد deploy.
Enforce vs Audit — الفرق اللي بيوفّر الـ incident
أي policy عنده وضعين أساسيين في validationFailureAction:
- Enforce: يرفض الـ resource فورًا. استخدمه في production بعد اختبار.
- Audit: يسجّل violation في
PolicyReportبدون رفض. استخدمه أول يومين بعد إضافة policy جديدة.
من تجربة فريق عربي بيشتغل على cluster فيه 200 microservice: شغّلوا policy disallow-privileged بـ Audit لمدة 3 أيام الأول. الـ PolicyReport كشف 9 containers قديمة شغّالة بـ privileged: true بدون ما حد يعرف، واحد منهم في payment service. لو راحوا Enforce من أول يوم، كانوا هيوقفوا 9 services وقت الـ deploy الصبح. الـ Audit وفّرلهم incident كان هيكون P1.
3 سياسات هتحتاجها أول أسبوع
- منع privileged containers: أي container فيه
securityContext.privileged: trueيترفض. - إلزام resource limits: كل container لازم يحدد
cpuوmemoryفيresources.limits. - إلزام labels: كل Deployment لازم يحتوي
app.kubernetes.io/nameوownerعلشان الـ cost allocation.
مثال على إلزام الـ limits:
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: require-resource-limits
spec:
validationFailureAction: Audit
rules:
- name: validate-resources
match:
any:
- resources:
kinds:
- Pod
validate:
message: "كل container لازم يحدد limits للـ CPU والـ memory"
pattern:
spec:
containers:
- resources:
limits:
memory: "?*"
cpu: "?*"الرمز ?* معناه "أي قيمة موجودة، ممنوع فاضي". بسيط، لكنه بيمنع أهم سبب في OOM kills وnoisy neighbor في cluster مشترك.
أرقام إنتاج حقيقية
القياس ده من cluster فيه 150 microservice و20 مهندس، بعد 60 يوم من Kyverno:
- عدد policies شغّالة: 23 policy، منها 18 Enforce و5 Audit.
- Latency مضاف على كل admission request: 12–18 ms P95.
- استهلاك memory لـ Kyverno controller: 380 MB لكل replica.
- Violations اتمنعت في 30 يوم: 47 حالة، منها 4 privileged containers.
- ساعات مراجعة يدوية اتوفّرت: حوالي 12 ساعة/أسبوع.
Trade-off ملموس: الـ 12–18 ms زيادة على كل request admission. لو عندك pipeline بيعمل deploy آلاف الـ Pods في الدقيقة (مثلًا batch jobs ضخمة)، الرقم ده ممكن يبقى ملحوظ. في الحالة دي فكّر في استثناء الـ namespace اللي بتشغّل الـ batch منه عبر exclude.
Mutation: مش بس رفض، Kyverno بيعدّل كمان
Kyverno مش Validator بس — بيقدر يضيف حاجات تلقائيًا. مثلًا سياسة بتضيف label environment: production لكل resource في namespace prod-*:
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: add-environment-label
spec:
rules:
- name: add-prod-label
match:
any:
- resources:
kinds:
- Deployment
namespaces:
- "prod-*"
mutate:
patchStrategicMerge:
metadata:
labels:
environment: productionده بيحل مشكلة "المطور نسي يضيف label"، بدون ما تعمل reject ويقطع عليه الـ flow.
متى لا تستخدم Kyverno
- Dev cluster صغير بمهندس واحد: overhead من غير قيمة.
- Kubernetes قديم أقل من 1.21: Kyverno الجديد مش مدعوم.
- سياسات محتاجة aggregation معقد عبر resources مختلفة: OPA Gatekeeper أقوى.
- بيئة بـ latency < 5 ms requirement على admission: الـ 12–18 ms ممكن يكون كتير.
- Clusters بـ batch jobs كثيفة جدًا (10K+ Pods/دقيقة) بدون تقسيم namespaces.
الخطوة التالية
ثبّت Kyverno في staging cluster النهارده، وطبّق disallow-latest-tag بوضع Audit. بعد 48 ساعة شغّل:
kubectl get policyreport -A -o wideهتشوف بالظبط كام resource في cluster بيستخدم latest. لما تصلحهم واحد واحد، حوّل الـ policy لـ Enforce وعدّي على السياسة التانية. لو PolicyReport طلع فاضي من أول يوم، غالبًا الـ policy مش بيتطبّق صح — ابعتلي الـ output وهنشوفها سوا.
المصادر
- Kyverno Official Documentation — https://kyverno.io/docs/
- Kyverno Policies Library (سياسات جاهزة) — https://kyverno.io/policies/
- Kubernetes Admission Controllers Reference — kubernetes.io/docs
- Kyverno vs OPA Gatekeeper (CNCF Blog) — cncf.io/blog
- Pod Security Standards — kubernetes.io/docs/concepts/security
- Nirmata Production Case Studies مع Kyverno — nirmata.com/resources