Kubernetes 1.28: 変更点まとめ(What's new!)とアップグレード時の注意事項

# はじめに

このエントリは、Kubernetes 1.28 の [CHANGELOG](https://github.com/kubernetes/kubernetes/blob/master/CHANGELOG/CHANGELOG-1.28.md) 及び[Kubernetes v1.28: Planternetes](https://kubernetes.io/blog/2023/08/15/kubernetes-v1-28-release/)からWhat's new!とアップグレード時の注意事項、各変更点についてまとめたページへのリンクです。
詳細については各まとめページを参照してください。

# 変更点の詳細へのリンク

- [Metrics Changes と SIG Instrumentation](https://qiita.com/watawuwu/items/7c14a68db116fed2847f) @watawuwu 
- [SIG Apps](https://qiita.com/yosshi_/items/bfc36dd2b021ebbac375) @yosshi_ 
- [SIG API Machinery](https://qiita.com/Ladicle/items/9675b23c9fdfd91fb31d) @Ladicle
- [SIG Auth](https://qiita.com/hiyosi/items/ba421eea517e3eff22b8) @hiyosi
- [SIG CLI](https://qiita.com/superbrothers/items/3192390d0a4dd99b7f0b) @superbrothers
- [SIG Cluster Lifecycle](https://qiita.com/yuanying/items/486d725ff246272b6531) @yuanying
- [SIG Storage](https://qiita.com/ysakashita/items/456d853dd6fe7b0807bb) @ysakashita 
- [SIG Network](https://qiita.com/tkusumi/items/eaec7845fb391346c768) @tkusumi
- [SIG Scheduling](https://qiita.com/ordovicia/items/df66b4f3712f1783c62a) @ordovicia 
- [SIG Node](https://qiita.com/y1r96/items/f557ab7db3a2fe0f01bb) @y1r96


# What's New (Major Themes) 

## Changes to supported skew between control plane and node versions 

<!--
This enables testing and expanding the supported skew between core node and control plane components by one version from n-2 to n-3, so that node components (kubelet and kube-proxy) for the oldest supported minor version work with control plane components (kube-apiserver, kube-scheduler, kube-controller-manager, cloud-controller-manager) for the newest supported minor version.

This is valuable for end users as control plane upgrade will be a little faster than node upgrade, which are almost always going to be the longer with running workloads.

The Kubernetes yearly support period already makes annual upgrades possible. Users can upgrade to the latest patch versions to pick up security fixes and do 3 sequential minor version upgrades once a year to "catch up" to the latest supported minor version.

However, since the tested/supported skew between nodes and control planes is currently limited to 2 versions, a 3-version upgrade would have to update nodes twice to stay within the supported skew.
-->

コアノードとコントロールプレーンコンポーネント間のサポートされるバージョンのSkewをn-2からn-3に拡大・テストできるようにし、最も新しいサポートされるマイナーバージョンのコントロールプレーンコンポーネント（kube-apiserver、kube-scheduler、kube-controller-manager、cloud-controller-manager）と、最も古いサポートされるマイナーバージョンのノードコンポーネント（kubeletおよびkube-proxy）が上手く動作するようになりました。
コントロールプレーンのアップグレードは、ほとんどの場合時間がかかってしまうワークロードを実行中のノードのアップグレードよりも少し速くなるため、これはエンドユーザーにとって価値があります。
Kubernetesの1年間のサポート期間はすでに年単位のアップレードを可能にしています。ユーザはセキュリティの修正のために最新のパッチバージョンへアップグレードでき、そして最新のマイナーバージョンへ追いつくために、年に1度だけ3マイナーバージョンのアップグレードを実行できます。
ただし、ノードとコントロール プレーン間のテスト/サポートされているskewは現在2バージョンに制限されているため、3バージョンのアップグレードでは、サポートされているskew内に収まるようにノードを2回更新する必要があります。

![スクリーンショット 2023-09-13 14.02.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224576/1303c909-d3fa-1a1c-6cb5-e6ad1b2ef4d5.png)


## Generally available: recovery from non-graceful node shutdown 

<!--
If a node shuts down down unexpectedly or ends up in a non-recoverable state (perhaps due to hardware failure or unresponsive OS), Kubernetes allows you to clean up afterwards and allow stateful workloads to restart on a different node. For Kubernetes v1.28, that's now a stable feature.

This allows stateful workloads to failover to a different node successfully after the original node is shut down or in a non-recoverable state, such as the hardware failure or broken OS.

Versions of Kubernetes earlier than v1.20 lacked handling for node shutdown on Linux, the kubelet integrates with systemd and implements graceful node shutdown (beta, and enabled by default). However, even an intentional shutdown might not get handled well that could be because:

- the node runs Windows
- the node runs Linux, but uses a different init (not systemd)
- the shutdown does not trigger the system inhibitor locks mechanism
- because of a node-level configuration error (such as not setting appropriate values for shutdownGracePeriod and shutdownGracePeriodCriticalPods).
When a node shutdowns or fails, and that shutdown was not detected by the kubelet, the pods that are part of a StatefulSet will be stuck in terminating status on the shutdown node. If the stopped node restarts, the kubelet on that node can clean up (DELETE) the Pods that the Kubernetes API still sees as bound to that node. However, if the node stays stopped - or if the kubelet isn't able to start after a reboot - then Kubernetes may not be able to create replacement Pods. When the kubelet on the shut-down node is not available to delete the old pods, an associated StatefulSet cannot create a new pod (which would have the same name).

There's also a problem with storage. If there are volumes used by the pods, existing VolumeAttachments will not be disassociated from the original - and now shut down - node so the PersistentVolumes used by these pods cannot be attached to a different, healthy node. As a result, an application running on an affected StatefulSet may not be able to function properly. If the original, shut down node does come up, then their pods will be deleted by its kubelet and new pods can be created on a different running node. If the original node does not come up (common with an immutable infrastructure design), those pods would be stuck in a Terminating status on the shut-down node forever.

For more information on how to trigger cleanup after a non-graceful node shutdown, read non-graceful node shutdown.
-->

ノードが予期しない・復帰できない状態で終了する場合(おそらくハードウェアの障害やOSの応答がない)、Kubernetesを使用すると、後にクリーンアップし、ステートフル ワークロードを別のノードで再起動できるようになります。Kubernetes v1.28で、それは安定した機能となりました。
これにより、元のノードがシャットダウンや復帰できない状態となった後、ステートフルワークロードが異なるノードへフェイルオーバーできるようになります。
v1.20以前のKubernetesのバージョンはLinux上のノードのシャットダウンのためのハンドリングが欠けていましたが、kubeletがsystemdと統合し、graceful node shutdownを実装しました(betaとなっており、デフォルト有効)。しかしながら、以下の理由から意図したシャットダウンであっても上手く処理されない場合がありました。

- ノードがWindows上で動作している
- ノードがLinux上で動作しているが、systemdとはことなるinitを利用している
- シャットダウンがsystem inhibitor locks mechanismをトリガーしない
- ノードレベルの設定エラー(適切な値がshutdownGracePeriodやshutdownGracePeriodCriticalPodsへ設定されていないなど)

ノードがシャットダウンまたは失敗時、そのシャットダウンがkubeletにより検知されなかった場合、StatefulSetのPodはシャットダウンノード上で終了ステータスのままとなります。停止したノードが再起動すると、そのノード上のkubeletはkubernetes APIがまだそのノードにバインドされているとみなしているPodをクリーンアップ(DELETE)できます。しかし、もしノードが停止し続けたり、リブート後にkubeletがスタートできない場合、Kubernetesは代替のPodを作成できない可能性があります。シャットダウンノード上のkubeletが古いPodの削除ができない時、関連したStatefulSetは新しいPod(それは同じ名前をもつ)を作成できません。

またストレージにも問題があります。もしそのPodによって利用されているボリュームが存在する場合、既存の VolumeAttachmentsは元のノード（現在はシャットダウンされている）から切り離されないため、これらのポッドで使用されている PersistentVolumesを別の正常なノードにアタッチすることはできません。その結果、影響を受けたStatefulSet上で実行されているアプリケーションが正しく機能しなくなる可能性があります。シャットダウンされた元のノードが起動した場合、それらのPodはそのkubeletによって削除され、別の実行中のノードで新しいPodを作成できます。元のノードが立ち上がらない場合（[イミュータブル・インフラストラクチャ](https://glossary.cncf.io/immutable-infrastructure/)の設計では一般的）、それらのPodは、シャットダウンされたノード上のターミネーション・ステータスから永遠に抜け出せなくなります。

Non Graceful node shutdownの後のクリーンアップをトリガーする方法については、[non-graceful node shutdown](https://kubernetes.io/docs/concepts/architecture/nodes/#non-graceful-node-shutdown)をご参照ください。

- :pencil: `NodeOutOfServiceVolumeDetachfeature` がGAとなった話のようです。
- :pencil: 詳細は @ysakashita さんの [Kubernetes: Non Graceful Node Shutdownの動作検証](https://qiita.com/ysakashita/items/1a7fdf1688819a0a4580)　をご参照ください。

## Improvements to CustomResourceDefinition validation rules 

<!--
The Common Expression Language (CEL) can be used to validate custom resources. The primary goal is to allow the majority of the validation use cases that might once have needed you, as a CustomResourceDefinition (CRD) author, to design and implement a webhook. Instead, and as a beta feature, you can add validation expressions directly into the schema of a CRD.

CRDs need direct support for non-trivial validation. While admission webhooks do support CRDs validation, they significantly complicate the development and operability of CRDs.

In 1.28, two optional fields reason and fieldPath were added to allow user to specify the failure reason and fieldPath when validation failed.

For more information, read validation rules in the CRD documentation.
-->

[Common Expression Language(CEL)](https://github.com/google/cel-go)は[CustomResource](https://kubernetes.io/docs/concepts/extend-kubernetes/api-extension/custom-resources/)のvalidateをするために利用できるようになりました。メインのゴールはかつてCustomResourceDefinition(CRD)の作成者としてwebhookのデザイン・実装が必要だったvalidationのユースケースの大部分です。ベータ機能として、webhookの代わりにvalidation式を直接CRDのスキーマに追加できます。

CRDには、複雑なvalidationに対する直接のサポートが必要です。Admission webhookはCRDのvalidationをサポートしていますが、それらはCRDの開発と運用を複雑化させる要因となります。

1.28から、validationが失敗した場合にユーザーが失敗の理由とフィールドパスを指定できるように、reasonおよびfieldPathという2つのオプションフィールドが追加されました。

詳細はCRDのドキュメントの[validation rules](https://kubernetes.io/docs/tasks/extend-kubernetes/custom-resources/custom-resource-definitions/#validation-rules)をご参照ください。

## ValidatingAdmissionPolicies graduate to beta 

<!--
Common Expression language for admission control is customizable, in-process validation of requests to the Kubernetes API server as an alternative to validating admission webhooks.

This builds on the capabilities of the CRD Validation Rules feature that graduated to beta in 1.25 but with a focus on the policy enforcement capabilities of validating admission control.

This will lower the infrastructure barrier to enforcing customizable policies as well as providing primitives that help the community establish and adhere to the best practices of both K8s and its extensions.

To use ValidatingAdmissionPolicies, you need to enable both the admissionregistration.k8s.io/v1beta1 API group and the ValidatingAdmissionPolicy feature gate in your cluster's control plane.
-->

Common Expression Language(CEL)を用いたAdmisson Controlは、Validating Admission Webhookに代わる形で、Kubernetes APIサーバーへのリクエストのカスタマイズ可能なin-processなvalidationを提供します。

これは1.25でbetaとなったCRDのValidation Rulesの機能をベースにしていますが、Validating admission controlのポリシーを強制する機能にフォーカスしたものです。

これにより、カスタマイズ可能なポリシーを実施するためのインフラの障壁が低くなるとともに、コミュニティがK8sとその拡張機能の両方のベストプラクティスを確立し、遵守するのに役立つ基本的な要素が提供されます。

[ValidatingAdmissionPolicies](https://kubernetes.io/docs/reference/access-authn-authz/validating-admission-policy/)を使うためには、admissionregistration.k8s.io/v1beta1 APIグループとValidatingAdmissionPolicy feature gateをコントロールプレーンで有効化する必要があります。

## Match conditions for admission webhooks 

<!--
Kubernetes v1.27 lets you specify match conditions for admission webhooks, which lets you narrow the scope of when Kubernetes makes a remote HTTP call at admission time. The matchCondition field for ValidatingWebhookConfiguration and MutatingWebhookConfiguration is a CEL expression that must evaluate to true for the admission request to be sent to the webhook.

In Kubernetes v1.28, that field moved to beta, and it's enabled by default.

To learn more, see matchConditions in the Kubernetes documentation.
-->
Kubernetes v1.27はadmission webhookのための一致条件を指定できるようになり、それはKubernetesがadmission時に外部へHTTPを呼び出す時のスコープを狭くできるようになりました。
ValidatingWebhookConfigurationとMutatingWebhookConfigurationのmatchConditionフィールドはwebhookへ送られるべきadmission requestの場合trueを評価するCELの式を記述します。

Kubernetes v1.28から、そのフィールドはbetaとなり、デフォルトで有効化されます。

詳細は、Kubernetesのドキュメントの[matchConditions](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#matching-requests-matchconditions)をご参照ください。

## Beta support for enabling swap space on Linux 

<!--
This adds swap support to nodes in a controlled, predictable manner so that Kubernetes users can perform testing and provide data to continue building cluster capabilities on top of swap.

There are two distinct types of users for swap, who may overlap:

- Node administrators, who may want swap available for node-level performance tuning and stability/reducing noisy neighbor issues.
- Application developers, who have written applications that would benefit from using swap memory.
-->

これにより、Kubernetesユーザーがテストを実施し、スワップ上にクラスタ機能を構築し続けるためのデータを提供できるように、制御された予測可能な方法でノードにスワップサポートが追加されます。

スワップのユーザーには、重複する場合がある2つの明確なタイプがあります：

- ノードレベルのパフォーマンスチューニングや安定性の向上/隣接するノイズの問題を減少させるために、スワップを利用したいノード管理者
- スワップメモリ利用するとメリットがあるアプリケーションを開発したアプリケーション開発者

## Mixed version proxy (alpha) 

<!--
When a cluster has multiple API servers at mixed versions (such as during an upgrade/downgrade or when runtime-config changes and a rollout happens), not every apiserver can serve every resource at every version.

For Kubernetes v1.28, you can enable the mixed version proxy within the API server's aggregation layer. The mixed version proxy finds requests that the local API server doesn't recognize but another API server inside the control plan is able to support. Having found a suitable peer, the aggregation layer proxies the request to a compatible API server; this is transparent from the client's perspective.

When an upgrade or downgrade is performed on a cluster, for some period of time the API servers within the control plane may be at differing versions; when that happens, different subsets of the API servers are able to serve different sets of built-in resources (different groups, versions, and resources are all possible). This new alpha mechanism lets you hide that skew from clients.
-->

クラスタに複数の異なるバージョンのAPIサーバが存在する時(upgrade/downgradeやruntime-configの変更時やロールアウトが発生した時のような)、全てのapiserverがすべてバージョンの全リソースをサーブできるわけではありません。

Kubernetes v1.28では、API serverのaggregation layer内にmixed version proxyを有効化できます。mixed version proxyはローカルのAPIサーバが認識できないが、他のサポート可能なAPIサーバを見つけます。適切なピアが見つかった場合、aggregation layerはリクエストを互換性のあるAPI serverへプロキシします。これはクライアント視点では透過的です。

クラスタのアップグレードやダウングレード時、しばらくの間コントロールプレーンのAPIサーバは異なるバージョンとなるかもしれません。そうなると、APIサーバの異なるサブセットは異なる組み込みリソース・セット（異なるグループ、バージョン、リソースがすべて可能）を提供できるようになります。この新しいアルファ機能はクライアントからそれらのskewを隠蔽してくれます。

## Source code reorganization for control plane components 

<!--
Kubernetes contributors have begun to reorganize the code for the kube-apiserver to build on a new staging repository that consumes k/apiserver but has a bigger, carefully chosen subset of the functionality of kube-apiserver such that it is reusable.

This is a gradual reorganization; eventually there will be a new git repository with generic functionality abstracted from Kubernetes' API server.
-->

Kubernetesのコントリビュータは、kube-apiserverのコードを再編成し始めており、k/apiserverを利用するが、再利用可能なようにkube-apiserverの機能のより大きく、慎重に選ばれたサブセットを持つ新しいステージングリポジトリを基盤として構築しています。

これは段階的な再編成であり、最終的にはKubernetesのAPIサーバーから抽象化された汎用機能を持つ新しいgitリポジトリが存在することになります。

## Support for CDI injection into containers (alpha) 

<!--
CDI provides a standardized way of injecting complex devices into a container (i.e. devices that logically require more than just a single /dev node to be injected for them to work). This new feature enables plugin developers to utilize the CDIDevices field added to the CRI in 1.27 to pass CDI devices directly to CDI enabled runtimes (of which containerd and crio-o are in recent releases).
-->

CDIは複雑なデバイスをコンテナへインジェクションするスタンダードな方法を提供します（つまり、動作させるためにノードの/devを一つ以上注入する必要があるデバイス）。この新機能により、プラグイン開発者は、1.27のCRIに追加されたCDIDevicesフィールドを使用して、CDIデバイスを直接CDI対応のランタイム（最近のリリースではcontainerdとcrio-oが該当）に渡すことができます。

## API awareness of sidecar containers (alpha) 

<!--
Kubernetes 1.28 introduces an alpha restartPolicy field for init containers, and uses that to indicate when an init container is also a sidecar container. The will start init containers with restartPolicy: Always in the order they are defined, along with other init containers. Instead of waiting for that sidecar container to complete before starting the main container(s) for the Pod, the kubelet only waits for the sidecar init container to have started.
-->

Kubernetes 1.28ではalphaで[init container](https://github.com/kubernetes/website/blob/main/content/en/docs/concepts/workloads/pods/init-containers.md)のためにrestartPolicyフィールドを導入し、init containerがサイドカーコンテナとして存在していることを示すためにそのフィールドを利用します。これによりrestartPolicy: Alwaysが設定されたinit containerは定義された順番で、他のinit containerと共にスタートします。Podのメインのコンテナがスタートする前に、kubeletはそのサイドカーコンテナが完了を待つ代わりに、サイドカーのinit containerがスタートするのだけ待ちます。

<!--
The condition for startup completion will be that the startup probe succeeded (or if no startup probe is defined) and postStart handler is completed. This condition is represented with the field Started of ContainerStatus type. See the section "Pod startup completed condition" for considerations on picking this signal.
-->

そのスタートアップの完了条件はstartup probeが成功したということ(もしくはstartup probeが定義されていない場合)そしてpostStart handlerが完了したこととなります。この条件はContainerStatus型のStartedフィールドで表現されます。このシグナルを選択した判断については"Pod startup completed condition"セクションをご確認ください。

<!--
For init containers, you can either omit the restartPolicy field, or set it to Always. Omitting the field means that you want a true init container that runs to completion before application startup.

Sidecar containers do not block Pod completion: if all regular containers are complete, sidecar containers in that Pod will be terminated.
<!--
init containerでは、restartPolicyフィールドを省略またはAlyawsをセットすることが可能です。フィールドを省略することはinit containerがアプリケーションのスタートアップ前に完了するまで動作することを意味します。

<!--
For sidecar containers, the restart behavior is more complex than for init containers. In a Pod with restartPolicy set to Never, a sidecar container that fails during Pod startup will not be restarted and the whole Pod is treated as having failed. If the Pod's restartPolicy is Always or OnFailure, a sidecar that fails to start will be retried.
-->

サイドカーコンテナでは、init containerよりrestartの振る舞いが複雑です。restartPolicyがNeverへセットされているPodでは、Podのスタートアップ中に失敗するサイドカーコンテナはリスタートされず、Pod全体が終了として扱われます。もしPodのrestartPolicyがAlwaysまたはOnFailureにセットされている場合、起動に失敗したサイドカーはリトライされます。

<!--
Once the sidecar container has started (process running, postStart was successful, and any configured startup probe is passing), and then there's a failure, that sidecar container will be restarted even when the Pod's overall restartPolicy is Never or OnFailure. Furthermore, sidecar containers will be restarted (on failure or on normal exit) even during Pod termination.

To learn more, read API for sidecar containers.
-->

一度サイドカーコンテナが起動後(プロセスが動作し、postStartが成功し、全ての設定されたstartup probeがパス)、何らかで失敗すると、Pod全体のrestartPolicyがNeverまたはOnFailureであってもサイドカーコンテナはリスタートされます。さらに、サイドカーコンテナはPodがTermination中でさえもリスタートされます(失敗または通常の終了で)。

詳細は[サイドカーコンテナのAPI](https://kubernetes.io/docs/concepts/workloads/pods/init-containers/#api-for-sidecar-containers)をご参照ください。

## Automatic, retroactive assignment of a default StorageClass graduates to stable 

<!--
Kubernetes automatically sets a storageClassName for a PersistentVolumeClaim (PVC) if you don't provide a value. The control plane also sets a StorageClass for any existing PVC that doesn't have a storageClassName defined. Previous versions of Kubernetes also had this behavior; for Kubernetes v1.28 is is automatic and always active; the feature has graduated to stable (general availability).

To learn more, read about StorageClass in the Kubernetes documentation.
-->

KubernetesはPersistentVolumeClaimのstorageClassNameがセットされてない場合に、自動的にセットします。コントロールプレーンは、storageClassNameが定義されていない既存のPVCすべてにStorageClassを設定します。Kubernetesの以前のバージョンもこの動作を持っていましたが、Kubernetes v1.28ではこれは自動で常にアクティブです。この機能は安定版（一般提供）に昇格しました。

詳しくは、Kubernetesのドキュメント内の[StorageClass](https://kubernetes.io/docs/concepts/storage/storage-classes/)に関する部分を読んでください。

## Pod replacement policy for Jobs (alpha) 

<!--
Kubernetes 1.28 adds a new field for the Job API that allows you to specify if you want the control plane to make new Pods as soon as the previous Pods begin termination (existing behavior), or only once the existing pods are fully terminated (new, optional behavior).
-->

Kubernetes 1.28では、Job APIに新しいフィールドが追加され、前のPodが終了を開始すると、すぐに新しいPodをコントロールプレーンが作成するか（既存の動作）、または既存のPodが完全に終了するまで待つか（新しいオプションの動作）を指定することができます。

<!--
Many common machine learning frameworks, such as Tensorflow and JAX, require unique pods per index. With the older behaviour, if a pod that belongs to an Indexed Job enters a terminating state (due to preemption, eviction or other external factors), a replacement pod is created but then immediately fails to start due to the clash with the old pod that has not yet shut down.
-->

多くの一般的な機械学習フレームワーク、例えばTensorflowやJAXは、インデックスごとにユニークなPodを必要とします。古い動作において、Indexed Jobに属するPodが終了状態に入ると（プリエンプション、eviction、またはその他の外部要因のため）、代替のPodが作成されますが、まだシャットダウンしていない古いPodとの競合のため、すぐに起動に失敗します。

<!--
Having a replacement Pod appear before the previous one fully terminates can also cause problems in clusters with scarce resources or with tight budgets. These resources can be difficult to obtain so pods may only be able to find nodes once the existing pods have been terminated. If cluster autoscaler is enabled, early creation of replacement Pods might produce undesired scale-ups.
-->

前のPodが完全に終了する前に代替のPodが現れることは、リソースが少ないクラスターや予算が厳しいクラスターでも問題を引き起こすことがあります。これらのリソースは入手が難しいため、既存のポッドが終了した後でのみノードを見つけることができるかもしれません。クラスターオートスケーラが有効になっている場合、代替Podの早期作成は望ましくないスケールアップを引き起こす可能性があります。

<!--
To learn more, read Delayed creation of replacement pods in the Job documentation.
-->

詳しくは、Jobのドキュメント内の [Delayed creation of replacement pods](https://kubernetes.io/docs/concepts/workloads/controllers/job/#delayed-creation-of-replacement-pods) をお読みください。

## Job retry backoff limit, per index (alpha) 

<!--
This extends the Job API to support indexed jobs where the backoff limit is per index, and the Job can continue execution despite some of its indexes failing.

Currently, the indexes of an indexed job share a single backoff limit. When the job reaches this shared backoff limit, the job controller marks the entire job as failed, and the resources are cleaned up, including indexes that have yet to run to completion.

As a result, the existing implementation did not cover the situation where the workload is truly embarrassingly parallel: each index is fully independent of other indexes.

For instance, if indexed jobs were used as the basis for a suite of long-running integration tests, then each test run would only be able to find a single test failure.

For more information, read Handling Pod and container failures in the Kubernetes documentation.
-->

これにより、Job APIはインデックスごとのバックオフ制限を持ち、一部のインデックスが失敗してもJobの実行を続けることができるインデックス化されたジョブをサポートするように拡張されます。

現在、インデックス化されたJobのインデックスは単一のバックオフ制限を共有しています。Jobがこの共有バックオフ制限に達すると、ジョブコントローラはJob全体を失敗としてマークし、リソースがクリーンアップされます。これには、完了まで実行されていないインデックスも含まれます。

その結果、既存の実装は、ワークロードが本当に[Embarrassingly parallel](https://en.wikipedia.org/wiki/Embarrassingly_parallel)である場面をカバーしていませんでした：各インデックスは他のインデックスと完全に独立しています。

例えば、インデックス化されたJobが長時間実行される統合テストのスイートの基盤として使用される場合、各テスト実行は単一のテスト失敗のみを見つけることができます。

詳細については、Kubernetesのドキュメントの [Handling Pod and container failures](https://kubernetes.io/docs/concepts/workloads/controllers/job/#handling-pod-and-container-failures) セクションをお読みください。

## CRI container and pod statistics without cAdvisor 

<!--
This encompasses two related pieces of work (changes to the kubelet's /metrics/cadvisor endpoint and improvements to the replacement summary API).
-->

これには2つの関連する作業が含まれます。(kubeletの/metrics/cadvisorエンドポイントへの変更と、置き換えのsummary APIへの改善)

<!--
There are two main APIs that consumers use to gather stats about running containers and pods: summary API and /metrics/cadvisor. The Kubelet is responsible for implementing the summary API, and cadvisor is responsible for fulfilling /metrics/cadvisor.
-->

動作中のコンテナとPodに関する統計を収集するために消費者が使用する2つの主要なAPIがあります: summary APIと/metrics/cadvisorです。Kubeletはsummary APIの実装を担当し、cadvisorは/metrics/cadvisorの要求を満たすための責任を持っています。

<!--
This enhances CRI implementations to be able to fulfill all the stats needs of Kubernetes. At a high level, there are two pieces of this:

- It enhances the CRI API with enough metrics to supplement the pod and container fields in the summary API directly from CRI.
- It enhances the CRI implementations to broadcast the required metrics to fulfill the pod and container fields in the /metrics/cadvisor endpoint.
-->

これにより、CRIの実装がKubernetesの統計ニーズをすべて満たすことができるようになります。大まかには、これには2つの部分があります：

- CRI APIを強化して、summary APIのpodとcontainerフィールドをCRIから直接補完するための十分なメトリクスが提供されます。
- CRIの実装が、/metrics/cadvisorエンドポイントのpodとcontainerフィールドを満たすための必要なメトリクスをブロードキャストするように強化されます。

## Feature graduations and deprecations in Kubernetes v1.28 

<!--
This release includes a total of 12 enhancements promoted to Stable:
-->

このリリースでは合計12のエンハンスメントがステーブルとなりました。

- [kubectl events](https://github.com/kubernetes/enhancements/issues/1440)
- [Retroactive default StorageClass assignment](https://github.com/kubernetes/enhancements/issues/3333)
- [Non-graceful node shutdown](https://github.com/kubernetes/enhancements/issues/2268)
- [Support 3rd party device monitoring plugins](https://github.com/kubernetes/enhancements/issues/606)
- [Auth API to get self-user attributes](https://github.com/kubernetes/enhancements/issues/3325)
- [Proxy Terminating Endpoints](https://github.com/kubernetes/enhancements/issues/1669)
- [Expanded DNS Configuration](https://github.com/kubernetes/enhancements/issues/2595)
- [Cleaning up IPTables Chain Ownership](https://github.com/kubernetes/enhancements/issues/3178)
- [Minimizing iptables-restore input size](https://github.com/kubernetes/enhancements/issues/3453)
- [Graduate the kubelet pod resources endpoint to GA](https://github.com/kubernetes/enhancements/issues/3743)
- [Extend podresources API to report allocatable resources](https://github.com/kubernetes/enhancements/issues/2403)
- [Move EndpointSlice Reconciler into Staging](https://github.com/kubernetes/enhancements/issues/3685)

## Deprecations and removals 

### Removals

- [Removal of CSI Migration for GCE PD](https://github.com/kubernetes/enhancements/issues/1488)

### Deprecations

- [Ceph RBD in-tree plugin](https://github.com/kubernetes/kubernetes/pull/118303)
- [Ceph FS in-tree plugin](https://github.com/kubernetes/kubernetes/pull/118143)

## Urgent Upgrade Notes 

### (No, really, you MUST read this before you upgrade)

<!--
- Action required for the custom scheduler plugin developers. 
  Here's the breaking change in `EnqueueExtension` in the scheduling framework. 
  The `EventsToRegister` in `EnqueueExtension` changed the return value from `ClusterEvent` to `ClusterEventWithHint`. `ClusterEventWithHint` allows each plugin to filter out more useless events via the callback function named `QueueingHintFn`.
  When the scheduling queue receives a cluster event, before moving each Pod from unschedulable pod pool to activeQ/backoffQ, it will call QueueingHintFn of plugins that rejected each Pod in the previous scheduling cycle.
  Depending on the value returned from QueueingHintFn, the scheduling queue changes how it queues each Pod:
  - if more than one QueueingHintFn returns QueueImmediately, it queues Pod to activeQ.
  - If no QueueingHintFn returns QueueImmediately and more than one plugin returns QueueAfterBackoff, it queues Pod to backoffQ if Pod is backing off, or to activeQ if Pod's backoff has already finished.
  - If all QueueingHintFn return QueueSkip, it puts this pod back to the unschedulable pod pool
  
  Having appropriate QueueingHintFn contributes to reducing useless retries and thus improves the overall scheduler's performance.

  **How can I migrate?**
-->

- カスタムスケジューラプラグインの開発者はアクションが必要です。スケジューリングフレームワークにおいて`EnqueueExtension`で破壊的変更があります。`EnqueueExtension`の`EventsToRegister`は`ClusterEvent`から`ClusterEventWithHint`へ返り値を変更しました。`ClusterEventWithHint`はプラグインに対して`QueueingHintFn`と呼ばれるコールバック関数を用いて、より必要のないイベントを除外できます。スケジューリングキューがクラスターイベントの受信時、各Podを未スケジュールのPodプールからactiveQ/backoffQに移動する前に、前回のスケジューリングサイクルで各Podを拒否したプラグインのQueueingHintFnを呼び出します。
QueueingHintFnから返される値に応じて、スケジューリングキューは各Podのキューイング方法を変更します：
  - 1つ以上のQueueingHintFnがQueueImmediatelyを返す場合、PodをactiveQにキューします。
  - QueueingHintFnがQueueImmediatelyを返さず、1つ以上のプラグインがQueueAfterBackoffを返す場合、Podがバックオフ中の場合はPodをbackoffQにキューし、Podのバックオフが既に終了している場合はactiveQにキューします。
  - すべてのQueueingHintFnがQueueSkipを返す場合、このPodを未スケジュールポッドプールに戻します。

適切なQueueingHintFnを持つことで、無駄なリトライを削減し、結果としてスケジューラの全体的なパフォーマンスを向上させることができます。

**どのようにマイグレートすれば良いか？**

後方互換性のために、`QueueingHintFn`がnilの場合は常にQueueAfterBackoffを返していると使われます。
そのため、もし単に既存の挙動を続けたい場合、`QueueingHintFn`がない`ClusterEventWithHint`を登録できます。
しかし、適切な`QueueingHintFn`を登録することはもちろんスケジューリングのパフォーマンスを考慮すると良いです。([#118551](https://github.com/kubernetes/kubernetes/pull/118551), [@sanposhiho](https://github.com/sanposhiho)) [SIG Node, Scheduling, Storage and Testing]

<!--
For backward compatibility, nil `QueueingHintFn` is treated as always returning QueueAfterBackoff. 
So, if you want to just keep the existing behavior, you can register `ClusterEventWithHint` with no `QueueingHintFn` in it. 
But, registering appropriate `QueueingHintFn` is, of course, better from a scheduling performance perspective. ([#118551](https://github.com/kubernetes/kubernetes/pull/118551), [@sanposhiho](https://github.com/sanposhiho)) [SIG Node, Scheduling, Storage and Testing]
- CephFS volume plugin (`kubernetes.io/cephfs`) has been deprecated in this release and will be removed in a subsequent release. The alternative is to use the CephFS CSI driver (https://github.com/ceph/ceph-csi/) in your Kubernetes cluster. ([#118143](https://github.com/kubernetes/kubernetes/pull/118143), [@humblec](https://github.com/humblec))
- Deprecated support for CSI migration of `Ceph RBD volumes`. Users who were relying on Kubernetes' ability
 to migrate to an out-of-tree storage driver should complete that migration before the support for it is removed. ([#118303](https://github.com/kubernetes/kubernetes/pull/118303), [@carlory](https://github.com/carlory))
- RBD volume plugin (`kubernetes.io/rbd`) has been deprecated in this release
 and will be removed in a subsequent release. Alternative is to use RBD CSI driver
 (https://github.com/ceph/ceph-csi/) in your Kubernetes Cluster. ([#118552](https://github.com/kubernetes/kubernetes/pull/118552), [@humblec](https://github.com/humblec))
-->

- CephFSボリュームプラグイン (`kubernetes.io/cephfs`)はこのリリースで非推奨となり、今後のリリースで削除されます。代替としてはCephFS CSIドライバー (https://github.com/ceph/ceph-csi/)をクラスタで利用する事です。([#118143](https://github.com/kubernetes/kubernetes/pull/118143), [@humblec](https://github.com/humblec))
- `Ceph RBD volumes`のCSIマイグレーションのサポートは非推奨となりました。out-of-treeのストレージドライバーへの移行のためのKubernetesの機能を利用していたユーザは、そのサポートが完全に削除される前に移行を完了させる必要があります。([#118303](https://github.com/kubernetes/kubernetes/pull/118303), [@carlory](https://github.com/carlory))
- RBDボリュームプラグイン(`kubernetes.io/rbd`)はこのリリースで非推奨となり、今後のリリースで削除されます。代替としてはRBD CSI driver(https://github.com/ceph/ceph-csi/)をクラスタで利用することです。([#118552](https://github.com/kubernetes/kubernetes/pull/118552), [@humblec](https://github.com/humblec))