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

ترقية الكلاستر وإدارة العقد

22 دقيقة الدرس 4 من 30

ترقية الكلاستر وإدارة العقد

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

دورة إصدار Kubernetes وسياسة الانحراف

يُصدر Kubernetes ثلاثة إصدارات ثانوية سنوياً (كل أربعة أشهر تقريباً). يتلقى كل إصدار ثانوي تحديثات دورية وإصلاحات للثغرات الحرجة لمدة 14 شهراً تقريباً بعد تاريخ إصداره. سياسة الانحراف صارمة:

  • يجب أن يكون kube-apiserver على نفس الإصدار الثانوي أو إصدار ثانوي أحدث من kubelet. لا يمكنك استخدام apiserver بالإصدار v1.28 مع kubelet بالإصدار v1.26.
  • يمكن أن تكون مكونات مستوى التحكم (kube-scheduler وkube-controller-manager) إصداراً ثانوياً أحدث من kubelet — هذه هي النافذة التي تستغلها لترقيتها بأمان.
  • يمكن أن يكون kubectl في نطاق ±1 إصدار ثانوي من الـ apiserver.
خطط الترقيات بشكل تدريجي. لا يمكنك القفز من v1.26 إلى v1.29. يجب اجتياز كل إصدار ثانوي بالترتيب: 1.26 → 1.27 → 1.28 → 1.29. خصص نافذة صيانة واحدة على الأقل لكل قفزة، وتحقق من أن واجهات برمجة الأعمال (APIs) الخاصة بحمل العمل لديك غير مهملة في الإصدار المستهدف قبل البدء.

تسلسل الترقية: مستوى التحكم أولاً

القاعدة الذهبية: قم دائماً بترقية مستوى التحكم قبل مستوى البيانات. يجب أن يكون الـ apiserver دائماً أحدث مكون في الكلاستر. الترتيب الموصى به هو:

  1. عمل نسخة احتياطية من etcd.
  2. ترقية kube-apiserver.
  3. ترقية kube-controller-manager وkube-scheduler.
  4. ترقية كل مجموعة عقد، دفعة واحدة في كل مرة.
  5. ترقية الإضافات (CoreDNS، kube-proxy، إضافة CNI، metrics-server).

في الكلاسترات المُدارة (EKS، GKE، AKS) تتولى مزودات السحابة الخطوات من 1 إلى 3. تستدعيها عبر وحدة التحكم أو سطر الأوامر، وتنتظر استقرار مستوى التحكم، ثم تقوم بتفريغ مجموعات العقد واستبدالها بنفسك — أو تستخدم مجموعات العقد المُدارة التي تؤتمت ذلك. في الكلاسترات المُدارة ذاتياً، تشغّل kubeadm upgrade.

# --- الكلاسترات المُدارة ذاتياً: سير عمل ترقية kubeadm --- # الخطوة 1: ترقية kubeadm على عقدة مستوى التحكم الأولى apt-mark unhold kubeadm && \ apt-get install -y kubeadm=1.30.2-1.1 && \ apt-mark hold kubeadm # الخطوة 2: تشغيل جاف للتحقق مما سيتغير kubeadm upgrade plan v1.30.2 # الخطوة 3: تطبيق الترقية (تُرقّي الـ apiserver والـ controller-manager والـ scheduler وإعدادات etcd) kubeadm upgrade apply v1.30.2 # الخطوة 4: ترقية kubelet و kubectl على هذه العقدة apt-mark unhold kubelet kubectl && \ apt-get install -y kubelet=1.30.2-1.1 kubectl=1.30.2-1.1 && \ apt-mark hold kubelet kubectl systemctl daemon-reload && systemctl restart kubelet # الخطوة 5: التكرار لعقد مستوى التحكم الإضافية (استخدام 'upgrade node' وليس 'apply') kubeadm upgrade node # الخطوة 6: لكل عقدة عاملة — تفريغ، ترقية kubelet، رفع الحظر kubectl drain <node-name> --ignore-daemonsets --delete-emptydir-data apt-mark unhold kubelet kubectl && \ apt-get install -y kubelet=1.30.2-1.1 kubectl=1.30.2-1.1 && \ apt-mark hold kubelet kubectl systemctl daemon-reload && systemctl restart kubelet kubectl uncordon <node-name>

PodDisruptionBudgets: ضمان التوافر أثناء الصيانة

يُعدّ PodDisruptionBudget (PDB) العقد بين العمليات وأحمال العمل. يخبر واجهة برمجة الإخلاء في Kubernetes بالحد الأدنى من الـ Pods (أو النسبة المئوية) التي يجب أن تظل متاحة أثناء الاضطرابات الطوعية — تفريغ العقد، وترقيات الكلاستر، أو الإخلاء اليدوي. بدون PDBs، يمكن للتفريغ إنهاء جميع نسخ خدمة حيوية في آنٍ واحد.

تنطبق PDBs على الاضطرابات الطوعية فحسب. فشل الأجهزة اضطراب غير طوعي ولا يمكن للـ PDBs منعه — ذاك ما تتعامل معه النسخ المتعددة وقيود توزيع الـ Topology.

# PDB: يجب أن يظل 2 على الأقل من Pods الخاصة بـ api-server متاحاً في جميع الأوقات apiVersion: policy/v1 kind: PodDisruptionBudget metadata: name: api-server-pdb namespace: production spec: minAvailable: 2 # عدد مطلق؛ بديلاً يمكن استخدام maxUnavailable selector: matchLabels: app: api-server --- # PDB باستخدام نسبة مئوية: لا يتجاوز 25% من الـ Pods حالة عدم التوافر apiVersion: policy/v1 kind: PodDisruptionBudget metadata: name: worker-pdb namespace: production spec: maxUnavailable: "25%" selector: matchLabels: app: background-worker --- # التحقق من حالة PDB الحالية (عمود ALLOWED DISRUPTIONS يخبرك إذا كان التفريغ سيُحجب) kubectl get pdb -n production # NAME MIN-AVAILABLE MAX-UNAVAILABLE ALLOWED-DISRUPTIONS AGE # api-server-pdb 2 N/A 1 3d # worker-pdb N/A 25% 2 3d
جمود PDB — فخ حقيقي في الإنتاج. إذا كان minAvailable يساوي العدد الإجمالي للنسخ، أو maxUnavailable: 0، فسيتوقف التفريغ إلى الأبد. ستُرفض واجهة برمجة الإخلاء لأي Pod، وسيتوقف kubectl drain. دائماً اضبط PDBs بحيث يكون الاضطراب الواحد على الأقل مسموحاً به. الإعداد الآمن الشائع هو minAvailable: 1 للنشرات الصغيرة، وmaxUnavailable: "25%" للكبيرة.

تفريغ العقد بأمان

يقوم kubectl drain بأمرين: يُقيّد العقدة (cordon) (يضعها في حالة SchedulingDisabled حتى لا تستقبل Pods جديدة) ثم يُخلي جميع الـ Pods القابلة للإخلاء مع احترام PDBs. فهم كل خيار أمر ضروري:

  • --ignore-daemonsets — لا يمكن إخلاء Pods الخاصة بـ DaemonSet (سيعيد تحكم DaemonSet إنشاءها)؛ هذا الخيار يتجاوزها بأمان.
  • --delete-emptydir-data — يُخلي Pods التي تحتوي على وحدات تخزين emptyDir. مطلوب في معظم الكلاسترات الحقيقية. البيانات في emptyDir تُفقد عند الإخلاء — تأكد أن حمل العمل مصمم لذلك.
  • --pod-selector — يُفرّغ فقط Pods المطابقة لملصق معين، تاركاً الأخرى في مكانها (مفيد للصيانة التدريجية).
  • --timeout — المدة الزمنية لانتظار إنهاء الـ Pods. الافتراضي غير محدود؛ اضبط قيمة واقعية (مثل 300s) لتجنب التوقف من Pods المعطوبة.
  • --force — يُخلي Pods غير المُدارة بواسطة متحكم (Pods مجردة). استخدمه بحذر؛ تلك الـ Pods تختفي نهائياً.
# تسلسل التفريغ الآمن في الإنتاج # 1. التقييد أولاً (يوقف الجدولة الجديدة، يتيح لك المراجعة قبل الإخلاء) kubectl cordon ip-10-0-1-45.ec2.internal # 2. التحقق مما سيتأثر kubectl get pods --all-namespaces --field-selector spec.nodeName=ip-10-0-1-45.ec2.internal # 3. التفريغ مع احترام PDB وحارس المهلة kubectl drain ip-10-0-1-45.ec2.internal \ --ignore-daemonsets \ --delete-emptydir-data \ --timeout=300s # 4. التحقق أن العقدة فارغة (Pods الـ DaemonSet تبقى — هذا صحيح) kubectl get pods --all-namespaces --field-selector spec.nodeName=ip-10-0-1-45.ec2.internal # 5. تنفيذ الصيانة (تحديث نظام التشغيل، ترقية kubelet، استبدال الـ instance، إلخ) # 6. رفع الحظر لإعادة العقدة إلى مجموعة الجدولة kubectl uncordon ip-10-0-1-45.ec2.internal

مجموعات العقد وترقيات العقد بنمط الأزرق/الأخضر

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

Blue/green node pool upgrade strategy المرحلة 1: قبل الترقية Old Node Pool (v1.29) Node A Pod 1 Pod 2 Node B Pod 3 Pod 4 Node C Pod 5 Pod 6 New Node Pool (v1.30) — فارغة توفير عقد جديدة (لا أحمال عمل بعد) المرحلة 2: تفريغ القديمة، جدولة الجديدة المجموعة القديمة — مُقيَّدة وجارٍ تفريغها Node A ✗ Node B ✗ Node C ✗ إخلاء المجموعة الجديدة — تستقبل أحمال العمل Node D Pod 1 Pod 3 Node E Pod 2 Pod 5 Node F Pod 4 Pod 6 المرحلة 3: إنهاء العقد القديمة ← اكتملت الترقية
استراتيجية ترقية مجموعة عقد الأزرق/الأخضر: المجموعة الجديدة (v1.30) تستقبل أحمال العمل بينما تُقيَّد المجموعة القديمة (v1.29) وتُفرَّغ ثم تُنهى.

على EKS يستخدم النمط مجموعات العقد المُدارة أو مجموعات Auto Scaling المُدارة ذاتياً. سير العمل مع eksctl أو Terraform هو:

# EKS: ترقية مستوى التحكم أولاً عبر AWS CLI aws eks update-cluster-version \ --name prod-cluster \ --kubernetes-version 1.30 \ --region us-east-1 # انتظر حتى يصبح مستوى التحكم ACTIVE aws eks wait cluster-active --name prod-cluster --region us-east-1 # الخيار أ: تحديث متدحرج داخلي لمجموعة العقد المُدارة (AWS تُفرّغ العقد نيابةً عنك) aws eks update-nodegroup-version \ --cluster-name prod-cluster \ --nodegroup-name workers \ --kubernetes-version 1.30 \ --region us-east-1 # الخيار ب: الأزرق/الأخضر عبر eksctl (إنشاء مجموعة عقد جديدة ثم حذف القديمة) eksctl create nodegroup \ --cluster prod-cluster \ --name workers-v130 \ --kubernetes-version 1.30 \ --node-type m6i.2xlarge \ --nodes 6 --nodes-min 3 --nodes-max 12 \ --region us-east-1 # تقييد وتفريغ مجموعة العقد القديمة for node in $(kubectl get nodes -l eks.amazonaws.com/nodegroup=workers -o name); do kubectl cordon $node done for node in $(kubectl get nodes -l eks.amazonaws.com/nodegroup=workers -o name); do kubectl drain $node --ignore-daemonsets --delete-emptydir-data --timeout=300s done # التحقق من تشغيل جميع الـ Pods على العقد الجديدة ثم حذف مجموعة العقد القديمة eksctl delete nodegroup --cluster prod-cluster --name workers --region us-east-1

التلوينات والتحملات ومحددات العقد في سير عمل الصيانة

أثناء الترقيات المتدحرجة، غالباً ما تحتاج إلى التأكد من أن أحمال العمل تهبط فقط على العقد المُرقَّاة. طبّق NoSchedule taint على العقد القديمة كإجراء احتياطي إضافي إلى جانب التقييد، واستخدم الوعي بـ node.kubernetes.io/unschedulable. بالنسبة لمجموعات العقد المتخصصة (GPU، ذاكرة عالية، Spot Instances)، فإن التلوينات والتحملات هي الآلية الدائمة التي تمنع أحمال العمل العادية من استهلاك الموارد المكلفة.

صنّف مجموعات العقد باتساق منذ البداية. استخدم ملصقات مثل node.company.io/pool=workers وnode.company.io/lifecycle=spot وnode.company.io/generation=v2 على كل مجموعة عقد. هذه الملصقات تجعل استهداف عمليات التفريغ وكتابة قواعد PodAffinity والاستعلام عن العقد أثناء الحوادث أمراً سهلاً — دون الحاجة إلى تذكر معرفات الـ instances أو عناوين IP.

قائمة مراجعة الترقية للإنتاج

  1. تحقق من APIs المهملة باستخدام kubectl convert أو kubent قبل الترقية. إصدارات CRD المهملة ستنكسر بعد الترقية.
  2. انسخ etcd احتياطياً باستخدام etcdctl snapshot save أو لقطة مزود السحابة.
  3. تحقق من PDBs: أكد أن ALLOWED-DISRUPTIONS > 0 لكل حمل عمل حيوي.
  4. قم بترقية مستوى التحكم؛ انتظر حتى تُبلّغ جميع المكونات بـ Ready.
  5. قم بترقية العقد في دفعات بنسبة 25% أو استخدم استبدال مجموعة العقد بنمط الأزرق/الأخضر.
  6. راقب معدلات الأخطاء والكمون على منصة المراقبة الخاصة بك طوال العملية.
  7. قم بترقية الإضافات أخيراً (CoreDNS، CNI، metrics-server) إلى إصداراتها المتوافقة مع الإصدار الثانوي الجديد.
  8. شغّل اختبارات الامتثال التدخينية أو مجموعة الاختبارات التكاملية للتأكد من صحة الكلاستر.