أنماط تعدد المستأجرين في Kubernetes
أنماط تعدد المستأجرين في Kubernetes
تعدد المستأجرين هو ممارسة تشغيل أعباء عمل لفِرق أو منتجات أو عملاء متعددين على بنية تحتية Kubernetes مشتركة. عند تنفيذه بشكل صحيح، يُقلّص التكاليف والأعباء التشغيلية بشكل ملحوظ. أما عند تنفيذه بشكل خاطئ، فيُفضي إلى مشكلات "نطاق الانفجار" حيث يُعطّل الجار المزعج اتفاقية مستوى الخدمة، أو يتجاوز pod مُهيّأ بشكل خاطئ حدوده المفروضة. يدرس هذا الدرس مستويات العزل الثلاثة المستخدمة في بيئات الإنتاج، والعناصر الأساسية لمساحات الأسماء التي تُطبّقها، والدروس الصعبة التي تعلّمتها فِرق منصات كبرى من تشغيل كلاسترات مشتركة على نطاق واسع.
طيف العزل: مساحات الأسماء مقابل الكلاسترات
يمتد تعدد المستأجرين في Kubernetes على طيف بين طرفين:
- تعدد المستأجرين الخفيف (مساحة أسماء لكل مستأجر): يشترك عدة مستأجرين في كلاستر واحد، مفصولين بمساحات الأسماء وRBAC وNetworkPolicies وحصص الموارد. يُشارَك النواة وبيئة تشغيل الحاويات ومستوى التحكم. هذا هو النموذج الافتراضي لدى معظم فِرق المنصات في كبريات شركات التقنية للمستأجرين الداخليين (فِرق المنتجات) الموثوقين والذين يجب عزلهم عن بعضهم لأغراض تخصيص التكاليف ونطاق الانفجار وسياسة الأمان.
- تعدد المستأجرين الصارم (كلاستر لكل مستأجر): يحصل كل مستأجر على كلاستر مخصص — أو على أقل تقدير مجموعة عقد مخصصة مع محددات عقد صارمة. يُستخدم عندما يكون المستأجرون عملاء خارجيين، أو تختلف نطاقات الامتثال (مثل PCI مقابل غير-PCI)، أو يكون نطاق الانفجار الناجم عن ثغرة نواة غير مقبول. التكلفة هي التشغيل: N كلاستر يُضاعف عبء الترقية ودوران الشهادات والمراقبة بمقدار N.
- الكلاسترات الافتراضية (vcluster): حل وسط — خادم Kubernetes API كامل الوظائف يعمل داخل مساحة أسماء من كلاستر مضيف، مع etcd خاص به ومستوى تحكم خاص، لكنه يشترك في مجموعة عقد المضيف. تعمل أحمال العمل كـ pods اعتيادية على عقد المضيف. يرى المستأجرون كلاستر حقيقياً؛ فِرقة المنصة تُدير مجموعة عقد واحدة.
مساحات الأسماء: أساس تعدد المستأجرين الخفيف
مساحة الأسماء في Kubernetes هي قسم منطقي من مخزن كائنات خادم API. معظم الموارد ذات النطاق المحدد بمساحة الأسماء (Pods وServices وConfigMaps وSecrets وDeployments وServiceAccounts) مُقيّدة بمساحة أسماء؛ وقليل منها ذو نطاق عنقودي (Nodes وPersistentVolumes وClusterRoles وStorageClasses). لا توفر مساحات الأسماء بمفردها أي عزل للشبكة أو أي عزل للموارد — فهي آلية وضع علامات ونطاق RBAC فحسب. تُضاف عناصر التطبيق فوقها.
ResourceQuotas: حدود صارمة على استهلاك مساحة الأسماء
يُطبّق كائن ResourceQuota حدوداً إجمالية على مساحة أسماء. بمجرد تعيين الحصة، يجب أن يحتوي كل Pod جديد على requests وlimits صريحة — وإلا رفض webhook القبول أي Pod يُهمل تعريفها. هذا مقصود: يمنع الفِرق من استنزاف الكلاستر عن طريق نشر أحمال عمل بلا حصص.
LimitRanges: الافتراضيات لكل Pod وكل حاوية
تُطبّق الحصص الإجماليات الكلية. تُطبّق كائنات LimitRange حدوداً لكل مورد — الحد الأدنى والأقصى والقيم الافتراضية التي تُطبَّق تلقائياً حين لا تحدد حاوية قيودها الخاصة. بدون LimitRange افتراضي، فِريق ينسى تعيين requests/limits سيفشل عند قبول الحصة مع أخطاء محيّرة. مع الافتراضي، تُحقن حدود معقولة تلقائياً.
عزل الشبكة باستخدام NetworkPolicies
افتراضياً، يمكن لجميع pods في الكلاستر الوصول إلى كل pods أخرى بغض النظر عن مساحة الأسماء. لتعدد المستأجرين، يجب تقييد هذا السلوك. النمط القياسي هو سياسة رفض افتراضي لكل مساحة أسماء، ثم قواعد سماح صريحة للحركة المصرّح بها. بدون ذلك، pod مخترق في مساحة أسماء يمكنه الوصول إلى قواعد البيانات في كل مساحة أسماء أخرى.
نطاق RBAC: ServiceAccount واحد لكل فريق
يجب أن تحتوي كل مساحة أسماء للمستأجر على ServiceAccount خاصة بها، وRole يمنح الحد الأدنى من الصلاحيات التي يحتاجها الفريق، وRoleBinding يربط مجموعة الفريق (من موفر هوية مثل Okta أو Google Workspace أو Azure AD) بهذا Role. لا تربط ClusterRole الخاص بـ cluster-admin بفريق — فلا ينبغي أن يتمكنوا من قراءة Secrets في مساحات الأسماء الأخرى أو تعديل Nodes.
أنماط الفشل في الإنتاج
- غياب LimitRange وغياب طلب الحصة: Pod بلا resource requests يُجدوَل على أي عقدة. في عقدة تشغّل 40 Pod من هذا النوع، Pod واحد يقفز إلى 2 CPU يُجوّع الـ39 الباقين. احرص دائماً على وجود LimitRange افتراضي وResourceQuota في كل مساحة أسماء للمستأجر.
- حصص مُسرفة: تطلب الفِرق في أغلب الأحيان 10x حاجتها "احتياطاً". يبدو الكلاستر حينها ممتلئاً رغم أن متوسط الاستخدام 20%. فرض عملية مراجعة الحصص: ابدأ بمحافظة، وزد بناءً على الدليل، واستخدم
kubectl describe quota -n <ns>أسبوعياً لإعادة التحجيم الصحيح. - الحركة الجانبية عبر رموز ServiceAccount المشتركة: Pods في مساحة الأسماء A القادرة على استدعاء Kubernetes API وذات ClusterRole مرنة يمكنها سرد Secrets في مساحة الأسماء B. افحص كل ClusterRoleBinding شهرياً — فهي المسار الأكثر شيوعاً لتصعيد الصلاحيات في الكلاسترات المشتركة.
- إساءة استخدام NodePort: مستأجر يستطيع إنشاء Service من نوع NodePort يمكنه كشف منفذ على كل عقدة في الكلاستر، متجاوزاً NetworkPolicies. استخدم سياسة OPA/Gatekeeper لحظر خدمات NodePort وLoadBalancer في مساحات أسماء المستأجرين ما لم تُوافق عليها صراحة.
هيكلة مساحات الأسماء على نطاق واسع
على نطاق كبرى شركات التقنية (مئات مساحات الأسماء)، تصبح قائمة kubectl get namespaces المسطحة غير قابلة للإدارة. النمط الناضج هو تسلسل هرمي لمساحات الأسماء مُطبَّق عبر أداة منصة:
- Hierarchical Namespace Controller (HNC): طوّرته Google، وهو الآن مشروع Kubernetes SIG. يتيح تعريف شجرة من مساحات الأسماء (
org > division > team > environment) ونشر الكائنات (RoleBindings وNetworkPolicies وLimitRanges) تلقائياً أسفل الشجرة. تتدفق التغييرات على مستوى القسم إلى كل مساحات أسماء الفِرق الفرعية. - التسميات كمصدر الحقيقة: تحمل كل مساحة أسماء تسميات موحدة (
teamوenvوcost-centerوtier). تختار سياسات Gatekeeper وقواعد Kyverno مساحات الأسماء بالتسمية، مما يتيح لفريق المنصة تطبيق سياسات الأمان على جميع مساحات أسماءenv=productionبسياسة ClusterPolicy واحدة.
kubectl مباشرة لإنشاء مساحات الأسماء — بل يفتحون طلب سحب.