كتابة أول ملف Deployment لتشغيل تطبيقك على نظام Kubernetes
كتابة أول ملف Deployment لتشغيل تطبيقك على نظام Kubernetes
عندما تبدأ رحلتك مع Kubernetes ستكتشف سريعاً أن تشغيل التطبيق لم يعد مجرد أمر docker run أو ملف compose بسيط. هنا تدخل إلى عالم إدارة الحالة المرغوبة Desired State حيث تصف للنظام كيف يجب أن يبدو تطبيقك، ويتكفل هو بالحفاظ على هذا الوضع تلقائياً.
ملف Deployment هو نقطة الانطلاق العملية لأي مهندس DevOps يريد تشغيل تطبيق قابل للتوسع، قابل للتحديث، وقادر على التعافي عند فشل الحاويات. وإذا كنت قد فهمت مسبقاً Pods وNodes وClusters فهذه الخطوة ستربط النظرية بالتطبيق الحقيقي.
ما هو ملف Deployment ولماذا هو مهم؟
ملف Deployment هو كائن في Kubernetes API يعرّف كيف يجب تشغيل التطبيق: عدد النسخ، نوع الصورة، المنافذ، وآلية التحديث. هو لا يشغل الحاويات مباشرة، بل يدير كائناً وسيطاً يسمى ReplicaSet والذي بدوره يحافظ على وجود عدد معين من Pods.
هذه البنية تمنحك ميزات هندسية قوية جداً:
- إعادة تشغيل الحاوية تلقائياً عند الفشل.
- الحفاظ على عدد ثابت من النسخ
Replicas. - تنفيذ تحديثات تدريجية
Rolling Updates. - الرجوع لإصدار سابق عند حدوث مشكلة
Rollback.
لهذا السبب يعتبر Deployment حجر أساس في أي بيئة إنتاج تعتمد على الحاويات، خصوصاً إذا كان التطبيق قد تم تغليفه سابقاً عبر Dockerfile أو بعد فهم Containerization بشكل صحيح.
بنية أول ملف deployment.yaml
في أبسط صورة، نحتاج إلى ملف YAML يصف التطبيق المطلوب. المثال التالي يشغل تطبيق ويب بسيط من صورة Nginx بثلاث نسخ:
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-first-app
labels:
app: my-first-app
spec:
replicas: 3
selector:
matchLabels:
app: my-first-app
template:
metadata:
labels:
app: my-first-app
spec:
containers:
- name: nginx-container
image: nginx:1.25
ports:
- containerPort: 80
شرح الحقول الأساسية داخل الملف
apiVersion: يحدد نسخة الواجهة البرمجية الخاصة بالكائن.kind: يحدد نوع المورد، وهنا هوDeployment.metadata: يحتوي الاسم والتوصيفاتLabels.replicas: عدد النسخ التي تريد أن تبقى عاملة دائماً.selector: الطريقة التي يطابق بهاDeploymentالحاويات التابعة له.template: القالب الذي يُنشئ منهPodsالجديدة.containers: قائمة الحاويات داخل الـPod.
كيف تطبق الملف على الكلاستر؟
بعد حفظ الملف باسم deployment.yaml يمكنك تطبيقه باستخدام أداة kubectl:
kubectl apply -f deployment.yaml
kubectl get deployments
kubectl get pods
kubectl describe deployment my-first-app
الأمر الأول يرسل التعريف إلى API Server. بعد ذلك يبدأ Scheduler بتوزيع الحاويات على العقد المناسبة، بينما يتابع Controller Manager بقاء العدد المطلوب من النسخ نشطاً. هذه هي الفكرة الجوهرية وراء التشغيل الذكي في K8s.
إضافة منافذ وموارد وحد أدنى من الاحترافية
الملف الأولي يعمل، لكنه ليس كافياً للإنتاج. بيئات الإنتاج تتطلب تعريف الموارد، وسياسات إعادة التشغيل، وفحوصات الصحة. إليك نسخة محسنة أكثر واقعية:
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-first-app
spec:
replicas: 3
selector:
matchLabels:
app: my-first-app
template:
metadata:
labels:
app: my-first-app
spec:
containers:
- name: app
image: myrepo/myapp:1.0.0
ports:
- containerPort: 3000
resources:
requests:
memory: "128Mi"
cpu: "100m"
limits:
memory: "256Mi"
cpu: "300m"
readinessProbe:
httpGet:
path: /health
port: 3000
initialDelaySeconds: 5
periodSeconds: 10
livenessProbe:
httpGet:
path: /health
port: 3000
initialDelaySeconds: 15
periodSeconds: 20
لماذا هذه الإضافات مهمة؟
resources.requestsيضمن حجز حد أدنى من الذاكرة والمعالج.resources.limitsيمنع الحاوية من استهلاك الخادم بشكل مفرط.readinessProbeيمنع توجيه الزيارات إلى التطبيق قبل أن يصبح جاهزاً.livenessProbeيعيد تشغيل الحاوية إذا علقت أو فقدت الاستجابة.
لا تستخدم أبداً صورة بحقل
latestفي بيئة الإنتاج. تثبيت نسخة محددة مثل1.0.0يجعل النشر قابلاً للتتبع، ويسهل عملياتRollbackعند فشل الإصدار الجديد.
تحديث التطبيق بدون توقف الخدمة
من أجمل مزايا Deployment أنه يدعم التحديث التدريجي. يكفي تغيير الصورة إلى إصدار أحدث ثم إعادة التطبيق:
kubectl set image deployment/my-first-app app=myrepo/myapp:1.0.1
kubectl rollout status deployment/my-first-app
kubectl rollout history deployment/my-first-app
في الخلفية، يبدأ Kubernetes بإنشاء Pods جديدة ثم حذف القديمة تدريجياً. هذا النموذج هو الأساس الذي تعتمد عليه أنظمة CI/CD الحديثة عند ربط المستودع بعملية بناء صورة ثم نشرها تلقائياً، كما في Docker Image Build ثم دفعها إلى السجل وتشغيلها على الكلاستر.
أخطاء شائعة عند كتابة أول Deployment
1) عدم تطابق selector مع labels
إذا كان matchLabels لا يطابق القيم داخل القالب، فلن يستطيع Deployment إدارة الحاويات بشكل صحيح.
2) نسيان تعريف المنفذ الداخلي
الحقل containerPort لا ينشر الخدمة للعالم الخارجي، لكنه يوثق تصميم الحاوية ويساعد الأدوات الأخرى على فهم بنيتها.
3) غياب فحوصات الصحة
بدون Probes قد يرسل النظام الزيارات إلى تطبيق متجمد أو غير جاهز، وهو خطأ يسبب تدهوراً صامتاً يصعب اكتشافه.
4) تجاهل السجلات والتشخيص
استخدم أوامر الفحص باستمرار أثناء التعلم:
kubectl get pods
kubectl logs pod-name
kubectl describe pod pod-name
kubectl get events --sort-by=.metadata.creationTimestamp
أفضل الممارسات الأمنية والمعمارية
مع الوقت ستتحول ملفات Deployment من مجرد تعريف تشغيل إلى جزء من هندسة الإنتاج الكاملة. لذلك التزم بالممارسات التالية منذ البداية:
- استخدم صوراً صغيرة وآمنة، ويفضل بناؤها وفق مبادئ
Alpine Linuxعند ملاءمتها. - لا تضع كلمات المرور داخل الملف مباشرة، بل استخدم
SecretsوConfigMaps. - اربط النشر مع خطوط
Pipelineلضمان اختبار الصورة قبل وصولها إلى الإنتاج. - راقب الأداء والذاكرة والزمن الاستجابي عبر
PrometheusوGrafana.
أخطر خطأ معماري هو تشغيل التطبيق في
Kubernetesبنفس عقلية السيرفر الواحد. فكر دائماً بمنطق التطبيقات الموزعة: الحاوية قد تُقتل، قد تنتقل إلىNodeأخرى، وقد يعاد إنشاؤها في أي لحظة. لذلك اجعل الحالةStateخارج الحاوية كلما أمكن.
الخلاصة
كتابة أول ملف Deployment ليست مجرد تمرين على YAML، بل انتقال فعلي من تشغيل الحاويات يدوياً إلى إدارة تطبيقات سحابية بآليات تعافٍ وتحديث وتوسع تلقائي. حين تفهم الحقول الأساسية مثل replicas وselector وprobes، تصبح قادراً على بناء أساس قوي لتطبيقات الإنتاج الحديثة.
والخطوة التالية الطبيعية بعد هذا الملف هي إنشاء Service لربط التطبيق بالشبكة الداخلية أو الخارجية، ثم دمجه مع عمليات CI/CD حتى يتحول النشر إلى عملية موثوقة وقابلة للتكرار بالكامل.
3 comments