معرفی Cgroup در لینوکس

سلام دوستان خوبم.
خوبید؟ دماغتون چاقه؟! به به، به به! امیدوارم که خیلی عالی باشید.
همیشه آخرش شعر میذاشتم این سری میخوام اول شعر بذارم. باشد که جملگی کامروا شویم:

پیش ما رسم شکستن نبود عهد وفا را  /  الله الله تو فراموش مکن صحبت ما را
قیمت عشق نداند قدم صدق ندارد  /  سست عهدی که تحمل نکند بار جفا را
همه را دیده به رویت نگرانست ولیکن  /  خودپرستان ز حقیقت نشناسند هوا را

بگذریم چون این نیز میگذرد.

سی گروپ یا Cgruop که ممکنه به اسم Control Group هم بربخورید یه مدیر منابع هست. البته منابع انسانی مثل دیجی‌کالا که همه رو اخراج میکنه نه بلکه مدیریت منابع سخت افزاری است.
خیلی لازم و ضروری هست که باهاش کار بکنیم. به عنوان یه سیس‌ادمین حرفه‌ای. امروز قصد داریم در این پست به Cgroup در لینوکس یه نگاهی بندازیم! ماجرای این پست اینجوری شروع شد که یکی از هم شاگردیها یه سوالی از من پرسید که برای جواب دادن بهش دست و پام لرزید. در حالی که خیلی سوال ساده‌ای بود! به این فکر افتادم که چه چیزهای پیش پا افتاده‌ای که راحت از کنارشون رد شدم و اینقدر مهم باری، بریم سر اصل مطلب. توی دنیای لینوکس سی گروپ حدود سال ۲۰۰۶ توسط مهندسهای گوگل ارائه شد با اسم Container Group و خیلی هم طول نکشید که در اواخر ۲۰۰۷ به کرنل لینوکس مرج شد. خلاصه که رفت و جزوی از پروژه لینوکس شد خودش همینجوری با پای خودش.

  • به کمک cgroup ما قادر خواهیم بود که یه سری از مشکلاتمون در مدیریت منابع رو حل کنیم.!  از جمله :
  • CPU Time
  • System Memory
  • Disk Bandwidth
  • Network Bandwidth
  • مثلا بگیم CPU, RAM, IOPS و غیره ۱۰ درصدش برای سیستم عامل باشه و بقیش به طور کامل تحت امر Hypervisor. در نتیجه مثلا اگه سیستم عامل رو بخواهیم بروز کنیم فقط ۱۰ درصد از پهنای باند در دسترس به عملیات بروزرسانی اختصاص داده میشه و میتوان همزمان اطمینان حاصل کرد که ماشینهای مهمان به اون ۹۰ درصد باقی‌مانده دسترسی خواهند داشت. بخاطر دارم زمانی که با استاد عل حامدی کلاس مجازی سازی داشتم یه بحثی بود که چرا vsphere اینقدر سنگینه امروز که دارم بهش فکر میکنم به خودم یاد‌اوری میکنم زنده‌باد نرم‌افزار متن باز و خدا حافظ vmware (چند وقت پیش هم به همه کاربراش اعلام کارد که حاضره با دریافت اندکی هزینه تمام میهمان ها رو به AWS مهاجرت بده. یعنی دقیقا محصول جدیدشون شده مهاجرت کاربرای قدیمشون به AWS و این یعنی تسلیم در برابر قدرت)
    خبر خوب دیگه بعد از اخترع این مکانیزم این بود که خیلی پروژه‌ها به کمکش میسر شد. مثلا کانتینر کردن چیزها و در نهایت داکر و مصحولات مشابهش.
    بیشتر قصد داریم خودش رو درک کنیم تا بریم سر کانتینرها.
    من یه Vagrant Box ابونتو آماده کردم که تستامون رو روش بزنیم. حتما اگه تا حالا از Vagrant استفاده نکردید استفاده کنید که خیلی لذت بخشه
    راستش نمیدونم چرا تو این موضوع خاص کانونیکال یه خورده ضعیف عمل کرده! ولی برای اینکه Cgroup نصب بشه باید همه وابستگیها رو هم خودمان نصب کنیم که مجموعا باید این دستور رو اجرا کنیم:

    sudo apt-get install cgroup-bin cgroup-lite cgroup-tools cgroupfs-mount libcgroup1

    به هر حال سی گروپ توی دنیای اوبونتو اینجوری کار میکنه! راستش من خودم کلاه‌قرمزیم  ولی به اوبونتو و پدر بزرگوارش دبیان هم ارادت خواصی دارم و به جز این مورد خواص که بیشتر رد‌هتی بزرگ شده و کلی داکیومنت ازش موجوده به عنوان مثال سایت داکیومنت رد‌هت که لینکش رو براتون میگذارم، تمام توزیع‌های دیگه از سوزه تا آرچ باید پیش این دو (RedHat و Debian) شاگردی کنند. حداقل سواد من اینو بهم میگه که یا باید مثله Redhat استیبل بود و یا مثل Debian یه کامیونیتی قوی پشتش بود وگرنه از چرخ گردونه عقب خواهی افتاد. این مورد رو هم عمدا روی اوبونتو مثال زدم که ببینیم حتی اونجایی که فقدان داکیومنت خوب هست ولی جامعه‌کاربری چه جوری پشتش وا میسته و نگهش میداره! یه جورایی مثل اتحادیه اروپا میمونه کامیتونی دبیان، به علاوه که شاید، شاید روزی حین یک پروژه عملیاتی به درد کسی بخوره که اینجا رو پیدا کنه و کلی دعاگومون میشه.
    تو دنیای دبیانی مموری کنترل بصورت پیش فرض غیر فعاله و ما باید اینبیش کنیم. پس:

    GRUB_CMDLINE_LINUX_DEFAULT="quiet cgroup_enable=memory swapaccount=1" &&  sudo update-grub

    به جز اینکه الان سی‌گروپ یا همون Cgroup رو با موفقیت نصب کردیم چیزی باقی نمیمونه!.ولی باید یادآور بشیم که در توزیع اوبونتو cgroup به صورت پیشفرض کانفیگ فایلها رو نمیسازه! یا بهتر بگیم در مثال ما فقط نصب شده و میتونه تنظیم بشه و گرنه سیستم شما عین قبلش داره منابع رو مدیریت میکنه. اینجا تفاوت عمده بین کلاه‌قرمزیا و دبیانیا هست که قابل تامله! نتیجه گیری اینکه سی‌گروپ تو دنیای اوبونتو فرق داره کانفیگ کردنش ولی کانسپت همونه!

  • cgroup-سی‌گروب

اگه به تصویر بالا که نمیدونم از کدام بدبختی دزدیم اینجا گذاشتم دقت کنید میبنید که چه قدر این امکان وجود داره که منابع مختلف رو کنترل و حتی میشه جلوتر رفت و لایه های پایین‌تری از گروه‌بندی یا پارتیشن‌بندی رو اعمال کرد. (طی پیدا کردن این تصویر به این پی بردم که پروژه محبوب Apache-Mesos هم با استفاده از cgroup پیاده سازی شده! جالب بود!). بزارید از توضیح کانسپتی صرف نظر کنیم بریم سراغ اینکه چجوری میشه باهاش ور رفت. |
دو راه اصلی داره. یا اینکه کافیگ فایل رو درست کنیم. که گفتیم توی دنیای اوبونتو باید حتما درستشون کنیم با این مسیر:

/etc/cgconfig.conf

ویا

/etc/cgrules.confg

به نظر میاد که هر کدوم کاری میکنند ولی واقعیتش اینه که میتونه فقط یکی از اینها باشه و اون یکی حذف بشه و یا اینکه هر دو باشن و مانفستها یک جا نوشته بشه و کانفیگها یک جای دیگه(در واقع علتش هم همینه) ولی در نهایت باید مطابق سینتکش توی Directive مربوط به خودشون جدا بشن.  یه نکته خیلی بامزه دیگه اینکه همزمان میشه از cli هم استفاده کرد. و اونم هست:

cgcreate -a root -t ashkan -g cpu,memory:limitgroup

توی مثال بالا باید فرض کنید که یوزر ashkan قبلا sudoer شده باشه.توی دستور بالا limitgroup هم یه جورایی اون گروهیه که میخوام سطح دسترسیشون به منابع رو کنترل کنیم. از اونجای که قصد نداریم چیزی رو آموزش بدیم و فقط میخواهیم معرفی کنیم پیشنهاد میکنم حتما man رو برای همه دستورات مطالعه کنید. ولی مختصرا میگم وقتی از سویچ -g استفاده میکنیم داریم به منابع اشاره میکنیم و این میتونه شامل همه چیز بشه.
پردازنده، مموری، پهنای‌باند هارد‌دیسک و شبکه

حالا میشه به دایرکتوریهای مربوطه ایجاد شدن یه سری زد:

ls /sys/fs/cgroup/cpu
ls /sys/fs/cgroup/memor

یا اینکه از lscgroup استفاده کرد:

lscgroup

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

group limitgroup {
  perm {
    task {
      uid = 1001;
      gid = 1001;
    }  
  }
  cpu {
    cpu.shares = "700";
  }
  memory {
    memory.limit_in_bytes = "2G";
  }            
}

توی کافیگ بالا گفتیم که پرمیژن گروپ چی هست؟! از اونجایی که تو وایگرانت باکس من یورز ashkan یوزر‌آیدیش  1001 هست  و همنطور گروپ‌آیدیش به عنوان اینجا کننده پراسسها(یه بحث عمیق کرنلیه که هر یوزر یه یوزر اسپیس داره توی رجیستر که پردازنده و پراسسهایی که والدشونه به صف پردازش منتقل میشن) اعمال خواهند شد. برای درک بهتر وقتی ps -ely رو اجرا میکنید بهتون میگه هر پراسس رو کی تولید کرده البته بجای اسم یوزر‌آی‌دی و گروپ‌آی‌دی برمیگردونه.
بجز این در کانفیگ بالا میشه گفت ادمین کی باشه. مثلا فرض کنید ما میخواهیم apache رو کنترل کنیم و نمیخواهیم ادمین این سرویس رو root در نظر بگیریم. میخواهیم مثلا puppet یا یه کاربر انسانی ادمین باشد و یا هرچی. سینتکس اینشکلی میشه:

group limitgroup {
  perm {
    admin {
      uid = 33; #Puppet/Ansible/Chef
      gid = 33; #Puppet/Ansible/Chef
    }
    task {
      uid = 1001;
      gid = 1001;
 cpu { 
      cpu.shares = "700"; 
    }
 memory {
         memory.limit_in_bytes = "2G"; 
    } 
 }

این برای این هست که ما بتوانیم دقیقا هر پردازش را برای هر سرویس مدیریت کنیم. توی مثال قبل به cpu و mempry اشاره شده بود که مثلا گفته بودیم این گروه که اسمش رو گذاشتیم limitgroup فقط این اندازه Memory دسترسی داشته باشه و یا این اندازه Cpu بکشه(به اصطلاح) و این امکان هست که بگیم blkio یا غیره. توی مثال بالا حداکثر مقدار cpu.shares میتونه ۱۰۰۰ باشه بنابراین عدد ۷۰۰ برابر میشه با ۷۰٪ از کل توان پردازنده. و محدودیت مموری هم به ۲ گیگابایت تنظیم شده که واضحه!
توی دنیای غیر از دبیان(برای من در رد‌هت خلاصه میشه) کار کردن با Hierarchy یا سلسه مراتب سی‌گروپ یه جوره دیگه هست. نه اینکه نمیشه توی‌دبیان مثله RedHat پیاده بشه بلکه بصورت پیش فرض اونجوری نیست. بجز cgroup من فقط یه پروژه دیگه دیدم که داکیومنت رده‌تی بهتری داشته و اونم qemu بوده. شاید بخاطر اینکه رد‌هت خودش در توسعه این ابزارها نقش پر‌رنگی ایفا کرده.

sudo cgconfigparser -l /etc/cgconfig.conf

خودش یه دستور داره پارس(نه وق‌وق سگ بلکه تجزیه و تحلیل) و بعد از تنظیماتی که صدا زدیم اعمال میشه.
ولی ممکنه بخواهیم این سرویس بخشی از init باشه. و اینجا زیاد مهم نیست که از Upstart استفاده میکنید یا systemd مهم اینه میخواهید بعد از هر بار ریبوت این سرویس را با تنظیمات که داشتیم خودش اجرا بشه. اینجاست که فرقه تامل‌برانگیز دو توزیع اصلی آشکار میشه! چون در رد‌هت یا سنت‌او‌اس خودش بصورت اتوماتیک به اینیت اضافه میشه.

یه راه خیلی دم‌دست اینه که خودمون یه سرویس به اینیت اضافه کنیم، چجوری؟ اینجوری:

cat /etc/systemd/system/cgroup.service # مینونه هرچیزی باشه فقط باید با نقطه سرویس تمام بشه
[Unit]
Description=cGroup init modification

[Service]
ExecStartPre=/bin/bash -c cgconfigparser -l /etc/cgconfig.conf
ExecStart=/sbin/cgconfigparser
Restart=always
KillSignal=SIGQUIT
Type=notify
NotifyAccess=all

و حالا باید سرویس اینیت دوباره لود بشه. از اونجایی که نمیشه خود اینیت رو به عنوان سرویس restart یا stop و start کرد یه دستور براش پیش‌بینی شده:

sudo systemctl daemon-reload

برای اینکه این کانسپت براتون ملموس تر بشه پیشنهاد میکنم در مورد systemd مطالعه کنید.

حالا که یه معرفی مختصر داشتم بد نیست بگیم چجوری میشه توی واقعیت ازش استفاده کرد. در واقعیت برای اینکه از تکرار جلوگیری بشه همیشه یه سیستم منیجر داریم. من طرفدار Ansible هستم(گفتم Ansible یادم باشه یه چیزی ازش بنویسم) ولی ‌Chef و Puppet به همون اندازه قدرت منده و من در این خصوص بحثی ندارم. ایده اینه که یه سرویسی تسکهای تکراری را در همه سرور ها انجام بده حالا اینکه چه جوری زیاد مهم نیست. خوب وقتی از این سیستم بهره بگیرید میتونید روی هر سرور هم cgroup اینستال داشته باشید. توی یه مثال واقعی ممکنه مشتریهای یه شرکت در گوشه‌ای از دنیا بیشتر به دنبال استفاده از سرویس ویدئو باشند تا ایمیل. و در گوشه دیگه دنیا دقیقا برعکس مشتریها دنبال ایمیل باشند تا ویدئو! Best Practice  تو این مثال میگه ما طراحی محصولمون باید بر مبنای Resource Partitioning باشه  که بعدا بتونیم ازش استفاده کنیم. مثله این میمونه که میخوایم متغیر تعریف کنیم توی دنیای برنامه نویسی. بعدا بسته به نیاز میتونیم بگیم گروه ویدئو برادکستینگ ۶۰ ٪ و گروه ایمیل ۳۰٪ و ۱۰٪ هم خوده سیستم عامل و در قسمت دیگر دنیا جور دیگه ای منابع رو تخصیص بدیم. همینطور اگه مولتی ریجن(Multi Region) باشیم این الگو میتونه خیلی کمک کننده بشه که سرویسهای ایمیل به بهترین و نزدیک‌ترین ارائه دهنده مسیر‌دهی بشند بجای این به نزدیک‌ترین و بهترین . بجز این پدیده دیگری که خیلی سوال برانگیزه تو بخش طراحی اینکه که خوب ما الان یه وب سرور داریم و یه میل سرور هر دوی اینها از دیتابیس استفاده میکنند الان باید کدام سرویس بشه غالب و کدام سرویس بشه مغلوب؟ جوابش خیلی واضحه در این مثال بخصوص اگرچه دیتابیس به طور مستقیم به کاربر سرویس ارائه نمیده ولی در واقع مهم‌ترین سرویس هست چونکه دو سرویس دیگه یعنی میل و وب سرور وابسته به این سرویس هستنید. بنابراین بهترین طراحی اینه که هر سه اینها در سه گروه جدا بشوند و بعد بسته به نیاز بهشون منابع سخت‌افزاری تخصیص داده بشه. شاید بشه ساعتها در موردش صحبت کرد که دیگه از حوصله شما هم خارجه! ولی نکته مهم این بود که playbook ها و یا manifest هامون رو جوری بنویسیم که سرویسها و متعلقاتشون پارتیشن بندی بشن که بتونیم با cgroup کنترلشون کنیم.

منابع:

ویکی‌پدیا

سایت ردهت

گیت‌هاب این یارو

یا حق

دیدگاهی بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *