مثال عملي لربط التخزين المستند إلى Ceph بمجموعة Kubernetes

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

هل تتساءل كيف يعمل؟

مثال عملي لربط التخزين المستند إلى Ceph بمجموعة Kubernetes

إذن، لديك مجموعة Kubernetes في متناول يدك، منتشرة، على سبيل المثال، kubespray. هناك مجموعة Ceph تعمل في مكان قريب - يمكنك أيضًا تثبيتها، على سبيل المثال، باستخدام هذا مجموعة من كتب اللعب. آمل ألا تكون هناك حاجة إلى الإشارة إلى أنه من أجل الإنتاج بينهما يجب أن تكون هناك شبكة ذات نطاق ترددي لا يقل عن 10 جيجابت/ثانية.

إذا كان لديك كل هذا، فلنذهب!

أولاً، دعنا نذهب إلى إحدى عقد مجموعة Ceph ونتأكد من أن كل شيء على ما يرام:

ceph health
ceph -s

بعد ذلك، سنقوم على الفور بإنشاء تجمع لأقراص RBD:

ceph osd pool create kube 32
ceph osd pool application enable kube rbd

دعنا ننتقل إلى مجموعة Kubernetes. هناك، أولا وقبل كل شيء، سنقوم بتثبيت برنامج تشغيل Ceph CSI لـ RBD. سنقوم بالتثبيت، كما هو متوقع، من خلال Helm.
نضيف مستودعًا به مخطط، ونحصل على مجموعة من المتغيرات لمخطط ceph-csi-rbd:

helm repo add ceph-csi https://ceph.github.io/csi-charts
helm inspect values ceph-csi/ceph-csi-rbd > cephrbd.yml

أنت الآن بحاجة إلى ملء ملف cephrbd.yml. للقيام بذلك، تعرف على معرف المجموعة وعناوين IP الخاصة بالشاشات في Ceph:

ceph fsid  # так мы узнаем clusterID
ceph mon dump  # а так увидим IP-адреса мониторов

نقوم بإدخال القيم التي تم الحصول عليها في ملف cephrbd.yml. وفي الوقت نفسه، نقوم بتمكين إنشاء سياسات PSP (سياسات أمان Pod). الخيارات في الأقسام com.nodeplugin и الموفر الموجودة بالفعل في الملف، ويمكن تصحيحها كما هو موضح أدناه:

csiConfig:
  - clusterID: "bcd0d202-fba8-4352-b25d-75c89258d5ab"
    monitors:
      - "v2:172.18.8.5:3300/0,v1:172.18.8.5:6789/0"
      - "v2:172.18.8.6:3300/0,v1:172.18.8.6:6789/0"
      - "v2:172.18.8.7:3300/0,v1:172.18.8.7:6789/0"

nodeplugin:
  podSecurityPolicy:
    enabled: true

provisioner:
  podSecurityPolicy:
    enabled: true

بعد ذلك، كل ما تبقى لنا هو تثبيت المخطط في مجموعة Kubernetes.

helm upgrade -i ceph-csi-rbd ceph-csi/ceph-csi-rbd -f cephrbd.yml -n ceph-csi-rbd --create-namespace

عظيم، سائق RBD يعمل!
لنقم بإنشاء فئة تخزين جديدة في Kubernetes. يتطلب هذا مرة أخرى القليل من الترقيع مع Ceph.

نقوم بإنشاء مستخدم جديد في Ceph ونمنحه حقوق الكتابة في التجمع كوبي:

ceph auth get-or-create client.rbdkube mon 'profile rbd' osd 'profile rbd pool=kube'

الآن دعونا نرى أن مفتاح الوصول لا يزال موجودًا:

ceph auth get-key client.rbdkube

سيخرج الأمر شيئًا مثل هذا:

AQCO9NJbhYipKRAAMqZsnqqS/T8OYQX20xIa9A==

دعونا نضيف هذه القيمة إلى Secret في مجموعة Kubernetes - حيث نحتاج إليها مفتاح المستخدم:

---
apiVersion: v1
kind: Secret
metadata:
  name: csi-rbd-secret
  namespace: ceph-csi-rbd
stringData:
  # Значения ключей соответствуют имени пользователя и его ключу, как указано в
  # кластере Ceph. ID юзера должен иметь доступ к пулу,
  # указанному в storage class
  userID: rbdkube
  userKey: <user-key>

ونخلق سرنا:

kubectl apply -f secret.yaml

بعد ذلك، نحتاج إلى بيان StorageClass مثل هذا:

---
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
   name: csi-rbd-sc
provisioner: rbd.csi.ceph.com
parameters:
   clusterID: <cluster-id>
   pool: kube

   imageFeatures: layering

   # Эти секреты должны содержать данные для авторизации
   # в ваш пул.
   csi.storage.k8s.io/provisioner-secret-name: csi-rbd-secret
   csi.storage.k8s.io/provisioner-secret-namespace: ceph-csi-rbd
   csi.storage.k8s.io/controller-expand-secret-name: csi-rbd-secret
   csi.storage.k8s.io/controller-expand-secret-namespace: ceph-csi-rbd
   csi.storage.k8s.io/node-stage-secret-name: csi-rbd-secret
   csi.storage.k8s.io/node-stage-secret-namespace: ceph-csi-rbd

   csi.storage.k8s.io/fstype: ext4

reclaimPolicy: Delete
allowVolumeExpansion: true
mountOptions:
  - discard

يجب ملؤها معرف الكتلة، وهو ما تعلمناه بالفعل من قبل الفريق com.ceph fsid، وقم بتطبيق هذا البيان على مجموعة Kubernetes:

kubectl apply -f storageclass.yaml

للتحقق من كيفية عمل المجموعات معًا، لنقم بإنشاء PVC التالي (مطالبة الحجم المستمر):

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: rbd-pvc
spec:
  accessModes:
  - ReadWriteOnce
  resources:
    requests:
      storage: 1Gi
  storageClassName: csi-rbd-sc

دعونا نرى على الفور كيف قام Kubernetes بإنشاء المجلد المطلوب في Ceph:

kubectl get pvc
kubectl get pv

يبدو أن كل شيء رائع! كيف يبدو هذا على الجانب Ceph؟
نحصل على قائمة بالمجلدات الموجودة في المجمع ونعرض معلومات حول المجلد الخاص بنا:

rbd ls -p kube
rbd -p kube info csi-vol-eb3d257d-8c6c-11ea-bff5-6235e7640653  # тут, конечно же, будет другой ID тома, который выдала предыдущая команда

الآن دعونا نرى كيف يعمل تغيير حجم وحدة تخزين RBD.
قم بتغيير حجم الصوت في ملف بيان PVC.yaml إلى 2Gi وقم بتطبيقه:

kubectl apply -f pvc.yaml

دعنا ننتظر تفعيل التغييرات وننظر إلى حجم الصوت مرة أخرى.

rbd -p kube info csi-vol-eb3d257d-8c6c-11ea-bff5-6235e7640653

kubectl get pv
kubectl get pvc

نرى أن حجم PVC لم يتغير. لمعرفة السبب، يمكنك الاستعلام عن Kubernetes للحصول على وصف YAML لـ PVC:

kubectl get pvc rbd-pvc -o yaml

ها هي المشكلة:

الرسالة: في انتظار قيام المستخدم (بإعادة) تشغيل الكبسولة لإنهاء تغيير حجم نظام الملفات لوحدة التخزين على العقدة. النوع: FileSystemResizePending

أي أن القرص قد نما، لكن نظام الملفات الموجود عليه لم ينمو.
لتنمية نظام الملفات، تحتاج إلى تحميل وحدة التخزين. في بلدنا، لا يتم استخدام PVC/PV الذي تم إنشاؤه حاليًا بأي شكل من الأشكال.

يمكننا إنشاء حجرة اختبار، على سبيل المثال مثل هذا:

---
apiVersion: v1
kind: Pod
metadata:
  name: csi-rbd-demo-pod
spec:
  containers:
    - name: web-server
      image: nginx:1.17.6
      volumeMounts:
        - name: mypvc
          mountPath: /data
  volumes:
    - name: mypvc
      persistentVolumeClaim:
        claimName: rbd-pvc
        readOnly: false

والآن دعونا نلقي نظرة على PVC:

kubectl get pvc

لقد تغير الحجم، كل شيء على ما يرام.

في الجزء الأول، عملنا مع جهاز كتلة RBD (يرمز إلى جهاز Rados Block)، ولكن لا يمكن القيام بذلك إذا كانت الخدمات الصغيرة المختلفة بحاجة إلى العمل مع هذا القرص في وقت واحد. يعد CephFS أكثر ملاءمة للعمل مع الملفات بدلاً من صور القرص.
باستخدام مثال مجموعات Ceph وKubernetes، سنقوم بتكوين CSI والكيانات الضرورية الأخرى للعمل مع CephFS.

لنحصل على القيم من مخطط Helm الجديد الذي نحتاجه:

helm inspect values ceph-csi/ceph-csi-cephfs > cephfs.yml

مرة أخرى، تحتاج إلى ملء ملف cephfs.yml. كما كان من قبل، سوف تساعد أوامر Ceph:

ceph fsid
ceph mon dump

املأ الملف بقيم مثل هذه:

csiConfig:
  - clusterID: "bcd0d202-fba8-4352-b25d-75c89258d5ab"
    monitors:
      - "172.18.8.5:6789"
      - "172.18.8.6:6789"
      - "172.18.8.7:6789"

nodeplugin:
  httpMetrics:
    enabled: true
    containerPort: 8091
  podSecurityPolicy:
    enabled: true

provisioner:
  replicaCount: 1
  podSecurityPolicy:
    enabled: true

يرجى ملاحظة أن عناوين الشاشة محددة في نموذج بسيط بعنوان:port. لتركيب cephfs على عقدة، يتم نقل هذه العناوين إلى وحدة kernel، التي لا تعرف بعد كيفية العمل مع بروتوكول المراقبة v2.
نقوم بتغيير المنفذ الخاص بـ httpMetrics (سيذهب Prometheus إلى هناك لمراقبة المقاييس) بحيث لا يتعارض مع nginx-proxy، الذي تم تثبيته بواسطة Kubespray. قد لا تحتاج هذا.

قم بتثبيت مخطط Helm في مجموعة Kubernetes:

helm upgrade -i ceph-csi-cephfs ceph-csi/ceph-csi-cephfs -f cephfs.yml -n ceph-csi-cephfs --create-namespace

دعنا نذهب إلى مخزن بيانات Ceph لإنشاء مستخدم منفصل هناك. تنص الوثائق على أن موفر CephFS يتطلب حقوق وصول مسؤول المجموعة. لكننا سنقوم بإنشاء مستخدم منفصل fs بحقوق محدودة:

ceph auth get-or-create client.fs mon 'allow r' mgr 'allow rw' mds 'allow rws' osd 'allow rw pool=cephfs_data, allow rw pool=cephfs_metadata'

ودعونا نلقي نظرة فورًا على مفتاح الوصول الخاص به، وسنحتاجه لاحقًا:

ceph auth get-key client.fs

لنقم بإنشاء Secret وStorageClass منفصلين.
لا جديد، لقد رأينا هذا بالفعل في مثال RBD:

---
apiVersion: v1
kind: Secret
metadata:
  name: csi-cephfs-secret
  namespace: ceph-csi-cephfs
stringData:
  # Необходимо для динамически создаваемых томов
  adminID: fs
  adminKey: <вывод предыдущей команды>

تطبيق البيان:

kubectl apply -f secret.yaml

والآن - فئة تخزين منفصلة:

---
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: csi-cephfs-sc
provisioner: cephfs.csi.ceph.com
parameters:
  clusterID: <cluster-id>

  # Имя файловой системы CephFS, в которой будет создан том
  fsName: cephfs

  # (необязательно) Пул Ceph, в котором будут храниться данные тома
  # pool: cephfs_data

  # (необязательно) Разделенные запятыми опции монтирования для Ceph-fuse
  # например:
  # fuseMountOptions: debug

  # (необязательно) Разделенные запятыми опции монтирования CephFS для ядра
  # См. man mount.ceph чтобы узнать список этих опций. Например:
  # kernelMountOptions: readdir_max_bytes=1048576,norbytes

  # Секреты должны содержать доступы для админа и/или юзера Ceph.
  csi.storage.k8s.io/provisioner-secret-name: csi-cephfs-secret
  csi.storage.k8s.io/provisioner-secret-namespace: ceph-csi-cephfs
  csi.storage.k8s.io/controller-expand-secret-name: csi-cephfs-secret
  csi.storage.k8s.io/controller-expand-secret-namespace: ceph-csi-cephfs
  csi.storage.k8s.io/node-stage-secret-name: csi-cephfs-secret
  csi.storage.k8s.io/node-stage-secret-namespace: ceph-csi-cephfs

  # (необязательно) Драйвер может использовать либо ceph-fuse (fuse), 
  # либо ceph kernelclient (kernel).
  # Если не указано, будет использоваться монтирование томов по умолчанию,
  # это определяется поиском ceph-fuse и mount.ceph
  # mounter: kernel
reclaimPolicy: Delete
allowVolumeExpansion: true
mountOptions:
  - debug

دعونا نملأها هنا معرف الكتلة وقابلة للتطبيق في Kubernetes:

kubectl apply -f storageclass.yaml

Проверка

للتحقق، كما في المثال السابق، لنقم بإنشاء PVC:

---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: csi-cephfs-pvc
spec:
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 5Gi
  storageClassName: csi-cephfs-sc

والتحقق من وجود PVC/PV:

kubectl get pvc
kubectl get pv

إذا كنت تريد الاطلاع على الملفات والأدلة في CephFS، فيمكنك تركيب نظام الملفات هذا في مكان ما. على سبيل المثال كما هو موضح أدناه.

دعنا ننتقل إلى إحدى عقد مجموعة Ceph وننفذ الإجراءات التالية:

# Точка монтирования
mkdir -p /mnt/cephfs

# Создаём файл с ключом администратора
ceph auth get-key client.admin >/etc/ceph/secret.key

# Добавляем запись в /etc/fstab
# !! Изменяем ip адрес на адрес нашего узла
echo "172.18.8.6:6789:/ /mnt/cephfs ceph name=admin,secretfile=/etc/ceph/secret.key,noatime,_netdev    0       2" >> /etc/fstab

mount /mnt/cephfs

بالطبع، تركيب FS على عقدة Ceph مثل هذه مناسب فقط لأغراض التدريب، وهو ما نفعله على موقعنا دورات سلرم. لا أعتقد أن أي شخص قد يفعل ذلك أثناء الإنتاج، فهناك خطر كبير يتمثل في محو الملفات المهمة عن طريق الخطأ.

وأخيرًا، دعونا نتحقق من كيفية عمل الأشياء مع تغيير حجم وحدات التخزين في حالة CephFS. دعنا نعود إلى Kubernetes ونقوم بتحرير بياننا الخاص بـ PVC - قم بزيادة الحجم هناك، على سبيل المثال، إلى 7Gi.

لنطبق الملف المحرر:

kubectl apply -f pvc.yaml

دعونا نلقي نظرة على الدليل المثبت لنرى كيف تغيرت الحصة:

getfattr -n ceph.quota.max_bytes <каталог-с-данными>

لكي يعمل هذا الأمر، قد تحتاج إلى تثبيت الحزمة على نظامك ATTR.

العيون خائفة ، ولكن اليدين تفعل

تبدو كل هذه التعويذات وبيانات YAML الطويلة معقدة ظاهريًا، ولكن في الواقع، يتقنها طلاب Slurm بسرعة كبيرة.
في هذه المقالة لم نتعمق في الغابة - هناك وثائق رسمية لذلك. إذا كنت مهتمًا بتفاصيل إعداد تخزين Ceph باستخدام مجموعة Kubernetes، فستساعدك هذه الروابط:

المبادئ العامة لعمل Kubernetes مع المجلدات
وثائق RBD
دمج RBD وKubernetes من منظور Ceph
دمج RBD وKubernetes من منظور CSI
وثائق CephFS العامة
دمج CephFS وKubernetes من منظور CSI

في دورة Slurm قاعدة Kubernetes يمكنك المضي قدمًا قليلاً ونشر تطبيق حقيقي في Kubernetes يستخدم CephFS كمخزن للملفات. من خلال طلبات GET/POST، ستتمكن من نقل الملفات إلى Ceph واستلامها منها.

وإذا كنت مهتمًا أكثر بتخزين البيانات، فقم بالتسجيل دورة جديدة على Ceph. أثناء استمرار الاختبار التجريبي، يمكن الحصول على الدورة بسعر مخفض ويمكنك التأثير على محتواها.

مؤلف المقال: ألكسندر شفالوف، مهندس ممارس جسر جنوبي، مدير Kubernetes معتمد، مؤلف ومطور لدورات Slurm.

المصدر: www.habr.com