هر دیپلوی یک استرس است و فقط یک نفر بلد است
انتشار نسخه جدید با اتصال SSH، git pull و ریستارت دستی انجام میشود. اگر آن فرد در دسترس نباشد انتشار متوقف است و اگر مرحلهای فراموش شود، سرویس از کار میافتد.
پیادهسازی CI/CD یعنی هر تغییر کد بهطور خودکار build و تست شود و از یک مسیر مشخص و قابل برگشت به سرور برسد. کانفیگ سرور pipelineهای GitLab CI، Jenkins و GitHub Actions را طراحی میکند و روی زیرساخت شما راه میاندازد.
انتشار نسخه جدید با اتصال SSH، git pull و ریستارت دستی انجام میشود. اگر آن فرد در دسترس نباشد انتشار متوقف است و اگر مرحلهای فراموش شود، سرویس از کار میافتد.
تستها نوشته شدهاند، اما کسی پیش از انتشار اجرایشان نمیکند. در CI، هر merge request پیش از ادغام بهطور خودکار build و تست میشود.
دسترسی کاربران و سرورهای ایران به سرویسهایی مثل GitHub و GitLab.com در سالهای اخیر با محدودیتهای ناشی از تحریم و اختلال اینترنت همراه بوده است. GitLab و runner روی زیرساخت خودتان این ریسک را کم میکند.
کار شامل انتخاب ابزار متناسب با تیم، راهاندازی runner یا GitLab داخلی، نوشتن pipeline از build تا deploy و مستندسازی مسیر بازگشت به نسخه قبلی است.
مسیری روشن از commit تا production طراحی میکنیم.
کد، pipeline و رجیستری روی زیرساخت خودتان میماند.
برای تیمهایی است که Jenkins دارند یا به انعطاف آن نیاز دارند.
jobها روی سرورهای خودتان اجرا میشوند.
هر نسخه خروجی قابل ردیابی دارد.
انتشار قابل تکرار است و به نسخه قبلی برمیگردد.
CI یعنی هر تغییر کد پس از push بهطور خودکار build و تست شود و CD یعنی نسخهای که از این مراحل گذشته، با یک تأیید دستی یا کاملاً خودکار از مسیر مشخصی به سرور برسد. pipeline مجموعه همین مراحل است و اگر یکی از آنها شکست بخورد، نسخه خراب به production نمیرسد. پیادهسازی CI/CD برای تیم کوچک هم فایده دارد، چون انتشار را از حافظه یک نفر جدا میکند و قابل تکرار میکند. نکتههای زیر انتخاب ابزار، طراحی pipeline، امنیت و مسیر بازگشت را توضیح میدهد.
محل نگهداری کد اولین معیار انتخاب است. اگر کد در GitLab است یا میخواهید مخزن، pipeline و رجیستری در یک سامانه باشند، GitLab CI سادهترین مسیر است. Jenkins انعطاف و پلاگینهای بیشتری دارد و برای pipelineهای پیچیده یا ابزارهای متنوع مناسب است، اما بهروزرسانی Jenkins و پلاگینهایش کار منظمی میخواهد. GitHub Actions با runner خودمیزبان jobها را روی سرورهای شما اجرا میکند، ولی خود runner همچنان به github.com وصل میشود.
دسترسی کاربران و سرورهای ایران به GitHub و GitLab.com با محدودیتهای ناشی از تحریم و اختلال اینترنت همراه بوده و این محدودیتها ممکن است بدون اطلاع قبلی تغییر کنند. برای سازمانی که انتشار نرمافزارش نباید متوقف شود، GitLab خودمیزبان همراه GitLab Runner روی سرورهای خود سازمان پایدارترین گزینه است. اگر تیم Jenkins دارد و با آن راحت است، معمولاً مرتب کردن همان Jenkins کمهزینهتر از عوض کردن ابزار است.
pipeline خوب زود شکست میخورد: تستها و بررسیهای کوتاه اول اجرا میشوند تا خطا پیش از ساخت ایمیج و استقرار معلوم شود. cache وابستگیها و artifact مراحل قبلی زمان اجرا را کم میکنند. برای پروژهای که روی Docker اجرا میشود، مراحل معمول اینهاست:
قواعد شاخهبندی را هم کنار pipeline تعیین کنید: merge request فقط وقتی ادغام شود که pipeline آن موفق بوده و استقرار روی production فقط از شاخه محافظتشده انجام شود. اگر اپلیکیشن هنوز Dockerfile ندارد، کانتینرسازی آن پیش از pipeline در خدمات Docker و کانتینرسازی انجام میشود. برای کم کردن وابستگی به Docker Hub، ایمیجهای پایه را از میرور یا cache داخلی بگیرید.
runner کدی را اجرا میکند که در مخزن نوشته شده و معمولاً به سرورهای production هم دسترسی دارد، پس یکی از حساسترین سرورهای زیرساخت است. runner را روی سرور یا ماشین مجازی جدا نصب کنید و در صورت امکان executor از نوع Docker را انتخاب کنید تا هر job در محیط تمیز و جدا اجرا شود. رمزها و کلیدهای SSH را در متغیرهای محافظتشده CI یا مدیریت credential در Jenkins نگه دارید و فقط در اختیار jobهای شاخههای محافظتشده بگذارید.
کاربری که pipeline با آن روی سرور مقصد دیپلوی میکند، باید فقط به همان سرویس دسترسی داشته باشد. دسترسی runner خودمیزبان GitHub Actions را هم به مخزنهای مشخص محدود کنید. خود سرورهای مقصد دیپلوی باید جداگانه سختسازی شوند و این کار در امنسازی سرور انجام میشود.
چون هر نسخه با تگ مشخص ساخته میشود، بازگشت یعنی deploy دوباره تگ قبلی. این بازگشت را پیش از تحویل یک بار آزمایش میکنیم تا روز مشکل اولین اجرای آن نباشد. تغییرات دیتابیس بازگشت را سختتر میکنند، پس migration را طوری بنویسید که نسخه قبلی اپلیکیشن هم با ساختار جدید کار کند؛ مثلاً ستون جدید اضافه شود و حذف ستون قدیمی به انتشار بعدی بماند. پس از هر انتشار healthcheck اجرا میشود و اگر شکست بخورد، pipeline متوقف میشود.
healthcheck فقط زنده بودن سرویس را نشان میدهد. نرخ خطا و زمان پاسخ نسخه جدید را در سامانه پایش دنبال کنید تا مشکلی که در تست دیده نشده زود پیدا شود؛ این بخش در خدمات مانیتورینگ و Observability طراحی میشود. روی یک یا چند سرور، استقرار با Docker Compose روی SSH کافی است و وقتی سرویسها روی کلاستر اجرا شوند، دیپلوی در استقرار و مدیریت Kubernetes ادامه پیدا میکند.
تعداد پروژهها و سرویسها، وضعیت تستهای موجود، نیاز به راهاندازی GitLab خودمیزبان، تعداد محیطها و مقصدهای دیپلوی پایه برآورد هستند. pipeline را اول برای یک پروژه نمونه اجرا میکنیم تا تیم با روند جدید آشنا شود و بعد به پروژههای دیگر گسترش میدهیم، پس زمان کل به تعداد پروژههای بعدی هم بستگی دارد. نوشتن تستهای نرمافزاری جزو این خدمت نیست. برای برآورد، محل نگهداری کد، زبان اپلیکیشن، روش فعلی انتشار و سرورهای مقصد را بفرستید.
رمزها و کلیدهای SSH را در فایل gitlab-ci.yml، Jenkinsfile یا workflow ننویسید. هر کسی که به مخزن دسترسی دارد تاریخچه این فایلها را هم میبیند و رمزی که یک بار commit شده، با پاک کردن در commit بعدی از تاریخچه حذف نمیشود.
مخزن کد، شاخهها، تستهای موجود، محیطها و روش فعلی انتشار را بررسی میکنیم و گلوگاهها و ریسکها را فهرست میکنیم.
بر اساس محل نگهداری کد و شرایط دسترسی، ابزار و محل اجرای runnerها را انتخاب میکنیم و مراحل pipeline را با تیم توسعه شما نهایی میکنیم.
pipeline را اول برای یک سرویس اجرا، تست و بهینه میکنیم تا تیم با روند جدید آشنا شود و بعد آن را به پروژههای دیگر گسترش میدهیم.
فایلهای pipeline در مخزن کد، راهنمای افزودن پروژه جدید و روش بازگشت به نسخه قبلی را به تیم شما تحویل میدهیم.
این خدمت بخشی از خدمات DevOps و امنیت کانفیگ سرور است. Pipelineی که به دسترسی بیوقفه به سرویسهای خارجی وابسته باشد، در روز اختلال متوقف میشود، پس محل کد، runnerها و ایمیجها را از ابتدا با در نظر گرفتن این ریسک طراحی میکنیم.
ابزار را بر اساس تیم و محل نگهداری کد شما انتخاب میکنیم و اگر تیم ابزاری دارد، تا جای ممکن همان را نگه میداریم.
GitLab، runnerها و Harbor را روی سرورهای سازمان راه میاندازیم تا وابستگی به سرویسهای خارجی کم شود.
هر انتشار نسخهدار است و بازگشت به نسخه قبلی را پیش از تحویل تست میکنیم.
روش فعلی انتشار را در تلگرام شرح دهید تا ابزار و pipeline پیشنهادی را پیش از هر تعهدی با شما مرور کنیم.
CI یا یکپارچهسازی مداوم یعنی هر تغییر کد بهطور خودکار build و تست شود. CD دو معنای نزدیک دارد: تحویل مداوم (Continuous Delivery) که نسخه همیشه آماده انتشار است و انتشار با یک تأیید انجام میشود، و استقرار مداوم (Continuous Deployment) که انتشار هم بدون دخالت دستی انجام میشود.
pipeline مجموعه مراحل پشتسرهمی است که پس از هر push اجرا میشود و معمولاً build، تست، ساخت ایمیج و deploy را شامل میشود. اگر مرحلهای شکست بخورد، مراحل بعدی اجرا نمیشوند و نسخه خراب به production نمیرسد.
اگر کد شما در GitLab است یا میخواهید کد، pipeline و رجیستری را در یک سامانه داشته باشید، GitLab CI سادهتر است. Jenkins انعطاف و پلاگینهای بیشتری دارد و برای pipelineهای پیچیده یا ابزارهای متنوع مناسب است، اما نگهداری پلاگینها و بهروزرسانی آن کار بیشتری میخواهد.
استفاده از سرویسهای GitHub برای کاربران ایران تحت محدودیتهای تحریمی است و این محدودیتها ممکن است بدون اطلاع قبلی تغییر کنند. runner خودمیزبان کمک میکند jobها روی سرورهای شما اجرا شوند، اما همچنان به ارتباط با GitHub وابسته است. برای کاهش ریسک، GitLab خودمیزبان گزینه پایدارتری است.
راهاندازی GitLab داخلی یک سرور لینوکس با منابع کافی، فضای ذخیرهسازی برای مخازن و artifactها و یک یا چند سرور یا ماشین مجازی برای GitLab Runner لازم دارد. بکاپ منظم و بهروزرسانی امنیتی GitLab هم باید از ابتدا برنامهریزی شود.
بله؛ حتی برای یک توسعهدهنده، یک pipeline ساده build و deploy خطای انسانی را کم میکند و انتشار را قابل تکرار میکند. طراحی را متناسب با اندازه تیم ساده نگه میداریم تا نگهداری آن خودش سربار نشود.
چون هر نسخه با تگ مشخص ساخته میشود، بازگشت یعنی deploy دوباره تگ قبلی. پس از انتشار healthcheck اجرا میشود و تغییرات دیتابیس طوری برنامهریزی میشوند که با نسخه قبلی سازگار بمانند. اگر قطعی جدی رخ دهد، پاسخ اضطراری و رفع قطعی سرور (24/7) در دسترس است.
بگویید کد کجا نگهداری میشود، اپلیکیشن با چه زبانی نوشته شده و الان چگونه منتشر میشود. در مشاوره اولیه رایگان، ابزار و pipeline پیشنهادی را با شما مرور میکنیم.