تجربه ما در توسعه یک درایور CSI در Kubernetes برای Yandex.Cloud

تجربه ما در توسعه یک درایور CSI در Kubernetes برای Yandex.Cloud

ما خوشحالیم که اعلام کنیم که Flan با انتشار این نسخه، مشارکت خود را در ابزارهای منبع باز برای Kubernetes گسترش می دهد. نسخه آلفا درایور CSI (رابط ذخیره سازی کانتینر) برای Yandex.Cloud.

اما قبل از رفتن به جزئیات پیاده سازی، اجازه دهید به این سوال پاسخ دهیم که چرا وقتی Yandex قبلاً یک سرویس دارد، به این نیاز است. سرویس مدیریت شده برای Kubernetes.

معرفی

چرا این هست؟

در داخل شرکت ما، از همان ابتدای استفاده از Kubernetes در تولید (یعنی چندین سال است)، ما در حال توسعه ابزار خودمان (deckhouse) بوده‌ایم، که اتفاقاً، همچنین قصد داریم به زودی آن را به عنوان یک پروژه منبع باز در دسترس قرار دهیم. . با کمک آن، ما به طور یکنواخت همه خوشه های خود را پیکربندی و پیکربندی می کنیم، و در حال حاضر بیش از 100 مورد از آنها در طیف گسترده ای از پیکربندی های سخت افزاری و در همه سرویس های ابری موجود وجود دارد.

خوشه هایی که از دک هاوس استفاده می کنند دارای تمام اجزای لازم برای عملکرد هستند: متعادل کننده ها، نظارت با نمودارهای مناسب، معیارها و هشدارها، احراز هویت کاربر از طریق ارائه دهندگان خارجی برای دسترسی به تمام داشبوردها و غیره. نصب چنین خوشه "پمپ شده" در یک راه حل مدیریت شده هیچ فایده ای ندارد، زیرا این اغلب یا غیرممکن است یا منجر به نیاز به غیرفعال کردن نیمی از اجزا خواهد شد.

NB: این تجربه ما است و کاملا مشخص است. ما به هیچ وجه پیشنهاد نمی کنیم که همه باید به جای استفاده از راه حل های آماده، خوشه های Kubernetes را به تنهایی مستقر کنند. به هر حال، ما هیچ تجربه واقعی در کارکرد Kubernetes از Yandex نداریم و در این مقاله هیچ ارزیابی از این سرویس ارائه نمی دهیم.

چیست و برای چه کسی؟

بنابراین، ما قبلاً در مورد رویکرد مدرن ذخیره سازی در Kubernetes صحبت کرده ایم: CSI چگونه کار می کند؟ и چگونه جامعه آمد به این رویکرد

در حال حاضر، بسیاری از ارائه دهندگان خدمات ابری بزرگ درایورهایی را برای استفاده از دیسک های ابری خود به عنوان حجم پایدار در Kubernetes ایجاد کرده اند. اگر تامین کننده چنین درایوری نداشته باشد، اما تمام عملکردهای لازم از طریق API ارائه می شود، هیچ چیز مانع از اجرای درایور شما نمی شود. این همان چیزی است که با Yandex.Cloud اتفاق افتاد.

مبنای توسعه قرار گرفتیم درایور CSI برای DigitalOcean cloud و چند ایده از درایورهای GCP، از آنجایی که تعامل با API این ابرها (گوگل و یاندکس) دارای تعدادی شباهت است. به طور خاص، 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 از طریق sidecars این الزامات را برآورده نمی کند:

  • در ظرف کناری csi-attacher، که باید مسئول وجود شکاف مورد نیاز بین مانت ها باشد، این عملکرد به سادگی در تغییر اندازه آفلاین اجرا نمی شود. بحث در این باره آغاز شد اینجا.
  • کانتینر کناری در این زمینه دقیقاً چیست؟ خود پلاگین CSI با API Kubernetes تعاملی ندارد، بلکه فقط به تماس‌های gRPC که توسط کانتینرهای سایدکار به آن ارسال می‌شود پاسخ می‌دهد. آخرین در حال توسعه هستند توسط جامعه Kubernetes

در مورد ما (افزونه CSI)، عملیات افزایش دیسک به صورت زیر است:

  1. ما یک تماس gRPC دریافت می کنیم ControllerExpandVolume;
  2. ما سعی می کنیم دیسک را در API افزایش دهیم، اما خطای عدم امکان انجام عملیات را دریافت می کنیم زیرا دیسک نصب شده است.
  3. ما شناسه دیسک را در نقشه ذخیره می کنیم که حاوی دیسک هایی است که عملیات افزایش باید برای آنها انجام شود. در زیر، برای اختصار، ما این نقشه را به عنوان volumeResizeRequired;
  4. غلافی که از دیسک استفاده می کند را به صورت دستی بردارید. Kubernetes آن را دوباره راه اندازی خواهد کرد. به طوری که دیسک زمان نصب را نداشته باشد (ControllerPublishVolume) قبل از تکمیل عملیات افزایش هنگام تلاش برای نصب، بررسی می کنیم که دیسک داده شده هنوز داخل است volumeResizeRequired و یک خطا را برگردانید.
  5. درایور CSI سعی می کند عملیات تغییر اندازه را دوباره اجرا کند. اگر عملیات موفقیت آمیز بود، دیسک را از آن جدا کنید volumeResizeRequired;
  6. زیرا شناسه دیسک وجود ندارد volumeResizeRequired, ControllerPublishVolume با موفقیت عبور می کند، دیسک نصب می شود، غلاف شروع می شود.

همه چیز به اندازه کافی ساده به نظر می رسد، اما مانند همیشه مشکلاتی وجود دارد. دیسک ها را بزرگ می کند تغییر اندازه خارجی، که در صورت بروز خطا در حین عملیات از صف استفاده می کند با افزایش تصاعدی در زمان وقفه تا 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)

ما لازم ندیدیم که فوراً بحثی را شروع کنیم و تغییر اندازه‌دهنده خارجی را اصلاح کنیم، زیرا تغییر اندازه آفلاین دیسک‌ها بازگشتی است که به زودی از همه ارائه‌دهندگان ابری ناپدید می‌شود.

چگونه شروع به استفاده کنیم؟

درایور در Kubernetes نسخه 1.15 و بالاتر پشتیبانی می شود. برای اینکه راننده کار کند، شرایط زیر باید رعایت شود:

  • فلگ --allow-privileged مقدار را تنظیم کنید true برای سرور API و kubelet.
  • مشمول --feature-gates=VolumeSnapshotDataSource=true,KubeletPluginsWatcher=true,CSINodeInfo=true,CSIDriverRegistry=true برای سرور API و kubelet.
  • انتشار کوه (تکثیر سوار) باید در خوشه فعال شود. هنگام استفاده از Docker، دیمون باید به گونه‌ای پیکربندی شود که امکان نصب مشترک را فراهم کند.

تمام مراحل لازم برای خود نصب در README شرح داده شده است. نصب شامل ایجاد اشیا در Kubernetes از مانیفست است.

برای اینکه راننده کار کند به موارد زیر نیاز دارید:

  • شناسه دایرکتوری را در مانیفست مشخص کنید (folder-id) Yandex.Cloud (مستندات را ببینید);
  • برای تعامل با Yandex.Cloud API، درایور CSI از یک حساب سرویس استفاده می کند. در مانیفست، راز باید منتقل شود کلیدهای مجاز از حساب سرویس در مستندات شرح داده شده، نحوه ایجاد حساب سرویس و دریافت کلید.

در مجموع - آن را امتحان کنید، و ما خوشحال خواهیم شد که بازخورد دریافت کنیم و مسائل جدیداگر با هر مشکلی مواجه شدید!

حمایت بیشتر

در نتیجه، مایلیم متذکر شویم که ما این درایور CSI را نه به دلیل تمایل زیاد به سرگرم کردن برنامه های کاربردی در Go، بلکه به دلیل نیاز فوری در شرکت پیاده سازی کردیم. برای ما عملی به نظر نمی رسد که پیاده سازی خود را حفظ کنیم، بنابراین اگر Yandex علاقه نشان داد و تصمیم گرفت به پشتیبانی از درایور ادامه دهد، ما خوشحال خواهیم شد که مخزن را به آنها منتقل کنیم.

علاوه بر این، Yandex احتمالاً پیاده‌سازی خاص خود را از درایور CSI در کلاستر Kubernetes مدیریت شده خود دارد که می‌تواند در منبع باز منتشر شود. ما همچنین این گزینه توسعه را مطلوب می بینیم - جامعه می تواند از یک راننده اثبات شده از یک ارائه دهنده خدمات استفاده کند و نه از یک شرکت شخص ثالث.

PS

در وبلاگ ما نیز بخوانید:

منبع: www.habr.com

اضافه کردن نظر