عن المشروع

pillar-csi هو مشغّل CSI لـ Kubernetes مخصّص لعناقيد الخوادم المعدنية المستضافة ذاتياً. يأخذ وحدات ZFS zvol المحلية أو أحجام LVM المنطقية على عقدة تخزين مخصّصة ويصدّرها إلى بقية العنقود عبر NVMe-oF/TCP، بالكتابة مباشرة إلى النواة عبر configfs بدلاً من الاعتماد على SSH أو خوادم Python أو أدوات CLI خارجية للأهداف. وهو ليس نظام ملفات موزّعاً بشكل صريح: فهو لا ينسخ البيانات ولا يوزّعها على شرائط ولا يجمع التخزين عبر العقد. تتكوّن البنية من ثلاثة أحمال عمل. يعمل pillar-controller كـ Deployment ويوفّق بين موارد CRD من نوع Pillar* على نطاق العنقود. يعمل pillar-agent كـ DaemonSet على عقد التخزين فقط ويتولّى جميع عمليات الكتابة إلى configfs على المضيف. يعمل pillar-node على كل عامل ويتعامل مع خدمة CSI Node (اتصال المُبادر، mkfs، الربط bind-mount). يستخدم كلا الـ DaemonSets وضع hostNetwork حتى يتمكّن مستوى بيانات NVMe-oF/TCP من الارتباط بفضاء أسماء شبكة المضيف. التكوين تصريحي عبر CRDs: يحدّد PillarAgent موقع وكيل التخزين، ويصف PillarStore مجمّع تخزين (اسم مجمّع ZFS، LVM VG، تكوين الواجهة الخلفية)، ويصف PillarProtocol تكوين بروتوكول الشبكة، ويدمج PillarStorageClass المجمّع والبروتوكول في StorageClass مُولّد تلقائياً. يسجّل CRD داخلي باسم PillarVolumeState الحالة الدائمة للتعافي من إخفاقات التزويد الجزئي وتتبّع النشر؛ ويفرض المتحكّم حصرية أوضاع الوصول في CSI انطلاقاً من ذلك السجل. من العناصر التصميمية البارزة تحصين العمليات القديمة. كل نداء للوكيل يغيّر موارد حجم يحمل رمز تحصين مؤلّفاً من UID حالة الحجم (هوية دورة الحياة) وعدّاد publicationGeneration يُزاد عبر compare-and-swap. يحتفظ الوكيل بعلامات دائمة لكل حجم على القرص المحلي لعقدة التخزين تحت ‎/var/lib/pillar-csi/agent/generations/‎، مركّبة كـ hostPath حتى تبقى العلامات بعد إعادة التشغيل وإعادة الإقلاع. تُرفض الطلبات الأقدم من العلامة، أو الصادرة من دورة حياة منتهية أو مستبدلة، أو التي لا تحمل رمزاً، بخطأ FAILED_PRECONDITION. يذكر README تحذيراً عند الترقية: افصل جميع الأحجام قبل الترقية، لأن الإصدارات السابقة لم تسجّل أي عمليات نشر أو دورات حياة أو أجيال، ولا تُوفَّر طبقة توافق للترحيل. تُسجَّل حالة مرحلة العقدة تحت ‎/var/lib/pillar-csi/node/‎ على العامل، وتُكتب ذرّياً عبر ملف مؤقت ثم sync ثم rename. يقرأ NodeUnstageVolume السجل مرة أخرى لأن CO لا يرسل قدرة الحجم ولا سياق الحجم عند إلغاء المرحلة. تُفوَّض قرارات إلغاء التركيب إلى Unmount المتكرّر الآمن في المُركِّب، مع اعتبار أخطاء فحص التركيب التالف (EIO، ENOTCONN، ESTALE، EACCES) كأنها ما زالت مركّبة حتى يتمكّن kubelet من إنهاء الحاويات التي دخل نظام ملفاتها في إغلاق النواة. المصفوفة المدعومة: ZFS zvol وLVM LV عبر NVMe-oF/TCP مُطلَقة؛ iSCSI مصمّمة لكنها غير مُطلَقة بعد؛ NFS لمجموعات بيانات ZFS مصمّمة لكنها غير مُطلَقة بعد. تشمل عمليات CSI كلاً من CreateVolume وDeleteVolume وControllerPublish/Unpublish وControllerExpandVolume وNodeStage/Unstage وNodePublish/Unpublish وNodeExpandVolume وNodeGetVolumeStats وValidateVolumeCapabilities وGetCapacity. أوضاع الوصول هي ReadWriteOnce وReadWriteOncePod وReadOnlyMany؛ وأوضاع الحجم هي Filesystem (ext4/xfs) وBlock. التثبيت عبر Helm. mTLS بين المتحكّم والوكيل اختياري (وضع cert-manager أو وضع Secret مُقدَّم)؛ والافتراضي هو gRPC بنص صريح. يُشترط Kubernetes 1.24 أو أحدث. تحتاج عقد التخزين إلى وحدتي نواة nvmet وnvmet_tcp؛ وتحتاج عقد العمال إلى nvme_tcp وnvme_fabrics؛ وتشغّل حاويات init الأمر modprobe عند بدء التشغيل. يتضمّن README بداية سريعة بأمثلة YAML لـ CRD، واستكشاف الأخطاء عبر أوامر kubectl describe والسجلات المعتادة، وإجراء تعافٍ مفصّل للأحجام القديمة العالقة عند ExportSpecMissing، مع التأكيد على قرارات المشغّل الصريحة بشأن bindAddress وport وaclEnabled بدلاً من التخمين من ملاحظات وقت التشغيل.