مقال مرتبط · هذا الدليل جزء من سلسلة Kubernetes منزلي على Proxmox VE. الدليل السابق: Cilium CNI eBPF. الدليل التالي: Argo CD GitOps.
دون تخزين مستمرّ، عنقود Kubernetes لا يستطيع تشغيل سوى أحمال بلا حالة: نفقد كلّ البيانات بمجرّد إعادة تشغيل pod. لاستضافة قاعدة PostgreSQL، أو Vaultwarden، أو Nextcloud، أو MinIO، يلزم مزوِّد CSI (Container Storage Interface) يُنتج volumes مستمرّة عند الطلب. Rook هو مُشَغِّل Kubernetes يُنسِّق Ceph — تخزين موزَّع من فئة المؤسّسات — مباشرة داخل العنقود، على أقراص الـ workers. الإصدار 1.19.5 الصادر في ربيع 2026 يدعم Ceph Squid 19.2.0+ وKubernetes 1.30 كحدّ أدنى. يُثبّت هذا الدليل Rook 1.19، ينشر عنقود Ceph بثلاث OSDs، ويعرض StorageClass للكتل RBD، نظام ملفّات مشترك CephFS، وbucket S3 ObjectStore.
الخطوة 1 — تحضير الأقراص على الـ workers
Ceph يتطلّب أقراصًا مخصَّصة، بلا نظام ملفّات ولا تجزئة قائمة. على الـ workers Talos الثلاثة، أضفنا في الدليل السابق قرصًا ثانيًا بـ 32 جيغا (/dev/sdb). تحقّق من نظافة هذه الأقراص من محطّة العمل.
for ip in 192.168.1.71 192.168.1.72 192.168.1.73; do
echo "=== Worker $ip ==="
talosctl -n $ip get disks
done
# الخرج يجب إدراج sda (32 جيغا، نظام Talos) وsdb (32 جيغا، فارغ)
إن ظهر sdb بتجزئات سابقة من اختبار، امسحه نظيفًا قبل أن يتبنّاه Rook. الأمر wipefs غير موجود على Talos لانعدام shell، لكنّ Rook يفعل ذلك تلقائيًّا عبر CRD CephCluster.spec.storage.useAllDevices=true شريطة أن يكون القرص غير مُوَنَّت.
الخطوة 2 — تثبيت مُشَغِّل Rook
مُشَغِّل Rook يُثَبَّت عبر Helm من المستودع الرسمي. هو المتحكّم الذي يُفسِّر CRDs CephCluster، CephBlockPool، CephFilesystem، وCephObjectStore.
helm repo add rook-release https://charts.rook.io/release
helm repo update
kubectl create namespace rook-ceph
helm install rook-ceph rook-release/rook-ceph \
--version v1.19.5 \
--namespace rook-ceph \
--set crds.enabled=true \
--set monitoring.enabled=true \
--set csi.enableRBDDriver=true \
--set csi.enableCephFSDriver=true
Helm يُنشئ CRDs، نشر rook-ceph-operator، وحسابات RBAC الضرورية. تحقّق من أنّ المُشَغِّل في Running قبل المتابعة: kubectl get pods -n rook-ceph -w. احسب دقيقة إلى دقيقتين. إن دار الـ pod في CrashLoopBackOff، افحص السجلّات؛ السبب النمطي هو CRD قائم من تثبيت سابق.
الخطوة 3 — إعلان عنقود Ceph
عنقود Ceph يُعلَن عبر CRD CephCluster. المنفست أدناه ينشر ثلاثة moniteurs (واحد لكلّ worker)، ثلاثة مديرين، ويتبنّى تلقائيًّا الأقراص المتاحة.
apiVersion: ceph.rook.io/v1
kind: CephCluster
metadata:
name: rook-ceph
namespace: rook-ceph
spec:
cephVersion:
image: quay.io/ceph/ceph:v19.2.3
allowUnsupported: false
dataDirHostPath: /var/lib/rook
skipUpgradeChecks: false
mon:
count: 3
allowMultiplePerNode: false
mgr:
count: 2
modules:
- name: pg_autoscaler
enabled: true
dashboard:
enabled: true
ssl: true
monitoring:
enabled: true
storage:
useAllNodes: false
useAllDevices: false
nodes:
- name: talos-wk-1
devices:
- name: sdb
- name: talos-wk-2
devices:
- name: sdb
- name: talos-wk-3
devices:
- name: sdb
kubectl apply -f cephcluster.yaml
# تابع الإقلاع (5 إلى 10 دقائق)
kubectl -n rook-ceph get cephcluster -w
# Phase يتقدّم: Creating ← Failing ← Connecting ← Ready
حين تُبيّن المرحلة Ready، Ceph يعمل. ثلاثة pods rook-ceph-mon، اثنان rook-ceph-mgr، وثلاثة rook-ceph-osd يجب أن تكون في Running. إن لم يُقلِع OSD، تحقّق من وجود القرص الهدف على الـ worker المُقابل وأنّه حرّ.
الخطوة 4 — فحص صحّة عنقود Ceph
Rook يكشف pod toolbox مُجَهَّزًا بـ Ceph CLI. أداة التشخيص الرئيسية لفهم ما يجري على مستوى عنقود Ceph نفسه.
kubectl apply -f \
https://raw.githubusercontent.com/rook/rook/v1.19.5/deploy/examples/toolbox.yaml
kubectl -n rook-ceph exec -it deploy/rook-ceph-tools -- ceph status
# الخرج يجب الإشارة إلى health: HEALTH_OK و3 osds up
رؤية HEALTH_OK مع ثلاثة OSDs up وثلاثة moniteurs in quorum يُؤكِّد أنّ عنقود Ceph سليم. HEALTH_WARN مقبول مؤقّتًا (PGs في طور التوضع مثلًا) لكن لا يجب أن يستمرّ أكثر من بضع دقائق بعد التثبيت.
الخطوة 5 — إنشاء StorageClass للكتل RBD
RBD (RADOS Block Device) هو شكل كتلي لـ Ceph، نظير قرص افتراضي مُلحَق بـ pod. وضع التخزين الأكثر استعمالًا لقواعد البيانات والأحمال التي تتطلّب وصولًا ReadWriteOnce.
apiVersion: ceph.rook.io/v1
kind: CephBlockPool
metadata:
name: replicapool
namespace: rook-ceph
spec:
failureDomain: host
replicated:
size: 3
requireSafeReplicaSize: true
---
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: rook-ceph-block
annotations:
storageclass.kubernetes.io/is-default-class: "true"
provisioner: rook-ceph.rbd.csi.ceph.com
parameters:
clusterID: rook-ceph
pool: replicapool
imageFormat: "2"
imageFeatures: layering
csi.storage.k8s.io/provisioner-secret-name: rook-csi-rbd-provisioner
csi.storage.k8s.io/provisioner-secret-namespace: rook-ceph
csi.storage.k8s.io/controller-expand-secret-name: rook-csi-rbd-provisioner
csi.storage.k8s.io/controller-expand-secret-namespace: rook-ceph
csi.storage.k8s.io/node-stage-secret-name: rook-csi-rbd-node
csi.storage.k8s.io/node-stage-secret-namespace: rook-ceph
csi.storage.k8s.io/fstype: ext4
allowVolumeExpansion: true
reclaimPolicy: Delete
kubectl apply -f cephblockpool.yaml
kubectl get sc
# rook-ceph-block يجب أن يظهر بـ "(default)"
الـ StorageClass rook-ceph-block مُعلَنة افتراضية: كلّ PVC يُنشَأ دون storageClassName صريح سيستعملها. التكرار ×3 يضمن بقاء volume قابلًا للوصول حتى إن سقط worker (وهو ما سنختبره لاحقًا).
الخطوة 6 — اختبار توفير volume
الاختبار الكلاسيكي إنشاء PVC، نشر pod يستعمله، كتابة ملفّ، حذف الـ pod، إعادة إنشائه، والتحقّق من بقاء الملفّ.
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: test-pvc
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 5Gi
---
apiVersion: v1
kind: Pod
metadata:
name: test-pod
spec:
containers:
- name: app
image: busybox
command: ["sh", "-c", "echo persistent-data > /data/hello.txt && sleep 3600"]
volumeMounts:
- name: data
mountPath: /data
volumes:
- name: data
persistentVolumeClaim:
claimName: test-pvc
kubectl apply -f test-pvc.yaml
# تحقّق من ربط PVC بـ PV
kubectl get pvc test-pvc
# STATUS يجب أن يصير Bound بعد بضع ثوانٍ
# اقرأ الملفّ
kubectl exec test-pod -- cat /data/hello.txt
# يجب عرض: persistent-data
# دمِّر الـ pod وأعد إنشاءه
kubectl delete pod test-pod
kubectl apply -f test-pvc.yaml
kubectl exec test-pod -- cat /data/hello.txt
# يجب أن يظلّ يعرض: persistent-data
الملفّ الذي ينجو من تدمير الـ pod يُؤكِّد أنّ volume RBD مُوَفَّر، مُوَنَّت، ومستمرّ. هي إثبات المفهوم الأدنى الذي يُصادِق على سلسلة CSI كاملة.
الخطوة 7 — تفعيل CephFS لمشاركة الملفّات
للأحمال التي تتطلّب وصولًا ReadWriteMany (Nextcloud، WordPress متعدّد)، CephFS يُوفّر نظام ملفّات مشتركًا. يُفَعَّل عبر CRD CephFilesystem وStorageClass مخصَّصة.
apiVersion: ceph.rook.io/v1
kind: CephFilesystem
metadata:
name: myfs
namespace: rook-ceph
spec:
metadataPool:
failureDomain: host
replicated:
size: 3
dataPools:
- name: data0
failureDomain: host
replicated:
size: 3
metadataServer:
activeCount: 1
activeStandby: true
---
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: rook-cephfs
provisioner: rook-ceph.cephfs.csi.ceph.com
parameters:
clusterID: rook-ceph
fsName: myfs
pool: myfs-data0
csi.storage.k8s.io/provisioner-secret-name: rook-csi-cephfs-provisioner
csi.storage.k8s.io/provisioner-secret-namespace: rook-ceph
csi.storage.k8s.io/controller-expand-secret-name: rook-csi-cephfs-provisioner
csi.storage.k8s.io/controller-expand-secret-namespace: rook-ceph
csi.storage.k8s.io/node-stage-secret-name: rook-csi-cephfs-node
csi.storage.k8s.io/node-stage-secret-namespace: rook-ceph
allowVolumeExpansion: true
reclaimPolicy: Delete
بعد kubectl apply، الـ StorageClass rook-cephfs تُتيح إنشاء PVCs بوضع RWX. عدّة pods على عقد مختلفة يمكنها وَنت نفس الـ volume في الآن نفسه، وهو ما لا يُتيحه RBD.
الخطوة 8 — كشف bucket S3 متوافق عبر ObjectStore
Ceph يُوفّر خدمة متوافقة مع S3 عبر RGW (RADOS Gateway). مفيد جدًّا لاستضافة artefacts البناء، نسخ Velero، أو وسائط تطبيق ويب.
apiVersion: ceph.rook.io/v1
kind: CephObjectStore
metadata:
name: my-store
namespace: rook-ceph
spec:
metadataPool:
failureDomain: host
replicated:
size: 3
dataPool:
failureDomain: host
erasureCoded:
dataChunks: 2
codingChunks: 1
preservePoolsOnDelete: false
gateway:
port: 80
instances: 1
# ملاحظة: EC k=2 m=1 الحدّ الأدنى المطلوب لـ 3 مضيفين في failure domain host.
# فقدان مضيف يستهلك التكرار. لـ homelab جدّي، خَطِّط لـ 4 مضيفين (k+m+1)
# أو الانتقال إلى replicated x3 إن قبلت تكلفة المساحة الإضافية.
kubectl apply -f cephobjectstore.yaml
# أنشئ user S3 (يُولِّد access_key وsecret_key)
kubectl -n rook-ceph exec deploy/rook-ceph-tools -- \
radosgw-admin user create --uid=homelab --display-name="Homelab User"
# دوِّن access_key وsecret_key من الخرج
endpoint الـ S3 قابل للوصول عبر الخدمة rook-ceph-rgw-my-store. للوصول من الخارج، سننشئ Ingress في دليل الرصد. للاختبارات الفورية، port-forward يكفي.
الخطوة 9 — اختبار الصمود لفقدان OSD
قيمة التخزين المُكرَّر تُقاس حين يسقط قرص أو عقدة. نُوقِف عاتيًا worker للتحقّق من بقاء volumes متاحة.
# على Proxmox، أوقف worker
qm stop 1101
# من المحطّة، راقب Ceph
kubectl -n rook-ceph exec deploy/rook-ceph-tools -- ceph status
# health يمرّ إلى HEALTH_WARN، 1 OSD down، لكنّ العنقود يعمل
# تحقّق من أنّ PVC لا يزال صالحًا
kubectl exec test-pod -- cat /data/hello.txt
# يجب أن يبقى يعرض: persistent-data
# أعد تشغيل الـ worker
qm start 1101
sleep 60
kubectl -n rook-ceph exec deploy/rook-ceph-tools -- ceph status
# health يعود إلى HEALTH_OK بعد دقائق (recovery تلقائي)
ملفّ hello.txt الذي يبقى قابلًا للقراءة بينما ثلث التخزين offline يُظهر القيمة الحقيقية لـ Rook-Ceph: homelab ينجو من عطل مادي دون تدخّل بشري. هذا ما لا نملكه مع local-path-provisioner أو NFS على خادم وحيد.
أخطاء شائعة وحلولها
| العَرَض | السبب | الحلّ |
|---|---|---|
| OSDs تبقى Pending | أقراص مُجَزَّأة سلفًا أو مُوَنَّتة | امسح الأقراص (على Talos عبر reset كامل للعقدة) أو غيِّر القرص الهدف |
| HEALTH_WARN مستمرّ بعد التثبيت | عدد PGs قليل أو PG في طور التوضع | فعِّل pg_autoscaler وانتظر؛ وإلّا اضبط osd_pool_default_pg_num |
| PVCs تبقى Pending | StorageClass غير افتراضي، أو CSI provisioner ساقط | تحقّق من kubectl get sc وpods csi-rbdplugin-provisioner |
| pods مع PVC لا تُقلِع بعد reboot عقدة | قفل RBD غير مُحَرَّر في Ceph | rbd lock list ثم rbd lock remove عبر toolbox |
| أداء متَدَنٍّ بعد إضافة OSD | rebalancing جارٍ، طبيعي | انتظر أو أبطئ rebalance بـ osd_max_backfills=1 |
لاستكمال المسار
التخزين المستمرّ في مكانه: كتل RBD لقواعد البيانات، CephFS للمشاركة، ObjectStore لـ S3. أيّ حِمل يُنشَر من الآن سيستطيع طلب volumes دائمة. الخطوة التالية أتمتة نشر هذه الأحمال عبر GitOps. دليل Bootstrap GitOps مع Argo CD على Kubernetes يُفَصِّل تركيب Argo CD 3.4 وبنية مستودع Git المُرافق. للنظرة العامّة، عُد إلى الدليل الرئيسي.
مصادر وتوثيق رسمي
- توثيق Rook 1.19:
rook.io/docs/v1.19 - Quickstart Rook-Ceph:
rook.io/quickstart - توثيق Ceph Squid:
docs.ceph.com/squid - Charts Helm Rook:
artifacthub.io/rook-ceph - CephObjectStore وS3:
rook.io/object-storage - مواصفات CRD CephCluster:
rook.io/ceph-cluster-crd
الخطوة 10 — تفعيل لوحة Ceph والوصول عبر Ingress
لوحة Ceph تُوفّر واجهة ويب تُظهر صحّة العنقود، استعمال كلّ pool، أداء كلّ OSD، والتنبيهات الجارية. مُفَعَّلة في CRD CephCluster (الحقل dashboard.enabled: true) لكن غير مكشوفة خارج العنقود افتراضيًّا. ننشئ Ingress مع cert-manager للوصول HTTPS عبر اسم DNS محلّي.
# استرد كلمة سرّ admin للوحة
kubectl -n rook-ceph get secret rook-ceph-dashboard-password \
-o jsonpath="{['data']['password']}" | base64 --decode
# هذه الكلمة تُتيح الوصول الأوّلي، غيِّرها فور أوّل دخول
# أنشئ Service ClusterIP يكشف اللوحة
kubectl -n rook-ceph patch service rook-ceph-mgr-dashboard \
--type='merge' -p '{"spec":{"type":"ClusterIP"}}'
الـ Ingress المرافق سيُشير إلى هذه الخدمة على المنفذ 8443. ضبط cert-manager لـ Let’s Encrypt سيُفَصَّل في دليل الرصد، الذي ينطبق أيضًا على Grafana وعلى لوحة Ceph. بمجرّد التركيب، URL https://ceph.lan يفتح الواجهة الكاملة.
الخطوة 11 — فهم الاستهلاك وتخطيط النموّ
عامل التكرار 3 المستخدم حتى الآن يعني أنّ كلّ بايت مفيد يحتلّ ثلاثة بايتات على القرص. مع ثلاث OSDs بـ 32 جيغا، المساحة المفيدة الكلّية حوالي 30 جيغا (مع احتساب مساحة نظام Ceph). للانتقال إلى 100 جيغا قابلة للاستعمال، يجب إمّا إضافة ثلاث OSDs بـ 32 جيغا (واحدة لكلّ worker)، أو استبدال الأقراص بأكبر.
إضافة OSD تتمّ بتعديل CRD CephCluster لإعلان القرص الجديد. Rook يُقلِع تلقائيًّا pod OSD جديدًا ويبدأ rebalancing: Ceph يُعيد توزيع البيانات ليكون الحِمل موزَّعًا بانتظام بين كلّ OSDs. rebalancing شفّاف للأحمال؛ يستهلك ببساطة عرض نطاق شبكي وCPU لبضع دقائق إلى ساعات حسب الحجم.
# راقب rebalancing من toolbox
kubectl -n rook-ceph exec deploy/rook-ceph-tools -- ceph status
# misplaced objects ينخفض تدريجيًّا نحو 0
kubectl -n rook-ceph exec deploy/rook-ceph-tools -- ceph osd df
# يعرض الاستعمال لكلّ OSD: يجب التقارب نحو توزيع موحَّد
توزيع موحَّد على كلّ OSDs يُؤكِّد أنّ rebalancing انتهى وأنّ العنقود يستعمل كامل السعة المضافة. لنموّ كبير (> 50% من السعة المضافة)، الأفضل توزيع الإضافة على أيّام لئلّا تُشبَع الشبكة أثناء rebalancing.
الخطوة 12 — نسخ إعداد Ceph احتياطيًّا
كما مع Cilium، يجب وضع إعداد Rook-Ceph تحت إدارة الإصدارات للسماح بإعادة البناء. CRDs CephCluster وCephBlockPool وCephFilesystem وCephObjectStore والـ StorageClasses المُرافقة تُصدَّر وتُلتزَم في مستودع Git لـ Argo CD (الدليل التالي). الأسرار التي يُولّدها Rook (admin keyring، dashboard password) تبقى في العنقود؛ في حال إعادة البناء، يُولّد Rook جديدة.
mkdir -p homelab-gitops/storage
kubectl -n rook-ceph get cephcluster rook-ceph -o yaml > homelab-gitops/storage/cephcluster.yaml
kubectl -n rook-ceph get cephblockpool replicapool -o yaml > homelab-gitops/storage/cephblockpool.yaml
kubectl -n rook-ceph get cephfilesystem myfs -o yaml > homelab-gitops/storage/cephfilesystem.yaml
kubectl -n rook-ceph get cephobjectstore my-store -o yaml > homelab-gitops/storage/cephobjectstore.yaml
kubectl get sc rook-ceph-block rook-cephfs -o yaml > homelab-gitops/storage/storageclasses.yaml
cd homelab-gitops
git add storage/
git commit -m "Initial Rook-Ceph configuration"
رؤية الملفّات الستّة مُضافة لجذر المستودع والـ commit مُنشأ يُتيح إعادة بناء إعداد Ceph في أقلّ من خمس دقائق على عنقود جديد، شريطة وجود أقراص متاحة. هذه قاعدة الصمود التشغيلي: الإعداد يعيش في Git، والعنقود لا يفعل سوى تحقيق نسخة منه.