Kubernetes 1.30: SIG-Node (kubelet) 変更内容

本記事は、[Kubernetes 変更内容共有会(v1.30)](https://kubernetes-updates.connpass.com/event/317298/) の SIG-Node(kubelet)に関する資料として準備されました。
Kubernetes 1.30の [CHANGELOG](https://github.com/kubernetes/kubernetes/blob/master/CHANGELOG/CHANGELOG-1.30.md) から、SIG-Nodeに関するところを抜粋して紹介します。

:pencil: は筆者(@y1r96)による補足です。

## 所感
:pencil:

今回の Kubernetes 1.30 の SIG-Node (kubelet) に関しては、以下の2つの変更が大きなものでした：
- Dynamic Resource Allocation における構造化されたパラメータの導入 (KEP-4381)
- 再帰的な Read-only マウントのサポート (KEP-3857)

Dynamic Resource Allocation は、従来の device plugin をより柔軟にすべく提案・実装されている Pod とデバイスを紐付ける機能です。Kubernetes 1.30 では、構造化されたパラメータを導入しました。このパラメータを使うことで、ユーザがデバイスの初期化に必要なパラメータを設定することで、DRA driver がもつ特権を使ってデバイスを安全に初期化することができます。また、デバイス側も ResourceSlice リソースを使ってデバイスに対応する構造化されたパラメータを広報することで、ユーザ指定のパラメータと CEL ベースのマッチングを行い、スケジューラにデバイスを絞り込ませてから Pod のスケジュールを検討できるようになりました。

再帰的な Read-only マウントは、従来の Read-only マウントの挙動を改善するものです。従来の Read-only マウントでは、親ディレクトリを Read-only にするものの、サブディレクトリが書き込み可能であれば書き込めてしまいました。再帰的な Read-only マウントを使用することで、サブディレクトリを再帰的かつ確実に Read-only にすることができるようになり、より安全にマウントできるようになりました。

## Changes by Kind

### API Change

- CRI Container message に `image_id` フィールドを追加することで、コンテナランタイムがイメージのガベージコレクションのバグを修正できるようにしました。([#123508](https://github.com/kubernetes/kubernetes/pull/123508), [@saschagrunert](https://github.com/saschagrunert)) [sig/node]
  - :pencil:
    - CRI Container message には、 `image_ref` というフィールドがあり、イメージの参照としてダイジェストが格納されていました。kubelet が行う image GC では `image_ref` の値を使っていましたが、ダイジェストが格納されている場合はうまく機能しませんでした。そこで、`image_id` というフィールドを追加し、ノード上の一意なイメージ識別子を格納できるようにしました。
- Dynamic Resource Allocation: DRA ドライバは、構造化されたパラメータを使用して、スケジューラがクレームの割り当てを処理できるようになりました。 ([#123516](https://github.com/kubernetes/kubernetes/pull/123516), [@pohly](https://github.com/pohly)) [sig/scheduling,sig/storage,sig/node,sig/api-machinery,sig/cluster-lifecycle,sig/auth,sig/apps,sig/cli,sig/instrumentation,sig/testing,sig/release]
  - :pencil:
    - KEPは[こちら](https://github.com/pohly/enhancements/blob/master/keps/sig-node/4381-dra-structured-parameters/README.md)です。これまでの device plugin を使った方法では、デバイスの初期化に使用するパラメータを device plugin に渡す方法が、 pod の annotation に記述する hacky な方法しかありませんでした。この DRA with structured parameters を使う方法を使うことで、DRA driver に構造化されたパラメータを渡すことができるようになります。
    - また、ユーザ側だけではなく、ノード側でも ResourceSlice リソースを使って構造化されたパラメータを広報することで、構造化されたパラメータ同士のマッチングを CEL として記述するコントローラを介在させることで、スケジューラに利用したいデバイスを絞り込んでマッチングをとらせることが可能になります。
- cgroupv1 なノードで、NodeSwap を LimitedSwap で利用すると Kubelet が失敗する。 ([#123738](https://github.com/kubernetes/kubernetes/pull/123738), [@kannon92](https://github.com/kannon92)) [sig/node,sig/api-machinery,sig/testing]
- `readOnly` volumes が kernel バージョンが 5.12 以上の場合に再帰的な読み取り専用マウントをサポートするようになりました。([#123180](https://github.com/kubernetes/kubernetes/pull/123180), [@AkihiroSuda](https://github.com/AkihiroSuda)) [sig/node,sig/api-machinery,sig/apps,sig/testing]
  - :pencil:
    - これまでは、`/mnt` を readonly としてマウントするとき、`/mnt` 以下のサブディレクトリである `/mnt/usbstorage` が readonly になっている保証はありませんでした。この変更で、`/mnt` 以下のサブディレクトリも再帰的に readonly になります。
- cri-api: KEP-3857: 再帰的な read-only (RRO) マウントを実装しました。([#123272](https://github.com/kubernetes/kubernetes/pull/123272), [@AkihiroSuda](https://github.com/AkihiroSuda)) [sig/node]
  - :pencil:
    - ↑ の 実装の CRI API 部分です。
- kubelet が デフォルトの /var/log/pods ではないカスタムのルートディレクトリを `podLogsDir` kubelet configuration を利用して pod logs に指定できるようになりました。([#112957](https://github.com/kubernetes/kubernetes/pull/112957), [@mxpv](https://github.com/mxpv)) [sig/scalability,sig/node,sig/api-machinery,sig/testing]
- アルファ機能である `RelaxedEnvironmentValiableValidation` フィーチャーゲートを追加しました。このゲートを有効にすることで、Kubernetes はほぼすべての印刷可能な ASCII 文字を、Pod 内のコンテナの環境変数の名前に使用できるようになります。([#123385](https://github.com/kubernetes/kubernetes/pull/123385), [@HirazawaUi](https://github.com/HirazawaUi)) [sig/node,sig/apps,sig/testing]
- AppArmor プロファイルを `PodSecurityContext` や container `SecurityContext` フィールドを使って設定できるようになりました。ベータ版の AppArmor アノテーションは非推奨となり、AppArmor ステータスはノードの ready condition に含まれなくなりました。([#123435](https://github.com/kubernetes/kubernetes/pull/123435), [@tallclair](https://github.com/tallclair)) [sig/node,sig/api-machinery,sig/auth,sig/apps,sig/testing]
- kubelet で log rotation が並行に行われるようになりました。`containerLogMaxWorkers` 設定で、並行する rotation の数を設定でき、`containerLogMonitorInterval` で監視する間隔を調整できます。 ([#114301](https://github.com/kubernetes/kubernetes/pull/114301), [@harshanarayana](https://github.com/harshanarayana)) [sig/node,sig/api-machinery,sig/testing]
- kubelet の設定において、`.memorySwap.swapBehavior` フィールドが `NoSwap` という値を取れるようになりました。未指定の場合のデフォルトは `NoSwap` で、以前利用できた `UnlimitedSwap` は削除されました。([#122745](https://github.com/kubernetes/kubernetes/pull/122745), [@kannon92](https://github.com/kannon92)) [sig/node,sig/api-machinery,sig/testing]
- `ResourceClaims` を使っている Pod と、使っていない Pod を混在させてスケジュールするとき、`ResourceClaims` を使っている Pod のスケジュールの遅延が小さくなりました。 ([#121876](https://github.com/kubernetes/kubernetes/pull/121876), [@pohly](https://github.com/pohly)) [sig/scheduling,sig/node,sig/api-machinery,sig/testing]

### Feature

- cAdvisor を `v0.49.0` に更新しました。([#123599](https://github.com/kubernetes/kubernetes/pull/123599), [@bobbypage](https://github.com/bobbypage)) [sig/node]
- kubelet における `ImageGCMaxAge` の振る舞いを変更して、kubelet が再起動した後に `MaxAge` の時間待ってからガベージコレクションを行うようにしました。([#123343](https://github.com/kubernetes/kubernetes/pull/123343), [@haircommander](https://github.com/haircommander)) [sig/node,sig/testing]
- `NewVolumeManagerReconstruction` 機能が GA しました。 ([#123442](https://github.com/kubernetes/kubernetes/pull/123442), [@jsafrane](https://github.com/jsafrane)) [sig/node]
  - :pencil:
    - これは、Kubelet 起動時に、マウントされたボリューム情報の探索を改善する機能です。コードがかなりリファクタリングされたので、Kubernetes 1.25 ~ 1.29 ではこの機能を無効化することができました。1.30 からは GA となり、この機能を無効化することはできなくなります。
- kubectl の `port-forward` を WebSocket (SPDY トンネル) 上で行う機能を、`Alpha` フィーチャーゲート環境変数 `KUBECTL_PORT_FORWARD_WEBSOCKETS=true` を使って有効にできるようにしました。通信先の API Server でも `PortForwardWebsockets` という `Alpha` フィーチャーゲートが有効になっている必要があります。([#123413](https://github.com/kubernetes/kubernetes/pull/123413), [@seans3](https://github.com/seans3)) [sig/node,sig/api-machinery,sig/cli,sig/testing]
- kubelet の新しいメトリクス `image_pull_duration_seconds` が追加されました。このメトリクスは、待機キューでの時間も含めてイメージを pull するのにかかる時間を秒単位で計測します。このメトリクスは、イメージサイズによりバケット化されています。([#121719](https://github.com/kubernetes/kubernetes/pull/121719), [@ruiwen-zhao](https://github.com/ruiwen-zhao)) [sig/node,sig/instrumentation]
- Kubelet の新しいメトリクス `lifecycle_handler_sleep_terminated_total` が追加されました。このメトリクスは、LifecycleHandler の sleep が予期せず終了した回数を記録します。 ([#122456](https://github.com/kubernetes/kubernetes/pull/122456), [@AxeZhan](https://github.com/AxeZhan)) [sig/node,sig/testing]
- `image_garbage_collected_total` メトリクスに `reason` フィールドを追加して、管理者がイメージが削除された理由が `age` なのか `space` によるものかを区別できるようにしました。 ([#123345](https://github.com/kubernetes/kubernetes/pull/123345), [@haircommander](https://github.com/haircommander)) [sig/node]
- Kubelet の新しいメトリクス `memory_manager_pinning_requests_total`, `memory_manager_pinning_errors_total` が追加されました。このメトリクスは、memory manager の割当とpinningを追跡します。 ([#121778](https://github.com/kubernetes/kubernetes/pull/121778), [@Tal-or](https://github.com/Tal-or)) [sig/node,sig/testing]
- `volume_manager_selinux_*` メトリクスに `access_mode` ラベルを追加しました。([#123667](https://github.com/kubernetes/kubernetes/pull/123667), [@jsafrane](https://github.com/jsafrane)) [sig/storage,sig/node,sig/testing]
- Forensic Container Checkpointing (KEP 2008) が Beta に昇格しました。 ([#123215](https://github.com/kubernetes/kubernetes/pull/123215), [@adrianreber](https://github.com/adrianreber)) [sig/node,sig/testing]
  - :pencil:
    - Kubernetes Blog による解説記事は[こちら](https://kubernetes.io/blog/2023/03/10/forensic-container-analysis/)です。コンテナの状況を診断目的であとから解析できるようにする機能で、メモリダンプやrootfsの差分など、必要なデータが一通り揃っています。
    - コンテナランタイムによるサポートも必要で、CRI-O や containerd がこの機能をサポートしています。Kubernetes の外ではありますが、この checkpoint からコンテナを再開することも可能だそうです。
- cloud provider を使用する場合に、`kubelet --node-ip` にデュアルスタックの値を渡すことがサポートされました。この機能は GA となり、`CloudDualStackNodeIPs` フィーチャーゲートは常に有効です。([#123134](https://github.com/kubernetes/kubernetes/pull/123134), [@danwinship](https://github.com/danwinship)) [sig/node,sig/api-machinery,sig/cloud-provider]
- `SELinuxMount` というフィーチャーゲートが Alpha で追加されました。これを有効にすることで、SELinux のリラベリングを高速化できます。([#123157](https://github.com/kubernetes/kubernetes/pull/123157), [@jsafrane](https://github.com/jsafrane)) [sig/storage,sig/node]
  - :pencil:
    - この機能は、ReadWriteOncePod では既にサポートされていましたが、今回すべてのアクセスモードでサポートされるようになりました。
    - SELinux のリラベリングとは、ファイルのアクセス権などをラベルとして管理する SELinux において、ファイルのラベルを再設定することです。これまではファイルを1つずつ更新する必要がありましたが、この機能ではマウント単位で一括でリラベリングが行えるようになります。
- Kubelet は user namespace を作成する際に使用する ID を設定できるようになりました。 ([#123593](https://github.com/kubernetes/kubernetes/pull/123593), [@giuseppe](https://github.com/giuseppe)) [sig/node]
- Node podresources API が、`SidecarContainers` フィーチャーゲートが有効になっていて、`containerRestartPolicy` が Always になっているとき（サイドカーコンテナを利用しているとき）、init container を含むようになりました。 ([#120718](https://github.com/kubernetes/kubernetes/pull/120718), [@gjkim42](https://github.com/gjkim42)) [sig/node,sig/testing]
- `ImageMaximumGCAge` フィーチャーゲートが Beta に昇格しました。([#123424](https://github.com/kubernetes/kubernetes/pull/123424), [@haircommander](https://github.com/haircommander)) [sig/node,sig/testing]
  - :pencil:
    - この機能は、Image がガベージコレクトされるまでの最大時間を設定するものです。
- Pod における `status.hostIPs` フィールドが GA しました。`PodHostIPs` フィーチャーゲートは効果がなく、Pod API を通じていつでも `status.hostIPs` を利用することができます。 ([#122870](https://github.com/kubernetes/kubernetes/pull/122870), [@wzshiming](https://github.com/wzshiming)) [sig/network,sig/node,sig/apps,sig/testing]
- `NodeLogQuery` フィーチャーが Beta に昇格しました。Alpha バージョンから機能に変更はありません。([#123205](https://github.com/kubernetes/kubernetes/pull/123205), [@aravindhp](https://github.com/aravindhp)) [sig/node,sig/windows]
  - :pencil:
    - この機能は、ノードのログ（たとえば、/var/log 以下のファイルや systemd のログ）を kubelet から取得する機能です。
- drop-in kubelet configuration directory 機能が Beta に昇格しました。([#122907](https://github.com/kubernetes/kubernetes/pull/122907), [@sohankunkerkar](https://github.com/sohankunkerkar)) [sig/node,sig/testing]
- CRI ランタイムが user namespace をサポートしていない場合、`hostUserns=false` で Pod を作成しようとすると、kubelet が Pod の作成を拒否するようになりました。([#123216](https://github.com/kubernetes/kubernetes/pull/123216), [@giuseppe](https://github.com/giuseppe)) [sig/node]

### Documentation

- kubelet の新しい内部メトリクス `kubelet_first_network_pod_start_sli_duration_second` が追加され、開発者がノード起動時のレイテンシ問題の原因を特定できるようになりました。([#121720](https://github.com/kubernetes/kubernetes/pull/121720), [@aojea](https://github.com/aojea)) [sig/network,sig/node,sig/instrumentation]

### Failing Test

なし

### Bug or Regression
- デフォルトの `EvictionHard` 設定に `imagefs.inodesfree` を追加しました。([#121834](https://github.com/kubernetes/kubernetes/pull/121834), [@vaibhav2107](https://github.com/vaibhav2107)) [sig/node]
- Windows ノードにおいて、`PodAndContainerStatsFromCRI` フィーチャーが有効になっているときに、`AvailableBytes` が正しく報告されない問題を修正しました。([#122846](https://github.com/kubernetes/kubernetes/pull/122846), [@marosset](https://github.com/marosset)) [sig/node,sig/windows]
- ノード再起動後に、`NodePublishVolume` が呼び出されずにマウントポイントがローカルになる問題を修正しました。([#119923](https://github.com/kubernetes/kubernetes/pull/119923), [@cvvz](https://github.com/cvvz)) [sig/storage,sig/node]
- ファイルがサブパスとして使用されているときに、Pod ボリュームマウントのクリーンアップが修正されました。([#123052](https://github.com/kubernetes/kubernetes/pull/123052), [@jsafrane](https://github.com/jsafrane)) [sig/node]
- `EventedPLEG` フィーチャー（ベータだが、デフォルト無効）が、既知の問題により Alpha に戻されました。([#122697](https://github.com/kubernetes/kubernetes/pull/122697), [@pacoxu](https://github.com/pacoxu)) [sig/node]
  - :pencil:
    - https://github.com/kubernetes/kubernetes/issues/121349 で、static pod 絡みの CI falling が発生し、解析の結果 EventedPLEG 機能が原因であることが判明したようです。
- DRA: ResourceClaim と PodSchedulingContext の status の更新により、object の metadata が更新されてしまうバグが修正されました。([#123730](https://github.com/kubernetes/kubernetes/pull/123730), [@pohly](https://github.com/pohly)) [sig/node]
  - :pencil:
    - 新しい status の更新時に、前の object により metadata を上書きしないといけなかったのですが、それが漏れてしまっていて、metadata を RBAC 回避しつつ更新できてしまったようです。
- ノード再起動時に raw block volumes を使用している Pod を削除できるようになりました。([#122211](https://github.com/kubernetes/kubernetes/pull/122211), [@gnufied](https://github.com/gnufied)) [sig/storage,sig/node]
  - :pencil:
    - ノードが再起動などでしばらくダウンしていて、pod が evict された場合に、raw block volume を使っていると pod が terminating で stuck してしまっていたようです。
- init container を containerRestartPolicy `Always` で利用しているとき（サイドカーコンテナを利用しているとき）、restartPolicy `Never` か `OnFailure` で利用している Pod に対して、init container の state が terminated から non-terminated に更新できないバグを修正しました。([#123323](https://github.com/kubernetes/kubernetes/pull/123323), [@gjkim42](https://github.com/gjkim42)) [sig/node,sig/apps]
  - :pencil:
    - これまでは、pod の restartPolicy が尊重されずに、init container の state が terminated から non-terminated に更新されてしまっていたようです。
- DRA において、実際の問題はないが data race が発生する可能性がある問題を修正しました。([#123222](https://github.com/kubernetes/kubernetes/pull/123222), [@pohly](https://github.com/pohly)) [sig/node]
- node expansion を必要としないボリュームを拡張しようとするとエラーが発生する問題を修正しました。([#123055](https://github.com/kubernetes/kubernetes/pull/123055), [@gnufied](https://github.com/gnufied)) [sig/storage,sig/node]
- Windows ノードにおいて、トータルの CPU 使用率が正しく計算されない問題を修正しました。([#122999](https://github.com/kubernetes/kubernetes/pull/122999), [@marosset](https://github.com/marosset)) [sig/node,sig/windows]
- node lifecycle controller が conditionType ready を 誤って `nil` でパッチすると panic する問題を修正しました。([#122874](https://github.com/kubernetes/kubernetes/pull/122874), [@fusida](https://github.com/fusida)) [sig/network,sig/node,sig/apps]
- kubelet 起動時の `EventedPLEG` の panic が修正されました。([#122475](https://github.com/kubernetes/kubernetes/pull/122475), [@pacoxu](https://github.com/pacoxu)) [sig/node]
- `InPlacePodVerticalScaling` が有効なときに、quota 計算エラーによりリソース削除が失敗する問題を修正しました。([#122701](https://github.com/kubernetes/kubernetes/pull/122701), [@carlory](https://github.com/carlory)) [sig/node,sig/api-machinery,sig/testing]
- google.golang.org/protobuf が `CVE-2024-24786` を修正するために `v1.33.0` に更新されました。([#123758](https://github.com/kubernetes/kubernetes/pull/123758), [@liggitt](https://github.com/liggitt)) [sig/network,sig/storage,sig/node,sig/api-machinery,sig/cluster-lifecycle,sig/auth,sig/cli,sig/instrumentation,sig/architecture,sig/cloud-provider]

### Other (Cleanup or Flake)

- `ConsistentHTTPGetHandlers` フィーチャーゲートが有効にロックされました。([#122578](https://github.com/kubernetes/kubernetes/pull/122578), [@carlory](https://github.com/carlory)) [sig/node]
- GAした `KubeletPodResourcesGetAllocatable` フィーチャーゲートが削除されました。 ([#122138](https://github.com/kubernetes/kubernetes/pull/122138), [@ii2day](https://github.com/ii2day)) [sig/node]
- GAした `KubeletPodResources` フィーチャーゲートが削除されました。 ([#122139](https://github.com/kubernetes/kubernetes/pull/122139), [@bzsuni](https://github.com/bzsuni)) [sig/node]
- GAした `ExperimentalHostUserNamespaceDefaultingGate` フィーチャーゲートが削除されました。 ([#122088](https://github.com/kubernetes/kubernetes/pull/122088), [@bzsuni](https://github.com/bzsuni)) [sig/node]
- cni-plugins が `v1.4.0` に更新されました。 ([#122178](https://github.com/kubernetes/kubernetes/pull/122178), [@saschagrunert](https://github.com/saschagrunert)) [sig/node,sig/testing,sig/cloud-provider]