ProHoster > وبلاگ > اداره > Kubernetes: با حذف محدودیت های CPU، سرعت خدمات خود را افزایش دهید
Kubernetes: با حذف محدودیت های CPU، سرعت خدمات خود را افزایش دهید
در سال 2016 ما در Buffer به Kubernetes تغییر مکان داد، و اکنون حدود 60 گره (در AWS) و 1500 کانتینر روی خوشه k8s ما کار می کنند که توسط لگد زدن. با این حال، ما از طریق آزمون و خطا به سمت میکروسرویس ها رفتیم و حتی پس از چندین سال کار با k8s همچنان با مشکلات جدیدی روبرو هستیم. در این پست در مورد آن صحبت خواهیم کرد محدودیت های پردازنده: چرا فکر می کردیم آنها تمرین خوبی هستند و چرا در نهایت خوب نبودند.
محدودیت های پردازنده و دریچه گاز
مانند بسیاری از کاربران دیگر Kubernetes، گوگل به شدت توصیه می کند که محدودیت های CPU را تعیین کنید. بدون چنین تنظیماتی، کانتینرها در یک گره می توانند تمام قدرت پردازنده را اشغال کنند، که به نوبه خود باعث فرآیندهای مهم Kubernetes می شود (به عنوان مثال kubelet) پاسخ به درخواست ها را متوقف می کند. بنابراین، تنظیم محدودیت های CPU راه خوبی برای محافظت از گره های شما است.
محدودیتهای پردازنده، ظرف را روی حداکثر زمان CPU که میتواند برای یک دوره خاص استفاده کند (پیشفرض 100 میلیثانیه است) تنظیم میکند و ظرف هرگز از این حد تجاوز نمیکند. در Kubernetes برای گاز دادن ظرف و جلوگیری از تجاوز از حد مجاز، از ابزار خاصی استفاده می شود سهمیه CFS، اما این محدودیت های مصنوعی CPU در نهایت به عملکرد و افزایش زمان پاسخ ظروف شما آسیب می زند.
اگر محدودیت های پردازنده را تعیین نکنیم چه اتفاقی می افتد؟
متأسفانه ما خودمان مجبور شدیم با این مشکل روبرو شویم. هر گره دارای فرآیندی است که مسئول مدیریت کانتینرها است kubelet، و او به درخواست ها پاسخ نداد. گره، زمانی که این اتفاق می افتد، به حالت می رود NotReady، و کانتینرهای آن به جای دیگری هدایت می شوند و همان مشکلات را در گره های جدید ایجاد می کنند. حداقل یک سناریوی ایده آل نیست.
تجلی مشکل دریچه گاز و پاسخ
معیار کلیدی برای ردیابی کانتینر این است trottling، نشان می دهد که ظرف شما چند بار گاز گرفته شده است. ما با علاقه متوجه وجود گاز در برخی کانتینرها شدیم، صرف نظر از اینکه بار پردازنده بسیار زیاد است یا نه. به عنوان مثال، اجازه دهید نگاهی به یکی از API های اصلی خود بیاندازیم:
همانطور که در زیر می بینید، ما این محدودیت را تعیین کرده ایم 800m (0.8 یا 80٪ هسته)، و مقادیر اوج در بهترین حالت ممکن است 200m (20 درصد هسته). به نظر می رسد که قبل از خنثی کردن سرویس، ما هنوز قدرت پردازنده زیادی داریم، با این حال...
ممکن است متوجه شده باشید که حتی زمانی که بار پردازنده کمتر از محدودیت های مشخص شده است - به طور قابل توجهی کمتر - همچنان دریچه گاز رخ می دهد.
در مواجهه با این موضوع، ما به زودی چندین منبع را کشف کردیم (مشکل در github, ارائه در zadano, پست در omio) در مورد افت عملکرد و زمان پاسخگویی سرویس ها به دلیل دریچه گاز.
چرا در بار کم CPU شاهد گاز گرفتگی هستیم؟ نسخه کوتاه آن این است: "یک اشکال در هسته لینوکس وجود دارد که باعث می شود کانتینرهای با محدودیت های پردازنده مشخص شده به صورت غیرضروری خفه شوند." اگر به ماهیت مشکل علاقه مند هستید، می توانید ارائه را بخوانید (تصویری и متن گزینه ها) توسط دیو چیلوک.
حذف محدودیت های CPU (با احتیاط شدید)
پس از بحثهای طولانی، تصمیم گرفتیم محدودیتهای پردازنده را از همه سرویسهایی که به طور مستقیم یا غیرمستقیم بر عملکرد حیاتی کاربران ما تأثیر میگذارد، حذف کنیم.
این تصمیم آسان نبود زیرا ما برای ثبات خوشه خود ارزش زیادی قائل هستیم. در گذشته، ما قبلاً بیثباتی خوشه خود را آزمایش کردهایم، و سپس سرویسها منابع زیادی را مصرف کردند و کار کل گره خود را کند کردند. اکنون همه چیز تا حدودی متفاوت بود: ما درک روشنی از آنچه از خوشه های خود انتظار داشتیم و همچنین استراتژی خوبی برای اجرای تغییرات برنامه ریزی شده داشتیم.
مکاتبات تجاری در مورد یک موضوع مبرم.
چگونه از گره های خود در هنگام برداشته شدن محدودیت ها محافظت کنیم؟
جداسازی خدمات "بدون محدودیت":
در گذشته، ما قبلاً شاهد بوده ایم که برخی از گره ها در یک حالت قرار می گیرند notReady، در درجه اول به دلیل خدماتی است که منابع زیادی را مصرف می کنند.
ما تصمیم گرفتیم چنین خدماتی را در گره های جداگانه ("برچسب") قرار دهیم تا با خدمات "مرتبط" تداخل نداشته باشند. در نتیجه، با علامتگذاری برخی از گرهها و افزودن پارامتر تلورانس به سرویسهای «غیر مرتبط»، کنترل بیشتری روی خوشه به دست آوردیم و شناسایی مشکلات گرهها برای ما آسانتر شد. برای انجام فرآیندهای مشابه خودتان، می توانید با آن آشنا شوید مستندات.
تخصیص یک درخواست پردازشگر و حافظه صحیح:
بزرگترین ترس ما این بود که فرآیند منابع زیادی را مصرف کند و گره به درخواست ها پاسخ ندهد. از آنجایی که اکنون (به لطف Datadog) میتوانستیم به وضوح همه سرویسهای موجود در خوشه خود را نظارت کنیم، چندین ماه عملکرد سرویسهایی را که قصد داشتیم به عنوان «غیر مرتبط» معرفی کنیم، تجزیه و تحلیل کردم. من به سادگی حداکثر استفاده از CPU را با حاشیه 20٪ تنظیم می کنم و بنابراین فضایی را در گره اختصاص می دهم در صورتی که k8s سعی کند خدمات دیگری را به گره اختصاص دهد.
همانطور که در نمودار مشاهده می کنید، حداکثر بار روی پردازنده رسیده است 242m هسته های CPU (0.242 هسته های پردازنده). برای درخواست پردازنده کافی است عددی کمی بزرگتر از این مقدار بگیرید. لطفاً توجه داشته باشید که از آنجایی که خدمات کاربر محور هستند، مقادیر اوج بار با ترافیک منطبق است.
همین کار را با استفاده از حافظه و پرس و جوها و voila انجام دهید - همه چیز را آماده کرده اید! برای امنیت بیشتر، میتوانید مقیاس خودکار غلاف افقی را اضافه کنید. بنابراین، هر بار که بار منبع زیاد باشد، مقیاس خودکار پادهای جدیدی ایجاد میکند و kubernetes آنها را در گرههایی با فضای خالی توزیع میکند. در صورتی که فضایی در خود خوشه باقی نماند، میتوانید یک هشدار برای خود تنظیم کنید یا اضافه کردن گرههای جدید را از طریق مقیاس خودکار آنها پیکربندی کنید.
از معایب، شایان ذکر است که ما در "تراکم ظرف"، یعنی تعداد کانتینرهایی که روی یک گره در حال اجرا هستند. همچنین ممکن است در تراکم ترافیک کم، "آرامش" زیادی داشته باشیم، و همچنین این احتمال وجود دارد که شما به بار پردازنده بالایی برسید، اما گره های مقیاس خودکار باید در مورد دومی کمک کنند.
یافته ها
من خوشحالم که این نتایج عالی از آزمایشهای چند هفته گذشته را منتشر میکنم؛ ما قبلاً شاهد پیشرفتهای قابل توجهی در پاسخ به همه سرویسهای اصلاحشده بودهایم:
ما بهترین نتایج را در صفحه اصلی خود به دست آوردیم (buffer.com) در آنجا سرویس شتاب گرفت بیست و دو بار!
با این حال، پس از خواندن مشکلات kubernetes در githubبرای دوم سپتامبر 2020 ما هنوز در مورد برخی از پروژه های لینوکس با یک باگ مشابه صحبت می کنیم. من معتقدم که برخی از توزیعهای لینوکس هنوز این باگ را دارند و فقط در حال رفع آن هستند.
اگر نسخه توزیع شما پایینتر از 4.19 است، توصیه میکنم بهروزرسانی را به جدیدترین نسخه انجام دهید، اما در هر صورت باید محدودیتهای پردازنده را حذف کنید و ببینید آیا throttling ادامه دارد یا خیر. در زیر می توانید لیستی جزئی از خدمات مدیریت Kubernetes و توزیع های لینوکس را مشاهده کنید:
دبیان: اصلاح یکپارچه شده در آخرین نسخه توزیع، شکننده، و کاملا تازه به نظر می رسد (آگوست 2020). برخی از نسخه های قبلی نیز ممکن است رفع شوند.
EKS هنوز راه حلی دریافت کرده است در دسامبر 2019. اگر نسخه شما کمتر از این است، باید AMI را به روز کنید.
کپس: از ژوئن 2020 у kops 1.18+ تصویر میزبان اصلی اوبونتو 20.04 خواهد بود. اگر نسخه kops شما قدیمی تر است، ممکن است مجبور باشید منتظر رفع مشکل باشید. ما خودمون الان منتظریم
مطمئن نیستم که مشکل به طور کامل حل شده باشد. وقتی با اصلاح به نسخه هسته رسیدیم، کلاستر را تست می کنم و پست را به روز می کنم. اگر کسی قبلاً بهروزرسانی کرده است، مایلم نتایج شما را بخوانم.
نتیجه
اگر با کانتینرهای Docker تحت لینوکس کار می کنید (بدون توجه به Kubernetes، Mesos، Swarm یا دیگران)، کانتینرهای شما ممکن است به دلیل دریچه گاز عملکرد خود را از دست بدهند.
سعی کنید به آخرین نسخه توزیع خود را به روز رسانی کنید به این امید که اشکال قبلاً برطرف شده باشد.
حذف محدودیت های پردازنده مشکل را حل می کند، اما این یک تکنیک خطرناک است که باید با احتیاط زیاد استفاده شود (بهتر است ابتدا هسته را به روز کنید و نتایج را با هم مقایسه کنید).
اگر محدودیتهای CPU را حذف کردهاید، استفاده از CPU و حافظه خود را به دقت کنترل کنید و مطمئن شوید که منابع CPU شما از مصرف شما بیشتر است.
یک گزینه مطمئن، مقیاس خودکار پادها برای ایجاد غلاف های جدید در صورت بار سخت افزاری بالا است، به طوری که kubernetes آنها را به گره های آزاد اختصاص می دهد.
امیدوارم این پست به شما در بهبود عملکرد سیستم های کانتینری کمک کند.
PS اینجا نویسنده با خوانندگان و مفسران مکاتبه می کند (به زبان انگلیسی).