أساسيات Kubernetes

مساحات الأسماء والتسميات

18 دقيقة الدرس 7 من 32

مساحات الأسماء والتسميات

تبدو عنقود Kubernetes الجديد نظيفاً. أما عنقود الإنتاج بعد ثلاثة أشهر — يشغّل خدمات الدفع وخطوط تحليل البيانات ومكدس المراقبة وميزتين تجريبيتين — فهو قصة مختلفة. بدون تنظيم مقصود، تتشارك كل الفرق نفس مساحة الأسماء المسطحة، والتسميات غير متسقة، ويُعيد kubectl get pods مئات النتائج دون ملكية واضحة. يغطي هذا الدرس آليتين رئيسيتين يوفرهما Kubernetes لحل هذا: مساحات الأسماء (أقسام منطقية للعنقود) والتسميات مع المحددات (نظام وضع علامات مرن بقيم مفتاحية واستعلام يقود معظم منطق مستوى التحكم).

مساحات أسماء Kubernetes: التقسيم المنطقي للعنقود

مساحة الأسماء في Kubernetes هي عنقود فرعي افتراضي. تُحدّد نطاق معظم كائنات API (Pods، Services، Deployments، ConfigMaps، Secrets، ServiceAccounts، ResourceQuotas) بحيث تحتاج الأسماء إلى أن تكون فريدة فقط داخل مساحة الأسماء، وليس عبر العنقود بأكمله. يتيح هذا لفرق أو بيئات متعددة التعايش على بنية تحتية مشتركة دون التعارض مع بعضها.

يأتي كل عنقود بأربع مساحات أسماء مدمجة:

  • default — حيث تصل كائناتك عندما لا تحدد مساحة أسماء. في الإنتاج، النشر في default هو نمط مضاد؛ إذ يخلط كل شيء معاً ويجعل تطبيق RBAC والحصص مستحيل التحديد.
  • kube-system — محجوزة لمكونات العنقود (kube-dns، kube-proxy، metrics-server، إضافات CNI). لا تضع أعباء تطبيقات هنا أبداً؛ الحذف غير المقصود لأحد المكونات كارثي.
  • kube-public — قابلة للقراءة علناً حتى من قِبَل المستخدمين غير المصادق عليهم. تُستخدم فقط لـ ConfigMap الخاص بـ cluster-info من قِبَل أدوات الإقلاع.
  • kube-node-lease — تحتوي على كائنات Lease التي يستخدمها آلية نبضات قلب العقدة (يقرأ متحكم دورة حياة العقدة هذه لاكتشاف إخفاقات العقدة). لا تتدخل فيها.
الفكرة الأساسية: مساحات الأسماء هي حدود إدارة الموارد والتحكم في الوصول، وليست حدود أمان. يمكن للـ Pods في مساحات أسماء مختلفة التواصل بحرية عبر شبكة العنقود ما لم تحظرها صراحةً بـ NetworkPolicies. لا تعتمد على فصل مساحات الأسماء وحده لعزل الأحمال المعادية — أضف NetworkPolicies وRBAC.

إنشاء مساحات الأسماء واستخدامها

أنشئ مساحات الأسماء بصورة حتمية أو بملف بيان. افضّل دائماً الملفات في الإنتاج حتى تكون تهيئة مساحة الأسماء تحت إدارة الإصدارات:

# حتمي (سريع لكن غير خاضع لإدارة الإصدارات) kubectl create namespace payments # تصريحي (مفضّل) — namespace.yaml # --- # apiVersion: v1 # kind: Namespace # metadata: # name: payments # labels: # team: platform # env: production kubectl apply -f namespace.yaml # تبديل السياق النشط إلى مساحة أسماء (يوفّر كتابة --namespace في كل أمر) kubectl config set-context --current --namespace=payments # التحقق — كل أمر لاحق يُحدَّد نطاقه للـ 'payments' الآن kubectl config view --minify | grep namespace: # سرد جميع مساحات الأسماء kubectl get namespaces # سرد pods في مساحة أسماء محددة (يتجاوز الافتراضي للسياق) kubectl get pods -n kube-system # سرد pods عبر جميع مساحات الأسماء (مفيد للمراجعات على مستوى العنقود) kubectl get pods --all-namespaces # أو الشكل المختصر المكافئ: kubectl get pods -A

تُعلَن مساحة الأسماء في كل ملف بيان تحت metadata.namespace. إذا حُذفت، يُصل الكائن إلى مساحة الأسماء التي يشير إليها سياق kubeconfig — عادةً default. في خطوط الإنتاج، كن دائماً صريحاً:

apiVersion: apps/v1 kind: Deployment metadata: name: checkout-api namespace: payments # <-- دائماً صريح في ملفات بيان الإنتاج labels: app: checkout-api team: payments env: production spec: replicas: 3 selector: matchLabels: app: checkout-api template: metadata: labels: app: checkout-api team: payments env: production version: "2.4.1" spec: containers: - name: checkout-api image: myregistry/checkout-api:2.4.1 ports: - containerPort: 8080

ResourceQuotas وLimitRanges: تطبيق الحواجز الحمائية

مساحة الأسماء بدون حصص هي نطاق ضرر غير محروس. يمكن لمهمة فريق جامحة أن تستهلك كل ذاكرة العنقود وتُجوّع الجميع. أرفق ResourceQuota بكل مساحة أسماء إنتاجية لتعيين سقوف صارمة وLimitRange لتعيين إعدادات افتراضية لكل Pod:

# resource-quota.yaml — حدود صارمة لمساحة أسماء 'payments' apiVersion: v1 kind: ResourceQuota metadata: name: payments-quota namespace: payments spec: hard: requests.cpu: "8" # إجمالي طلبات CPU عبر جميع Pods requests.memory: 16Gi # إجمالي طلبات الذاكرة limits.cpu: "16" # إجمالي حدود CPU limits.memory: 32Gi # إجمالي حدود الذاكرة count/pods: "50" # الحد الأقصى لعدد Pods count/services: "20" count/secrets: "100" count/configmaps: "50" persistentvolumeclaims: "10" --- # limit-range.yaml — إعدادات افتراضية لكل حاوية apiVersion: v1 kind: LimitRange metadata: name: payments-limits namespace: payments spec: limits: - type: Container default: # مُطبَّق عندما تحذف الحاوية 'resources.limits' cpu: 500m memory: 512Mi defaultRequest: # مُطبَّق عندما تحذف الحاوية 'resources.requests' cpu: 100m memory: 128Mi max: # سقف صارم لكل حاوية cpu: "4" memory: 8Gi min: # حد أدنى لكل حاوية cpu: 50m memory: 64Mi
مصيدة إنتاجية: إذا كانت مساحة الأسماء تحتوي على ResourceQuota بإدخالات CPU/ذاكرة، فيجب على كل Pod مجدوَل في تلك المساحة أن يُصرّح بطلبات وحدود الموارد. ستُرفض Pods بدون موارد صريحة من قِبَل متحكم الإدخال. اقرن دائماً ResourceQuota بـ LimitRange يوفر إعدافات افتراضية — وإلا سيحصل المطورون الذين ينسون مواصفات الموارد على أخطاء "تجاوز الحصة" محيّرة حتى عندما تكون مساحة الأسماء بعيدة عن السقف.

التسميات: نظام الوسوم الشامل

التسميات هي أزواج مفتاح-قيمة اعتباطية مرفقة بأي كائن في Kubernetes. إنها ليست مجرد بيانات وصفية تنظيمية — يستخدمها مستوى التحكم باستمرار: الـ Services تجد Pods عبر التسميات، والـ Deployments تدير ReplicaSets عبر التسميات، وNetworkPolicies تُطبَّق على Pods عبر التسميات، وPodDisruptionBudgets تستهدف الأحمال عبر التسميات، وHorizontal Pod Autoscalers يُطابق pods عبر التسميات. صياغة مخطط تسميات صحيح من البداية تُوفر ألماً تشغيلياً هائلاً لاحقاً.

يوصي Kubernetes بمجموعة قياسية من التسميات المعروفة (تحت بادئة app.kubernetes.io/) تعرف أدوات المراقبة وRHelm charts ولوحات التحكم كيفية تفسيرها:

  • app.kubernetes.io/name — اسم التطبيق (مثل checkout-api)
  • app.kubernetes.io/instance — اسم نسخة فريد (مثل checkout-api-prod)
  • app.kubernetes.io/version — الإصدار الحالي (مثل 2.4.1)
  • app.kubernetes.io/component — الدور المعماري (مثل frontend، backend، cache، worker)
  • app.kubernetes.io/part-of — التطبيق الأعلى مستوى الذي ينتمي إليه هذا (مثل ecommerce-platform)
  • app.kubernetes.io/managed-by — الأداة التي تدير هذا المورد (مثل helm، argocd)
ممارسة احترافية: تبنَّ بادئة app.kubernetes.io/ من اليوم الأول. Prometheus ولوحات تحكم Grafana ولوحة تحكم Kubernetes ومعظم Helm charts تقرأ هذه التسميات جميعاً. إذا استخدمت مفاتيح مجردة مثل app أو version، ستفقد التكامل التلقائي مع النظام البيئي بأكمله. تكلفة الترحيل لاحقاً، عندما تحتاج مئات الكائنات إلى إعادة وضع التسميات، هائلة.

محددات التسميات: الاستعلام عن العنقود

المحددات هي كيفية الاستعلام عن الكائنات بتسمياتها. يدعم Kubernetes بنيتَي استعلام:

قائمة على المساواة (مدعومة في كل مكان): =، ==، !=

قائمة على المجموعات (مدعومة في الموارد الأحدث مثل Deployments وReplicaSets وJobs): in، notin، exists، !

# قائم على المساواة — الحصول على جميع pods الإنتاجية لفريق payments kubectl get pods -n payments -l env=production,team=payments # قائم على المجموعات — الحصول على pods التي طبقتها إما frontend أو backend kubectl get pods -l 'tier in (frontend, backend)' # النفي — استبعاد pods الكناري من النتائج kubectl get pods -l 'track notin (canary)' # وجود المفتاح — pods لديها تسمية version (أي قيمة) kubectl get pods -l version # غياب المفتاح — pods بدون تسمية version kubectl get pods -l '!version' # الجمع بين المجموعات والمساواة kubectl get deployments -l 'env=production,app.kubernetes.io/component in (backend, worker)' # وضع تسمية على pod يعمل بشكل حتمي (مفيد للتشخيص) kubectl label pod checkout-api-7d6f8c9b4-xk2pn debug=true # إزالة تسمية (أضف - إلى المفتاح) kubectl label pod checkout-api-7d6f8c9b4-xk2pn debug- # إظهار التسميات على الكائنات kubectl get pods --show-labels # استخدام محددات التسميات مع موارد أخرى kubectl get services -l app=checkout-api kubectl delete pods -l env=staging # خطر — تحقق مرتين قبل التشغيل!

المحددات داخل ملفات البيان

المحدد في spec الـ Deployment غير قابل للتغيير بعد الإنشاء — لا يمكن تغييره دون حذف Deployment وإعادة إنشائه. هذا قيد بالغ الأهمية. يجب أن يُطابق المحدد تسميات قالب Pod بالضبط، ويجب تصميم مخطط التسميات قبل كتابة أول ملف بيان:

# Service يختار Pods بالتسمية — التوصيل الأساسي لشبكة Kubernetes apiVersion: v1 kind: Service metadata: name: checkout-api namespace: payments spec: selector: app.kubernetes.io/name: checkout-api # يُطابق pods بهذه التسمية env: production # وهذه التسمية (يجب تطابق جميع الشروط) ports: - protocol: TCP port: 80 targetPort: 8080 type: ClusterIP --- # محدد Deployment (غير قابل للتغيير بعد الإنشاء) apiVersion: apps/v1 kind: Deployment metadata: name: checkout-api namespace: payments spec: selector: matchLabels: app.kubernetes.io/name: checkout-api template: metadata: labels: app.kubernetes.io/name: checkout-api # يجب أن يتضمن تسميات المحدد app.kubernetes.io/version: "2.4.1" # التسميات الإضافية على pods مقبولة env: production team: payments

التعليقات التوضيحية: البيانات الوصفية غير المعرِّفة

التعليقات التوضيحية أيضاً أزواج مفتاح-قيمة لكنها تختلف جوهرياً عن التسميات: لا يمكن الاستعلام عنها بالمحددات. تُوجد للبيانات الوصفية التي تحتاج الأدوات والمشغّلون والبشر إلى قراءتها لكن Kubernetes نفسه لا يستخدمها لاختيار الكائنات. فكّر فيها كتعليقات منظَّمة مرفقة بالكائنات.

الاستخدامات الشائعة للتعليقات التوضيحية في مجموعات الإنتاج:

  • بيانات النشر: kubernetes.io/change-cause: "رفع الصورة إلى 2.4.1 لإصلاح CVE-2024-1234" (تظهر في تاريخ الطرح)
  • توجيهات متحكم Ingress: nginx.ingress.kubernetes.io/proxy-body-size: "50m"
  • جمع Prometheus: prometheus.io/scrape: "true"، prometheus.io/port: "9090"
  • مصدر CI/CD: ci.mycompany.com/pipeline: "123"، ci.mycompany.com/commit: "abc123"
  • تلميحات توسيع العنقود: cluster-autoscaler.kubernetes.io/safe-to-evict: "false"
  • ربط دور IAM (AWS): eks.amazonaws.com/role-arn: "arn:aws:iam::123456789:role/checkout-api"
Namespace partitioning and label-based selector wiring Kubernetes Cluster namespace: payments Service selector: app=checkout Pod A app=checkout env=production Pod B app=checkout env=production ResourceQuota CPU limit: 16 cores Memory limit: 32Gi Max pods: 50 selects by label namespace: monitoring Prometheus Pod app=prometheus team=platform Grafana Pod app=grafana team=platform ResourceQuota CPU limit: 4 cores / Memory: 8Gi Max pods: 20 Cross-Namespace Rules Services only select Pods in the SAME namespace NetworkPolicy selectors are namespace-scoped ClusterRoles span all namespaces (RBAC)
مساحتا أسماء مع ResourceQuotas مستقلة. يختار Service في مساحة أسماء payments الـ Pods بالتسمية — فقط Pods في نفس مساحة الأسماء مؤهلة. تفرض ResourceQuotas سقوفاً صارمة لكل مساحة أسماء.

استراتيجية مساحات الأسماء على نطاق Big-Tech

كيف تُهيكل الشركات الكبرى فعلاً مساحات الأسماء؟ ظهرت عدة أنماط:

  • مساحات أسماء لكل بيئة (payments-dev، payments-staging، payments-prod) — بسيطة، تعمل جيداً عندما تكون البيئات في نفس العنقود. شائعة في المنظمات الأصغر.
  • مساحات أسماء لكل فريق على عناقيد مشتركة — كل فريق يمتلك مساحة أسماء أو أكثر. يمنح RBAC أعضاء الفريق وصولاً كاملاً لمساحتهم. هذا النمط الأكثر شيوعاً في المؤسسات لكفاءة التكلفة.
  • مساحات أسماء لكل خدمة — مساحة أسماء لكل خدمة مصغرة أو سياق محدود. توفر أدق تحكم في الحصة وRBAC، بتكلفة عبء تشغيلي لإدارة مساحات أسماء كثيرة. أدوات مثل Argo CD وHelm تتعامل مع هذا جيداً بأسماء مساحات أسماء مُولَّدة.
ممارسة احترافية: استخدم اتفاقية تسمية مساحات أسماء تُضمّن الفريق والبيئة: <team>-<env> (مثل payments-prod، analytics-staging). هذا يجعل قواعد RBAC مقروءة، وResourceQuotas سهلة المراجعة، وkubectl get pods -A | grep payments-prod مفيداً فوراً. تجنب الأسماء العامة مثل production — تصبح مكبّات غير منظمة.

العثور على الموارد الضالة أو غير المسمّاة

في العناقيد الناضجة، تتراكم الموارد الشاردة — Pods نُشرت بصورة حتمية دون تسميات، ConfigMaps من تجارب مهجورة، Services لم تعد لديها Pods مطابقة. اجعل مراجعة هذه الأمور ممارسة روتينية:

# إيجاد Services التي لا تُطابق أي Pods (المحدد لا يجد شيئاً — خدمة معلّقة) kubectl get services -A -o json | python3 -c " import json, sys, subprocess data = json.load(sys.stdin) for svc in data['items']: ns = svc['metadata']['namespace'] name = svc['metadata']['name'] sel = svc['spec'].get('selector', {}) if not sel: continue label_str = ','.join(f\"{k}={v}\" for k, v in sel.items()) result = subprocess.run( ['kubectl', 'get', 'pods', '-n', ns, '-l', label_str, '--no-headers'], capture_output=True, text=True ) if not result.stdout.strip(): print(f'DANGLING: {ns}/{name} selector={sel}') " # سرد جميع pods الناقصة لمجموعة التسميات الموصى بها kubectl get pods -A -o json | \ python3 -c " import json, sys data = json.load(sys.stdin) required = ['app.kubernetes.io/name', 'app.kubernetes.io/version', 'env'] for p in data['items']: labels = p['metadata'].get('labels', {}) missing = [k for k in required if k not in labels] if missing: ns = p['metadata']['namespace'] name = p['metadata']['name'] print(f'{ns}/{name} missing: {missing}') " # سريع: عد الكائنات لكل مساحة أسماء لاكتشاف التمدد في المساحات kubectl get all -A --no-headers | awk '{print $1}' | cut -d/ -f1 | sort | uniq -c | sort -rn

التسميات ومساحات الأسماء هي أساسية. كل ميزة ستتعلمها من هنا — NetworkPolicies وRBAC وPodAffinity وHorizontalPodAutoscaler وجمع Prometheus — تستهدف الكائنات باستخدام هذه الآليات بالضبط. استثمر الوقت في جعل مخطط التسميات متسقاً قبل نمو عنقودك؛ إعادة وضع التسميات على مئات الكائنات الجارية في عنقود إنتاجي حي، مع تقليل وقت التوقف، مشروع لا تريد تشغيله.