الوحدة 4 · أساسيات Kubernetes
الـ Pods والـ ReplicaSets والـ Deployments
20 دقراءة 4 داكتشف الخطأ
الدرس في لمحة
اكتب manifest لـ Deployment خاص بـ notes-api، وافهم كيف يملك الـ ReplicaSets والـ Pods عبر الـ labels والـ selectors، وطبّقه وافحصه ووسّعه انطلاقًا من الملفات.
- 1الـ Pods: الوحدة التي يشغّلها Kubernetes
- 2الـ Deployments والـ ReplicaSets والـ Pods
- 3الـ Labels والـ Selectors
- 4طبّق وافحص ووسّع
لا فيديو هنا، بل الشيء الحقيقي: درس مكتوب وأمثلة قابلة للتشغيل واختبار وتدريب.
الأمر المباشر kubectl create deployment من الدرس السابق كان جيدًا لعرض توضيحي، وبلا فائدة لفريق. لا أحد يستطيع مراجعته، ولا أحد يعرف أي خيارات استُخدمت، وفي الأسبوع القادم لا أحد يستطيع تكراره. من الآن فصاعدًا، تعيش إعدادات Kubernetes الخاصة بـ notes-api في ملفات YAML تحت k8s/، بجوار الـ Dockerfile، وتُراجع مثل الكود.
الـ Pods: الوحدة التي يشغّلها Kubernetes
الـ Pod هو container واحد أو أكثر تُجدوَل معًا على node واحد، وتتشارك network namespace واحدة (عنوان IP واحد، وlocalhost واحد) وأي volumes تصرّح بها. معظم الـ Pods لها container رئيسي واحد. والـ container الثاني يكون لشيء مرتبط بالأول ارتباطًا وثيقًا، مثل أداة شحن سجلات أو proxy يجب أن يعيش ويموت معه.
يبدو manifest الـ Pod الأدنى هكذا:
apiVersion: v1
kind: Pod
metadata:
name: notes-api-test
spec:
containers:
- name: api
image: ghcr.io/skylane/notes-api:1.4.0
ports:
- containerPort: 3000لن تنشئ Pods بهذه الطريقة عمليًا. الـ Pod المجرّد لا يُستبدل إذا انهار على node ميت، ولا يمكن تغيير عدد نسخه، ولا يمكن تحديثه إلى image جديدة تدريجيًا. الـ Pods قطيع يُستبدل: كل واحد منها يمكن التخلّص منه، ويحصل على اسم وIP جديدين حين يُستبدل، ويديره شيء فوقه.
الـ Deployments والـ ReplicaSets والـ Pods
الـ Deployment هو ذلك الشيء. إنه يملك ReplicaSet، ومهمّته الوحيدة إبقاء N من الـ Pods المتطابقة قيد التشغيل. أما مهمّة الـ Deployment فهي إدارة الـ ReplicaSets عبر الزمن: حين تغيّر قالب الـ Pod، ينشئ ReplicaSet جديدًا وينقل الـ Pods إليه، وهذا هو التحديث المتدرّج (rolling update) الذي ستدرسه في القسم الخامس.
apiVersion: apps/v1
kind: Deployment
metadata:
name: notes-api
labels:
app.kubernetes.io/name: notes-api
spec:
replicas: 3
selector:
matchLabels:
app.kubernetes.io/name: notes-api
template:
metadata:
labels:
app.kubernetes.io/name: notes-api
spec:
containers:
- name: api
image: ghcr.io/skylane/notes-api:1.4.0
ports:
- name: http
containerPort: 3000
env:
- name: PORT
value: "3000"اقرأه على نصفين. النصف العلوي هو الـ Deployment نفسه: اسمه، وعدد النسخ، والـ Pods التي يملكها (selector). وكل ما تحت template هو مواصفات Pod، المخطّط الذي تُطبع منه كل نسخة. لاحظ أن apiVersion يختلف حسب النوع: الـ Pods في v1 الأساسية، والـ Deployments في apps/v1.
الـ Labels والـ Selectors
كائنات Kubernetes لا يشير بعضها إلى بعض بالاسم. إنها تجد بعضها عبر الـ labels (الوسوم)، وهي أزواج مفتاح-قيمة في metadata.labels، وعبر الـ selectors (المحدِّدات)، وهي استعلامات على تلك الـ labels. يعدّ الـ ReplicaSet الـ Pods الخاصة به بتشغيل الـ selector الخاص به؛ وفي الدرس التالي سيجد Service الـ Pods التي يرسل إليها الحركة بالطريقة نفسها.
لهذا يجب أن يطابق selector.matchLabels في الـ Deployment الحقل template.metadata.labels: يجب أن يستطيع الـ Deployment إيجاد الـ Pods التي ينشئها قالبه. يتحقّق الـ API server من ذلك ويرفض عدم التطابق. والـ selector أيضًا غير قابل للتغيير (immutable) بعد وجود الـ Deployment، فاختره بعناية. المفتاح app.kubernetes.io/name أحد الـ labels الموصى بها في Kubernetes؛ تفهمه الأدوات ولوحات المتابعة، واستخدامه باتّساق يؤتي ثماره.
طبّق وافحص ووسّع
kind load docker-image ghcr.io/skylane/notes-api:1.4.0 --name notes
kubectl apply -f k8s/deployment.yaml
kubectl get deploy,rs,pods -l app.kubernetes.io/name=notes-api
kubectl describe deployment notes-apiالأمر kind load ينسخ الـ image إلى الـ cluster باسمها الكامل، فيستطيع الـ manifest استخدام المرجع نفسه الذي سيستخدمه الإنتاج. و-l يصفّي حسب الـ label، وهي الآلية نفسها التي تستخدمها الـ controllers. انظر إلى أسماء الـ Pods: notes-api-6c8f9d7b5-x2k4q هو اسم الـ Deployment، ثم الـ pod-template-hash الخاص بالـ ReplicaSet، ثم لاحقة عشوائية. غيّر أي شيء في القالب وستحصل على ReplicaSet جديد بـ hash جديد.
لزيادة عدد النسخ، غيّر replicas: 3 إلى 5 في الملف وطبّق مجددًا. يقارن kubectl apply ملفك بما هو مخزّن ولا يرسل إلا الفرق. والأمر kubectl diff -f k8s/ يعرض ذلك الفرق قبل أن تلتزم به، ويجب أن تعتاد تشغيله.
الأمر kubectl scale deployment/notes-api --replicas=5 يعمل أيضًا، وله مكانه في حالات الطوارئ. لكن الملف ما زال يقول 3، فيُرجع الـ apply الروتيني التالي العدد إلى 3 بصمت. كل ما تغيّره يدويًا، غيّره في Git مباشرة بعده.
الـ Pods لديك تعمل، لكن كلًّا منها يملك عنوان IP خاصًا يتغيّر في كل مرة يُستبدل فيها. لا شيء يستطيع الوصول إليها بشكل موثوق بعد. وهذا ما وُجدت الـ Services من أجله.
أهم النقاط
- الـ Pod هو container واحد أو أكثر تتشارك هوية شبكية وتخزينًا؛ إنه أصغر شيء يُجدوِله Kubernetes، ويمكن التخلّص منه.
- نادرًا ما تنشئ Pods مجرّدة؛ فالـ Deployment يدير ReplicaSet، وهذا الأخير يُبقي العدد الصحيح من الـ Pods قيد التشغيل.
- يجب أن يطابق
spec.selector.matchLabelsفي الـ Deployment الـ labels الموجودة فيspec.template.metadata.labels، ولا يمكن تغيير الـ selector بعد الإنشاء. - احفظ الـ manifests في Git وغيّرها بـ
kubectl apply -f، حتى تبقى الملفات مصدر الحقيقة. - استخدم إصدارات الـ API الحالية مثل
apps/v1؛ فالـ manifests المنسوخة من مقالات قديمة بـextensions/v1beta1لم تعد تعمل.