فصل ۵: پیاده‌سازی لایه سرویس‌های در سطح کاربر

۵.۱ مدل دسترسی چندکاربره

در معماری پلتفرم، لایه سرویس‌های کاربر بر مبنای مدل چندکاربره (Multi-tenant) طراحی شده است؛ به‌گونه‌ای که هر محقق یا تیم تحقیقاتی در محیطی ایزوله از سایرین فعالیت می‌کند. این ایزولاسیون در چند سطح اعمال می‌شود: نخست در سطح Namespaceهای Kubernetes که برای هر کاربر یا پروژه فضای نام اختصاصی در نظر گرفته شده است؛ سپس در سطح شبکه با NetworkPolicyهای Calico برای کنترل ترافیک بین Namespaceها؛ و در نهایت در سطح منابع محاسباتی با اتکا به ResourceQuota و LimitRange.

احراز هویت کاربران با یکپارچه‌سازی با SSO سازمانی و پروتکل OIDC انجام می‌گیرد. مدیریت دسترسی‌ها به‌صورت متمرکز و از طریق تعریف Role و RoleBinding در Kubernetes پیش می‌رود؛ به این ترتیب، نقش‌های متفاوتی برای کاربران عادی، سرپرستان پروژه و مدیران سیستم تعریف شده است. مطابق این سیاست، هر کاربر صرفاً به منابع Namespace خود دسترسی دارد و امکان ورود به محیط سایر کاربران یا اعمال تغییر در تنظیمات سطح کلاستر را ندارد.

برای تضمین تخصیص منصفانه منابع، سیاست‌های سهمیه‌بندی پویا پیاده‌سازی شده است. سهمیه هر کاربر متناسب با نیاز پروژه و اولویت آن تعیین می‌شود و شامل CPU، حافظه و GPU است. این سهمیه‌ها قابلیت تنظیم دارند و در صورت بلااستفاده‌ماندن، منابع آزادشده در اختیار صف انتظار سایر کاربران قرار می‌گیرد. افزون بر این، از Priority Class در Kubernetes برای اولویت‌بندی بارهای کاری استفاده شده است.

۵.۲ پلتفرم JupyterHub و پروفایل‌های GPU/CPU

JupyterHub به‌عنوان بستر اصلی تعامل کاربران با زیرساخت محاسباتی انتخاب شده است. این سامانه امکان ایجاد محیط‌های Notebook اختصاصی را فراهم می‌کند؛ به‌طوری که هر Notebook در قالب یک Pod مستقل روی Kubernetes اجرا می‌شود. استقرار JupyterHub با Helm Chart رسمی انجام شده و برای نیازهای محیط تحقیقاتی، پیکربندی‌های سفارشی روی آن اعمال گردیده است.

در این پیاده‌سازی، «پروفایل‌های محاسباتی» به‌عنوان یکی از مؤلفه‌های اصلی در نظر گرفته شده است. کاربر هنگام راه‌اندازی Notebook می‌تواند از میان پروفایل‌های از پیش تعریف‌شده انتخاب کند: پروفایل CPU-Only برای پردازش داده و تحلیل‌های سبک، پروفایل GPU-Single برای آموزش مدل‌های یادگیری ماشین با یک GPU، و پروفایل GPU-Multi برای سناریوهایی که به چند GPU نیاز دارند. هر پروفایل، مقادیر مشخصی از CPU، حافظه، تعداد GPU و نیز Imageهای کانتینر متناظر را تعیین می‌کند.

Imageهای کانتینر به‌صورت لایه‌ای ساخته شده‌اند: یک Image پایه با کتابخانه‌های علمی متداول مانند NumPy و Pandas، مجموعه Imageهای مجهز به CUDA و cuDNN برای پردازش‌های GPU، و Imageهای تخصصی برای فریمورک‌هایی نظیر TensorFlow یا PyTorch. در کنار این موارد، امکان تعریف Image سفارشی مطابق نیازهای هر پروژه نیز فراهم شده است. ذخیره‌سازی دائمی داده‌های کاربران از طریق PVCهای متصل به هر Pod تأمین می‌شود تا داده‌ها پس از بسته‌شدن Notebook نیز حفظ شوند.

۵.۳ روش اجرای Batch Job/CronJob، صف و اولویت‌ها

برای اجرای کارهای پردازشی سنگین که به تعامل مستقیم کاربر وابسته نیستند، از Job و CronJob در Kubernetes استفاده می‌شود. این سازوکار اجرای خودکار فرآیندهای طولانی‌مدت—مانند آموزش مدل‌های یادگیری عمیق یا پردازش دسته‌ای داده—را بدون نیاز به پایش مستمر ممکن می‌کند.

صف‌بندی کارها با ترکیبی از Priority Classهای Kubernetes و یک کنترلر سفارشی انجام شده است. کارها در سه سطح اولویت دسته‌بندی می‌شوند: High برای کارهای فوری و پروژه‌های دارای ددلاین نزدیک، Normal برای فعالیت‌های رایج پژوهشی، و Low برای اجراهای آزمایشی یا کم‌اهمیت. در صورت کمبود منابع، کارها وارد صف می‌شوند و به‌محض آزادشدن منابع، با لحاظ اولویت و زمان ثبت، اجرا خواهند شد.

CronJobها برای زمان‌بندی دوره‌ای به کار می‌روند و در وظایفی از قبیل بازآموزی دوره‌ای مدل‌ها، پردازش داده‌های ورودی جدید یا تولید گزارش‌های عملکردی کاربرد دارند. هر CronJob با Concurrency Policy مشخص می‌کند که اجرای هم‌زمان مجاز است یا باید تا پایان اجرای قبلی منتظر ماند.

در کنار این موارد، مکانیزم Preemption نیز فعال شده است؛ بنابراین، هنگامی که منابع برای کارهای با اولویت بالاتر لازم باشد، کارهای کم‌اولویت متوقف می‌شوند تا منابع آزاد گردد. این رفتار با تعریف PriorityClassهای متناسب و تنظیم preemptionPolicy در هر کلاس کنترل می‌شود.

۵.۴ ذخیره‌سازی مشترک Dataset و Checkpoint

مدیریت داده‌های آموزشی و وضعیت‌های میانی مدل از مسائل مهم در محیط‌های یادگیری ماشین است. در پلتفرم حاضر، لایه ذخیره‌سازی مشترک به‌نحوی طراحی شده است که دسترسی هم‌زمان چندین Pod به Datasetهای حجیم و فایل‌های Checkpoint را با کارایی مناسب پشتیبانی کند.

این معماری بر TopoLVM استوار است و با بهره‌گیری از قابلیت‌های LVM، ذخیره‌سازی بلوکی محلی را در سطح کلاستر مدیریت می‌کند. در مقایسه با راهکارهای متداول مبتنی بر فایل‌سیستم شبکه‌ای، تأخیر دسترسی کاهش می‌یابد. برای هر نود ورکر، یک Volume Group اختصاصی بر اساس درایوهای NVMe محلی ایجاد شده است و TopoLVM به‌صورت خودکار Logical Volumeهای موردنیاز را مطابق درخواست‌های PVC تخصیص می‌دهد.

در لایه Kubernetes سه StorageClass مجزا تعریف شده است: dataset-storage برای داده‌های آموزشی با سیاست ReadOnlyMany، checkpoint-storage برای ذخیره وضعیت مدل‌ها با قابلیت ReadWriteOnce، و shared-workspace برای فضای کاری مشترک تیم‌ها با حالت ReadWriteMany. این تفکیک اجازه می‌دهد سیاست‌های بهینه‌سازی متناسب با ماهیت هر نوع داده اعمال شود.

برای Datasetهای بزرگ که در چند آزمایش به‌طور هم‌زمان مصرف می‌شوند، از Volume Cloning استفاده شده است. این قابلیت با Snapshotهای LVM، نسخه‌های سبک ایجاد می‌کند و از کپی فیزیکی غیرضروری می‌کاهد. همچنین برای Checkpointهای حجیم، سیاست Backup خودکار به Object Storage خارجی پیاده‌سازی شده است تا احتمال از دست‌رفتن داده در شرایط بحرانی کاهش یابد.

چرخه حیات داده‌ها نیز با یک Operator اختصاصی مدیریت می‌شود؛ به این ترتیب که Volumeهای بلااستفاده شناسایی شده و پس از سپری‌شدن دوره نگهداری تعیین‌شده، به‌صورت خودکار حذف می‌گردند.

۵.۵ رجیستری داخلی و مدیریت Imageها

برای کاهش وابستگی به منابع خارجی و حفظ استقلال عملیاتی، رجیستری داخلی Container Image در نظر گرفته شده است. این رجیستری علاوه بر نگهداری Imageهای سفارشی کاربران، نقش Cache محلی برای Imageهای عمومی پرکاربرد را نیز ایفا می‌کند.

پیاده‌سازی رجیستری بر پایه Harbor انجام شده است. Harbor در قالب Helm Chart مستقر شده و برای متادیتا از PostgreSQL و برای Caching از Redis استفاده می‌کند. ذخیره‌سازی Imageها نیز به TopoLVM متصل است تا کارایی خواندن و نوشتن در سطح مطلوب حفظ شود.

یکپارچگی احراز هویت از طریق OIDC صورت گرفته است؛ بنابراین کاربران با همان اعتبارنامه‌های مورد استفاده برای JupyterHub به رجیستری متصل می‌شوند. سیاست‌های دسترسی نیز بر اساس نقش‌های تعریف‌شده در Keycloak اعمال می‌گردد؛ برای نمونه، کاربران عادی تنها مجاز به مدیریت Imageهای مربوط به Namespace اختصاصی خود هستند.

به‌منظور ارتقای امنیت، Image Scanning با Trivy فعال شده است. هر Image پیش از مجازشدن برای استفاده در کلاستر، به‌صورت خودکار از نظر آسیب‌پذیری‌های شناخته‌شده بررسی می‌شود. در صورت مشاهده آسیب‌پذیری با سطح بحرانی، Image قرنطینه می‌شود و اعلان لازم برای مدیر سیستم ارسال می‌گردد.

فرآیندهای Pull و Push نیز با هدف کاهش بار شبکه بهینه شده‌اند. Image Replication باعث می‌شود Imageهای پرمصرف به‌صورت پیشگیرانه در رجیستری محلی کش شوند. همچنین Garbage Collection به‌صورت دوره‌ای اجرا می‌شود تا Layerهای بلااستفاده حذف و فضای ذخیره‌سازی مدیریت شود.

۵.۶ اجزای پایه MLOps

پشتیبانی کامل از چرخه توسعه مدل‌های یادگیری ماشین مستلزم زیرساختی است که آزمایش، آموزش، ارزیابی و استقرار را در قالبی منسجم پوشش دهد. لایه MLOps پلتفرم با تکیه بر مجموعه‌ای از ابزارهای متن‌باز و یکپارچه این نیاز را پاسخ می‌دهد.

در این لایه، MLflow به‌عنوان بستر مدیریت چرخه حیات مدل به کار گرفته شده است و در سه جزء اصلی مستقر می‌شود: Tracking Server برای ثبت آزمایش‌ها و معیارها، Model Registry برای نسخه‌بندی و مدیریت مدل‌های آموزش‌دیده، و Projects برای بسته‌بندی کد قابل‌بازتولید. دسترسی به سرویس از طریق Ingress فراهم شده و با سامانه احراز هویت یکپارچه ادغام گردیده است.

برای ارکستراسیون Pipelineهای چندمرحله‌ای، Kubeflow Pipelines پیاده‌سازی شده است. این ابزار امکان تعریف گردش‌کار با Python SDK را فراهم می‌کند؛ هر مرحله به‌صورت یک Job مستقل روی Kubernetes اجرا می‌شود و تبادل خروجی‌ها از طریق Artifact Store مشترک صورت می‌گیرد. قابلیت Caching نیز فعال است تا مراحل تکراری، در صورت امکان، از نتایج قبلی استفاده کنند.

در سطح نیازهای پیشرفته‌تر، Kubeflow Training Operators نصب شده‌اند تا الگوهای آموزش توزیع‌شده را پوشش دهند؛ از جمله TFJob برای TensorFlow، PyTorchJob برای PyTorch و MPIJob برای سناریوهای MPI-based. این Operatorها مدیریت Podهای Worker و Parameter Server و نیز پیکربندی شبکه بین آن‌ها را به‌صورت خودکار انجام می‌دهند.

یکپارچگی اجزا از طریق یک Dashboard مرکزی فراهم شده است؛ به‌طوری که کاربر می‌تواند از محیط JupyterLab، Pipeline تعریف کند، آزمایش را در MLflow ثبت نماید و نتیجه را در Model Registry منتشر سازد. این زنجیره یکپارچه، مسیر انتقال مدل از مرحله آزمایش تا بهره‌برداری را کوتاه‌تر می‌کند.

۵.۷ مدیریت Secrets و Configuration

در استقرار سرویس‌های کاربری، مدیریت ایمن داده‌های حساس و پیکربندی‌های متغیر اهمیت ویژه دارد. در معماری حاضر، برای تفکیک داده‌های پیکربندی از منطق اپلیکیشن، رویکردی چندلایه اتخاذ شده است.

تنظیمات غیرحساس در ConfigMap نگهداری می‌شوند؛ از جمله پیکربندی‌های محیطی، آدرس سرویس‌ها و پارامترهای عملیاتی. این روش تغییر تنظیمات را بدون نیاز به بازسازی Imageهای کانتینری ممکن می‌کند. به‌عنوان نمونه، تنظیمات JupyterHub شامل آدرس سرویس احراز هویت، سقف پیش‌فرض مصرف منابع و پیکربندی شبکه در یک ConfigMap مستقل ذخیره شده است.

اطلاعات حساس—مانند کلیدهای API، گواهی‌نامه‌های TLS و رمزهای عبور پایگاه داده—از طریق Secret مدیریت می‌شوند. در مقایسه با ConfigMap که داده‌ها را به‌صورت متن ساده نگه می‌دارد، Secret امکان رمزنگاری داده‌ها در سطح etcd را فراهم می‌کند. در این پیاده‌سازی، کلیدهای خصوصی گواهی‌نامه‌های SSL، توکن‌های احراز هویت OAuth2 و اطلاعات دسترسی به سامانه‌های خارجی در Secret ذخیره شده‌اند.

کنترل دسترسی به Secret با RBAC محدود شده است تا فقط Podهای مجاز امکان استفاده از داده‌های حساس را داشته باشند. همچنین Secretها به‌صورت volume در کانتینر mount می‌شوند تا از قرارگرفتن آن‌ها در متغیرهای محیطی—که ریسک افشا در آن‌ها بالاتر است—پرهیز شود.

در مدیریت پیکربندی، الگوی immutable configuration نیز رعایت شده است؛ یعنی با هر تغییر، نسخه جدیدی از ConfigMap یا Secret ایجاد و Deployment مرتبط به‌روزرسانی می‌شود. نتیجه این رویکرد، امکان ردیابی تغییرات و بازگشت سریع به نسخه‌های قبلی است.

۵.۸ پیاده‌سازی GitOps

برای مدیریت چرخه حیات اپلیکیشن‌ها، رویکرد GitOps به‌کار گرفته شده است؛ به این معنا که Git نقش منبع واحد حقیقت (Single Source of Truth) را برای تعاریف زیرساختی و پیکربندی‌های کلاستر ایفا می‌کند.

در این چارچوب، ArgoCD به‌عنوان ابزار همگام‌سازی وضعیت کلاستر با مخزن Git انتخاب شده است. manifestهای Kubernetes شامل Deployment، Service، Ingress و سایر منابع، در ساختار دایرکتوری مشخصی سازماندهی شده‌اند. ArgoCD به‌صورت پیوسته مخزن را پایش می‌کند و هر اختلاف میان وضعیت تعریف‌شده و وضعیت واقعی کلاستر را تشخیص می‌دهد.

فرآیند استقرار بدین ترتیب انجام می‌شود که توسعه‌دهندگان تغییرات را در شاخه مربوطه commit می‌کنند و پس از بازبینی و تأیید، به شاخه اصلی merge می‌شود. سپس ArgoCD تغییرات را اعمال می‌کند؛ این اعمال می‌تواند خودکار باشد یا با تأیید دستی انجام شود. در کنار اتوماسیون، قابلیت ممیزی (Audit) نیز به‌واسطه ثبت تاریخچه تغییرات در Git فراهم است.

برای جداسازی محیط‌ها (توسعه، آزمون، تولید)، ساختار چندمخزنی به کار رفته است. هر محیط مخزن یا شاخه مستقل دارد و ArgoCD Application متناظر با همان محیط تعریف شده است؛ بنابراین، امکان ارزیابی تغییرات در محیط staging پیش از اعمال روی تولید فراهم می‌شود.

بازگشت (Rollback) نیز از مزیت‌های مستقیم این رویکرد است: در صورت بروز مسئله، با بازگردانی به commit قبلی، کلاستر به وضعیت پایدار قبل بازمی‌گردد. در نهایت، استفاده از Helm و Chart در کنار ArgoCD، مدیریت پیکربندی‌های پیچیده‌تر را تسهیل کرده است.