التعافي من الكوارث: إعادة بناء نزال من الصفر
هذا هو التسلسل الذي تتمرّن عليه وهو نفسه الذي تتبعه عندما يضيع الكلستر. وهو يفترض أسوأ حالة واقعية: لم يعد الكلستر موجودًا وكل ما لديك ملف نسخة احتياطية وخادم git الخاص بك.
وهو عن قصد دليل إجراءات وليس أمرًا واحدًا. فأمر الاستعادة الذي يمكن تشغيله على تثبيت يعمل وسيلة لتدميره. وخطة التعافي من الكوارث التي يستطيع فريق أمني أن يعتمدها تسلسل يتمرّن عليه موظفوه أنفسهم وليست زرًا يُضغط.
وتنفّذ فحوص الإصدار في نزال هذه الخطوات نفسها على كلستر جديد قبل كل إصدار. لذلك لا يمكن أن يتقادم الإجراء.
ما تحتاج إليه قبل أن تبدأ
| العنصر | أين ينبغي أن يكون الآن | إن لم يكن لديك |
|---|---|---|
| نسخة احتياطية من قاعدة البيانات | حيث يكتب الـ CronJob الخاص بالنسخ الاحتياطي (راجع دليل المشرف) | لا يمكن استعادة التثبيت. راجع "إذا لم تكن لديك نسخة احتياطية" |
الـ Secret المسمّى nezal-api-keys |
منسوخ احتياطيًا بمعزل عن قاعدة البيانات | لا يمكن فك تشفير النسخة الاحتياطية. ولا يوجد أي طريق للاستعادة |
| مفتاح الترخيص | سجلاتك الخاصة. وهو أيضًا داخل النسخة الاحتياطية | اطلب مفتاحًا بديلًا من جهة اتصالك في نزال |
| بيانات اعتماد المستودعات | سجلاتك الخاصة | لا يستطيع المشغّل قراءة مستودعاتك من جديد حتى تُدخل هذه البيانات مرة أخرى |
| صور الحاويات | مرآة سجل الصور لديك أو الحزمة غير المتصلة | انسخ الصور إلى المرآة من الحزمة من جديد قبل التثبيت |
| تفريغ لكائنات CRDs الخاصة بنزال | أداة النسخ الاحتياطي للكلستر لديك (Velero أو لقطات etcd أو kubectl get -o yaml) |
يجب إدخال التطبيقات والسياسات يدويًا من جديد. راجع الخطوة 6 |
المفاتيح هي ما يجب أن تتحقق منه الآن لا لاحقًا. فهي في الـ Secret المسمّى nezal-api-keys
وهي عن قصد ليست داخل النسخة الاحتياطية: فاللقطة المسروقة من وحدة التخزين لا ينبغي أن تعطي
البيانات والمفتاح الذي يفك تشفيرها معًا. ويذكّرك أمر النسخ الاحتياطي بذلك في كل مرة يعمل فيها.
خذ نسخة احتياطية من ذلك الـ Secret في مكان لا تصل إليه أدوات النسخ الاحتياطي لقاعدة البيانات.
يحتوي الـ Secret على ثلاثة مفاتيح:
backupيفك تشفير النسخ الاحتياطية.sessionيوقّع رموز تسجيل الدخول ويشفّر أسرار العامل الثاني المخزّنة.audit-exportيوقّع حزم الأدلة.
وفقدان session يكلّف الجميع إعادة التسجيل. أما فقدان backup فيكلّفك النسخ الاحتياطية
نفسها ولا يمكن فعل شيء بعد ذلك.
التسلسل
1. التثبيت على الكلستر الجديد
اتبع دليل التثبيت كما في التثبيت الأول مع فرق واحد: لا تُدخل مفتاح الترخيص ولا تضبط أي شيء بعد. فأنت تنشئ تثبيتًا فارغًا لتستعيد البيانات إليه.
helm install nezal oci://registry.nezal.dev/charts/nezal --version <the version you were running> \
--namespace nezal-system --create-namespace \
--set ingress.domain=dev.acme.internal \
--set api.persistence.enabled=true
ثبّت الإصدار نفسه الذي كنت تشغّله. فالنسخة الاحتياطية تُستعاد إلى مخطط قاعدة البيانات الذي أُخذت منه. والإصدار الأحدث سيرحّلها إلى مخططه عند أول تشغيل. وهذا تغيير ثانٍ يحدث أثناء حادثة والقاعدة تغيير واحد في كل مرة.
2. أعد المفاتيح قبل قاعدة البيانات
مفاتيح التوقيع الخاصة بالـ API موجودة في الـ Secret المسمّى nezal-api-keys وليست في النسخة
الاحتياطية. استعد ذلك الـ Secret من المكان الذي تحفظه فيه:
kubectl apply -f ./nezal-api-keys.yaml # the Secret as you backed it up
kubectl rollout restart deploy/nezal-api -n nezal-system
فمن دون هذا الـ Secret لا يمكن أبدًا فك تشفير النسخة الاحتياطية في الخطوة 3. ولهذا تأتي هذه الخطوة أولًا.
والمفاتيح تأتي أولًا لأن الـ API ينشئ مفاتيح جديدة عند أول تشغيل إن لم يجد مفاتيح. وعندها تصبح
أسرار TOTP المخزّنة في قاعدة البيانات المستعادة غير قابلة لفك التشفير لأنها شُفّرت بمفتاح session
القديم. فيُمنع من الدخول كل مستخدم لديه عامل ثانٍ.
وإذا ضاعت المفاتيح فإن قاعدة البيانات تُستعاد مع ذلك ويعمل المنتج. ويسجّل الجميع الدخول من جديد. ويجب على المستخدمين الذين لديهم عامل ثانٍ أن يسجّلوه من جديد (المستخدمون → إعادة تعيين العامل الثاني). ولا يمكن بعد ذلك التحقق من حزم الأدلة المصدَّرة قبل الفقدان بالمفتاح العام لهذا التثبيت. لكن يبقى التحقق منها ممكنًا بالمفتاح العام القديم الموجود داخل تلك الحزم. لذلك احتفظ بالحزم نفسها.
3. استعد قاعدة البيانات
اتبع قسم النسخ الاحتياطي والاستعادة في دليل المشرف بدءًا من الخطوة 1. وباختصار: قلّص الـ API
إلى الصفر وفك تشفير النسخة الاحتياطية. ثم انسخها فوق nezal.db في وحدة تخزين البيانات من pod
يربط مطالبة التخزين نفسها وأعد التوسيع إلى نسخة واحدة.
فك تشفيرها بمفتاح backup من الـ Secret الذي استعدته في الخطوة 2:
kubectl -n nezal-system get secret nezal-api-keys -o jsonpath='{.data.backup}' | base64 -d > ./backup.key
nezal-api verify-backup --in ./nezal-2026-09-12.db.enc --key-file ./backup.key
nezal-api decrypt-backup --in ./nezal-2026-09-12.db.enc --out ./nezal.db --key-file ./backup.key
يثبت verify-backup أن المفتاح صحيح وأن الملف يُفتح قبل أن تكتب فوق أي شيء. ثم يكتب
decrypt-backup قاعدة البيانات غير المشفّرة لتنسخها إلى مكانها. واحذف تلك النسخة غير المشفّرة
والملف backup.key بعد إتمام الاستعادة.
4. تحقق مما عاد قبل أن تتابع
kubectl -n nezal-system port-forward svc/nezal-api 8080:8080 &
curl -s -H "Authorization: Bearer $TOKEN" localhost:8080/api/v1/audit/verify | jq
ظهور intact: true مع قيمة headSeq تطابق ما كان لديك هو الدليل على أن هذا هو التثبيت نفسه
وليس تثبيتًا جديدًا يحمل اسمه. فقاعدة البيانات هذه تحتوي على المستخدمين ومساحات العمل مع تعريفات
المستودعات والإعدادات والترخيص. ويجب أن تكون كلها موجودة. أما التطبيقات والسياسات فليست
فيها: فهي كائنات Kubernetes وتتناولها الخطوة 6.
5. أعد إدخال بيانات اعتماد المستودعات
بيانات الاعتماد محفوظة في كائنات Secret في Kubernetes وليست في قاعدة البيانات. لذلك لم تعد معها. أعد إدخال بيانات الاعتماد لكل مستودع في شاشة المستودعات. أما كل ما عدا ذلك في المستودع من عنوانه URL ومرجعه والتطبيق المبني منه فقد استُعيد بالفعل.
6. استعد كائنات Kubernetes
التطبيقات (كائنات Baseline) والبيئات والسياسات موجودة في الكلستر وليست في قاعدة البيانات. فهي موارد مخصّصة (Custom Resources) وقد ذهبت مع الكلستر. وهذه هي الخطوة الأكثر عرضة للخطأ وهي التي يجب أن تتمرّن عليها.
إذا كان لديك تفريغ لكائنات CRDs من Velero أو من لقطة etcd أو من أمر مجدول
kubectl get baselines,policies -A -o yaml فاستعد منه كائنات Baseline وPolicy:
kubectl apply -f ./nezal-baselines.yaml
kubectl apply -f ./nezal-policies.yaml
خذ هذا التفريغ وفق جدول زمني. فهو كائنان لكل فريق وهو الفرق بين استعادة تستغرق عشر دقائق وإعادة إدخال حصص كل فريق وحدود المدة (TTL) وإعدادات الطرفية يدويًا:
kubectl get baselines,policies -A -o yaml > nezal-crds-$(date +%F).yaml
وإذا لم يكن لديك تفريغ فأعد إنشاءها من لوحة التحكم. اربط كل تطبيق من جديد في شاشة التطبيقات (مستودعه وبيانات اعتماده مستعادة فالأمر لا يعدو تعبئة النموذج نفسه). واضبط سياسة كل فريق من جديد في شاشة الحصص والتكلفة. ودوّن سياساتك قبل أن تحتاج إلى ذلك.
أما البيئات فلا تستحق الاستعادة: فالبيئة الشخصية نسخة من فرع ويعيد المطوّر إنشاء بيئته بالأمر
nezal up في دقيقة. وتعود بيئات طلبات السحب مع أول حدث webhook تالٍ من طلب سحب مفتوح.
7. تأكد من العمل من البداية إلى النهاية
أنشئ بيئة واحدة وافتح رابط المعاينة الخاص بها. وتحقق من أن سجل التدقيق يعرض التسلسل كاملًا. ويكون التثبيت قد استُعيد عندما يستطيع المطوّر أداء عمله المعتاد.
ما يعود وما لا يعود
| يُستعاد من النسخة الاحتياطية لقاعدة البيانات | يحتاج إلى تفريغ CRDs أو إلى إعادة الإدخال | ضاع ولا يستحق الحفظ |
|---|---|---|
| المستخدمون والأدوار وعضويات الفرق | التطبيقات وكائنات Baseline الخاصة بها | البيئات (أعد إنشاءها بالأمر nezal up) |
| مساحات العمل | السياسات: الحصص والمدة (TTL) وإعدادات الطرفية | بيئات طلبات السحب (تعود مع حدث webhook التالي) |
| تعريفات المستودعات وسجلات الصور (دون بيانات اعتمادها) | الجلسات: يسجّل الجميع الدخول من جديد | |
| الترخيص وجميع الإعدادات (SSO وSMTP وSIEM والوكيل الذكي) | عمليات البناء الجارية | |
| سجل التدقيق وسلسلته سليمة | جلسات الطرفية المفتوحة | |
| تاريخ الإصدارات واستخدام المقاعد |
تاريخ الطرفية يبقى. فالطرفية التي كانت مفتوحة لحظة ضياع الكلستر ضاعت معه. لكن إدخالات سجل التدقيق لكل جلسة موجودة في قاعدة البيانات وتعود معها. فمن فتح كل جلسة وأي pod دخلت إليه ومتى ولماذا انتهت كل ذلك يبقى متاحًا للمحقق.
إذا لم تكن لديك نسخة احتياطية
سجل التدقيق ضاع ولا شيء يعيد إنشاءه: فهذا هو الغرض من السجل المتسلسل بالتجزئة. أما ما يمكنك إعادة بنائه فهو المنتج العامل. ثبّت من جديد وأدخل الترخيص. ثم أعد إنشاء مساحات العمل وأعد ربط المستودعات. ويعود المستخدمون للظهور كلما سجّلوا الدخول عبر مزوّد الهوية لديك.
قل ذلك بوضوح في تقرير الحادثة بدلًا من أن تبدأ سجلًا جديدًا بصمت. فالمدقق الذي يجد فجوة لم يُخبَر بها يصل إلى استنتاج أسوأ من المدقق الذي يقرأ أن الكلستر ضاع في تاريخ معروف وأن السجل يبدأ من جديد عنده.
التمرّن على الإجراء
تمرّن عليه يدويًا مرة كل سنة على نسخة مستعادة من نسختك الاحتياطية. والأجزاء التي تتعثر في الواقع هي دائمًا الثلاثة نفسها:
- الـ Secret المسمّى
nezal-api-keysالذي لم يأخذ له أحد نسخة احتياطية - بيانات اعتماد المستودعات التي لم يدوّنها أحد
- إصدار مخطط Helm الذي لم يعد يطابق النسخة الاحتياطية
والتحقق من الثلاثة اليوم قليل الكلفة واكتشافها أثناء حادثة باهظ الكلفة.