این مقاله نحوه استفاده تیم پلتفورم یادگیری ماشین Cauldron از پایپلاین های والد-فرزند گیتلب برای تولید پوشه های CI گیتلب به صورت دینامیک را به نمایش می گذارد تا محدودیت های گیتلب برای مخزن های بزرگ را حل کند

    ساده سازی فایل CI گیتلب از 1800 خط به 50 خط. کاهش نیاز به فایل های nestedgitlab-ciyml.

مقدمه

Cauldron تیم پلتفرم یادگیری ماشین در Grab است. تیم Cauldron ابزارهایی برای مدیریت دوره عمر انتها به انتها مدل های یادگیری ماشین را ارائه می دهد، از آموزش تا استقرار. گیتلب و ابزارهای آن بخشی از پالتفرم ما هستند ، برای تحویل مداوم یادگیری ماشین.

یکی از محصولات اصلی ما پایپلاین های MerLin است. هر تیم دارای یک ریپوی اختصاصی برای نگهداری کد پایپلاین ML خود است. هر پایپلاین شامل یک زیرپوشه اختصاصی است. ما به طور قوی بر قوانین گیتلب برای تشخیص تغییرات خاص برای راه اندازی مراحل مختلف پایپلاین های مختلف (به عنوان مثال، سرویس مدل با کت واک) وابسته هستیم.

زمینه

رویکرد 1: فایل های nested فرزند

رویکرد اول ما به طور قوی بر تولید کد استاتیک برای تولید فایل های فرزندgitlab-ci.ymlدر مراحل فردی تکیه می کرد. برای مثال شکل 1 نشان دهنده ساختار پوشه مثالی با فایلهایgitlab-ci. فایل های yml جایگزینه همگان سازی شده با استفاده از کلمه کلیدیincludeدر مخزن commit شده است.

شکل 1: ساختار پوشه مثال با فایل های gitlab-ci.yml فرزند. فایل های فرزندgitlab-ci.ymlبا استفاده از کلمه کلیدیincludeاضافه می شوند.

 

شکل 2: فایل .gitlab-ci.yml ریشه مثال و شامل کلز است.

 

شکل 3: فایل .gitlab-ci.yml فرزند مثال برای یک مرحله خاص (مدل Deploy) در یک پایپلاین (پایپلاین 1).

 

هنگامی که تیم ها بیشترین پایپلاین ها و مراحل را اضافه می کنند، به سرعت با محدودیت این رویکرد برخورد می کنیم:

محدودیت نرم در تعداد includes که می توان در فایل base.gitlab-ci.yml قرار داد.

روش 1: تولید دینامیک یک فایل CI بزرگ

تلاش بعدی ما برای حل این مشکل تلاش برای درج و درج فایلنقی زنجیره فرزند فایلgitlab-ci.ymlبا استفاده از فایلgitlab-ci.ymlفراهم شده بود، بنابراین دیگر نیازی به وابستگی به کلمه کلیدی شامل گیتلب نداشتیم.

gitlab-ci.yml

برای دستیابی به آن، ما یک ابزار نوشتیم که یک rawgitlab-ciفایل را پارس می کند و درخت را به منظور بازیابی همه فایلهای فرزند گیتلب-cif که شامل include است پیمایش می کند و به جایی که شامل های را برای تولید یک فاینال بیگیتلب-ci فایل تغییر دهد.

شکل 4 نشان می دهد که فایل نتیجه از شکل 3 تولید شده است.

شکل 4: فایل YAML "ظاهر" از طریق این رویکرد، فرض فایل raw از شکل 3.

 

این رویکرد مشکل ما را به طور موقت حل می کند. متاسفانه، با این رویکرد با فایل های گیتلب تا 1800 خط طولانی مواجه می شویم. همچنین محدودیت نرم به حجم فایلهایgitlab-ci.ymlوجود دارد. روشن شد که در نهایت به محدودیت های این رویکرد بر خواهیم خورد.

راه حل

تلاش اولیه ما برای استفاده از تولید کد استاتیک ما به طور جزئی مونه را در آنجا قرار داد. ما قادر به پیش تولید و استنتاج نام های مرحله و پایپلاین ها از اطلاعات موجود بودیم. تولید کد به هر حال مورد نیاز بود، اما تولید پیش از وقوع محدودیت های کلیدی را داشت که در بالا نشان داده شده است. به نوعی بهبودی بر روی این کار نیاز داشتیم، به نحوی که بتوانیم مراحل GitLab را در حالت پویا برای همیشه تولید کنیم. پس از کمی تحقیق، به پیپلاین های فرزند پویا برخوردیم.

از وب سایت رسمی نقل قول می کنیم:

به جای اجرای یک پایپلاین فرزند از یک فایل YAML استاتیک، شما می توانید یک job تعریف کنید که اسکریپت خود را برای تولید یک فایل YAML اجرا کند، که سپس برای راه اندازی یک پایپلاین فرزند استفاده می شود.این تکنیک می تواند در تولید پایپلاین هایی با محتوایی که تغییر کرده اند یا برای ساخت یک ماتریس از هدف ها و معماری ها بسیار قدرتمند باشد.

ما قبلاً در مسیر صحیح بودیم. فقط نیاز به ترکیب تولید کد با پایپلاین های فرزند بود تا مراحل مورد نیاز را به صورت پویا تولید کنیم.

جزئیات معماری

شکل 5: شماتیک جریان نحوه استفاده ما از تولیدیم دینامیک YAML. کاربر یک درخواست ادغام را در یک شاخه ایجاد می کند و سپس شاخه را با استفاده از مستر ادغام می کند.

 

پیاده سازی

جریان Git کاربر در شکل 5 قابل مشاهده است که در آن کاربر فایل ها را در مخزن گیت تیمی مربوطه خود تغییر می دهد یا اضافه می کند. به عنوان یک بازنگر مجدد ، ساختار معمولی مخزن شامل پایپلاین ها و مرحله ها است (شکل 1). ما نیازمندیم اطلاعات لازم را از محیط شاخه در شکل 5 دریافت کنیم و یک مرحله را اجرایی برای تولید برنامه های مرحله مورد نیاز به طور برنامه ریزی شده (به عنوان مثال، شکل 3).

به طور خلاصه نیازمندی های ما می توانند به صورت زیر خلاصه شوند:

    تشخیص فایلهایی که در شاخه git تغییر کرده اند.استخراج اطلاعات مورد نیاز از فایلهایی که تغییر کرده اند.تمپلیت سازی آن برای تولید مراحل مورد نیاز.

بیایید یک مثال بسیار ساده را در نظر بگیریم ، جایی که یک کاربر دارد یک فایل را در stage_1inpipeline_1در شکل 1 ویرایش می کند. خروجی مطلوب ما به شکل زیر است:

شکل 6: خروجی مطلوب که باید به طور پویا تولید شود.

 

قالب ما در فرم زیر خواهد بود:

شکل 7: الگوی مثالی ، و اطلاعات مورد نیاز. آن را template_file.yml نام بگذاریم.

 

ابتدا باید فایلهایی که در شاخه تغییر کرده اند را تشخیص دهیم. این را با استفاده از دستورات diff گیت native انجام می دهیم و در برابر پایه شاخه بررسی می کنیم که چه فایلهایی در درخواست ادغام مودی شده اند. خروجی (آن را diff.txt بنامید) به صورت زیر خواهد بود:

M    pipelines/pipeline_1/stage_1/modelserving.yaml
شکل 8: diff.txt مثالی تولید شده از git diff.

ما باید اطلاعات زرد و سبز را از خط استخراج کنیم ، متناظر با نام نوع پایپلاین و نام مرحله.

شکل 9: اطلاعاتی که باید از فایل استخراج شود.

 

اینجا به روش بسیار ساده ای روی می آوریم ، با معرفی مفهوم الگوهای متوقف شده.

الگوهای متوقف شده به عنوان یک لیست جدا شده به وابسته از نام های متغیر و کلماتی که در آن متوقف می شود تعریف می شوند. که دو نقطه (:) نشان می دهد چندین سطح قبل از کلمه متوقف است.

به عنوان مثال ، الگوی متوقف شده:

نام پایپلاین:pipelines

به پارسر می گوییم که برای پوشهpipelinesبگردد و قبل از آن متوقف شود وpipeline_1را از مثال بالا که به نام متغیرpipeline_nameبرچسب خورده است استخراج کند.

الگوی متوقف شده با دو دونت (::):

نام مرحله::pipelines

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

ابزارcli ما به الگوهای متوقف شده مجاز است تا به صورت جدا شده نوشته شود ، لذا دستور نهایی به صورت زیر خواهد بود:

cauldron_repo_util diff.txt template_file.ymlpipeline_name:pipelines,stage_name::pipelines >generated.yml

ما تصمیم گرفتیم util در Rust را بنویسیم به دلیل عملکرد بالای آن و کتابخانه های قالب سازی غنی (مانند Tera) و کتابخانه های خط فرمان قابل قبول (clap).

ترکیب تمامی اینها با هم ، ما قادر به استخراج اطلاعات لازم ازgit diffبودیم و از الگوهای متوقف استفاده کردیم تا اطلاعات مورد نیاز را برای تمپلیت برگزار کنیم. الگوهای متوقف کافی انعطاف پذیر بودند برای پشتیبانی از انواع مختلف ساختار های پوشه.

شکل 10: قطعه کد مثال Rust برای پارس diff Git.

 

وقتی برنامه را در شاخه اصلی راه اندازی می کنیم (شکل راست شکل 5) ، جریان همان است با این تفاوت کوچک که ما باید از همان فایلdiff.txtشاخه مبدا را بازیابی کنیم. این را با استفاده از رابط برنامه نویسی برنامه نویسی پر قدرت گیتلب انجام می دهیم ، هندل کردن جعبه های پایپلاین و با استفاده از همان util برای تولید مراحل مورد نیاز گیتلب به صورت پویا.

تاثیر

بعد از پیاده سازی این تغییر ، بزرگترین موفقیت ما حذف یکی از بزرگترین مخازن ML پایپلاین گیت از 1800 خط به 50 خط بود. این رویکرد اندازه فایل.gitlab-ci.yamlرا در 50 خط ثابت نگه می دارد و اطمینان می حاصل می شود که با هر چقدر پایپلاین اضافه شود ، اندازه آن متناسب باشد.

کاربران ما ، متخصصان یادگیری ماشین ، همچنین در تولید محصول موثرتر هستند زیرا دیگر نیازی به نگرانی در مورد فایل های yaml گیتلب ندارند.

یادگیری ها و نتیجه گیری

با ابتکاری و انعطاف پذیری پایپلاین های فرزند گیتلب ، ما توانستیم تلاشی را برای تهیه پیکربندی قابل استفاده مجدد ، با رعایت اصول DRY داشته باشیم.


تشکر ویژه از تیم پلتفرم ML Cauldron.


بعدی چیست

ما ممکن است راه حل خود را منبع باز کنیم.

منابع

    پایپلاین های والد-فرزندBackend: فایل gitlab-ci.yml تا 100 شامل می شود

به ما بپیوندید

ٰمجله زیبایی و درمانی آذروت نیرومند ترین پلتفرم superapp در جنوب شرق آسیا است که خدمات روزمره مهم را برای مصرف کنندگان فراهم می کند. بیش از یک اپلیکیشن سفارش آنلاین غذا و سرویس های ارائه خدمات است،ٰمجله زیبایی و درمانی آذروت خدمات گسترده ای در منطقه ارائه می دهد، از جمله خدمات حمل و نقل، غذا، بسته بندی و خرید موبایل ، پرداخت های موبایلی و خدمات مالی در 428 شهر در هشت کشور.

با قدرت فناوری و محرک قلبی ، ماموریت ما ارتقا جنوب شرق آسیا را از طریق




-4451