تجربتنا في تطوير محرك CSI في Kubernetes لـ Yandex.Cloud



يسعدنا أن نعلن أن Flant تعمل على تجديد مساهمتها في أدوات المصدر المفتوح لـ Kubernetes من خلال إصدار نسخة ألفا من برنامج تشغيل CSI (واجهة تخزين الحاويات) لـ Yandex.Cloud.

ولكن قبل الانتقال إلى تفاصيل التنفيذ ، سنجيب على سؤال لماذا يكون ذلك ضروريًا على الإطلاق عندما تمتلك Yandex بالفعل خدمة Managed Service لخدمة Kubernetes .

المقدمة


لماذا هذا؟


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

تحتوي المجموعات التي تستخدم deckhouse على جميع المكونات اللازمة للعمل: الموازنات ، والمراقبة مع الرسوم البيانية والمقاييس والتنبيهات المناسبة ، ومصادقة المستخدم من خلال موفرين خارجيين للوصول إلى جميع لوحات المعلومات ، وما إلى ذلك. ليس من المنطقي وضع مثل هذه المجموعة "المضخمة" في حل مُدار ، لأنه غالبًا ما يكون مستحيلًا أو سيؤدي إلى الحاجة إلى تعطيل نصف المكونات.

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

ما هو ولمن؟


لذلك، تحدثنا بالفعل عن النهج الحديث لتخزين في Kubernetes: كيف CSI يعمل و كيف جاء المجتمع لهذا النهج.

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

كأساس للتطوير ، أخذنا برنامج تشغيل CSI للسحابة DigitalOcean وفكرتين من برنامج التشغيل لـ GCP ، نظرًا لأن التفاعل مع واجهة برمجة التطبيقات لهذه الغيوم (Google و Yandex) له عدد من أوجه التشابه. على وجه الخصوص ، API ويعيد كل من GCP و Yandex كائنًا Operationلتتبع حالة العمليات الطويلة (على سبيل المثال ، إنشاء قرص جديد). للتفاعل مع Yandex.Cloud API ، يتم استخدام Yandex.Cloud Go SDK .

يتم نشر نتيجة العمل الذي تم القيام به على GitHub وقد يكون مفيدًا لأولئك الذين يستخدمون لسبب ما التثبيت الخاص بهم لـ Kubernetes على Yandex.Cloud الأجهزة الظاهرية (ولكن ليس مجموعة جاهزة مُدارة) ويرغبون في استخدام أقراص (طلب) عبر CSI.

التنفيذ


دلائل الميزات


يدعم برنامج التشغيل حاليًا الوظائف التالية:

  • ترتيب الأقراص في جميع مناطق المجموعة وفقًا لطوبولوجيا العقد في المجموعة ؛
  • إزالة الأقراص المطلوبة مسبقًا ؛
  • تغيير الحجم دون اتصال للأقراص ( لا يدعم Yandex. Cloud الزيادة في الأقراص التي يتم تركيبها على جهاز افتراضي). حول كيفية تعديل برنامج التشغيل من أجل تغيير الحجم بألم ممكن ، انظر أدناه.

في المستقبل ، من المخطط تنفيذ الدعم لإنشاء وإزالة أقراص اللقطة.

الصعوبة الرئيسية والتغلب عليها


إن عدم القدرة على توسيع الأقراص في الوقت الحقيقي في Yandex.Cloud API هو قيود تعقيد عملية تغيير الحجم لـ PV (حجم مستمر): في هذه الحالة ، من الضروري إيقاف جراب التطبيق الذي يستخدم القرص ، ويمكن أن يتسبب ذلك في التطبيقات.

وفقًا لمواصفات CSI ، إذا أبلغت وحدة تحكم CSI أنها لا يمكنها إلا تغيير حجم الأقراص "غير المتصلة" ( VolumeExpansion.OFFLINE) ، فيجب أن تتم عملية زيادة القرص على النحو التالي:

إذا كان المكون الإضافي لديه VolumeExpansion.OFFLINEإمكانية التوسع فقط وتم نشر الحجم حاليًا أو متاحًا على عقدة ، ControllerExpandVolumeفيجب الاتصال به فقط بعد:

  • يحتوي المكوِّن الإضافي على PUBLISH_UNPUBLISH_VOLUMEإمكانية التحكم ControllerUnpublishVolumeوقد تم استدعاءه بنجاح.

او اخرى

  • المكون الإضافي ليس لديه PUBLISH_UNPUBLISH_VOLUMEإمكانية تحكم ، المكون الإضافي لديه STAGE_UNSTAGE_VOLUMEقدرة عقدة ، NodeUnstageVolumeوقد اكتمل بنجاح.

او اخرى

  • لم يكن لديك البرنامج المساعد تحكم PUBLISH_UNPUBLISH_VOLUMEالقدرة، ولا عقدة STAGE_UNSTAGE_VOLUMEالقدرة، و NodeUnpublishVolumeتمت بنجاح.

وهذا يعني في الأساس الحاجة إلى فصل القرص عن الجهاز الظاهري قبل زيادته.

ومع ذلك ، لسوء الحظ ، فإن تنفيذ مواصفات CSI من خلال المسح الجانبي لا يفي بالمتطلبات التالية:

  • في الحاوية الجانبية csi-attacher، التي يجب أن تكون مسؤولة عن وجود الفجوة اللازمة بين الحوامل ، لا يتم تنفيذ هذه الوظيفة ببساطة مع تغيير الحجم في وضع عدم الاتصال. بدأ مناقشة حول هذا هنا .
  • ما هي الحاوية الجانبية في هذا السياق؟ لا يتفاعل المكون الإضافي CSI نفسه مع Kubernetes API ، ولكنه يستجيب فقط لمكالمات gRPC التي ترسلها حاويات السيارة الجانبية إليه. يتم تطوير هذه الأخيرة من قبل مجتمع Kubernetes.

في حالتنا (CSI plugin) ، تكون عملية زيادة القرص كما يلي:

  1. نتلقى مكالمة gRPC ControllerExpandVolume؛
  2. نحن نحاول زيادة القرص في واجهة برمجة التطبيقات ، ولكن لدينا خطأ حول استحالة تنفيذ العملية ، حيث تم تركيب القرص ؛
  3. نقوم بحفظ معرف القرص في الخريطة التي تحتوي على الأقراص التي تحتاج إلى إجراء عملية زيادة لها. وعلاوة على ذلك الإيجاز سنطالب هذه الخريطة كما volumeResizeRequired.
  4. يدوياً حذف جراب يستخدم القرص. ستقوم Kubernetes بإعادة تشغيله. بحيث لا يتوفر للقرص وقت للتثبيت ( ControllerPublishVolume) قبل إتمام عملية الزيادة عند محاولة التثبيت ، نتحقق من أن هذا القرص لا يزال قيد التشغيل volumeResizeRequiredونرجع خطأ ؛
  5. يحاول برنامج تشغيل CSI إعادة تنفيذ عملية تغيير الحجم. إذا كانت العملية ناجحة ، فاحذف القرص من volumeResizeRequired؛
  6. لان معرّف القرص مفقود في volumeResizeRequired، إنه ControllerPublishVolumeناجح ، تم تحميل القرص ، يبدأ pod.

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

func DefaultControllerRateLimiter() RateLimiter {
  return NewMaxOfRateLimiter(
  NewItemExponentialFailureRateLimiter(5*time.Millisecond, 1000*time.Second),
  // 10 qps, 100 bucket size.  This is only for retry speed and its only the overall factor (not per item)
  &BucketRateLimiter{Limiter: rate.NewLimiter(rate.Limit(10), 100)},
  )
}

يمكن أن يؤدي هذا بشكل دوري إلى حقيقة أن عملية زيادة القرص تمتد لأكثر من 15 دقيقة ، وبالتالي ، عدم إمكانية الوصول إلى الجراب المقابل.

كان الخيار الوحيد الذي سمح لنا بتقليل فترة التوقف عن العمل بسهولة تامة وبدون ألم هو استخدام نسختنا من أداة تغيير الحجم الخارجية بحد أقصى للمهلة الزمنية هو 5 ثوان :

workqueue.NewItemExponentialFailureRateLimiter(5*time.Millisecond, 5*time.Second)

لم نعتبر أنه من الضروري البدء بشكل عاجل في مناقشة وتصحيح أداة تغيير الحجم الخارجية ، لأن أقراص تغيير الحجم في وضع عدم الاتصال هي atavism ستختفي قريبًا من جميع مزودي الخدمات السحابية.

كيفية البدء باستخدام؟


برنامج التشغيل مدعوم في الإصدار 1.15 من Kubernetes والإصدارات الأحدث. لكي يعمل السائق ، يجب تلبية المتطلبات التالية:

  • يتم --allow-privilegedتعيين العلم إلى قيمة trueخادم API و kubelet ؛
  • وشملت --feature-gates=VolumeSnapshotDataSource=true,KubeletPluginsWatcher=true,CSINodeInfo=true,CSIDriverRegistry=trueلخادم API و kubelet ؛
  • ينبغي تضمين مجموعة الانتشار ( انتشار الانتشار ) في المجموعة. عند استخدام Docker ، يجب تكوين البرنامج الخفي بحيث يسمح بالتصاعد المشترك.

يتم وصف جميع الخطوات اللازمة للتثبيت نفسه في README . التثبيت هو إنشاء كائنات في Kubernetes من القوائم.

لكي يعمل السائق ، ستحتاج إلى ما يلي:

  • تشير إلى معرف دليل كتالوج Yandex.Cloud ( folder-id) في البيان ( انظر الوثائق ) ؛
  • للتفاعل مع Yandex.Cloud API في برنامج تشغيل CSI ، يتم استخدام حساب الخدمة. في البيان السري ، يجب عليك تمرير المفاتيح المعتمدة لحساب الخدمة. تصف الوثائق كيفية إنشاء حساب الخدمة والحصول على المفاتيح.

بشكل عام - جربه ، وسنكون سعداء لتلقي الملاحظات والمشكلات الجديدة إذا واجهت أي مشاكل!

مزيد من الدعم


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

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

ملاحظة


اقرأ أيضا في مدونتنا:

Source: https://habr.com/ru/post/undefined/


All Articles