المكونات الإضافية لوحدة التخزين لتخزين Kubernetes: من Flexvolume إلى CSI

المكونات الإضافية لوحدة التخزين لتخزين Kubernetes: من Flexvolume إلى CSI

عندما كان Kubernetes لا يزال الإصدار 1.0.0، كانت هناك مكونات إضافية لوحدة التخزين. كانت هناك حاجة إليها لتوصيل الأنظمة بـ Kubernetes لتخزين بيانات الحاوية الدائمة (الدائمة). كان عددهم صغيرًا، وكان من بين الأوائل موفرو التخزين مثل GCE PD وCeph وAWS EBS وغيرهم.

تم تسليم المكونات الإضافية مع Kubernetes، ولهذا السبب حصلت على اسمها - in-tree. ومع ذلك، بالنسبة للكثيرين، تبين أن المجموعة الحالية من هذه المكونات الإضافية غير كافية. أضاف الحرفيون مكونات إضافية بسيطة إلى جوهر Kubernetes باستخدام التصحيحات، وبعد ذلك قاموا بتجميع Kubernetes الخاص بهم وتثبيته على خوادمهم. ولكن مع مرور الوقت، أدرك مطورو Kubernetes ذلك سمك لا يمكن حل المشكلة. يحتاج الناس قصبة الصيد. وفي إصدار Kubernetes v1.2.0 ظهر...

البرنامج المساعد Flexvolume: الحد الأدنى من قصبة الصيد

قام مطورو Kubernetes بإنشاء البرنامج الإضافي FlexVolume، والذي كان عبارة عن إطار منطقي للمتغيرات وطرق العمل مع برامج تشغيل Flexvolume التي ينفذها مطورو الطرف الثالث.

دعونا نتوقف ونلقي نظرة فاحصة على ما هو برنامج تشغيل FlexVolume. هذا أمر مؤكد ملف تنفيذي (ملف ثنائي، برنامج Python النصي، برنامج Bash النصي، وما إلى ذلك)، والذي، عند تنفيذه، يأخذ وسيطات سطر الأوامر كمدخلات ويعيد رسالة تحتوي على حقول معروفة مسبقًا بتنسيق JSON. وفقًا للاتفاقية، تكون وسيطة سطر الأوامر الأولى دائمًا طريقة، والوسيطات المتبقية هي معلماتها.

المكونات الإضافية لوحدة التخزين لتخزين Kubernetes: من Flexvolume إلى CSI
مخطط اتصال لمشاركات CIFS في OpenShift. برنامج تشغيل Flexvolume - في المركز مباشرةً

الحد الأدنى من مجموعة الأساليب يشبه هذا:

flexvolume_driver mount # отвечает за присоединение тома к pod'у
# Формат возвращаемого сообщения:
{
  "status": "Success"/"Failure"/"Not supported",
  "message": "По какой причине был возвращен именно такой статус",
}

flexvolume_driver unmount # отвечает за отсоединение тома от pod'а
# Формат возвращаемого сообщения:
{
  "status": "Success"/"Failure"/"Not supported",
  "message": "По какой причине был возвращен именно такой статус",
}

flexvolume_driver init # отвечает за инициализацию плагина
# Формат возвращаемого сообщения:
{
  "status": "Success"/"Failure"/"Not supported",
  "message": "По какой причине был возвращен именно такой статус",
  // Определяет, использует ли драйвер методы attach/deatach
  "capabilities":{"attach": True/False}
}

استخدام الأساليب attach и detach سيحدد السيناريو الذي سيعمل فيه kubelet في المستقبل عند استدعاء السائق. هناك أيضًا طرق خاصة expandvolume и expandfs، المسؤولة عن تغيير حجم الصوت ديناميكيًا.

كمثال على التغييرات التي تضيفها الطريقة expandvolumeومعها القدرة على تغيير حجم وحدات التخزين في الوقت الفعلي، يمكنك التعرف عليها طلب السحب لدينا في مشغل Rook Ceph.

وإليك مثال على تنفيذ برنامج التشغيل Flexvolume للعمل مع NFS:

usage() {
    err "Invalid usage. Usage: "
    err "t$0 init"
    err "t$0 mount <mount dir> <json params>"
    err "t$0 unmount <mount dir>"
    exit 1
}

err() {
    echo -ne $* 1>&2
}

log() {
    echo -ne $* >&1
}

ismounted() {
    MOUNT=`findmnt -n ${MNTPATH} 2>/dev/null | cut -d' ' -f1`
    if [ "${MOUNT}" == "${MNTPATH}" ]; then
        echo "1"
    else
        echo "0"
    fi
}

domount() {
    MNTPATH=$1

    NFS_SERVER=$(echo $2 | jq -r '.server')
    SHARE=$(echo $2 | jq -r '.share')

    if [ $(ismounted) -eq 1 ] ; then
        log '{"status": "Success"}'
        exit 0
    fi

    mkdir -p ${MNTPATH} &> /dev/null

    mount -t nfs ${NFS_SERVER}:/${SHARE} ${MNTPATH} &> /dev/null
    if [ $? -ne 0 ]; then
        err "{ "status": "Failure", "message": "Failed to mount ${NFS_SERVER}:${SHARE} at ${MNTPATH}"}"
        exit 1
    fi
    log '{"status": "Success"}'
    exit 0
}

unmount() {
    MNTPATH=$1
    if [ $(ismounted) -eq 0 ] ; then
        log '{"status": "Success"}'
        exit 0
    fi

    umount ${MNTPATH} &> /dev/null
    if [ $? -ne 0 ]; then
        err "{ "status": "Failed", "message": "Failed to unmount volume at ${MNTPATH}"}"
        exit 1
    fi

    log '{"status": "Success"}'
    exit 0
}

op=$1

if [ "$op" = "init" ]; then
    log '{"status": "Success", "capabilities": {"attach": false}}'
    exit 0
fi

if [ $# -lt 2 ]; then
    usage
fi

shift

case "$op" in
    mount)
        domount $*
        ;;
    unmount)
        unmount $*
        ;;
    *)
        log '{"status": "Not supported"}'
        exit 0
esac

exit 1

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

/usr/libexec/kubernetes/kubelet-plugins/volume/exec/имя_поставщика_хранилища~имя_драйвера/

... ولكن عند استخدام توزيعات Kubernetes مختلفة (OpenShift، Rancher...) قد يكون المسار مختلفًا.

مشاكل Flexvolume: كيفية صب صنارة الصيد بشكل صحيح؟

تبين أن تحميل برنامج التشغيل Flexvolume إلى عقد المجموعة مهمة غير تافهة. بعد إجراء العملية يدويًا مرة واحدة، من السهل مواجهة موقف تظهر فيه عقد جديدة في المجموعة: بسبب إضافة عقدة جديدة، أو القياس الأفقي التلقائي، أو - ما هو أسوأ - استبدال العقدة بسبب عطل. في هذه الحالة، يجب أن يتم العمل مع التخزين على هذه العقد مستحيل، حتى تقوم بإضافة برنامج التشغيل Flexvolume يدويًا إليهم.

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

فيما يلي مثال على DaemonSet لتصميم مكون إضافي Flexvolume:

apiVersion: extensions/v1beta1
kind: DaemonSet
metadata:
  name: flex-set
spec:
  template:
    metadata:
      name: flex-deploy
      labels:
        app: flex-deploy
    spec:
      containers:
        - image: <deployment_image>
          name: flex-deploy
          securityContext:
              privileged: true
          volumeMounts:
            - mountPath: /flexmnt
              name: flexvolume-mount
      volumes:
        - name: flexvolume-mount
          hostPath:
            path: <host_driver_directory>

... ومثال لبرنامج نصي Bash لتصميم برنامج تشغيل Flexvolume:

#!/bin/sh

set -o errexit
set -o pipefail

VENDOR=k8s.io
DRIVER=nfs

driver_dir=$VENDOR${VENDOR:+"~"}${DRIVER}
if [ ! -d "/flexmnt/$driver_dir" ]; then
  mkdir "/flexmnt/$driver_dir"
fi

cp "/$DRIVER" "/flexmnt/$driver_dir/.$DRIVER"
mv -f "/flexmnt/$driver_dir/.$DRIVER" "/flexmnt/$driver_dir/$DRIVER"

while : ; do
  sleep 3600
done

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

المكونات الإضافية لوحدة التخزين لتخزين Kubernetes: من Flexvolume إلى CSI
رسم تخطيطي للعمل مع Ceph في مشغل Rook: يوجد برنامج تشغيل Flexvolume في الرسم التخطيطي داخل وكيل Rook

المشكلة التالية عند استخدام برامج تشغيل Flexvolume هي مشكلة معظم وحدات التخزين على عقدة نظام المجموعة ويجب تثبيت البرامج اللازمة لذلك (على سبيل المثال، الحزمة المشتركة ceph لـ Ceph). في البداية، لم يتم تصميم البرنامج المساعد Flexvolume لتنفيذ مثل هذه الأنظمة المعقدة.

يمكن رؤية الحل الأصلي لهذه المشكلة في تطبيق برنامج تشغيل Flexvolume لمشغل Rook:

تم تصميم برنامج التشغيل نفسه كعميل RPC. يوجد مقبس IPC للاتصال في نفس الدليل مثل برنامج التشغيل نفسه. نتذكر أنه لنسخ ملفات برنامج التشغيل، سيكون من الجيد استخدام DaemonSet، الذي يربط الدليل ببرنامج التشغيل كوحدة تخزين. بعد نسخ ملفات برنامج تشغيل الرخ الضرورية، لا تموت هذه الكبسولة، ولكنها تتصل بمقبس IPC من خلال وحدة التخزين المرفقة كخادم RPC كامل. تم بالفعل تثبيت حزمة ceph-common داخل حاوية الكبسولة. يضمن مقبس IPC أن يتواصل kubelet مع البود الموجود على نفس العقدة بالضبط. كل شيء عبقري بسيط!..

وداعًا، أيها الحنون... المكونات الإضافية داخل الشجرة!

اكتشف مطورو Kubernetes أن عدد المكونات الإضافية للتخزين داخل النواة يبلغ عشرين. والتغيير في كل واحد منهم، بطريقة أو بأخرى، يمر عبر دورة إصدار Kubernetes الكاملة.

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

الوضع أكثر من كوميدي، ألا تعتقد ذلك؟ وأصبح من الواضح للمجتمع بأكمله أن هذا النهج لم يكن ناجحا. بقرار متعمد، يعلن مطورو Kubernetes أن المكونات الإضافية الجديدة للعمل مع التخزين لن يتم قبولها في النواة بعد الآن. بالإضافة إلى ذلك، كما نعلم بالفعل، تم تحديد عدد من أوجه القصور في تنفيذ البرنامج الإضافي Flexvolume...

تم استدعاء أحدث مكون إضافي مضاف لوحدات التخزين في Kubernetes، CSI، لإغلاق مشكلة التخزين المستمر للبيانات مرة واحدة وإلى الأبد. تم الإعلان عن إصدار ألفا الخاص به، والذي يشار إليه بشكل كامل باسم Out-of-Tree CSI Volume Plugins، في الإصدار Kubernetes 1.9 تحديث.

واجهة تخزين الحاويات، أو قضيب الغزل CSI 3000!

بادئ ذي بدء، أود أن أشير إلى أن CSI ليس مجرد مكون إضافي للحجم، ولكنه حقيقي معيار حول إنشاء مكونات مخصصة للعمل مع مستودعات البيانات. كان من المفترض أن "تتعلم" أنظمة تنسيق الحاويات مثل Kubernetes وMesos كيفية العمل مع المكونات المنفذة وفقًا لهذا المعيار. والآن تعلمت بالفعل Kubernetes.

ما هو هيكل البرنامج المساعد CSI في Kubernetes؟ يعمل البرنامج المساعد CSI مع برامج تشغيل خاصة (برامج تشغيل منظمة التضامن المسيحي الدولية) كتبه مطورو الطرف الثالث. يجب أن يتكون برنامج تشغيل CSI في Kubernetes على الأقل من مكونين (pods):

  • مراقب — يدير المخازن الدائمة الخارجية. يتم تنفيذه كخادم gRPC، حيث يتم استخدام البدائي StatefulSet.
  • العقدة - مسؤول عن تركيب التخزين المستمر على عقد المجموعة. يتم تنفيذه أيضًا كخادم gRPC، ولكنه يستخدم البدائي DaemonSet.

المكونات الإضافية لوحدة التخزين لتخزين Kubernetes: من Flexvolume إلى CSI
كيف يعمل البرنامج المساعد CSI في Kubernetes

يمكنك التعرف على بعض التفاصيل الأخرى الخاصة بعمل CSI على سبيل المثال من مقال “فهم C.S.I." الترجمة التي نشرنا قبل عام.

مزايا مثل هذا التنفيذ

  • بالنسبة للأشياء الأساسية مثل تسجيل برنامج تشغيل للعقدة، قام مطورو Kubernetes بتنفيذ مجموعة من الحاويات. لم تعد بحاجة إلى إنشاء استجابة JSON بالإمكانات بنفسك، كما حدث مع المكون الإضافي Flexvolume.
  • بدلاً من "إدخال" الملفات القابلة للتنفيذ إلى العقد، نقوم الآن بتحميل البودات إلى المجموعة. هذا ما نتوقعه في البداية من Kubernetes: تتم جميع العمليات داخل الحاويات المنشورة باستخدام أساسيات Kubernetes.
  • لم تعد بحاجة إلى تطوير خادم RPC وعميل RPC لتنفيذ برامج التشغيل المعقدة. تم تنفيذ العميل لنا بواسطة مطوري Kubernetes.
  • يعد تمرير الوسائط للعمل عبر بروتوكول gRPC أكثر ملاءمة ومرونة وموثوقية من تمريرها عبر وسيطات سطر الأوامر. لفهم كيفية إضافة دعم لمقاييس استخدام الحجم إلى CSI عن طريق إضافة طريقة gRPC موحدة، يمكنك قراءة: طلب السحب لدينا لسائق vsphere-CSI.
  • يتم الاتصال عبر مقابس IPC، حتى لا يتم الخلط بين ما إذا كان kubelet قد أرسل الطلب إلى الكبسولة الصحيحة.

هل تذكرك هذه القائمة بأي شيء؟ مزايا CSI هي حل تلك المشاكل نفسهاوالتي لم يتم أخذها بعين الاعتبار عند تطوير البرنامج الإضافي Flexvolume.

النتائج

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

في بداية عام 2019، الإضافات داخل الشجرة تم إعلانها عفا عليها الزمن. نحن نخطط لمواصلة دعم البرنامج الإضافي Flexvolume، لكننا لن نقوم بتطوير وظائف جديدة له.

نحن أنفسنا لدينا بالفعل خبرة في استخدام ceph-csi وvsphere-csi ومستعدون للإضافة إلى هذه القائمة! حتى الآن، تتعامل CSI مع المهام الموكلة إليها بقوة، لكننا سننتظر ونرى.

لا تنس أن كل ما هو جديد هو إعادة تفكير جيدة في القديم!

PS

اقرأ أيضًا على مدونتنا:

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

إضافة تعليق