تصویر کلی
systemd واحدهای service، scope و slice را به hierarchy کنترل منابع در cgroup متصل میکند.
برای فهم این موضوع بهتر است اجزا را بهعنوان یک مسیر ببینیم، نه مجموعهای از گزینههای مستقل. در Production معمولاً مشکل زمانی شکل میگیرد که تنظیم روی دیسک، وضعیت Runtime و فرض تیم درباره رفتار سیستم با هم یکی نیستند. به همین دلیل مشاهده وضعیت مؤثر، Log و Metric باید کنار Configuration بررسی شود.
اجزای اصلی و مرز مسئولیت
CPUWeight، MemoryMax و IOWeight انواع متفاوتی از کنترل هستند؛ وزن رقابتی با hard limit یک مفهوم نیست.
در طراحی عملی، برای هر جزء یک سؤال روشن بنویسید: چه ورودی میگیرد، چه خروجی تولید میکند، چه Stateای نگه میدارد و در خرابی چه کسی مسئول Recovery است. این مدل ساده کمک میکند خطاهای شبکه، هویت، ذخیرهسازی یا Replication بهاشتباه به جزء دیگری نسبت داده نشوند.
خطاهای رایج
قبل از اعمال محدودیت در Production باید pressure، OOM behavior و dependencyهای سرویس مشاهده شوند تا throttling ناخواسته رخ ندهد.
خطای دیگر، فعالکردن قابلیت پیشرفته بدون تعریف معیار موفقیت است. قبل از تغییر، Baseline بگیرید؛ بعد از تغییر همان Signalها را مقایسه کنید. اگر سیستم توزیعشده است، Failure Modeهای قطع شبکه، Restart، Lag، Timeout و از دسترفتن Dependency را نیز آزمایش کنید.
چکلیست عملی
- نسخه و Configuration مؤثر را ثبت کنید، نه فقط فایل مورد انتظار را.
- مسیر داده و کنترل را جدا رسم کنید.
- Health، Latency، Error Rate و ظرفیت را قبل و بعد از تغییر مقایسه کنید.
- برای تغییرات Stateful، Backup/Restore یا Rollback واقعی را آزمایش کنید.
- دسترسی مدیریتی را حداقل کنید و Log تصمیمها را نگه دارید.
- مستندات همان نسخه محصول را مرجع نهایی قرار دهید.
تمرین IROSG
یک محیط کوچک آزمایشی بسازید و فقط یک Failure را تزریق کنید؛ مثلاً قطع Upstream، حذف یک Replica، خطای DNS یا تغییر Route. قبل از آزمایش بنویسید انتظار دارید کدام Metric و Log تغییر کند. بعد نتیجه واقعی را با انتظار مقایسه کنید. این تمرین معمولاً سریعتر از حفظکردن Optionها، مدل ذهنی سیستم را اصلاح میکند.
مرجع
این راهنما بر پایه مستندات رسمی systemd نوشته شده و مثالهای عملی تحریریه برای آموزش دفاعی و عملیاتی هستند.
ابتدا سهم، سقف و اندازهگیری را جدا کنید
کنترل منابع با systemd به گروه فرایندهای یک unit اعمال میشود و از ساختار cgroup استفاده میکند. سه مفهوم را نباید یکی گرفت: accounting مصرف را اندازه میگیرد، weight سهم نسبی هنگام رقابت را تعیین میکند و limit سقف یا مرز مشخصی میگذارد. فعال کردن شمارش حافظه به تنهایی مصرف را محدود نمیکند. از طرف دیگر، تعیین سقف بدون دیدن الگوی مصرف میتواند سرویس سالم را در زمان شروع یا بار دورهای متوقف کند. نخست رفتار واقعی را مشاهده و سپس نوع کنترل مناسب را انتخاب کنید.
یک مثال، میزبان دارای API و کار پردازش دستهای است. میخواهید هنگام رقابت، API سهم بیشتری از CPU داشته باشد، ولی وقتی API بیکار است کار دستهای بتواند از ظرفیت آزاد استفاده کند. weight برای بیان این ترجیح مناسبتر از سقف سخت است. اگر هدف جلوگیری از مصرف بیش از مقدار مشخص حتی در میزبان خلوت باشد، quota معنای دیگری دارد. انتخاب میان این دو باید از نیاز سرویس بیاید، نه از تصور اینکه عدد کوچکتر همیشه ایمنتر است.
سلسله مراتب تعیینکننده است
Unitها در sliceها و شاخههای cgroup قرار میگیرند. محدودیت والد میتواند بر فرزند اثر بگذارد، حتی اگر خود سرویس محدودیت بزرگی داشته باشد. بنابراین هنگام مشاهده throttling یا کمبود حافظه، فقط فایل unit همان سرویس را نخوانید؛ جای آن در سلسله مراتب و تنظیمات والد را نیز بررسی کنید. دو سرویس در شاخههای متفاوت ممکن است با اعداد ظاهراً مشابه رفتار متفاوتی نشان دهند، زیرا سهم در سطح همسطحها تقسیم میشود.
برای جدا کردن بارهای تعاملی و دستهای، sliceهای روشن با نام و هدف مشخص بسازید. عمق بیش از حد ساختار، تفسیر سهم و سقف را سخت میکند. نمودار کوتاهی از والد و فرزندها نگه دارید و کنار هر شاخه هدف کنترل را بنویسید. اگر سرویس دیگری بعداً به همان slice اضافه شود، منابع مشترک تغییر میکنند. بنابراین تغییر عضویت نیز یک تغییر ظرفیت است و باید مانند تغییر عدد limit بررسی شود.
CPUWeight و CPUQuota چه تفاوتی دارند؟
وزن CPU در زمان رقابت نسبت را مشخص میکند و رزرو ثابت تعداد هسته نیست. وقتی رقیبی وجود ندارد، استفاده از ظرفیت آزاد میتواند ادامه یابد. quota زمان مجاز پردازنده در یک بازه را محدود میکند و میتواند باعث throttling شود. درصد CPU را نیز با درصد کل ظرفیت میزبان اشتباه نگیرید؛ معنای آن را طبق مستندات systemd و تعداد CPUهای قابل استفاده تفسیر کنید. یک برنامه چندریسمانی ممکن است سقف را سریعتر مصرف کند و در باقی بازه منتظر بماند.
اگر تأخیر API پس از اعمال quota بالا رفت ولی میانگین مصرف CPU کم به نظر میرسد، دورههای کوتاه burst و آمار throttling را بررسی کنید. میانگین بلندمدت میتواند توقفهای کوتاه اما مهم را پنهان کند. کوچک یا بزرگ کردن کورکورانه سهم، بدون دیدن نرخ درخواست و مدت پردازش، علت را روشن نمیکند. یک آزمون با بار ثابت و سپس burst طراحی کنید تا فرق رفتار پایدار و لحظهای آشکار شود.
حافظه؛ فشار نرم با حد نهایی فرق دارد
MemoryHigh برای اعمال فشار و کنترل رشد مصرف در سطحی مشخص به کار میرود و MemoryMax حد سختتری ایجاد میکند. عبور از مرزهای حافظه میتواند به reclaim، کندی یا در نهایت کشتن فرایند در دامنه مربوط منجر شود. این رفتار را با خطای عادی تخصیص حافظه در برنامه یکسان فرض نکنید. اگر سقف بسیار نزدیک به مصرف عادی باشد، شروع مجدد یا بار کوتاه ممکن است سرویس را وارد چرخه شکست کند.
MemoryLow و MemoryMin مفاهیم حفاظت از حافظه دارند و باید با بودجه کل میزبان سازگار باشند. حفاظت بیش از ظرفیت واقعی برای همه سرویسها تعارض ایجاد میکند. همچنین مصرف حافظه فقط heap برنامه نیست؛ cache، فرایندهای فرزند و اجزای دیگر گروه نیز میتوانند اثر داشته باشند. هنگام تعیین عدد، بار راهاندازی، پردازش بزرگ و نگهداری دورهای را اندازه بگیرید. کاهش سقف تا مقدار میانگین روزانه، حاشیه لازم برای عملیات مشروع را حذف میکند.
ورودیوخروجی و وابستگی به دستگاه
IOWeight ترجیح نسبی برای رقابت ورودیوخروجی بیان میکند، ولی رفتار دقیق به stack ذخیرهسازی و پشتیبانی مربوط وابسته است. محدودیت پهنای باند یا تعداد عملیات برای دستگاه مشخص، معنای متفاوتی دارد. اگر داده از لایههای مجازی، device mapper یا ذخیره شبکهای عبور کند، باید مطمئن شوید کنترل بر دستگاه مورد نظر اعمال میشود. عددی که در پیکربندی ثبت شده ولی مسیر واقعی را هدف نمیگیرد، حفاظت عملی ایجاد نمیکند.
برای آزمون، یک کار خواندن یا نوشتن کنترلشده روی داده غیرحساس اجرا کنید و هم مصرف سرویس و هم تأخیر برنامه مهم را ببینید. آزمون تخریبی روی دیسک دارای داده انجام ندهید. cache میتواند نتیجه را تغییر دهد؛ خواندن مکرر همان فایل ممکن است اصلاً فشار مورد انتظار روی دستگاه ایجاد نکند. بنابراین روش اندازهگیری باید توضیح دهد داده از کجا خوانده شده و چه بخشی از زمان به ذخیرهسازی مربوط بوده است.
تعداد taskها و فرایندهای فرزند
TasksMax میتواند رشد تعداد taskها را محدود کند و در برابر ایجاد بیرویه فرایند یا thread مفید باشد. با این حال، سرویسهای دارای thread pool بزرگ یا بار متغیر ممکن است به سقف واقعبینانه نیاز داشته باشند. خطای ساخت thread را صرفاً به کمبود حافظه نسبت ندهید؛ محدودیت task نیز میتواند علت باشد. تعداد فرایندها و threadهای واقعی را هنگام شروع، اوج بار و خاموش شدن مشاهده کنید تا سقف به الگوی درست نزدیک شود.
کنترل cgroup معمولاً فرایندهای وابسته در همان گروه را نیز شامل میشود، اما واگذاری مدیریت زیرشاخهها به runtime یا مدیر دیگر نیازمند طراحی آگاهانه است. Delegate را صرفاً برای رفع یک خطا فعال نکنید. باید معلوم باشد کدام کنترلگر و کدام بخش درخت به چه مؤلفهای سپرده میشود. مدیریت همزمان یک زیرشاخه توسط چند مدیر میتواند باعث رفتار غیرمنتظره و اختلاف میان پیکربندی و وضعیت واقعی شود.
اعمال تغییر و مشاهده مقدار مؤثر
برای تغییر پایدار، drop-in مناسب unit و بازخوانی تنظیمات را طبق روش systemd به کار ببرید. برخی تغییرها در زمان اجرا قابل اعمالاند، ولی پایداری آنها پس از reboot باید روشن باشد. مقدار نوشتهشده در یک فایل تنها مرجع حقیقت نیست؛ تنظیم مؤثر unit و فایلهای cgroup را نیز بررسی کنید. ترتیب drop-inها یا تنظیم والد میتواند نتیجه را تغییر دهد. ثبت مقدار قبل و بعد به عیبیابی کمک میکند.
یک تغییر را ابتدا روی سرویس آزمایشی یا نمونه محدود انجام دهید. معیار پذیرش فقط کاهش مصرف نیست؛ زمان پاسخ، نرخ خطا و توان انجام کار باید حفظ شوند. اگر یک job با سقف جدید دو برابر طول میکشد، ممکن است همپوشانی اجرای بعدی ایجاد کند و مشکل تازهای بسازد. زمان پایان کار و صف منتظر را همراه مصرف منابع اندازه بگیرید. کنترل منابع باید خدمت مورد نیاز را ممکن کند، نه صرفاً نمودار مصرف را پایین بیاورد.
تشخیص رخداد OOM و بازگشت
در صورت توقف سرویس، نتیجه unit، پیام kernel و شمارندههای cgroup را کنار هم بررسی کنید. restart خودکار میتواند علت اولیه را پنهان کند و فقط تعداد شروعهای مجدد را نشان دهد. اگر سقف حافظه علت بود، ابتدا شواهد را ثبت و سپس تصمیم بگیرید افزایش حاشیه، اصلاح برنامه یا کاهش همزمانی مناسبتر است. حذف همه محدودیتها بدون تحلیل ممکن است خرابی یک سرویس را به فشار کل میزبان تبدیل کند. راهنمای بازگشت باید مقدار قبلی و روش اعمال آن را دقیق نگه دارد.
در میزبانهای قدیمی یا محیط کانتینری، وجود directive در مستندات جدید به معنی پشتیبانی کامل محیط شما نیست. نسخه systemd، نوع سلسله مراتب cgroup و کنترلگرهای قابل استفاده را ثبت کنید. اگر گزینه نادیده گرفته شده یا کنترلگر واگذار نشده باشد، عدد تنظیمشده اثر مورد انتظار ندارد. آزمون مصرف کنترلشده و مشاهده مقدار مؤثر، این فاصله میان پیکربندی و اجرا را آشکار میکند.