PerfectScalePerfectScale

PerfectScale

Kubernetes v1.35の新機能と改善点

Kubernetes v1.35「Timbernetes」が登場。スケーリング、セキュリティ、デバイス管理、スケジューリングなど60の機能強化を詳しく解説します。

このページはEnglish、Deutsch、Español、Français、Italiano、Portuguêsでもご覧いただけます。

Tania Duggal
By Tania Duggal
Jan 5, 202622 min read

Kubernetes v1.35は「Timbernetes(The World Tree Release)」とも呼ばれ、現代のワークロードを大規模に扱う力を高める多数の新機能が追加されています。本リリースには60の新機能が含まれ、そのうち17がStable(GA)、19がBeta、22がAlphaになりました。「世界樹(World Tree)」というテーマは、基盤からコアシステム、拡張ポイントに至るまで、あらゆるレベルでKubernetesを強化するこのバージョンの姿を表しています。これにより、AI/MLからステートフル、エッジまで、幅広いワークロードに対応できるようになります。

Kubernetes v1.35で特に注目したい機能は、ギャングスケジューリングのサポート、Podリソースのインプレース更新、スケジューラーのオポチュニスティックバッチングなどです。これらの改善により、Kubernetesのパフォーマンス最適化、スケーラビリティ、リソース管理が大きく向上します。

それでは、Kubernetes v1.35の主な機能強化を見ていきましょう。

Kubernetes v1.35のStable機能

1. Podリソースのインプレース更新****

機能グループ: SIG Node | KEP: #1287

Kubernetes v1.35では、PodのCPUおよびメモリリソースのインプレース更新がGA(General Availability)に昇格しました。

この機能が登場する前は、.spec.resources.requestsや.spec.resources.limitsを変更するたびにPodを再作成する必要がありました。Kubernetesはリソースの変更を不変フィールドとして扱っていたため、CPUやメモリのわずかな調整でも完全な再起動が発生していました。これはステートフルサービス、長時間実行のバッチジョブ、レイテンシに敏感なアプリケーションにとって大きな中断要因であり、ダウンタイムの原因にもなっていました。

v1.35では、実行中のPodのCPUおよびメモリのrequestsやlimitsを、Podやコンテナを再起動することなく変更できます。ランタイムとノードの構成が対応していれば、リソースの変更を実行中のコンテナに直接適用できるようになりました。kubeletはcgroup設定をその場で更新し、Podは稼働を継続します。リソース変更を安全に適用できない場合は、従来どおりPodの再作成にフォールバックするため、後方互換性も維持されます。これにより、垂直スケーリングをより簡単に、安全に、効果的に行えるようになります。

2. PreferSameNodeによるトラフィック分散

機能グループ: SIG Network | KEP:#3015

Kubernetes v1.35では、PreferSameNodeによるトラフィック分散がGA(General Availability)になりました。

この変更以前、KubernetesにはtrafficDistributionフィールドにPreferCloseというオプションがありました。便利ではあったものの、その意味は明確ではありませんでした。PreferCloseは暗黙的に「近くのエンドポイントを優先する」ことを意味し、実際にはノードレベルではなくゾーンレベルの近接性を指していました。ノードローカルを厳密に優先したいという意図を明示する手段がなく、APIからはノードレベルとゾーンレベルのルーティング動作の違いを読み取れませんでした。

v1.35では、Serviceトラフィックの宛先を選択できるようになりました。クライアントPodと同じノード上のエンドポイントを強く優先し、ローカルにエンドポイントがない場合にのみリモートのエンドポイントを使用します。同一ノード上のエンドポイントを優先する新しいオプションPreferSameNodeが導入されました。同時に、PreferCloseはPreferSameZoneに名称変更され、APIがより自己記述的で分かりやすくなっています。後方互換性のためPreferCloseも引き続きサポートされますが、ゾーンルーティングにはPreferSameZoneが推奨される明示的なオプションとなりました。これらの変更により、ノードレベルとゾーンレベルのトラフィック優先設定が明確に区別されます。パフォーマンスを重視し、レイテンシやノード間トラフィックを削減したいワークロードに有効です。

apiVersion: v1
kind: Service
metadata:
name: node-local-service
spec:
selector:
app: web
ports:
- port: 80
targetPort: 8080
trafficDistribution: PreferSameNode

この設定では、クライアントPodと対応するバックエンドPodが同じノード上で動作している場合、Kubernetesはトラフィックをローカルにルーティングします。ローカルにエンドポイントが存在しない場合にのみ、他のノード上のPodにトラフィックが送信されます。

3. Topology Managerの設定可能なNUMAノード上限

機能グループ: SIG Node | KEP:#4622

Kubernetes v1.35では、Topology Managerの設定可能なNUMAノード上限がGA(General Availability)に昇格しました。

NUMA(Non-Uniform Memory Access)は、サーバーを複数のメモリ領域(NUMAノード)に分割し、それぞれを特定のCPU群に直接接続するハードウェアアーキテクチャです。Topology Managerは、CPU、メモリ、デバイスの割り当てを揃えることで、ワークロードが物理的に近いハードウェア上で動作するようにするkubeletのコンポーネントです。

この機能が登場する前は、Topology Managerを有効にすると、KubernetesはNUMAノード数に8という上限を設けていました。これはNUMAアフィニティ計算時の状態爆発を防ぐための安全策でした。その結果、8を超えるNUMAノードを持つノードでは、kubeletがTopology Managerを完全に無効化していました。この制限により、CPU、メモリ、デバイスの局所性がパフォーマンスを大きく左右する大規模なマルチソケットサーバーを、Kubernetesが十分に活用できませんでした。

v1.35では、max-allowable-numa-nodesポリシーオプションがStableになりました。クラスター管理者は、8を超えるNUMAノードを持つマシンでもTopology Managerを実行できます。これにより人為的な上限が撤廃され、非常に大規模なマシンでもCPU、メモリ、デバイスの配置を調整できるようになります。極めて大規模なNUMAシステムでは依然としてパフォーマンス上の課題が残りますが、ハードウェアとワークロードの要件に応じて運用者がオプトインできるようになりました。

この機能により、HPC、AI/ML、通信、低レイテンシワークロードで一般的に使用される最新のハイエンドサーバーを、Kubernetesがより有効に活用できるようになります。

apiVersion: kubelet.config.k8s.io/v1
kind: KubeletConfiguration
topologyManagerPolicy: restricted
topologyManagerScope: pod
topologyManagerPolicyOptions:
max-allowable-numa-nodes: "true"

4. reservedSystemCPUsを厳格化するCPUManagerポリシーオプションの追加

機能グループ: SIG Node | KEP: #4540

この機能が登場する前は、reservedSystemCPUsを使用して特定のCPUをシステム用に予約できましたが、この予約が強制されるのは整数のCPUリクエストを持つGuaranteed Podに対してのみでした。BurstableやBestEffortのPod、および小数のCPUリクエストを持つGuaranteed Podは、予約済みコアのCPU時間を消費できてしまいました。実際のクラスターでは、アプリケーションワークロードがシステムプロセスに干渉するノイジーネイバー問題が発生し、ノードの不安定化、スケジューリングの遅延、高負荷時のパフォーマンス低下を引き起こしていました。

Kubernetes v1.35では、static CPUManagerポリシーのstrict-cpu-reservationオプションがGA(General Availability)になりました。有効にすると、QoSクラスにかかわらず、すべてのPodがreservedSystemCPUsに指定されたCPU上で実行されることを厳格に防ぎます。これによりCPU分離が予測可能かつ確実になり、システムデーモンが常に専用のCPU容量を確保できます。その結果、ノードがより安定し、重要なシステムコンポーネントと並行して動作するレイテンシに敏感なワークロードや高スループットワークロードのパフォーマンスが向上します。

apiVersion: kubelet.config.k8s.io/v1
kind: KubeletConfiguration
cpuManagerPolicy: static
reservedSystemCPUs: "0-1"
cpuManagerPolicyOptions:
strict-cpu-reservation: "true"

この設定では、CPU 0〜1はOSとKubernetesシステムデーモン専用に予約されます。BestEffort、Burstable、Guaranteedのいずれであっても、アプリケーションPodがこれらのCPU上で実行されることはありません。

5. kubeletの並列イメージプル数の制限

機能グループ: SIG Node | KEP: #3673

kubeletの並列イメージプル制限は、1つのノードが同時にダウンロードできるコンテナイメージの数を制御します。イメージのプルはネットワークとディスクに大きな負荷がかかる処理です。

この機能が登場する前、kubeletの動作は実質的に二者択一でした。serializeImagePullsをtrueに設定するとイメージは1つずつプルされ、リソース競合は避けられるものの、スケールアップやノード再起動時のPod起動が大幅に遅くなりました。serializeImagePullsをfalseに設定すると並列イメージプルに上限がなく、負荷の高いノードではネットワークの飽和、ディスクの逼迫、ノード上の他の重要な処理の遅延を招く可能性がありました。

Kubernetes v1.35では、maxParallelImagePulls設定がGA(General Availability)になりました。これにより、管理者は同時イメージプル数に明示的な上限を設定できます。Kubernetesは複数のイメージを並列にプルしつつ、運用者が定めた安全な上限を超えないようにします。上限を超えるイメージプルは、進行中のプルが完了するまでキューに入れられ、「全か無か」ではなく制御された並列性を実現します。

apiVersion: kubelet.config.k8s.io/v1
kind: KubeletConfiguration
serializeImagePulls: false
maxParallelImagePulls: 3

この設定では、kubeletは1つのノードで最大3つのイメージを同時にプルできます。

6. 最大保持期間を超えたイメージのkubeletガベージコレクション

機能グループ: SIG Node | KEP:#4210

この機能が登場する前、kubeletのイメージガベージコレクションは主にディスク使用率のしきい値によって駆動されていました。イメージが削除されるのはディスク使用率がHighThresholdPercentを超えた場合のみで、使用率がLowThresholdPercentを下回るまでクリーンアップが続きました。ディスク枯渇の防止には効果的でしたが、ノードにディスク逼迫がない限り、ほとんど使われないイメージや古いイメージが無期限にディスクに残る可能性がありました。時間の経過とともに、イメージキャッシュの肥大化と非効率なディスク利用につながっていました。

Kubernetes v1.35では、imageMaximumGCAge設定がStableになり、ディスク使用率にかかわらず、指定した期間使用されていないイメージをkubeletがガベージコレクションできるようになりました。管理者は未使用イメージの最大保持期間をdurationとして定義できます。この期間を超えて使用されていないイメージは削除対象となります。これは既存のディスクベースのGCを補完し、イメージのクリーンアップをリアクティブからプロアクティブに変えるものです。

apiVersion: kubelet.config.k8s.io/v1
kind: KubeletConfiguration
imageMaximumGCAge: 24h
imageGCHighThresholdPercent: 85
imageGCLowThresholdPercent: 70

この設定では、24時間使用されていないコンテナイメージは、ディスク使用率が高しきい値未満であってもkubeletによって削除される可能性があります。

7. Job APIのmanagedByメカニズム

機能グループ: SIG Apps | KEP:#4368

この機能が登場する前、すべてのJobオブジェクトは常に組み込みのJobコントローラーによって調整(reconcile)されていました。外部システム(カスタムコントローラーやマルチクラスタースケジューラーなど)が実行やステータスを管理したい場合でも、KubernetesはPodの作成、Jobのcondition更新、失敗時のリトライ、完了セマンティクスの適用を行っていました。そのため、クラスター間でJobをミラーリングするような高度なユースケースでは、競合を避けるためにアノテーション、コントローラーの回避策、抑制ロジックが必要でした。

Kubernetes v1.35では、managedByフィールドがGA(General Availability)になりました。このフィールドを設定すると、KubernetesはそのJobを外部管理とみなし、Podやステータスの調整を行いません。これにより、管理クラスターでJobを作成し、ワーカークラスターで実行し、ネイティブのJobコントローラーの干渉なしにステータスを同期し戻すMultiKueueのような仕組みが実現できます。この機能は意図的に限定されており、Job管理の委譲を可能にするだけで、Jobのセマンティクス、CronJobの動作は変更せず、外部コントローラーへの設定の受け渡しも行いません。

apiVersion: batch/v1
kind: Job
metadata:
name: delegated-job
spec:
managedBy: kueue.x-k8s.io/multikueue
........

8. Pod Generation(信頼性の高いPod更新の追跡)

機能グループ: SIG Node | KEP: #5067

この機能が登場する前、PodにはDeploymentやStatefulSetのような上位オブジェクトが持つmetadata.generationフィールドがありませんでした。コントローラーはPodのspecを更新できましたが、kubeletが特定の変更を処理済みかどうかを知るための、組み込みの単調増加する手段がありませんでした。そのため、Podの更新が保留中なのか、部分的に適用されたのか、ステータスに完全に反映されたのかを確実に検出することが困難でした。特にインプレース更新や短時間に連続する変更ではその傾向が顕著でした。

Kubernetes v1.35では、Podのgeneration追跡がGA(General Availability)になりました。各Podはmetadata.generation: 1から始まり、Pod specの可変フィールドが更新されるたびにこの値がインクリメントされます。kubeletは処理したgenerationをstatus.observedGenerationに記録します。これにより、Podの現在のステータスが最新の望ましいspecを反映しているのか、それ以前のバージョンなのかが明示的に分かります。外部コントローラーはこの2つのフィールドを比較するだけで、タイミングや推測に頼ることなく、調整が完了したかどうかを安全に判断できます。

Kubernetes v1.35のBeta機能

9. HorizontalPodAutoscalerの設定可能なtolerance

機能グループ: SIG Autoscaling | KEP: #4951

Horizontal Pod Autoscaler(HPA)は、CPUやメモリ使用率などの観測メトリクスに基づいて、ワークロードのPodレプリカ数を自動調整します。

この機能が登場する前、HPAはスケールの判断にクラスター全体で固定の10%のtoleranceを使用していました。この値はワークロードごとに設定できませんでした。その結果、非常に敏感なアプリケーションは小さな負荷増加に反応すべきときにスケールできず、他のワークロードでは不要なスケーリングや振動が発生する可能性がありました。この動作を調整するにはグローバルなコントローラーフラグを変更するしかなく、クラスター内のすべてのHPAに影響が及びました。

Kubernetes v1.35では、設定可能なtoleranceがBetaに昇格し、デフォルトで有効になりました。behaviorフィールドを使って、HPAごと、スケーリング方向ごとにtolerance値を定義できます。これにより、他のワークロードに影響を与えることなく、オートスケーリングの感度をきめ細かく制御できます。重要なサービスは積極的にスケールするようチューニングしつつ、感度の低いワークロードは安定させることが可能です。

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: web-hpa
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: web
minReplicas: 2
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 60
behavior:
scaleUp:
tolerance: 0.05

この設定では、HPAはCPU使用率が65%(ターゲットの5%超)を上回った場合にのみスケールアップします。

10. 変更可能なボリュームアタッチ上限

機能グループ: SIG Storage | KEP:#4876

ボリュームアタッチ上限は、1つのノードに同時にアタッチできるストレージボリュームの数を定義します。Kubernetesは、永続ボリュームを使用するPodをどこにスケジュールするかを決定する際にこの情報を利用します。CSIドライバーはCSINodeオブジェクトを通じてこの上限を報告します。

この機能が登場する前、CSINode.spec.drivers[*].allocatable.countで報告されるボリュームアタッチ容量は静的でした。CSIドライバーが起動時にアタッチ上限を登録すると、Kubernetesはその値が常に正しいと想定していました。外部操作、ノード再起動、一時的な障害などによって後からボリュームスロットが消費されると、スケジューラーはすでに容量のないノードにPodを配置してしまう可能性がありました。その結果、ボリュームを実際にはアタッチできず、PodがContainerCreatingのままスタックしていました。

Kubernetes v1.35では、allocatableなボリュームアタッチ上限が変更可能になり、この機能はBetaとしてデフォルトで有効です。CSIドライバーはノードの利用可能なアタッチ容量を実行時に動的に更新できます。また、CSIDriverオブジェクトを通じて設定可能な更新間隔が導入され、allocatable数の再計算頻度をドライバー側で制御できます。さらに、容量不足によるアタッチ失敗を検出すると、Kubernetesが自動的にallocatable数を更新します。これによりスケジューリングの判断がより正確になり、Pod起動の失敗やスタックが大幅に減少します。

apiVersion: storage.k8s.io/v1
kind: CSIDriver
metadata:
name: example.csi.storage
spec:
attachRequired: true
nodeAllocatableUpdatePeriodSeconds: 30 # Note: minimum is 10 seconds

この設定により、kubeletは30秒ごとにCSIドライバーのNodeGetInfoエンドポイントを定期的に呼び出し、CSINode.spec.drivers[].allocatable.countを更新します。

11. オポチュニスティックバッチング

機能グループ: SIG Scheduling | KEP: #5598

オポチュニスティックバッチングは、同一または同等のスケジューリング要件を持つ多数のPodをKubernetesがスケジュールする際のパフォーマンスを向上させる、スケジューラーの最適化です。

この機能が登場する前、kube-schedulerはPodを1つずつ処理しており、スケジューリングの計算量はPod数とノード数の積に比例していました。リソースリクエスト、アフィニティ、制約が同じで、スケジューリングの観点では同一の複数のPodであっても、スケジューラーはPodごとに同じフィルタリングとスコアリングの計算を繰り返していました。これは冗長な処理とスケジューリングの遅さにつながり、特にバッチジョブ、MLワークロード、大規模なレプリカ作成で顕著でした。

Kubernetes v1.35では、オポチュニスティックバッチングがBeta機能として導入され、デフォルトで有効です。スケジューラーは、Pod spec、ノード属性、クラスター状態など、スケジューリングに関係するあらゆる要素を捉えたPodスケジューリングシグネチャを計算するようになりました。同じシグネチャを持つPodがスケジューリングキューに連続して到着すると、スケジューラーはそれらをまとめて処理します。最初のPodのスケジューリング結果をキャッシュし、同じシグネチャを持つ後続のPodに再利用することで、計算の繰り返しを回避します。キャッシュは短命で、クラスター状態の変化に応じて自動的に更新されるため、正確性が保たれます。

この最適化は透過的に動作し、ユーザーによる設定は不要です。主にJob、並列MLワーカー、大規模デプロイメントなど、多数の同一Podを持つワークロードにメリットがあります。冗長なスケジューリング処理を減らすことで、KubernetesはPodをより速く配置し、高負荷時でもワークロードをより効率的にスケールできます。

12. StatefulSetのmaxUnavailable

機能グループ: SIG Apps | KEP: #961

StatefulSetは、安定したID、順序付けられた起動と終了、永続ストレージを必要とするPod群を管理します。

この機能が登場する前、RollingUpdate戦略を使用するStatefulSetは、序数(ordinal)の大きいPodから厳密に1つずつ更新していました。更新中に何個のPodを利用不可にできるかを制御する方法はありませんでした。ステートフルアプリケーションが複数のPodの一時的な停止に耐えられる場合でも、Kubernetesは直列更新を強制していたため、大規模なStatefulSetではロールアウトに長い時間がかかっていました。

Kubernetes v1.35では、StatefulSetのローリングアップデートにおけるmaxUnavailableフィールドがBetaになり、デフォルトで有効です。これにより、更新中に利用不可にできるPodの数を、絶対数またはレプリカに対する割合で指定できます。podManagementPolicy: Parallelと組み合わせると、可用性の制約を守りながら複数のPodを同時に更新できます。未設定の場合、デフォルトは従来どおり1のままです。

apiVersion: apps/v1
kind: StatefulSet
metadata:
name: database
spec:
replicas: 10
podManagementPolicy: Parallel
updateStrategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 20%
........

13. Deploymentステータス: 終了中レプリカ数の表示

機能グループ: SIG Apps | KEP: #3973

DeploymentはPodのローリングアップデートとスケーリングを管理し、そのステータスは運用者や自動化ツールがロールアウトの進捗を把握するために使用されます。

この機能が登場する前、Deploymentのステータスにはreplicas、updatedReplicas、readyReplicas、availableReplicasといったフィールドしかありませんでした。終了中(terminating)のPodはDeploymentのステータスに明示的に表示されませんでした。そのため、Deploymentが本当に安定しているのか、まだバックグラウンドでPodのクリーンアップが続いているのかを判断するのが困難でした。運用者やコントローラーはPodを手動でリストしてdeletionTimestampでフィルタリングする必要があり、エラーが発生しやすく非効率でした。

Kubernetes v1.35では、status.terminatingReplicasフィールドがBetaに昇格し、デフォルトで有効です(APIサーバーとコントローラーマネージャーでDeploymentReplicaSetTerminatingReplicasフィーチャーゲートが有効な場合)。このフィールドは、終了中でまだ完全には削除されていないPodの数を報告します。ロールアウトやスケールダウン時の可観測性が向上し、シャットダウンの進捗を考慮したよりスマートなPod置換ポリシーなど、将来のDeployment動作の改善に向けた基盤にもなります。

apiVersion: apps/v1
kind: Deployment
metadata:
name: web
status:
replicas: 5
updatedReplicas: 5
readyReplicas: 4
availableReplicas: 4
terminatingReplicas: 1
........

14. Downward APIによるノードトポロジーラベルの公開

機能グループ: SIG Node | KEP:#4742

ノードトポロジーラベルは、ノードのリージョンやアベイラビリティゾーンなど、Podがインフラストラクチャのどこで実行されているかを表します。

この機能が登場する前、Podはノードのトポロジー情報に直接アクセスできませんでした。ゾーンやリージョンの情報が必要なワークロードは、Kubernetes APIサーバーへの問い合わせ、サイドカーの利用、追加のRBAC権限の付与といった手段に頼る必要がありました。これは運用の複雑さを増し、アプリケーションPodに本来必要のない権限を与えることでセキュリティリスクを生んでいました。

Kubernetes v1.35では、ノードトポロジーラベルがPodに注入され、Downward APIを通じて公開されるようになりました。この機能はBetaで、デフォルトで有効です。kubeletはtopology.kubernetes.io/zoneやtopology.kubernetes.io/regionといった標準ラベルをノードからPodに伝播し、環境変数またはprojectedファイルとして利用できるようにします。これにより、APIアクセスなしでワークロードをトポロジー対応にでき、設定が簡素化されるとともに最小権限の原則も守られます。

apiVersion: v1
kind: Pod
metadata:
name: topology-aware-pod
spec:
containers:
- name: app
image: busybox
command: ["sh", "-c", "env"]
env:
- name: ZONE
valueFrom:
fieldRef:
fieldPath: metadata.labels['topology.kubernetes.io/zone']
- name: REGION
valueFrom:
fieldRef:
fieldPath: metadata.labels['topology.kubernetes.io/region']

この設定では、Podは自分が動作しているノードのゾーンとリージョンを自動的に受け取ります。

Kubernetes v1.35のAlpha機能

15. Kubernetesにおけるギャングスケジューリングのサポート

機能グループ: SIG Scheduling | KEP: #4671

この機能が登場する前、KubernetesはPodを個別にスケジュールしていました。密結合のワークロードでは、これが部分的なスケジューリングを引き起こしていました。一部のPodは実行を開始する一方、リソース不足により他のPodはpendingのまま残ります。こうした部分的にスケジュールされたジョブはデッドロックを起こし、クラスターリソースを浪費し、他のワークロードをブロックする可能性がありました。そのため、ユーザーはギャングセマンティクスを実現するために外部スケジューラーやカスタムコントローラーに頼らざるを得ませんでした。

Kubernetes v1.35では、新しいWorkload APIとPodグループポリシーを使ったネイティブのギャングスケジューリングがAlpha機能として導入されました。ユーザーはPodをグループ化するWorkloadを定義し、minCount要件を指定します。スケジューラーはグループが揃うまでPodを保留し、その後まとめて配置を試みます。タイムアウト内に必要な数のPodをスケジュールできない場合はどのPodもバインドされず、十分なリソースが利用可能になるまでPodは待機します。これにより、ギャングセマンティクスに対するファーストクラスなスケジューラーレベルのサポートがKubernetes本体に組み込まれました。

例:

ギャングとなるPod群を定義するWorkload

apiVersion: scheduling.k8s.io/v1alpha1
kind: Workload
metadata:
name: ml-training
spec:
podGroups:
- name: workers
policy:
gang:
minCount: 4

Workloadに紐付けられたPod:

apiVersion: v1
kind: Pod
metadata:
name: worker-0
spec:
workloadRef:
name: ml-training
podGroup: workers
containers:
- name: trainer
image: <your-image>

この設定では、少なくとも4つのワーカーが同時に実行できる場合にのみ、KubernetesはPodをスケジュールします。クラスターがその要件を満たせない場合、どのPodも起動されません。

16. しきい値ベースの配置を実現するToleration演算子の拡張

機能グループ: SIG Scheduling | KEP: #5471

Kubernetesでは、taintとtolerationによってPodの実行場所を制御します。ノードはtaintで「ここにPodを配置しないで」と表明し、Podはtolerationで「このノードで実行してもよい」と表明します。

この機能が登場する前、tolerationはExistsやEqualといった基本的な演算子しかサポートしていませんでした。つまり、Podはtaintを許容するかしないかの二択であり、許容の「度合い」を表現できませんでした。たとえば、「SLAが99.9以上のノードでのみ実行する」や「信頼性が一定のしきい値を下回るノードを避ける」といった指定はできませんでした。その結果、SLAを考慮した配置を行いたいクラスターは、カスタムスケジューラー、複数のノードプール、複雑なアドミッションロジックに頼る必要がありました。

Kubernetes v1.35では、tolerationに数値比較演算子(「より大きい」「より小さい」などのセマンティクス)が追加され、拡張スケジューリングの一部として提供されます。ノードはSLA指向のtaint(信頼性スコアや障害ドメインの品質など)を公開でき、Podはノードのtaint値が数値条件を満たす場合にのみマッチするtolerationを指定できます。これにより、重要なワークロードは高SLAノードをターゲットにできる一方、ベストエフォートのワークロードは低コスト・低SLAのインフラ上で意図的に実行して、信頼性を犠牲にすることなく利用率を高められます。

SLAレベルを表すノードのtaint:

kubectl taint nodes node-a
servicelevel.org.example/agreed-service-level=800:NoSchedule

十分なSLAを持つノードのみを許容するPod:

apiVersion: v1
kind: Pod
metadata:
name: sla-tolerant-pod
spec:
tolerations:
- key: servicelevel.org.example/agreed-service-level
operator: LessThan
value: "900"
effect: NoSchedule
containers:
- name: app
image: busybox
command: ["sh", "-c", "echo running on lower-SLA node"]

この設定では、SLAのtaint値が900未満のノードにのみPodがスケジュールされます。

17. 一時停止中のJobでのコンテナリソース変更

機能グループ: SIG Apps | KEP: #5440

Kubernetes Jobは、タスクが正常に終了するまで実行し、その完了を保証します。

この機能が登場する前、Job内のPodテンプレートは実質的に不変でした。CPUやメモリの不足(たとえば繰り返されるOOM kill)でJobが失敗した場合、既存のJobのリソース値を調整する方法はありませんでした。唯一の選択肢はJobを削除して、更新したリソースで新しいJobを作成することであり、Jobの履歴、ステータス、進捗やリトライを追跡するツールの情報が失われてしまいました。

Kubernetes v1.35では、MutableJobPodResourcesForSuspendedJobsフィーチャーゲートを有効にすると、一時停止(suspend)状態のJobのコンテナリソースのrequestsとlimitsを変更できます。失敗しているJobを一時停止し、Podテンプレートを適切なリソース値に更新してからJobを再開できます。KubernetesはJobのIDとライフサイクル状態を維持したまま、更新された設定で実行を継続するため、リソースの設定ミスからの復旧が格段にスムーズになります。

apiVersion: batch/v1
kind: Job
metadata:
name: data-processor
spec:
suspend: true
template:
spec:
restartPolicy: OnFailure
containers:
- name: worker
image: busybox
command: ["sh", "-c", "echo processing && sleep 30"]
resources:
requests:
cpu: "1"
memory: "1Gi"
limits:
cpu: "2"
memory: "2Gi"

リソースを更新した後、spec.suspendをfalseに設定するとJobを再開できます。Jobを削除・再作成することなく、新しいCPUとメモリの値で処理が継続されます。

18. スケジューリング前のノードによる機能宣言

機能グループ: SIG Node | KEP: #5328

この機能が登場する前、Kubernetesは、サポートされるバージョンスキューの範囲内であれば、ノードはコントロールプレーンとおおむね互換性があると想定していました。コントロールプレーンレベルで新機能が有効化されると、スケジューラーはその機能を使用するPodを、まだ対応していない古いノードに配置してしまう可能性がありました。配置の判断自体は妥当に見えても、実行時の失敗、分かりにくい誤動作、スケジューリング後のPodのスタックにつながっていました。

Kubernetes v1.35では、Nodeオブジェクトの新しいstatus.declaredFeaturesフィールドを通じて、ノードがサポートする機能を宣言する正式なメカニズムがAlpha機能として導入されました。有効にすると、ノードは自身が理解できるKubernetes機能のセットを公開します。スケジューラー、アドミッションコントローラー、外部コンポーネントはこの情報を使ってPodを検証し、互換性のあるノードにのみスケジューリングを制限できるため、Podがバインドされる前に機能スキューの問題を防止できます。

Dynamic Resource Allocation(DRA) - 継続的な取り組み

機能グループ: SIG Node / SIG Scheduling

Dynamic Resource Allocation(DRA)は、GPU、アクセラレーター、デバイスなどの特殊なハードウェアリソースを、スケジューラーと連携し、ライフサイクルの観点でも安全に管理するためのKubernetesネイティブのフレームワークです。デバイスの割り当てをKubernetesのスケジューリングおよびバインディングプロセスに直接統合することで、従来のデバイスプラグインが抱えていた多くの制限を解消します。

Kubernetes v1.35以前、DRAのコア機能はv1.34ですでにStableに到達していました。

Kubernetes v1.35では、DRAは常に有効となり、いくつかの重要なAlpha機能が大きく成熟しました。v1.35の焦点は新しいAPIではなく、既存のDRAのコンセプトをより完全で、信頼性が高く、可観測なものにすることです。

順に見ていきましょう。

DRAによる拡張リソースリクエスト

拡張リソースリクエストにより、initコンテナ間での再利用やスケジューリング時のより適切なスコアリングなど、より豊かなセマンティクスでPodがデバイスをリクエストできるようになります。****

****Kubernetes v1.35以前、DRAは一部のシナリオでデバイスプラグインに後れを取っていました。たとえば、initコンテナとアプリコンテナの間でデバイスをきれいに再利用できず、特定のデバイスタイプではスケジューリング判断に適切なスコアリングシグナルがありませんでした。

Kubernetes v1.35では、これらのギャップが解消されました。initコンテナ間でのデバイス再利用が正しく動作し、スケジューリングロジックがデバイス配置をより適切に評価します。これにより、より複雑なPodライフサイクルや多段階のワークロードでもDRAを実用的に利用できるようになりました。

デバイスのtaintとtoleration

デバイスtaintにより、ノード全体ではなく個々のデバイスが、ノードtaintと同様に、スケジューリングとevictionに影響する状態を表現できます。

Kubernetes v1.35以前、デバイスtaintは機能が限定的で、evictionを強制する前にその影響を安全に評価する手段がありませんでした。NoExecuteを持つtaintは、そのデバイスを使用するPodを即座にevictしていました。

Kubernetes v1.35では、新しいeffectであるNoneが導入されました。これにより、運用者はドライランを実行できます。影響を受けるPodの数を確認し、準備ができてからNoExecuteに切り替えることが可能です。

さらに、DeviceTaintRuleがステータス情報を報告するようになり、evictionが可観測になって、より安全に運用できるようになりました。

パーティション可能なデバイス

パーティション可能なデバイスとは、より小さな論理単位(たとえばGPUスライス)に分割できる物理デバイスのことです。

以前は**、**デバイスのすべてのパーティションを単一のResourceSlice内で定義する必要があり、デバイスのモデリングと公開の柔軟性が制限されていました。

Kubernetes v1.35では、同じパーティション可能なデバイスに属するデバイスを、複数のResourceSliceにまたがって定義できるようになりました。これによりモデリングの柔軟性が向上し、最新のハードウェアがパーティション化されたリソースを公開する方法により適合します。

消費型キャパシティ

消費型キャパシティ(Consumable Capacity)は、排他的に割り当てられるのではなく、徐々に消費されていくデバイスリソース(たとえばメモリ帯域幅や使用回数に制限のあるアクセラレーター)を追跡します。

初期の実装には正確性の問題と不十分なテストカバレッジがあり、スケジューリングと計上の動作に対する信頼が限られていました。

現在(v1.35)では、複数のバグが修正され、テストカバレッジが拡充されました。キャパシティの消費と解放の動作がより信頼できるものになり、この機能をより安全に試せるようになっています。

デバイスバインディング条件

バインディング条件は、Podのスケジューリングとアドミッションの過程で、デバイス割り当てがいつどのように確定するかを定義します。

以前は、障害シナリオにおいてバインディングの動作が曖昧になったり、正しく処理されなかったりするエッジケースが存在していました。

現在(v1.35)では、複数の修正と検証によって正確性が向上しています。特にリトライや部分的な障害の際に、バインディングの判断がより予測可能で堅牢になりました。

比較可能なリソースバージョンのセマンティクス

リソースバージョンにより、クライアントとコントローラーはKubernetesオブジェクトの変更を時系列で追跡できます。

Kubernetes v1.35以前、リソースバージョンは等価性の比較しかできず、順序の比較はできませんでした。クライアントは、サーバー側の助けなしに、あるバージョンが別のバージョンより新しいかどうかを確実に判断できませんでした。

Kubernetes v1.35では、すべてのin-treeリソースバージョンが厳密で比較可能な数値フォーマットに従います。クライアントは自らバージョンを安全に比較できます。これによりinformerのパフォーマンスが向上し、コントローラーの信頼性が高まります。この変更は基盤となるものであり、Kubernetes全体にわたる複数の上位レベルの改善を可能にします。

非推奨化 / 削除

cgroup v1サポートの削除

cgroupは、コンテナのCPUとメモリを管理するためにKubernetesが使用する仕組みです。以前のバージョンでは、主に後方互換性のためにcgroup v1とv2の両方をサポートしていました。

v1.35では、cgroup v1のサポートが完全に削除され、cgroup v2が必須となります。

kube-proxyのIPVSモードの非推奨化

kube-proxyは、さまざまなバックエンドモードを使ってServiceトラフィックをPodにルーティングします。IPVSモードは、運用の複雑さと最新のデータプレーンとの重複を理由に、v1.35で非推奨となりました。

Kubernetesは今後、スケーラブルなネットワーキングにはiptablesモードまたはeBPFベースのCNIを推奨しています。

これによりメンテナンスの負担が軽減され、長期的なネットワークの信頼性が向上します。

containerd v1.xからの移行に向けた最終アナウンス

containerdは、Kubernetesが使用するデフォルトのコンテナランタイムです。
古いcontainerd v1.xはサポート終了が近づいています。
Kubernetes v1.35は、新しいcontainerdリリースへアップグレードするための最後の呼びかけとなります。

Kubernetes 1.35には合計60のKubernetes Enhancement Proposal(KEP)が含まれています。これらの機能強化は、Kubernetesの機能性、柔軟性、リソース管理、可観測性など多岐にわたります。

ここで取り上げた主要な変更以外にも、k8sチームによって追加された機能があります。ぜひKubernetes v1.35のリリースノートに目を通し、詳細はこちらをご確認ください。