نسخه 1.35 Kubernetes که قرار است 17 دسامبر منتشر شود، مجموعه‌ای از بهبودهای آزمایشی را با خود آورده که هدفشان افزایش انعطاف‌پذیری زیرساخت و تقویت امنیت است. در این مرور، روی ویژگی‌های Alpha تمرکز می‌کنیم؛ از reconcile شدن route controller بر پایه watch و قابلیت موردانتظار Gang Scheduling برای workloadهای AI/ML گرفته تا secrets field برای پاس‌دادن Service Account tokenها، mutable volume attach limits و proxy کردن درخواست‌های API server برای رفع version skew. ⚙️

نکته مهم این است که با توجه به تغییرات مداوم در نقشه راه Kubernetes، بعضی از KEPهایی که اینجا درباره‌شان صحبت می‌شود ممکن است هر لحظه از milestone حذف شوند، مخصوصاً هرچه به زمان انتشار نزدیک‌تر می‌شویم. 🔄

Nodes
Node Declared Features (قبلاً Node Capabilities)
KEP #5328 (issue)
Feature gate: NodeDeclaredFeatures

KEP-5328 یک مکانیزم جدید به نام Node Declared Features معرفی می‌کند تا nodeها بتوانند قابلیت‌های Kubernetes در دسترس خودشان را به‌صورت خودکار اعلام کنند. این کار به scheduler کمک می‌کند وقتی نسخه‌های componentها با هم هم‌خوان نیستند و version skew داریم، تصمیم درست‌تری بگیرد. در این طرح، فیلدی به نام declaredFeatures به node status اضافه می‌شود که kubelet آن را پر می‌کند و scheduler و admission controllerها از آن استفاده می‌کنند تا Pod فقط روی node سازگار قرار بگیرد. این مکانیزم هم با قوانین سخت‌گیرانه کنترل می‌شود تا هم قابل‌اعتماد بماند و هم داده‌هایش معتبر باشد. نکته کلیدی این است که این featureها دائمی نیستند؛ فقط تا وقتی kubelet آن‌ها را تأیید و اعلام می‌کند معتبرند. 🧩

برای این‌که Podها در وضعیت Failed گیر نکنند، kubelet در مرحله bootstrap و قبل از اینکه اولین Pod روی node schedule شود، فهرست کامل featureهای پشتیبانی‌شده را تشخیص می‌دهد. این فهرست به‌صورت خودکار مدیریت می‌شود و اگر کاربر یا controller آن را دستی تغییر بدهد، به حالت اولیه برمی‌گردد. از زمان شروع kubelet تا reboot بعدی بدون تغییر می‌ماند و به‌نوعی «منبع معتبر حقیقت» برای declared featureها محسوب می‌شود؛ چیزی که consistency لازم را برای scheduler حفظ می‌کند. ✅

مثال: in-place Pod resizing به شما اجازه می‌دهد بدون ساختن دوباره Pod، مقدار CPU و memory request و limit یک container را تغییر بدهید. اما ممکن است Pod روی node قدیمی‌تری اجرا شود که از قابلیت‌هایی مثل in-place Pod resize برای guaranteed QOS پشتیبانی نمی‌کند. در چنین حالتی، درخواست API برای تغییر resourceهای یک Pod در حال اجرا باید رد شود. در مقابل، اگر node از feature جدید پشتیبانی کند، specification Pod چیزی شبیه این خواهد داشت:

declaredFeatures:
– GuaranteedQoSPodCPUResize

Allow HostNetwork Pods to Use User Namespaces
KEP #5607 (issue)
Feature gate: UserNamespacesHostNetworkSupport

الان در Kubernetes یک محدودیت مشخص وجود دارد: یا می‌توانید Pod را روی host network اجرا کنید (hostNetwork: true)، یا از user namespaces برای ایزوله‌سازی کاربران استفاده کنید (hostUsers: false)، اما ترکیب این دو مجاز نیست و API server آن را رد می‌کند. خیلی از componentهای control plane مثل kube-apiserver و kube-controller-manager معمولاً به‌صورت static Pod و با دسترسی hostNetwork: true اجرا می‌شوند تا بتوانند روی پورت‌های host گوش بدهند یا مستقیم با network stack در ارتباط باشند. اما به‌خاطر همین محدودیت، این Podها نمی‌توانند از user namespaces برای isolation بیشتر استفاده کنند و همین آن‌ها را نسبت به Podهای معمولی ریسکی‌تر می‌کند. 🔐

KEP-5607 این محدودیت را برمی‌دارد. وقتی این feature فعال باشد، API server دیگر specهایی را که هم hostNetwork: true و هم hostUsers: false دارند رد نمی‌کند. نتیجه این است که می‌توانید containerها را روی host network اجرا کنید و در عین حال با user namespaces، کاربران داخل آن‌ها را ایزوله نگه دارید. البته اگر container runtime شما از این قابلیت پشتیبانی نکند، API server Pod را قبول می‌کند، اما Pod در حالت ContainerCreating گیر می‌کند. به همین خاطر هم نویسندگان KEP فعلاً این feature را alpha نگه داشته‌اند تا زمانی که runtimeهای پرکاربرد مثل containerd و CRI-O از آن پشتیبانی کنند و بعد به beta برسد. 🛠️

Pod Level Resources Support With In-Place Pod Vertical Scaling
KEP #5419 (issue)
Feature gate: InPlacePodLevelResourcesVerticalScaling

KEP-1287 که در Kubernetes 1.27 معرفی شد، این امکان را داد که CPU و memory request و limit هر container را بدون restart کردن آن تغییر بدهید. بعدتر KEP-2837 در K8s 1.32 دو فیلد جدید به Pod API اضافه کرد: pod.spec.resources.requests و pod.spec.resources.limit. این فیلدها اجازه می‌دهند علاوه بر تنظیمات سطح container، برای کل Pod هم resource request و limit تعیین کنید. با این حال، برای اعمال این تنظیمات سطح Pod هنوز مجبور بودید Pod را restart کنید. ⏱️

KEP-5419 این محدودیت را برمی‌دارد. حالا می‌توانید روی یک Pod در حال اجرا، pod.spec.resources را patch کنید بدون اینکه Pod را restart کنید. علاوه بر این، این KEP به PodStatus هم توسعه می‌دهد تا یک معادل سطح Pod برای فیلدهای resource statusِ containerها داشته باشیم؛ یعنی بتوانید ببینید چه مقدار resource واقعاً برای کل Pod رزرو شده است. این برای مانیتورینگ و ظرفیت‌سنجی خیلی کاربردی است. 📊

Restart All Containers on Container Exits
KEP #5532 (issue)
Feature gate: RestartAllContainersOnContainerExits

KEP-5532 ادامه منطقی و گسترش قابلیت‌هایی است که در KEP-5307 معرفی شده بود. در نسخه قبلی، مکانیزم restartPolicy rules فقط برای containerهای تکی وجود داشت و kubelet می‌توانست بر اساس exit code آن‌ها را restart کند. اما در این بهبود، همین منطق به سطح Pod منتقل شده است. حالا می‌توانید بر اساس exit code، همه containerهای داخل Pod را restart کنید، نه فقط همان containerی که خطا داده است. 🔁

وقتی این action اجرا می‌شود، history وضعیت containerها کامل حفظ می‌شود و restart count هم برای containerهای جداگانه و هم برای Pod به‌درستی افزایش پیدا می‌کند. این فرایند به‌صورت in-place انجام می‌شود: IP، sandbox و volumeهای attach شده حفظ می‌شوند، اما همه init containerها و containerهای اصلی از صفر دوباره بالا می‌آیند. با این حال، اگر Pod دارای restartPolicy: Never باشد و یکی از init containerها بعد از فعال شدن RestartAllContainers با خطا crash کند، کل Pod در حالت Failed علامت می‌خورد. 🚨

مثال:

apiVersion: v1
kind: Pod
metadata:
name: my-ml-worker
spec:
restartPolicy: Never
initContainers:
– name: setup-envs
image: setup
– name: watcher-sidecar
image: watcher
restartPolicy: Always
restartPolicyRules:
– action: RestartAllContainers # New action introduced in KEP-5532
onExit:
exitCodes:
operator: In # Choosing from several exit codes
values: [88] # A specific exit code indicating the Pod should be restarted
containers:
– name: main-container
image: training-app

Scheduling Extended Toleration Operators for Threshold-Based Placement
KEP #5471 (issue)
Feature gate: TaintTolerationComparisonOperators

این KEP ساختار core/v1 Toleration API را گسترش می‌دهد و دو operator مقایسه‌ای جدید به آن اضافه می‌کند: Lt برای کمتر از و Gt برای بزرگ‌تر از. هم‌زمان، منطق scheduler pluginِ TaintToleration هم به‌روزرسانی می‌شود تا taint و toleration را به‌جای مقایسه متنی ساده، به‌صورت عددی تفسیر کند. با اینکه فیلد Value از نظر فنی هنوز string است، اما وقتی از operatorهای جدید استفاده می‌کنید، سیستم سعی می‌کند آن را به عدد 64 بیتی int64 تبدیل کند. اگر یکی از مقدارهای taint یا toleration عدد معتبر نباشد، مقایسه ناموفق در نظر گرفته می‌شود و toleration اعمال نمی‌شود. 🧠

پشتیبانی از اعداد اعشاری عمداً حذف شده تا خطاهای دقت عددی پیش نیاید. به جای آن، پیشنهاد می‌شود از scaling استفاده کنید؛ مثلاً 95.5% را به‌صورت عدد 955 بنویسید. این کار برای سناریوهای حساس به threshold خیلی کاربردی است. 📍

مثال: فرض کنید می‌خواهید Podهای latency-critical فقط روی nodeهایی اجرا شوند که SLA آن‌ها بالاتر از 95% است. همچنین اگر SLA node پایین‌تر از این حد آمد، Pod باید evict شود. این KEP چنین چیزی را ممکن می‌کند، چیزی که با NodeAffinity به‌تنهایی به‌سادگی شدنی نبود:

# High-SLA on-demand node
apiVersion: v1
kind: Node
metadata:
name: ondemand-node-1
spec:
taints:
– key: node.kubernetes.io/sla
value: “950”
effect: NoExecute

# Inference service requires SLA > 950 with 30s grace period
apiVersion: apps/v1
kind: Deployment
metadata:
name: inference-service
spec:
template:
spec:
tolerations:
– key: node.kubernetes.io/sla
operator: Gt
value: “950”
effect: NoExecute
tolerationSeconds: 30

Gang Scheduling Support in Kubernetes
KEP #4671 (issue)
Feature gate: GenericWorkload

Kubernetes به‌طور گسترده برای workloadهای AI، ML و HPC استفاده می‌شود؛ جاهایی که چندین process باید هم‌زمان اجرا شوند. scheduler معمولی Kubernetes بر اساس Pod به Pod کار می‌کند و Podها را به‌صورت ترتیبی روی nodeها می‌گذارد. وقتی منابع کم باشد، ممکن است همه workerهای لازم برای اجرای یک job schedule نشوند. فرض کنید کلاستر شما فقط بتواند 5 worker از 10 worker موردنیاز را بپذیرد؛ در این حالت همان 5 worker روی nodeها می‌نشینند و منابع را نگه می‌دارند، در حالی که بقیه workerها هنوز schedule نشده‌اند. نتیجه می‌تواند deadlock و هدررفت منابع باشد. 😕

این قابلیت Alpha جدید با پیاده‌سازی چیزی به نام gang scheduling این مشکل را هدف می‌گیرد. اصل آن «همه یا هیچ» است: یک گروه از Podها فقط وقتی روی nodeها schedule می‌شوند که منابع برای همه اعضای gang فراهم باشد، یا حداقل quorum موردنیاز که با پارامتر minCount تعیین می‌شود. API هم یک نوع core جدید به نام Workload می‌گیرد که چرخه عمر یک گروه از Podها را مثل یک entity واحد مدیریت می‌کند تا scheduler بتواند کل job را یکجا هندل کند. 🧠

منطق ارتباط بین Podها بر پایه PodGroups است؛ جایی که پارامترهای گروه مثل minCount یعنی حداقل تعداد Pod لازم برای شروع، تعریف می‌شود. specification Pod هم با یک فیلد جدید تکمیل می‌شود تا به object والد Workload اشاره کند و scheduler بداند این Pod بخشی از یک گروه است. علاوه بر این، Workload objectها از workloadهای با ساختار داخلی پیچیده هم پشتیبانی می‌کنند؛ هم workloadهای built-in مثل Job و StatefulSet و هم workloadهای سفارشی مثل JobSet، LeaderWorkerSet، MPIJob و TrainJob. 🚀

مثال از تعریف Workload:

apiVersion: scheduling/v1alpha1
kind: Workload
metadata:
namespace: ns-1
name: job-1
spec:
podGroups:
– name: “pg1”
policy:
gang:
minCount: 100

Opportunistic Batching
KEP #5598 (issue)
Feature gate: SchedulerOpp