{"id":"l-dk-4-1","courseId":"docker-kubernetes","lang":"ar","kind":"lesson","summary":"اشرح كيف يحوّل Kubernetes الحالة المرغوبة المصرَّح بها إلى containers تعمل عبر حلقات التحكّم، وسمِّ المكوّنات الرئيسية في الـ cluster، وأنشئ cluster محليًا بـ kind لتعمل فيه.","html":"<p>‏Compose يشغّل بيئتك على جهاز واحد. حين يموت ذلك الجهاز، تموت خدمتك معه، ولا شيء يعيدها حتى يلاحظ أحد. ‏Kubernetes موجود للحالة الأخرى: أجهزة كثيرة، وcontainers يجب أن تستمر في العمل حين يفشل أي جهاز منها، وتغييرات تُنشر دون توقّف للخدمة. لتستخدمه جيدًا، تحتاج إلى فكرة واحدة أكثر من حاجتك إلى أي أمر.</p>\n<h2 id=\"sec-1\" tabindex=\"-1\">حلقة التحكّم</h2>\n<p>في Kubernetes لا تقول «شغّل ثلاثة containers». تقول «يجب أن توجد ثلاث نسخ من notes-api»، وتخزّن ذلك ككائن في الـ cluster (العنقود). ثم يشغّل <strong>controller</strong> حلقة، بلا توقّف:</p>\n<ol>\n<li><strong>راقب</strong> الحالة الفعلية: كم Pod من notes-api موجود ويعمل؟</li>\n<li><strong>قارن</strong> بينها وبين الحالة المرغوبة في الكائن.</li>\n<li><strong>تصرّف</strong> لسدّ الفجوة: أنشئ Pod، أو احذف واحدًا، أو استبدل واحدًا.</li>\n</ol>\n<p>الحلقة لا تنتهي أبدًا. إذا مات node وأخذ معه Pod، فالدورة التالية ترى اثنين حيث المطلوب ثلاثة فتنشئ واحدًا. إذا غيّرت العدد المرغوب إلى خمسة، تنشئ اثنين آخرين. وإذا حذف أحدهم Pod يدويًا، يُستبدل خلال ثوانٍ. هذا ما يقصده الناس بـ <strong>التصريحي</strong> (declarative): تصف الوجهة، والنظام يواصل التوجّه نحوها.</p>\n<p>تشبيه منظّم الحرارة مفيد هنا. تضبطه على 21°C؛ فلا يشغّل المنظّم سكربتًا ثابتًا من نوع «سخّن لمدة 20 دقيقة». إنه يقيس ويقارن ويشغّل المدفأة أو يطفئها ما دام موصولًا بالكهرباء.</p>\n<h2 id=\"sec-2\" tabindex=\"-1\">أجزاء الـ cluster</h2>\n<figure class=\"diagram\"><svg class=\"diagram-svg\" focusable=\"false\" viewBox=\"0 0 700 330\" role=\"img\" aria-labelledby=\"l-dk-4-1-t1\"><defs><marker id=\"arrow-l-dk-4-1-1\" viewBox=\"0 0 10 10\" refX=\"9\" refY=\"5\" markerWidth=\"7\" markerHeight=\"7\" orient=\"auto-start-reverse\"><path d=\"M0 0 L10 5 L0 10 z\" class=\"d-arrowhead\"/></marker></defs>\n  <title id=\"l-dk-4-1-t1\">‏kubectl يرسل الكائنات إلى الـ API server، الذي يخزّنها في etcd. الـ scheduler والـ controller manager يراقبان الـ API server. على كل node عامل، يراقب الـ kubelet الـ Pods المسندة إليه ويشغّل الـ containers عبر الـ container runtime.</title>\n  <rect class=\"d-box\" x=\"20\" y=\"40\" width=\"120\" height=\"50\" rx=\"10\"/>\n  <text class=\"d-code\" x=\"80\" y=\"70\" text-anchor=\"middle\">kubectl</text>\n  <rect class=\"d-box-primary\" x=\"180\" y=\"20\" width=\"500\" height=\"130\" rx=\"14\"/>\n  <text class=\"d-label-muted\" x=\"430\" y=\"42\" text-anchor=\"middle\">مستوى التحكّم (control plane)</text>\n  <rect class=\"d-box-accent\" x=\"200\" y=\"56\" width=\"150\" height=\"50\" rx=\"10\"/>\n  <text class=\"d-label-strong\" x=\"275\" y=\"86\" text-anchor=\"middle\">API server</text>\n  <rect class=\"d-box-warn\" x=\"200\" y=\"112\" width=\"150\" height=\"32\" rx=\"8\"/>\n  <text class=\"d-label\" x=\"275\" y=\"133\" text-anchor=\"middle\">etcd</text>\n  <rect class=\"d-box\" x=\"380\" y=\"56\" width=\"130\" height=\"50\" rx=\"10\"/>\n  <text class=\"d-label\" x=\"445\" y=\"86\" text-anchor=\"middle\">scheduler</text>\n  <rect class=\"d-box\" x=\"530\" y=\"56\" width=\"140\" height=\"50\" rx=\"10\"/>\n  <text class=\"d-label\" x=\"600\" y=\"80\" text-anchor=\"middle\">controller</text>\n  <text class=\"d-label\" x=\"600\" y=\"98\" text-anchor=\"middle\">manager</text>\n  <path class=\"d-arrow\" d=\"M140 65 L198 78\" marker-end=\"url(#arrow-l-dk-4-1-1)\"/>\n  <path class=\"d-line\" d=\"M350 81 L380 81\"/>\n  <path class=\"d-line\" d=\"M275 106 L275 112\"/>\n  <path class=\"d-line\" d=\"M510 72 L530 72\"/>\n  <rect class=\"d-box-success\" x=\"120\" y=\"200\" width=\"250\" height=\"110\" rx=\"12\"/>\n  <text class=\"d-label-strong\" x=\"245\" y=\"224\" text-anchor=\"middle\">node 1</text>\n  <text class=\"d-label\" x=\"245\" y=\"252\" text-anchor=\"middle\">kubelet → containerd</text>\n  <text class=\"d-code\" x=\"245\" y=\"282\" text-anchor=\"middle\">pod  pod</text>\n  <rect class=\"d-box-success\" x=\"410\" y=\"200\" width=\"250\" height=\"110\" rx=\"12\"/>\n  <text class=\"d-label-strong\" x=\"535\" y=\"224\" text-anchor=\"middle\">node 2</text>\n  <text class=\"d-label\" x=\"535\" y=\"252\" text-anchor=\"middle\">kubelet → containerd</text>\n  <text class=\"d-code\" x=\"535\" y=\"282\" text-anchor=\"middle\">pod</text>\n  <path class=\"d-arrow\" d=\"M260 150 L245 198\" marker-end=\"url(#arrow-l-dk-4-1-1)\"/>\n  <path class=\"d-arrow\" d=\"M300 150 L520 198\" marker-end=\"url(#arrow-l-dk-4-1-1)\"/>\n  <text class=\"d-label-muted\" x=\"420\" y=\"182\" text-anchor=\"middle\">مراقبة: Pods هذا الـ node</text>\n</svg><figcaption>كل مكوّن يتحدّث مع الـ API server؛ والـ controllers والـ kubelets توفّق الحالة</figcaption></figure>\n<ul>\n<li>الـ <strong>API server</strong> هو الباب الأمامي. ‏kubectl والـ controllers والـ kubelets كلها تتحدّث معه، وهو يتحقّق من صحة كل طلب ومن هوية مرسله وصلاحياته.</li>\n<li>الـ <strong>etcd</strong> مخزن مفتاح-قيمة متّسق يحفظ كل الكائنات. لا يتحدّث معه إلا الـ API server.</li>\n<li>الـ <strong>scheduler</strong> (المُجدوِل) يراقب الـ Pods التي لا node لها ويختار لها واحدًا، بناءً على الموارد الحرّة والقيود والتوزيع.</li>\n<li>الـ <strong>controller manager</strong> يشغّل الـ controllers المدمجة: الـ Deployments، والـ ReplicaSets، والـ Jobs، وصحة الـ nodes، وغيرها.</li>\n<li>على كل node (عقدة) عامل، يراقب الـ <strong>kubelet</strong> الـ Pods المسندة إلى الـ node الخاص به ويشغّل الـ containers الخاصة بها عبر <strong>container runtime</strong>، وهو عادةً containerd. الـ images التي بنيتها بـ Docker تعمل هناك دون تغيير، لأن الـ images تتبع معيار OCI.</li>\n</ul>\n<p>الخدمات المُدارة مثل Amazon EKS تشغّل مستوى التحكّم نيابة عنك. لكنك ما زلت تحتاج إلى فهمه، لأن كل رسالة خطأ ستقرؤها تشير إلى أحد هذه الأجزاء.</p>\n<h2 id=\"sec-3\" tabindex=\"-1\">cluster على حاسوبك</h2>\n<p>‏kind ‏(“Kubernetes in Docker”) يشغّل cluster كاملًا داخل containers في Docker. إنشاؤه سريع والتخلّص منه سريع، وهذا بالضبط ما تريده للتعلّم:</p>\n<div class=\"code-block\" dir=\"ltr\" data-lang=\"bash\" data-index=\"0\"><div class=\"code-head\"><span class=\"code-title\">Terminal</span><span class=\"code-actions\"><button type=\"button\" class=\"code-btn\" data-action=\"copy\" aria-label=\"نسخ الكود\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><rect width=\"14\" height=\"14\" x=\"8\" y=\"8\" rx=\"2\" ry=\"2\"/><path d=\"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2\"/></svg><span>نسخ</span></button></span></div><pre class=\"shiki\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#953800;--shiki-dark:#FFA657\">kind</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> create</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> cluster</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> --name</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> notes</span></span>\n<span class=\"line\"><span style=\"color:#953800;--shiki-dark:#FFA657\">kubectl</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> config</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> current-context</span><span style=\"color:#6E7781;--shiki-dark:#8B949E\">      # kind-notes</span></span>\n<span class=\"line\"><span style=\"color:#953800;--shiki-dark:#FFA657\">kubectl</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> get</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> nodes</span></span>\n<span class=\"line\"><span style=\"color:#953800;--shiki-dark:#FFA657\">kind</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> load</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> docker-image</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> notes-api:1.0.0</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> --name</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> notes</span></span></code></pre></div>\n<p>الأمر الأخير ينسخ الـ image المحلية إلى الـ node في kind، فيستطيع الـ cluster تشغيلها دون registry. يعمل minikube وKubernetes المدمج في Docker Desktop أيضًا؛ وأوامر <code dir=\"ltr\">kubectl</code> في هذه الدورة هي نفسها في كل مكان.</p>\n<p>في kind، يعمل مستوى التحكّم نفسه كـ Pods على الـ node المخصّص له. شغّل <code dir=\"ltr\">kubectl get pods -n kube-system</code> وسترى الـ API server وetcd والـ scheduler والـ controller manager مدرجة مثل أي حمل عمل آخر، ومعها DNS الخاص بالـ cluster ‏(CoreDNS) وkube-proxy. أما في cluster مُدار فلن ترى مستوى التحكّم هناك، لأن المزوّد يشغّله بعيدًا عن الأنظار.</p>\n<h2 id=\"sec-4\" tabindex=\"-1\">راقب الحلقة وهي تعمل</h2>\n<p>أنشئ Deployment بالأوامر المباشرة، مرة واحدة، لترى التوفيق بعينيك:</p>\n<div class=\"code-block\" dir=\"ltr\" data-lang=\"bash\" data-index=\"1\"><div class=\"code-head\"><span class=\"code-title\">Terminal</span><span class=\"code-actions\"><button type=\"button\" class=\"code-btn\" data-action=\"copy\" aria-label=\"نسخ الكود\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><rect width=\"14\" height=\"14\" x=\"8\" y=\"8\" rx=\"2\" ry=\"2\"/><path d=\"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2\"/></svg><span>نسخ</span></button></span></div><pre class=\"shiki\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#953800;--shiki-dark:#FFA657\">kubectl</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> create</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> deployment</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> notes-api</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> --image=notes-api:1.0.0</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> --replicas=3</span></span>\n<span class=\"line\"><span style=\"color:#953800;--shiki-dark:#FFA657\">kubectl</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> get</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> pods</span></span>\n<span class=\"line\"><span style=\"color:#953800;--shiki-dark:#FFA657\">kubectl</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> delete</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> pod</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> &#x3C;</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">one-of-the-pod-name</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">s</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">></span></span>\n<span class=\"line\"><span style=\"color:#953800;--shiki-dark:#FFA657\">kubectl</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> get</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> pods</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> --watch</span></span></code></pre></div>\n<p>خلال ثوانٍ يظهر Pod جديد باسم جديد. لم تطلبه؛ الـ controller أدّى عمله. والآن انظر إلى ما أنشأته:</p>\n<div class=\"code-block\" dir=\"ltr\" data-lang=\"bash\" data-index=\"2\"><div class=\"code-head\"><span class=\"code-title\">Terminal</span><span class=\"code-actions\"><button type=\"button\" class=\"code-btn\" data-action=\"copy\" aria-label=\"نسخ الكود\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><rect width=\"14\" height=\"14\" x=\"8\" y=\"8\" rx=\"2\" ry=\"2\"/><path d=\"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2\"/></svg><span>نسخ</span></button></span></div><pre class=\"shiki\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#953800;--shiki-dark:#FFA657\">kubectl</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> get</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> deployment</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> notes-api</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> -o</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> yaml</span></span>\n<span class=\"line\"><span style=\"color:#953800;--shiki-dark:#FFA657\">kubectl</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> explain</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> deployment.spec.replicas</span></span>\n<span class=\"line\"><span style=\"color:#953800;--shiki-dark:#FFA657\">kubectl</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> delete</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> deployment</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> notes-api</span></span></code></pre></div>\n<p>الخيار <code dir=\"ltr\">-o yaml</code> يعرض الكائن الكامل الذي خزّنه Kubernetes، بما فيه قيم افتراضية كثيرة لم تضبطها. والأمر <code dir=\"ltr\">kubectl explain</code> يوثّق أي حقل من الـ cluster نفسه؛ إنه أسرع مرجع لديك. بدءًا من الدرس التالي ستكتب هذه الكائنات كملفات وتطبّقها، وهكذا تعمل الفرق الحقيقية.</p>\n<aside class=\"callout callout-mistake\" role=\"note\"><p class=\"callout-title\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><path d=\"m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3\"/><path d=\"M12 9v4\"/><path d=\"M12 17h.01\"/></svg><span><span class=\"callout-kind\">خطأ شائع</span><span class=\"callout-sep\" aria-hidden=\"true\"> · </span>الـ context الخطأ</span></p>\n<p>يتصرّف kubectl على الـ <em>context الحالي</em>. الذين يعملون مع عدّة clusters يشغّلون في النهاية أمر حذف على الإنتاج وهم يظنون أنهم في staging. تحقّق بـ <code dir=\"ltr\">kubectl config current-context</code>، واعرض الـ context في الـ prompt الخاص بالـ shell، وبدّل عن قصد بـ <code dir=\"ltr\">kubectl config use-context kind-notes</code>. بعض الفرق تعطي الإنتاج ملف kubeconfig منفصلًا كليًا.</p>\n</aside>\n<p>التالي: الكائنات التي لمحتها للتوّ، مكتوبة كما يجب. الـ Pods والـ ReplicaSets والـ Deployments.</p>\n","toc":[{"id":"sec-1","text":"حلقة التحكّم","level":2},{"id":"sec-2","text":"أجزاء الـ cluster","level":2},{"id":"sec-3","text":"cluster على حاسوبك","level":2},{"id":"sec-4","text":"راقب الحلقة وهي تعمل","level":2}],"takeaways":["تخبر Kubernetes بالحالة التي تريدها؛ والـ controllers تواصل مقارنتها بالحالة الفعلية وتتصرّف لسدّ الفجوة، إلى الأبد.","الـ API server هو الباب الأمامي، وهو المكوّن الوحيد الذي يتحدّث مع etcd، حيث تُخزَّن كل حالة الـ cluster.","الـ scheduler يختار node لكل Pod جديد؛ والـ kubelet على ذلك الـ node يشغّل الـ containers الخاصة به عبر الـ container runtime.","حذف Pod يديره controller لا يزيله لوقت طويل، لأن الـ controller يرى أن واحدًا ناقص فينشئ بديلًا.","تحقّق دائمًا من الـ cluster الذي يشير إليه <code dir=\"ltr\">kubectl</code> بالأمر <code dir=\"ltr\">kubectl config current-context</code> قبل تغيير أي شيء."],"further":[{"title":"Kubernetes components","url":"https://kubernetes.io/docs/concepts/overview/components/"},{"title":"Controllers","url":"https://kubernetes.io/docs/concepts/architecture/controller/"},{"title":"Install and set up kubectl","url":"https://kubernetes.io/docs/tasks/tools/"}],"quiz":[{"q":"<p>‏Deployment يريد 3 نسخ (replicas). ينهار node ويأخذ معه Pod واحدًا. ما الذي يعيد الـ Pod الثالث؟</p>","options":[{"text":"يلاحظ controller وجود 2 من الـ Pods حيث المطلوب 3، فينشئ واحدًا جديدًا، ويضعه الـ scheduler على node سليم.","why":"صحيح. الـ controller الخاص بالـ ReplicaSet يواصل التوفيق بين الفعلي والمرغوب، فيستبدل الـ Pod المفقود دون أن يشغّل أحد أي أمر."},{"text":"يعيد الـ kubelet على الـ node المنهار تشغيل الـ Pod حين يعود الـ node.","why":"إذا ذهب الـ node، ذهب معه الـ kubelet الخاص به. التعافي يجب أن يأتي من مستوى التحكّم."},{"text":"لا شيء؛ يجب أن يعيد أحدهم تشغيل <code dir=\"ltr\">kubectl apply</code>.","why":"الحالة المرغوبة مخزّنة أصلًا. إعادة تطبيق الملف نفسه لا تغيّر شيئًا لا تفرضه الـ controllers بالفعل."},{"text":"يعيد etcd تشغيل الـ Pod من نسخته الاحتياطية.","why":"الـ etcd يخزّن الحالة. لا يشغّل أي شيء ولا يوقفه أبدًا."}],"answer":0},{"q":"<p>أي مكوّن هو الوحيد الذي يقرأ etcd ويكتب فيه مباشرة؟</p>","options":[{"text":"الـ scheduler","why":"الـ scheduler يراقب الـ Pods ويحدّثها عبر الـ API server، مثل كل المكوّنات الأخرى."},{"text":"الـ kubelet","why":"الـ kubelets تتحدّث مع الـ API server لمعرفة الـ Pods التي يجب تشغيلها وللإبلاغ عن حالتها."},{"text":"‏kubectl","why":"‏kubectl عميل للـ API server. لا يرى etcd أبدًا."},{"text":"الـ API server","why":"صحيح. كل شيء آخر يمرّ عبره، وهناك يحدث التحقّق والمصادقة والتفويض."}],"answer":3},{"q":"<p>تحذف Pod أنشأه Deployment بالأمر <code dir=\"ltr\">kubectl delete pod notes-api-7d9c-xk2lp</code>. ماذا ترى بعد بضع ثوانٍ في <code dir=\"ltr\">kubectl get pods</code>؟</p>","options":[{"text":"‏Pod أقل بواحد، حتى توسّع الـ Deployment من جديد.","why":"العدد المرغوب في الـ Deployment لم يتغيّر، فيُصحَّح النقص فورًا."},{"text":"‏Pod جديد باسم مختلف، أُنشئ ليحلّ محلّه.","why":"صحيح. يرى الـ controller الخاص بالـ ReplicaSet أن واحدًا ناقص فينشئ بديلًا. لإزالة الـ Pods نهائيًا، غيّر الـ Deployment."},{"text":"الـ Pod نفسه، مستعادًا بالاسم نفسه وعنوان IP نفسه.","why":"الـ Pods لا تُستعاد أبدًا. البديل Pod جديد باسم جديد، وغالبًا بعنوان IP جديد."},{"text":"خطأ، لأن Pods الـ Deployment لا يمكن حذفها.","why":"تستطيع حذفها. لكن الـ controller لن يسمح ببقاء العدد منخفضًا."}],"answer":1},{"q":"<p>قبل تشغيل <code dir=\"ltr\">kubectl delete deployment notes-api</code>، ما الذي يجب أن تتحقّق منه؟</p>","options":[{"text":"أن الـ image ما زالت موجودة في الـ registry.","why":"حذف Deployment لا يعتمد على الـ image. أما الـ cluster الذي تتحدّث معه فيهمّ فعلًا."},{"text":"أن لدى etcd نسخة احتياطية حديثة.","why":"ممارسة جيدة لمشغّلي الـ clusters، لكن الخطر المباشر هنا هو التصرّف على الـ cluster الخطأ."},{"text":"الـ cluster والـ namespace اللذين يشير إليهما kubectl، بالأمر <code dir=\"ltr\">kubectl config current-context</code>.","why":"صحيح. يتصرّف kubectl على أي context هو الحالي. الأمر نفسه يعني أشياء مختلفة جدًا في kind وفي الإنتاج."},{"text":"أن الـ Deployment فيه أقل من 10 نسخ.","why":"عدد النسخ لا يغيّر كون الحذف آمنًا أم لا."}],"answer":2}],"exercise":{"kind":"order","items":["send","store","rs","pods","schedule","start","report"],"title":"من kubectl apply إلى container يعمل","prompt":"<p>تشغّل <code dir=\"ltr\">kubectl apply -f deployment.yaml</code> لـ notes-api مع 3 نسخ على cluster جديد. رتّب ما يحدث بعد ذلك.</p>\n","hints":["لا شيء يحدث في أي مكان قبل أن يُخزَّن الكائن.","الـ Deployment لا ينشئ الـ Pods بنفسه؛ بل يدير شيئًا يفعل ذلك.","يجب أن يُسند الـ Pod إلى node قبل أن يتصرّف أي kubelet بشأنه."],"explanation":"<p>يرسل kubectl الكائن إلى الـ API server، الذي يتحقّق منه ويخزّنه في etcd. يرى الـ controller الخاص بالـ Deployments كائن Deployment جديدًا فينشئ ReplicaSet؛ وينشئ الـ controller الخاص بالـ ReplicaSet ثلاثة كائنات Pod. يُسند الـ scheduler كل Pod غير مُجدوَل إلى node. يسحب الـ kubelet على كل node مختار الـ image ويشغّل الـ containers، ثم يُبلغ عن حالة الـ Pod عبر الـ API server. كل خطوة مكوّن منفصل يتفاعل مع تغيير كان يراقبه.</p>\n","checkLabels":{},"itemText":{"send":"يرسل kubectl الـ Deployment إلى الـ API server","store":"يتحقّق الـ API server منه ويخزّنه في etcd","rs":"ينشئ الـ controller الخاص بالـ Deployments كائن ReplicaSet","pods":"ينشئ الـ controller الخاص بالـ ReplicaSet ثلاثة كائنات Pod","schedule":"يُسند الـ scheduler كل Pod إلى node","start":"يسحب الـ kubelet في كل node الـ image ويشغّل الـ containers","report":"يُبلغ الـ kubelet عن حالة الـ Pod إلى الـ API server"}},"words":617,"readMinutes":4}