أساسيات Kubernetes

معمارية الكلستر

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

معمارية الكلستر

ينقسم كلستر Kubernetes إلى مستويين يؤديان أدواراً مختلفة تماماً: مستوى التحكم (Control Plane) وهو العقل، ومستوى البيانات (Worker Nodes) وهو العضلات. كل عطل في الإنتاج، وكل مشكلة أداء، وكل قرار تحجيم يعود في نهاية المطاف إلى أحد هذه المكونات. فهم ما يفعله كل جزء — ولماذا صُمِّم بهذه الطريقة — هو ما يميز المهندسين الذين يشغّلون Kubernetes عن أولئك الذين يكتفون باستخدامه.

Kubernetes Cluster Architecture Control Plane API Server kube-apiserver — single entry point etcd cluster state store Scheduler kube-scheduler Controller Manager kube-controller-manager — reconciliation loops Cloud Controller Manager cloud-specific resources (LB, volumes, nodes) Worker Node 1 kubelet node agent kube-proxy iptables / eBPF containerd container runtime Pod app sidecar shared network + storage Worker Node 2 kubelet node agent kube-proxy iptables / eBPF containerd container runtime Pod app worker shared network + storage — — — API Server watches/pushes to kubelets
كلستر Kubernetes: مستوى التحكم يدير حالة الكلستر؛ عقد العمال تشغّل أحمال العمل.

مستوى التحكم (Control Plane)

مستوى التحكم هو مجموعة من العمليات التي تنفّذ Kubernetes API وتحافظ على الحالة المرغوبة للكلستر. في الخدمات المُدارة (GKE, EKS, AKS) لن ترى هذه الأجهزة الافتراضية أبداً — يشغّلها مزود الخدمة السحابية ويمنحك اتفاقية مستوى الخدمة (SLA). في الكلسترات ذاتية الإدارة (kubeadm, Talos, k3s) أنت المسؤول عن كل واحدة منها.

خادم الـ API (kube-apiserver)

خادم الـ API هو المكوّن الوحيد الذي يقرأ ويكتب إلى etcd. كل شيء آخر — kubelets، وحدات التحكم، kubectl — يتواصل مع خادم الـ API عبر HTTPS. يتحقق من كل طلب وارد مقابل المخطط، ويشغّل webhooks القبول (OPA/Gatekeeper, LimitRanger, ResourceQuota)، ثم يخزّن الكائن.

هذا التصميم بنقطة دخول واحدة يجعل خادم الـ API المكوّن الأكثر أهمية في كلسترك. في مستويات التحكم عالية التوافر تشغّل ثلاث أو خمس نسخ خلف موزّع الأحمال. على نطاق Google، يُقسَّم خادم الـ API أفقياً حسب نوع المورد، لكنك لن ترى هذا الإعداد حتى تشغّل كلسترات بعشرات الآلاف من العقد.

لماذا يمر كل شيء عبر خادم الـ API: أي مكوّن يتجاوز خادم الـ API ويكتب مباشرة إلى etcd سيتجاوز التحكم في القبول، وRBAC، وتسجيل المراجعة. خادم الـ API هو حدود التطبيق لجميع سياسات الكلستر.

etcd

etcd هو مخزن مفتاح-قيمة موزّع قوي الاتساق مبني على خوارزمية Raft للإجماع. يحمل حالة الكلستر بأكملها: كل مواصفة Pod، وكل تعريف Service، وكل Secret، وكل ConfigMap. يجب أن يتفق نصاب من أعضاء etcd قبل الإقرار بأي كتابة، ولهذا تشغّل دائماً عدداً فردياً من الأعضاء (3 أو 5) في الإنتاج — كلستر من 3 يتحمّل فشل عضو واحد؛ كلستر من 5 يتحمّل فشل عضوين.

etcd ليس قاعدة بيانات لبيانات تطبيقك. هو مُصمَّم للبيانات الوصفية وليس للكميات الكبيرة. القيم التي تتجاوز 1.5 ميجابايت (حد رسالة gRPC الافتراضي) ستُرفض. يقوم المشغّلون بضغط etcd وإلغاء تشرذمه بانتظام لمنع ملف قاعدة بياناته من النمو بلا حدود.

مشكلة إنتاجية — زمن استجابة قرص etcd: يستخدم etcd fsync بعد كل كتابة. على جهاز افتراضي سحابي بقرص بطيء، يمكن أن تتسلسل انتخابات قائد etcd إلى انتهاء مهل خادم الـ API وحالات فشل متتالية في الكلستر. دائماً شغّل etcd على وحدة تخزين ذات زمن استجابة كتابة منخفض (AWS io2, GCP pd-ssd، أو قرص NVMe محلي مخصص). راقب مقياس Prometheus etcd_disk_wal_fsync_duration_seconds — إذا تجاوز p99 قيمة 10 ميلي ثانية فهذا مؤشر خطر.

المجدوِل (kube-scheduler)

يراقب المجدوِل خادم الـ API بحثاً عن Pods لا تملك nodeName مُعيَّناً (أي Pods في حالة Pending) ويختار أفضل عقدة لكل منها. عملية الاختيار ذات مرحلتين:

  1. التصفية — تستبعد العقد التي لا تستطيع تلبية القيود الصارمة للـ Pod: طلبات CPU/الذاكرة، محدد العقدة، التلويثات، قواعد التقارب/مضادّ التقارب، توزيع الطوبولوجيا.
  2. التسجيل — تُرتَّب العقد المتبقية باستخدام مجموعة مرجّحة من الدوال (LeastAllocated, BalancedResourceAllocation, ImageLocality ...) وتُربط الـ Pod بأعلى عقدة نقاطاً.

يكتب المجدوِل اسم العقدة إلى خادم الـ API ككائن Binding؛ لا يتواصل مباشرة أبداً مع kubelet.

مدير وحدات التحكم (kube-controller-manager)

هو ملف تنفيذي واحد يشغّل عشرات حلقات التحكم (controllers) في goroutines. كل وحدة تحكم تراقب نوعاً أو أكثر من الموارد وتوفّق الحالة الفعلية نحو الحالة المرغوبة:

  • ReplicaSet controller — يضمن وجود العدد الصحيح من نسخ الـ Pod.
  • Deployment controller — يدير التحديثات المتدحرجة والتراجع عبر ReplicaSets.
  • Node controller — يضع علامة NotReady على العقد حين تتوقف ضرباتها القلبية ويُخلي الـ Pods بعد فترة سماح قابلة للتكوين (--node-monitor-grace-period، الافتراضي 40 ثانية).
  • Job controller، CronJob controller، Namespace controller، ServiceAccount controller — والمزيد.

مدير وحدات التحكم السحابية (Cloud Controller Manager)

استُخلصت المنطق الخاص بالسحابة من kube-controller-manager إلى ملفه التنفيذي الخاص حتى يتمكن مزودو السحابة من شحن تنفيذاتهم الخاصة بشكل مستقل عن دورة إصدار Kubernetes. يتولى: توفير موازنات أحمال السحابة لـ Service type: LoadBalancer، وربط وحدات تخزين السحابة لـ PersistentVolumeClaims، ومزامنة بيانات العقدة الوصفية (نوع المثيل، التسميات).

عقد العمال (Worker Nodes)

كل عقدة عاملة تشغّل ثلاثة مكونات تشكّل معاً بيئة تنفيذ الـ Pods.

kubelet

kubelet هو وكيل طويل الأمد يسجّل العقدة مع خادم الـ API ويوفّق مجموعة الـ Pods التي عيّنها المجدوِل لها. لكل Pod مُعيَّنة، يأمر kubelet وقت تشغيل الحاوية بسحب الصور وتشغيل الحاويات، ثم يراقب الصحة عبر فحوصات liveness وreadiness. يُبلّغ عن سعة العقدة والموارد القابلة للتخصيص وحالة الـ Pod إلى خادم الـ API تقريباً كل 10 ثوانٍ.

kubelet هو أيضاً المكوّن الوحيد الذي يتحدث مباشرة مع وقت تشغيل الحاوية — عبر واجهة وقت تشغيل الحاوية (CRI)، وهي واجهة برمجة تطبيقات gRPC. هذا التجريد يتيح لك استبدال containerd بوقت تشغيل آخر متوافق مع CRI دون تغيير أي شيء آخر.

نصيحة احترافية — سجلات kubelet هي نقطة التصحيح الأولى: عندما تكون Pod عالقة في Pending أو ContainerCreating، تحقق دائماً من سجل kubelet على العقدة المُعيَّنة: journalctl -u kubelet -f. تظهر هنا فشل سحب الصور، وأخطاء وقت التشغيل، ومشاكل cgroup قبل أن تنتشر إلى kubectl describe pod.

kube-proxy

يراقب kube-proxy الـ Services والـ Endpoints ويبرمج قواعد الشبكة على العقدة لتنفيذ توجيه عناوين IP الافتراضية. في معظم الكلسترات يستخدم وضع iptables — كل IP خدمة يحصل على سلسلة من قواعد DNAT التي توزّع الأحمال عبر Pod IPs السليمة. في الكلسترات عالية الإنتاجية، يتجاوز وضع eBPF (عبر Cilium أو بديل kube-proxy) iptables بالكامل لتأخير أقل وقابلية أفضل للتوسع.

وقت تشغيل الحاوية (Container Runtime)

وقت تشغيل الحاوية مسؤول عن إدارة الصور والدورة الحياتية الفعلية لعمليات الحاوية. المعيار الفعلي هو containerd (مشروع CNCF متخرّج، مستخلص من Docker). يسحب صور متوافقة مع OCI من السجلات، ويدير ذاكرة التخزين المؤقت للطبقات على القرص، ويستدعي runc ذو المستوى الأدنى (أو وقت تشغيل محمي كـ gVisor) لإنشاء عمليات معزولة بالـ namespaces.

# فحص صحة مكونات مستوى التحكم kubectl get componentstatuses # عرض جميع العقد وأدوارها kubectl get nodes -o wide # وصف عقدة لرؤية السعة والموارد القابلة للتخصيص والتلويثات والظروف kubectl describe node <node-name> # فحص حالة kubelet على عقدة (شغّل هذا على العقدة عبر SSH أو kubectl debug) systemctl status kubelet journalctl -u kubelet --since "5 min ago" | tail -40 # عرض Pods النظام الجارية في namespace مستوى التحكم (كلسترات kubeadm) kubectl get pods -n kube-system -o wide
# kubeadm: فحص صحة etcd من داخل Pod الخاص بها kubectl -n kube-system exec -it etcd-<control-plane-node> -- \ etcdctl \ --cacert=/etc/kubernetes/pki/etcd/ca.crt \ --cert=/etc/kubernetes/pki/etcd/server.crt \ --key=/etc/kubernetes/pki/etcd/server.key \ endpoint health # عرض قائمة أعضاء etcd (توقّع عدداً فردياً: 3 أو 5 في الإنتاج) kubectl -n kube-system exec -it etcd-<control-plane-node> -- \ etcdctl \ --cacert=/etc/kubernetes/pki/etcd/ca.crt \ --cert=/etc/kubernetes/pki/etcd/server.crt \ --key=/etc/kubernetes/pki/etcd/server.key \ member list -w table

كيف تتواصل المكونات عند تشغيل التطبيق

عند تشغيل kubectl apply -f deployment.yaml، هذا هو التسلسل الدقيق:

  1. kubectl يتسلسل المانيفست الخاص بك، ويرسل POST /apis/apps/v1/namespaces/.../deployments إلى خادم الـ API.
  2. خادم الـ API يُصادق (mTLS/OIDC)، يُخوِّل (RBAC)، يشغّل webhooks القبول، يتحقق من المخطط، ويكتب كائن Deployment إلى etcd.
  3. Deployment controller (داخل controller-manager) يراقب Deployments الجديدة، ينشئ كائن ReplicaSet، يكتبه إلى خادم الـ API.
  4. ReplicaSet controller ينشئ العدد المطلوب من كائنات Pod (بدون nodeName) — يكتبها إلى خادم الـ API.
  5. المجدوِل يكتشف الـ Pods غير المرتبطة، ينفّذ التصفية والتسجيل، يكتب ربط العقدة.
  6. kubelet على العقدة المختارة يكتشف أن الـ Pod مُعيَّنة له، يأمر containerd بسحب الصورة وتشغيل الحاويات.
  7. kubelet يُبلّغ عن حالة الـ Pod؛ يحدّث خادم الـ API الكائن في etcd. kubectl get pods يُظهر الآن Running.

كل خطوة هي حلقة مراقبة غير متزامنة — لا توجد استدعاءات RPC مباشرة بين المكونات إلا عبر خادم الـ API. هذه هي المعمارية التي تتيح لـ Kubernetes إصلاح نفسه ذاتياً: يمكن لأي مكوّن أن يتعطّل ويُعاد تشغيله، وتستكمل حلقات التوفيق من حيث توقفت بالضبط.