عمليات Kubernetes المتقدمة

مشروع: دليل العمليات التشغيلية

18 دقيقة الدرس 10 من 30

مشروع: دليل العمليات التشغيلية

دليل العمليات التشغيلية (Runbook) هو أهم وثيقة ينتجها فريق SRE على الإطلاق. إنه المرجع الرسمي القابل للتنفيذ الذي يُخبر المهندس المناوب بالضبط بما يجب فعله عند الساعة الثالثة صباحاً حين يُطلق تنبيه الإنتاج. على خلاف وثائق قرارات المعمارية أو وثائق التصميم، يجب أن يكون الدليل التشغيلي قاطعاً وتدريجياً خطوة بخطوة ومختبَراً على أرض الواقع. يأخذك هذا الدرس عبر كتابة دليل عمليات احترافي للإنتاج يغطي أعلى ثلاث فئات تشغيلية تأثيراً في أي كتلة Kubernetes: ترقيات الكتلة، وأحداث التوسع، والاستجابة للحوادث.

ما الذي يجعل الدليل التشغيلي على مستوى الإنتاج

في أبرز شركات التقنية (Google، Stripe، Cloudflare)، يُراجَع الدليل التشغيلي ربع سنوياً، ويُربط مباشرةً بتعريفات التنبيهات، ويُختبر في أيام المحاكاة — وهي تدريبات مقصودة تنفذ فيها الفرق الدليل على بيئة تجريبية تحاكي حركة الإنتاج. يجيب كل قسم من الدليل على أربعة أسئلة: ما المحفز؟ ما نطاق التأثير؟ ما الإجراء؟ ما خطة التراجع؟

احفظ الأدلة التشغيلية في Git إلى جانب مظاهر الكتلة وفرض المراجعة كجزء من أي طلب سحب للبنية التحتية يغيّر الإجراءات التشغيلية. أصدرها بإصدار نسخة الكتلة التي تصفها.

الدليل التشغيلي ليس درساً تعليمياً. أحذف الخلفية النظرية. اكتب فقط الأوامر الدقيقة المرتبة التي يحتاج إلى تنفيذها المهندس المناوب تحت الضغط دون وقت للتفكير.

القسم الأول — إجراء ترقية الكتلة

يُطلق Kubernetes إصداراً فرعياً كل أربعة أشهر تقريباً. يُدعَم كل إصدار فرعي حوالي أربعة عشر شهراً، مما يعني أن الكتلة التي تعمل بإصدار متأخر ثلاثة إصدارات أو أكثر خارج الدعم — بدون تصحيحات CVE ولا استعادة للأخطاء. يستهدف الإجراء أدناه كتلة مُدارة (EKS) مع مجموعات عقد مُدارة ذاتياً، وهو أكثر هياكل الإنتاج شيوعاً.

قائمة التحقق قبل الترقية: تأكد من توفر الإصدار المستهدف في مزودك السحابي، وتحقق من سجل التغييرات الخاص بـ Kubernetes لأي واجهات API مهملة باستخدام pluto detect-files -d ./k8s، وتحقق من أن جميع الإضافات (CoreDNS، kube-proxy، CNI، metrics-server) تمتلك إصدارات متوافقة، وتأكد من وجود PodDisruptionBudgets لجميع أعباء العمل الحساسة قبل لمس أي عقد.

#!/usr/bin/env bash # RUNBOOK: ترقية الكتلة — EKS # المحفز: الإصدار المستهدف متاح؛ الإصدار الحالي ضمن إصدارين من نهاية الدعم # نطاق التأثير: إعادة تشغيل خادم API بشكل مؤقت؛ استنزاف العقد يسبب إعادة جدولة الحاويات # التراجع: تراجع مستوى التحكم غير مدعوم في EKS؛ التراجع = استعادة قالب إطلاق مجموعة العقد السابق CLUSTER="prod-us-east-1" REGION="us-east-1" TARGET_VERSION="1.30" # الخطوة 1: اكتشاف استخدام واجهات API المهملة قبل الترقية pluto detect-files -d ./k8s --target-versions k8s=v${TARGET_VERSION} # الخطوة 2: ترقية مستوى التحكم (10-20 دقيقة؛ يعيد خادم API التشغيل نسخة واحدة في كل مرة) aws eks update-cluster-version \ --name "${CLUSTER}" \ --kubernetes-version "${TARGET_VERSION}" \ --region "${REGION}" aws eks wait cluster-active --name "${CLUSTER}" --region "${REGION}" # الخطوة 3: تحديث الإضافات الأساسية قبل لمس عقد مستوى البيانات eksctl update addon --cluster "${CLUSTER}" --name vpc-cni --version latest --region "${REGION}" eksctl update addon --cluster "${CLUSTER}" --name coredns --version latest --region "${REGION}" eksctl update addon --cluster "${CLUSTER}" --name kube-proxy --version latest --region "${REGION}" # الخطوة 4: ترقية مجموعات العقد واحدة تلو الأخرى (استراتيجية الزيادة: max-unavailable=0) for NG in $(eksctl get nodegroup --cluster "${CLUSTER}" --region "${REGION}" \ -o json | jq -r '.[].Name'); do echo "=== جارٍ ترقية مجموعة العقد: ${NG} ===" eksctl upgrade nodegroup \ --cluster "${CLUSTER}" \ --name "${NG}" \ --kubernetes-version "${TARGET_VERSION}" \ --region "${REGION}" done # الخطوة 5: التحقق kubectl get nodes -o wide kubectl get pods -A --field-selector=status.phase!=Running,status.phase!=Succeeded
قم دائماً بالترقية إصداراً فرعياً واحداً في كل مرة. لا يدعم Kubernetes تخطي الإصدارات الفرعية (مثلاً من 1.27 مباشرة إلى 1.30). التخطي يسبب سلوكاً غير محدد في خادم API وسيكسر الكتلة.

القسم الثاني — إجراء حدث التوسع

التوسع في الإنتاج ليس مجرد kubectl scale. يشمل فهم ما إذا كان الاختناق في المعالج أو الذاكرة أو الإدخال/الإخراج أو زمن استجابة الخدمات الخارجية؛ والتحقق من أن مُوسِّع الكتلة (Cluster Autoscaler أو Karpenter) لديه مجال لتوفير عقد جديدة؛ والتأكد من أن التطبيق يتعامل بشكل صحيح مع الطلبات الجارية أثناء التقليص. يغطي الدليل أدناه كلاً من التوسع التفاعلي (تنبيه أُطلق، حركة المرور ترتفع الآن) والتوسع المخطط (التوسع المسبق قبل حدث معروف كحملة تسويقية).

Scaling decision flow in a production Kubernetes cluster Alert Fires High CPU / Latency HPA at max replicas? kubectl get hpa No HPA scales pods Wait 2-3 min Yes Node capacity? Karpenter / CA logs Raise HPA maxReplicas + verify node quota Stable? Incident Resolved Document in postmortem If latency persists despite healthy pod count → investigate downstream deps (DB, cache, third-party APIs)
مسار القرار لحدث توسع تفاعلي مُثار بتنبيه ارتفاع المعالج أو زمن الاستجابة.
# RUNBOOK: التوسع التفاعلي # المحفز: زمن استجابة P99 يتجاوز حد SLO أو تنبيه HPA بالوصول إلى الحد الأقصى للنسخ # نطاق التأثير: اضطراب مؤقت في الحاويات؛ توفير العقد يستغرق 60-120 ثانية (Karpenter) أو 3-5 دقائق (CA) # 1. تحديد النشر المختنق kubectl top pods -n production --sort-by=cpu | head -20 kubectl get hpa -n production # 2. التحقق مما إذا كان HPA قد وصل للحد الأقصى kubectl describe hpa <name> -n production # ابحث عن: "Warning FailedGetResourceMetric" أو "unable to fetch metrics" # 3. إذا كانت خط أنابيب المقاييس معطوباً، وسّع يدوياً كحل مؤقت kubectl scale deployment <name> --replicas=20 -n production # 4. التحقق من مساحة العقد kubectl describe nodes | grep -A5 "Allocated resources" # أو مع Karpenter: kubectl get nodeclaims # 5. للأحداث المخطط لها — وسّع مسبقاً ليلة قبل الحدث kubectl patch hpa <name> -n production \ --type=merge -p '{"spec":{"minReplicas":10,"maxReplicas":50}}' # 6. بعد الحدث — استعد القيم الأصلية kubectl patch hpa <name> -n production \ --type=merge -p '{"spec":{"minReplicas":3,"maxReplicas":20}}' # 7. أمان التقليص: تأكد من أن terminationGracePeriodSeconds أكبر من أطول طلب kubectl get deployment <name> -n production -o jsonpath=\ '{.spec.template.spec.terminationGracePeriodSeconds}'

القسم الثالث — خطوات الاستجابة للحوادث

تتبع الاستجابة للحوادث في Kubernetes نمطاً عالمياً بغض النظر عن نوع العطل: الكشف → الاحتواء → التشخيص → المعالجة → الاستعادة → المراجعة. يغطي الدليل أدناه أكثر خمسة حوادث شيوعاً على مستوى الكتلة: عواصف CrashLoopBackOff، وأحداث عدم جاهزية العقد (NotReady)، وأعباء العمل المُنهاة بسبب نفاد الذاكرة (OOMKilled)، ومشاكل وحدات التخزين الدائمة، وأعراض تقسيم الشبكة.

# RUNBOOK: الاستجابة للحوادث — كتلة Kubernetes الإنتاجية # ============================================================= # ---- نوع الحادث 1: عاصفة CrashLoopBackOff ---- # المحفز: حاويات متعددة في CrashLoopBackOff؛ تنبيه: pod_restart_count > 10 في 5 دقائق # نطاق التأثير: الخدمة متدهورة / غير متاحة حسب عدد النسخ # تحديد الحاويات المتأثرة kubectl get pods -A --field-selector=status.phase=Running | grep -v Running kubectl get events -n <ns> --sort-by=.lastTimestamp | tail -30 # سحب السجلات من الحاوية السابقة (التي تعطلت) kubectl logs <pod> -n <ns> --previous # قائمة الأسباب الشائعة: # - إعداد خاطئ (ConfigMap / Secret مُحدَّث بقيمة خاطئة) # - OOMKilled (تحقق من kubectl describe pod — ابحث عن "OOMKilled") # - صورة معطوبة (تحقق من انجراف العلامة، بيانات اعتماد السجل) # - مسبار الحيوية عدواني جداً (تحقق من الحدود) # إيقاف الطوارئ: علّق النشر لوقف حلقة العطل kubectl rollout pause deployment/<name> -n <ns> # التراجع إذا كان نشر حديث هو السبب kubectl rollout undo deployment/<name> -n <ns> kubectl rollout status deployment/<name> -n <ns> # ---- نوع الحادث 2: عقدة NotReady ---- # المحفز: انتقال العقدة إلى NotReady؛ تنبيه: kube_node_status_condition # تحقق من حالة العقدة وشروطها kubectl get nodes kubectl describe node <node-name> # ابحث عن: DiskPressure, MemoryPressure, PIDPressure # SSH للعقدة (إن أمكن) أو استخدم kubectl debug kubectl debug node/<node-name> -it --image=ubuntu # على العقدة — تحقق من سجلات kubelet journalctl -u kubelet --since "10 minutes ago" | tail -50 # احجز العقدة فوراً لوقف جدولة حاويات جديدة عليها kubectl cordon <node-name> # استنزف العقدة إذا تأكدت مشكلة الأجهزة (يحترم PDBs) kubectl drain <node-name> --ignore-daemonsets --delete-emptydir-data --grace-period=60 # لمجموعات العقد المُدارة — أنهِ العقدة ودع ASG يستبدلها aws ec2 terminate-instances --instance-ids <id> --region us-east-1 # ---- نوع الحادث 3: أعباء عمل OOMKilled ---- # تحقق من الحاوية المُنهاة بسبب OOMKilled kubectl describe pod <pod> -n <ns> | grep -A10 "Last State" # زد حد الذاكرة كتخفيف فوري (ثم أنشئ تذكرة للضبط الصحيح) kubectl set resources deployment/<name> -n <ns> \ --limits=memory=1Gi --requests=memory=512Mi # اعرض توصية VPA إن كان مثبتاً kubectl describe vpa <name> -n <ns>
لا تتخطَّ أبداً kubectl drain --grace-period على عقدة تحت حمل نشط. تخطي فترات السماح يقتل الطلبات الجارية فوراً، محوّلاً عطل العقدة إلى انقطاع مرئي للمستخدمين.

نموذج ما بعد الحادث

كل حادث من درجة P0 أو P1 يجب أن ينتج وثيقة ما بعد الحادث خلال 48 ساعة. تحليل ما بعد الحادث بلا إلقاء لوم هو الآلية الأساسية التي تُحسّن بها منظمات SRE موثوقيتها. يجب أن تتضمن الوثيقة: الجدول الزمني للحادث بتوقيت UTC، والعوامل المساهمة (تقنية وإجرائية)، وتحديد كمي للتأثير (معدل الخطأ، المستخدمون المتأثرون، ميزانية SLO المستهلكة)، والسبب الجذري، وعناصر العمل مع المسؤولين وتواريخ الاستحقاق. يجب تتبع عناصر العمل في منظومة تذاكر الفريق — تحليل ما بعد الحادث بدون متابعة هو مجرد تقرير.

اربط كل دليل تشغيلي للتنبيه مباشرةً بسجل ما بعد الحادث. حين يُطلق التنبيه مرة أخرى، يستطيع المهندس المناوب رؤية جميع الحوادث السابقة فوراً، وما الذي أصلحها، وأي عناصر العمل لا تزال مفتوحة. تدعم PagerDuty وOpsgenie وGrafana Incident حقول عنوان URL للدليل التشغيلي في سياسات التنبيه.

إبقاء الدليل التشغيلي حياً

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

هذا الدرس المشروع يربط معاً كل مفهوم من مفاهيم البرنامج التعليمي: RBAC يقيّد من يستطيع تنفيذ أوامر المعالجة؛ وخطافات القبول تُنفِّذ PodDisruptionBudgets التي تجعل الاستنزاف آمناً؛ والعمليات المخصصة تُؤتمت الأجزاء المتكررة؛ والتوسع التلقائي يوفر المرونة؛ وسلامة etcd هي الأساس الذي يجعل أي استرداد ممكناً. الدليل التشغيلي هو الطبقة المقروءة من قِبل الإنسان التي تُنسّق كل هذه العناصر.