WIUNIX ACADEMY
پاد Evicted در Kubernetes؛ فشار نود رو از OOM و زمانبندی جدا کن
صفحهٔ 2 از 3؛ قبل از ادامه، مراحل قبلی و چیزهایی رو که لازم داری مرور کن.
آموزش متناسب با محیط تو
کجا اجرا میکنی؟
سیستمعامل و نسخهٔ سرورت رو انتخاب کن تا مراحل، دستورها و راهحلهای همون محیط رو ببینی.
آموزش متناسب با مقادیر تو
تنظیمات این آموزش
مقادیر نمونه رو با مشخصات سرورت عوض کن تا متن و دستورها با هم تغییر کنن. رمز، کلید خصوصی و توکن اینجا وارد نکن. مقدارها فقط توی همین زبانه میمونن و به سرور یا لینک اشتراکگذاری فرستاده نمیشن. قبل از اجرا، DNS، گواهیها و تنظیمات دسترسی شبکه رو روی سرورت بررسی کن.
اگر آیپی، دامنه یا پورتهای نمونه با سرورت فرق دارن، بخش تنظیمات پایین رو باز کن. مقدارها رو عوض کن و «اعمال در آموزش» رو بزن؛ بعد دستورهای تازه رو کپی کن.
تنظیم مقادیر برای محیط من3 مقدار قابلتغییر
قدم بعدی
علت، پیام و هویت پاد ناموفق رو بخون
قبل از رخدادها، UID، زمان ساخت، مرجع مالک، نود تخصیصیافته، phase و reason رو ثبت کن. ترکیب Evicted با پیامی دربارهٔ کمبود منبع نود، شاهد مفیدی برای فشار است. علت دیگر یا صرفاً نبودن پاد، eviction ناشی از فشار نود رو ثابت نمیکنه.
رخدادها منقضی و پیام تکراری ممکنه تجمیع بشه. زمان شکست و UID رو کنار رخداد مرکزی و پایش موجود نگه دار. اگر شیء دیگر وجود نداره، هویت تاریخی رو از مسئول برنامه بگیر؛ برای نمایش تمیزتر، حادثه رو دوباره نساز یا پاد جایگزین رو حذف نکن.
همان شل Bash مجاز روی میزبان مدیریت
k get pod 'example-app' -n 'apps' -o jsonpath='{.metadata.uid}{"\n"}{.metadata.creationTimestamp}{"\n"}{.metadata.ownerReferences}{"\n"}{.spec.nodeName}{"\n"}{.status.phase}{"\t"}{.status.reason}{"\n"}{.status.message}{"\n"}{range .status.conditions[*]}{.type}{"="}{.status}{"\t"}{.reason}{"\t"}{.lastTransitionTime}{"\n"}{end}'
k events -n 'apps' --for 'pod/example-app'پاد ناموفق مشخص و مرحلهٔ توقف یا زمانبندیاش از وضعیت و شواهد همزمان معلومه.
قدم بعدی
نود تخصیصیافته و شرطهای فشارش رو تطبیق بده
کنترل اول نود پاد رو با مقدار فرم مقایسه میکنه. اگر هنوز نودی تخصیص نیافته، این شاخه رو ادامه نده. UID نود، نسخهٔ kubelet/runtime و زمان تغییر شرطها رو ثبت کن، نه فقط چراغ Ready رو.
MemoryPressure، DiskPressure و PIDPressure از منبعهای متفاوت خبر میدن. نود ممکنه هم Ready باشه و هم فشار داشته باشه؛ ممکنه هم بعد از eviction فشار رفع شده و شرط فعلی false باشه. وضعیت فعلی یک نمونه است، نه تاریخچهٔ کامل رخداد. taint ساختهشده از شرط روی زمانبندی اثر میذاره، اما خودش اندازهگیری بازیابی منبع نیست.
همان شل Bash مجاز روی میزبان مدیریت
observed_node=$(k get pod 'example-app' -n 'apps' -o jsonpath='{.spec.nodeName}') || exit 1
test -n "$observed_node" || { printf 'STOP: no assigned node; investigate scheduling first.\n' >&2; exit 1; }
test "$observed_node" = 'worker-a' || { printf 'STOP: actual node is %s; reconcile the public example first.\n' "$observed_node" >&2; exit 1; }
k get node 'worker-a' -o jsonpath='{.metadata.uid}{"\n"}{.status.nodeInfo.kubeletVersion}{"\n"}{.status.nodeInfo.containerRuntimeVersion}{"\n"}{range .status.conditions[*]}{.type}{"="}{.status}{"\t"}{.reason}{"\t"}{.lastTransitionTime}{"\t"}{.message}{"\n"}{end}{.spec.taints}{"\n"}{.spec.unschedulable}{"\n"}'پاد اولیه به هویت درست نود و شرطهای زماندار وصل شده؛ نود غایب یا نامتطابق شاخه رو متوقف میکنه.
قدم بعدی
سابقهٔ نود رو با زمان شکست پاد کنار هم بذار
فقط با مجوز جداگانهٔ رخدادهای کل کلاستر، پیامهای همین نود رو بخون. تغییر فشار، پیام آزادسازی/eviction و زمان شکست پاد رو با هم مقایسه کن. شرطها ممکنه نوسان داشته باشن و گزارش هم همزمان نیست؛ یک پیام یا نبود پیام، کل داستان رو نمیگه.
اگر عرضهکننده مدیریت نود رو در اختیار داره یا تاریخچه منقضی شده، UID و نسخهٔ نود، منبع درگیر و بازهٔ زمانی رو به مسئولش بده. وضعیت سبز الان توضیحی برای شکست قبلی نیست.
همان شل Bash مجاز روی میزبان مدیریت
k events --all-namespaces --for 'node/worker-a'شواهد زمانیِ نود فرضیهٔ منبع درگیر رو پشتیبانی میکنه یا نبود تاریخچه صریح ثبت میشه.
قدم بعدی
OOM کانتینر رو با eviction پاد قاطی نکن
حالت پایان فعلی و قبلیِ کانتینرهای init و عادی رو بخون. OOMKilled از پایان یک کانتینر خبر میده؛ ممکنه سقف حافظهٔ cgroup عاملش باشه، بدون اینکه کل نود کمبود داشته باشه. برعکس، حافظهٔ نود ممکنه قبل از دیدن آستانه توسط kubelet تموم بشه و کرنل قربانی رو انتخاب کنه.
برای جداکردن این مسیرها، reason و message سطح پاد رو کنار شواهد نود و پایش کرنل/kubelet توسط مسئول بذار. کد خروج ۱۳۷ بهتنهایی نه OOM رو ثابت میکنه و نه eviction رو. lastState خالی هم تاریخچهٔ در دسترسنبوده است، نه موفقیت؛ ریاستارت کانتینر با پاد جایگزینی که کنترلکننده ساخته هویت یکسانی نداره.
همان شل Bash مجاز روی میزبان مدیریت
k get pod 'example-app' -n 'apps' -o jsonpath='{range .status.initContainerStatuses[*]}{.name}{"\tinit current="}{.state}{"\tlast="}{.lastState}{"\trestarts="}{.restartCount}{"\n"}{end}{range .status.containerStatuses[*]}{.name}{"\tcurrent="}{.state}{"\tlast="}{.lastState}{"\trestarts="}{.restartCount}{"\n"}{end}'پایان و تکرار کانتینر از تصمیم eviction پاد و OOM کل نود جدا شده.
قدم بعدی
قبل از قضاوت از روی QoS، درخواست و سقف و اولویت رو ببین
اولویت واقعی پاد، QoS، منابع کانتینرهای عادی و init، منابع احتمالی سطح پاد، overhead و تنظیم emptyDir رو بخون. request ورودی تخصیص و زمانبندی است؛ limit و مصرف فعلی مفهوم دیگری دارن. حساب منابع init، sidecar و سطح پاد قاعدهٔ خودش رو داره؛ عددهای چاپشده رو ساده جمع نکن و اسمش رو منبع آزاد نود نذار.
برای فشار حافظه، kubelet عبور مصرف از request، اولویت پاد و میزان مصرف در مقایسه با request رو در نظر میگیره. inode و PID اصلاً request ندارن؛ هنگام کمبود آنها، اولویت نسبی پادها معیار ترتیب است. در فشار دیسک هم ترتیب به سیگنال درگیر و چیدمان nodefs/imagefs/containerfs بستگی داره. QoS در بعضی حالتهای حافظه سرنخ میده ولی کلید مستقیم و همگانی ترتیب eviction نیست. QoS هم برای فشار ناشی از مصرف دیسک یا ephemeral-storage، محافظت جداگانهای به پاد نمیده. اولویت بالا یا Guaranteed مصونیت نیست؛ تغییر اولویت بدون افزودن ظرفیت، پیامد رو به برنامهٔ دیگری منتقل میکنه.
همان شل Bash مجاز روی میزبان مدیریت
k get pod 'example-app' -n 'apps' -o jsonpath='{.spec.priorityClassName}{"\tpriority="}{.spec.priority}{"\n"}{.status.qosClass}{"\n"}{.spec.overhead}{"\n"}{.spec.resources}{"\n"}{range .spec.initContainers[*]}{.name}{"\tinit resources="}{.resources}{"\n"}{end}{range .spec.containers[*]}{.name}{"\tresources="}{.resources}{"\n"}{end}{range .spec.volumes[*]}{.name}{"\temptyDir="}{.emptyDir}{"\n"}{end}'تنظیم واقعی منابع و اولویت برنامه معلومه، بدون تغییر آن یا مصونیتدادن به برچسب QoS.
قدم بعدی
بودجهٔ قابلتخصیص رو با موجودی همین لحظه یکی نگیر
فهرست اختیاریِ کلاستری، پادهای همین نود و علت و اولویت فعلیشون رو نشون میده. capacity با allocatable یکی نیست؛ رزروها و سیاست eviction بخشی از بودجه رو کنار میذارن. allocatable هم اندازهگیری لحظهای بایت آزاد حافظه یا دیسک نیست.
حساب requestهای scheduler رو با مصرف زماندارِ موجود و مسئول نود مقایسه کن. FailedScheduling بهدلیل کمبود ظرفیت درخواستی با ردکردن پاد تازه توسط kubelet در مرحلهٔ admission یا بیرونکردن پاد در حال اجرا فرق داره. ببین پیام رو کدام جزء و چه وقتی داده؛ هر سه رو با حذف پاد یا پاککردن taint فشار حل نکن.
همان شل Bash مجاز روی میزبان مدیریت
k get node 'worker-a' -o jsonpath='{.status.capacity}{"\n"}{.status.allocatable}{"\n"}'
k get pods --all-namespaces --field-selector='spec.nodeName=worker-a' --chunk-size=100 -o custom-columns='NAMESPACE:.metadata.namespace,NAME:.metadata.name,PHASE:.status.phase,REASON:.status.reason,PRIORITY:.spec.priority,QOS:.status.qosClass'بودجه و برنامههای روی نود روشنه؛ ظرفیت گزارششده، تخصیص درخواستی و سیگنال زندهٔ eviction با هم اشتباه نشدن.