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

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

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

## 所感
:pencil:

柔軟にリソースを管理する機能 `ResourceClaim` APIが利用できるようになりました．このAPIにより，これまでDevice Pluginで実現されてきたノード単位のデバイスだけではなく，クラスタ単位のデバイスなどユーザ定義の階層ごとに特別なリソースを定義できます．[KEP](https://github.com/kubernetes/enhancements/tree/master/keps/sig-node/3063-dynamic-resource-allocation)では，ユースケースとして，コンテナ起動時に特権でのリプログラミングが必要なFPGAデバイスや，NVIDIAのMIGのようにGPUを分割して複数のPod / Containerから共有する機能，optional なデバイス， ファブリックデバイス（network / link）などが挙げられていました．

他にも，Topology Managerの拡張として `--topology-manager-policy-options` フラグが追加され，NUMAノードの距離に応じた割り当てが可能になる `prefer-closest-numa-nodes` オプションが追加されました．これまで，2-wayのサーバで各ソケットに複数のNUMAノードが存在する場合に，kubeletがソケット内に閉じたワークロードの配置とソケットをまたぐ配置を区別しない割り当てを行っていましたが，この挙動が改善されるようで，とても楽しみにしています．[弊社のインターンさんによるブログ「KubernetesクラスタにおけるGPU-NIC割り当ての改善によるRDMAの高速化」](https://tech.preferred.jp/ja/blog/better-gpu-nic-affinity-for-faster-rdma-in-kubernetes/)も関連するところがありますので，興味のある方はぜひご参照ください．

## Urgent Upgrade Notes
SIG-Nodeに関するものはとくにありません．

## Changes by Kind

### Deprecation

SIG-Nodeに関するものはとくにありません．

### API Change

- `ResourceClaim` API (`resource.k8s.io/v1alpha1` 内) が追加されました（ `DynamicResourceAllocation` feature gate が必要です）．この新しいAPIは，これまでの Device Plugin に比べ，ノード単位，クラスタ単位などユーザ定義の階層ごとに特別なリソースの種類を定義できるので，より柔軟性があります． ([#111023](https://github.com/kubernetes/kubernetes/pull/111023), [@pohly](https://github.com/pohly))
  - :pencil:
    - KEPは[こちら](https://github.com/kubernetes/enhancements/tree/master/keps/sig-node/3063-dynamic-resource-allocation)，公式ブログは[こちら](https://kubernetes.io/blog/2022/12/15/dynamic-resource-allocation/)です．
    - APIの追加:
      - ResourceClass: storageClass のようなもので，クラスタ管理者が追加して，resource driverとの結び付けや，パラメータを指定する
      - ResourceClaim: persistentVolumeClaim のようなもので，どのようなリソースがほしいかを定義する
      - ResourceClaimTemplate: persistentVolumeClaimTemplate のようなもので，podSpecのなかでまとめて resourceClaim を定義する時に使う
      - PodScheduling: コントロールプレーンとresource driverの間で調停を行うためのオブジェクト
    - 実装する際に開発する必要のあるコンポーネント:
      - controller: 中央でこれらを管理するためのコンポーネント
      - kubelet plugin: kubelet にリソースを提供するためのコンポーネント（DaemonSet）
        - Device Plugin と同様に gRPC で kubelet と通信をする
          - NodePrepareResource rpc: デバイスの準備をするとき
          - NodeUnprepareResource rpc: デバイスの利用が完了したとき

- コンテナの `preStop` と `postStart` ライフサイクルハンドラのうち `httpGet` を利用するものについては，指定されたスキームとヘッダを尊重するようになりました．例えばカスタムヘッダを設定したり，スキームをHTTPSに設定したりできるので， container startup/readiness/liveness プローブと同様のことができるようになります．スキームをHTTPSに設定したハンドラは，HTTPにフォールバックされるとエラーを報告します．このとき， `LifecycleHTTPFallback` が pod のイベントに記録されるとともに， `kubelet_lifecycle_handler_http_fallbacks_total` メトリクスが加算されます．クラスタ管理者は `--feature-gates=ConsistentHTTPGetHandlers=false` を設定することで，この機能を無効化することもできます． ([#86139](https://github.com/kubernetes/kubernetes/pull/86139), [@jasimmons](https://github.com/jasimmons))

- Kubelet に `DisruptionTarget` という failure condition が追加されました (graceful node shutdown. node pressure eviction) ([#112360](https://github.com/kubernetes/kubernetes/pull/112360), [@mimowo](https://github.com/mimowo))
  - :pencil: KEPは[こちら](https://github.com/kubernetes/enhancements/tree/master/keps/sig-apps/3329-retriable-and-non-retriable-failures)です．リトライすべき失敗とリトライする必要がない失敗を区別することで，failure conditionごとに適切に処理することができるようになります．

- `--topology-manager-policy-options` フラグが kubelet に追加されました．これは， Topology Manager のポリシーを微調整するために使われるものです．最初のオプションでは `prefer-closest-numa-nodes` というNUMAノード間が近いときも許すようにするポリシーが追加されました．([#112914](https://github.com/kubernetes/kubernetes/pull/112914), [@PiotrProkop](https://github.com/PiotrProkop))
  - :pencil:
    - KEPは[こちら](https://github.com/kubernetes/enhancements/tree/master/keps/sig-node/3545-improved-multi-numa-alignment)です．
    - 近年のCPUは，1ソケット内に分割されたL3キャッシュを持っていたりチップレットで作られていたりと，コア間レイテンシが異なる場合があります．そのため，1ソケット内に複数のNUMAノードを設定することで，アプリケーションにより細粒度なNUMA情報を与えることができるようになっています．しかし，kubeletは「NUMAノード間の距離」を扱うことができず，代わりに「同じ」か「異なる」の2通りで判断していました．これにより，1ソケット内にワークロードを収められる場合でも，ソケットをまたいだ配置をしてしまったりと最適でない割り当てをしてしまうことがありました．`prefer-closest-numa-nodes` はcAdvisorから提供される「NUMAノード間の距離」を考慮して割り当てをすることで，よりワークロードの割り当てを改善します．

- CFS クオータのデフォルト値を 100ms に設定し， `cpuCFSQuotaPeriod` の最小値を 1ms にして，Linux kernel の実装と合わせます．([#112123](https://github.com/kubernetes/kubernetes/pull/112123), [@paskal](https://github.com/paskal))

- Kubelet の external Credential Provider 機能がGAしました．Credential Provider Plugin と Credential Provider Config APIs は `v1beta1` から `v1` に APIの変更なしに更新されました． ([#111616](https://github.com/kubernetes/kubernetes/pull/111616), [@ndixita](https://github.com/ndixita))

- `DynamicKubeletConfig` feature gate が API サーバから削除されました．古いノードでも dynamic kubelet reconfiguration は利用できなくなりました．これは Kubernetes version skew policy にも適合しています． ([#112643](https://github.com/kubernetes/kubernetes/pull/112643), [@SergeyKanzhelev](https://github.com/SergeyKanzhelev))
  - :pencil: [DynamicKubeletConfig](https://kubernetes.io/blog/2018/07/11/dynamic-kubelet-configuration/) は，ConfigMap を使ってkubeletの設定を変更できる機能でしたが，v1.11からずっとbetaだったためv1.21で非推奨になったようです．

### Feature

- `NodeOutOfServiceVolumeDetach` がベータになりました．([#113511](https://github.com/kubernetes/kubernetes/pull/113511), [@xing-yang](https://github.com/xing-yang))
  - :pencil: graceful ではないノードの停止などで StatefulSet の PV が外れないことで，別のノードに再スケジュールができない問題などをケアする機能です．
- `pod_status_sync_duration_seconds` ヒストグラムがアルファメトリクスとして報告されるようになりました．これにより，kubeletがpod statusの変更をどの程度の時間で反映できるかを推測することができます．([#107896](https://github.com/kubernetes/kubernetes/pull/107896), [@smarterclayton](https://github.com/smarterclayton))
- cAdvisor の代わりに CRI から container および pod のメトリクスを回収する機能のアルファサポートを追加しました． ([#113609](https://github.com/kubernetes/kubernetes/pull/113609), [@haircommander](https://github.com/haircommander))
- cpumanager の cpu allocation と pinning を確認するためのメトリクスが追加されました．([#112855](https://github.com/kubernetes/kubernetes/pull/112855), [@fromanirh](https://github.com/fromanirh))
- kubelet再起動後の SELinux mount context が再構築されるようになりました． 機能 `SELinuxMountReadWriteOncePod` は完全に実装され，kubeletはプロセス再起動後に SELinux context のキャッシュを失わなくなりました． ([#113596](https://github.com/kubernetes/kubernetes/pull/113596), [@jsafrane](https://github.com/jsafrane))
- Evented PLEG feature gate がサポートされました． ([#111384](https://github.com/kubernetes/kubernetes/pull/111384), [@harche](https://github.com/harche))
  - :pencil:
    - KEPは[こちら](https://github.com/kubernetes/enhancements/tree/master/keps/sig-node/3386-kubelet-evented-pleg) です．
    - PLEG とは，Pod Lifecycle Event Generator の略です．
    - Kubeletは，CRI経由で定期的にコンテナの情報を取得して，ステータスを更新しています．現在はコンテナの情報を取得するためにpollingを使っていますが，これはコンテナの情報が更新されていないときも変化があるかどうかを処理して検知する必要があるため，多くのCPU時間を浪費しています．これを解決するため，イベントを使ってCRI実装から更新をそのまま入手できるように開発が進められています．
    - しかしながら，イベントは取りこぼす可能性があるので，（list + watchで構成されるinformerと同様に）relist と組み合わせつつ listする頻度を下げることを目的としているようです．
- `pod_start_sli_duration_seconds` メトリクスが追加されました． ([#111930](https://github.com/kubernetes/kubernetes/pull/111930), [@azylinski](https://github.com/azylinski))
- `--container-runtime-endpoint` フラグが空でないように検証を追加しました． ([#112542](https://github.com/kubernetes/kubernetes/pull/112542), [@astraw99](https://github.com/astraw99))
- Kubelet cpu manager が GA しました． ([#113018](https://github.com/kubernetes/kubernetes/pull/113018), [@fromanirh](https://github.com/fromanirh))
- Kubelet device manager が GA しました．([#112980](https://github.com/kubernetes/kubernetes/pull/112980), [@swatisehgal](https://github.com/swatisehgal))
- `ComponentSLIs` feature gate が有効な時， `/metrics/slis` が有効になり，ヘルスチェックメトリクスを利用できるようになりました．([#113030](https://github.com/kubernetes/kubernetes/pull/113030), [@Richabanker](https://github.com/Richabanker))
- cAdvisor が v0.46.0 に更新されました． ([#113769](https://github.com/kubernetes/kubernetes/pull/113769), [@bobbypage](https://github.com/bobbypage))

### Documentation
- デフォルトの CFS quota period が 100ms ではなく 100μs であることを明確化しました．([#111554](https://github.com/kubernetes/kubernetes/pull/111554), [@paskal](https://github.com/paskal))

### Bug or Regression

- `search .` をコンテナ内の `/etc/resolv.conf` に入れないようにしました ([#112157](https://github.com/kubernetes/kubernetes/pull/112157), [@dghubble](https://github.com/dghubble))
  - :pencil: もともと `search .` は Alpine のような musl libc を使う環境下では追加してはいけない検索ドメインでしたが，バグでホストから伝搬してしまう可能性があったようです．
- runc を v1.1.4 に更新しました ([#113719](https://github.com/kubernetes/kubernetes/pull/113719), [@pacoxu](https://github.com/pacoxu))
- kubelet が `kubectl exec` するときに誤った名前のコンテナを選ぶバグを修正しました ([#113041](https://github.com/kubernetes/kubernetes/pull/113041), [@saschagrunert](https://github.com/saschagrunert))
- コンテナのcpu requestが明示的に0に設定されたときの相対的なCPU優先度を，cpu limitの値を使うのではなく，最も低い優先度に設定することで，他のpodのcpuを枯渇させる問題が発生しないようにします． ([#108832](https://github.com/kubernetes/kubernetes/pull/108832), [@waynepeking348](https://github.com/waynepeking348))
- `PodAndContainerStatsFromCRI` 機能を修正して，cAdvisorからのメトリクスを組み合わせないようにしました ([#113291](https://github.com/kubernetes/kubernetes/pull/113291), [@mengjiao-liu](https://github.com/mengjiao-liu))
- Kubelet が `--node-ip` フラグを指定していない場合にcloud node IP アノテーションをクリーンアップできるようにします． ([#112184](https://github.com/kubernetes/kubernetes/pull/112184), [@danwinship](https://github.com/danwinship))
- devicemanager における起動クラッシュを修正しました．([#113021](https://github.com/kubernetes/kubernetes/pull/113021), [@rphillips](https://github.com/rphillips))
- kubelet_getters.go におけるスパムのようなログ `Path does not exist` を修正しました ([#112650](https://github.com/kubernetes/kubernetes/pull/112650), [@rphillips](https://github.com/rphillips))
- kubelet: スタンドアロンモード時のreflector起動時の nil pointer を修正しました ([#113501](https://github.com/kubernetes/kubernetes/pull/113501), [@pacoxu](https://github.com/pacoxu))
- kubelet: `/etc/resolv.conf` に複数行の option 行があるとき，`Default` DNS ポリシーのときはそれらをpod内において1行にまとめるようにします． ([#112414](https://github.com/kubernetes/kubernetes/pull/112414), [@pacoxu](https://github.com/pacoxu))
- `LocalStorageCapacityIsolationFSQuotaMonitoring` を Alpha に戻しました ([#112076](https://github.com/kubernetes/kubernetes/pull/112076), [@rphillips](https://github.com/rphillips))
- Pod ログが `--timestamps` オプションを使ったときでも壊れないようにします． ([#113481](https://github.com/kubernetes/kubernetes/pull/113481), [@rphillips](https://github.com/rphillips))
- pod admission error message を改善しました． ([#112644](https://github.com/kubernetes/kubernetes/pull/112644), [@vitorfhc](https://github.com/vitorfhc))
- `golang.org/x/text` を `v0.3.8`` に更新してCVE-2022-32149に対処しました． ([#112989](https://github.com/kubernetes/kubernetes/pull/112989), [@ameukam](https://github.com/ameukam))

### Other (Cleanup or Flake)

- `kubelet_kubelet_credential_provider_plugin_duration` は `kubelet_credential_provider_plugin_duration`に，`kubelet_kubelet_credential_provider_plugin_errors` は `kubelet_credential_provider_plugin_errors` に改名しました ([#113754](https://github.com/kubernetes/kubernetes/pull/113754), [@logicalhan](https://github.com/logicalhan))
- Container Runtime Interface (CRI) の `v1alpha2` のサポートをやめて，`v1` を実装することを必須にしました． ([#110618](https://github.com/kubernetes/kubernetes/pull/110618), [@saschagrunert](https://github.com/saschagrunert))
- `PodOverhead` feature gate を，v1.24からGAしているので削除しました． ([#112579](https://github.com/kubernetes/kubernetes/pull/112579), [@SergeyKanzhelev](https://github.com/SergeyKanzhelev))
- コンテナイメージのガベージコレクションに失敗したときのログをよりわかりやすくしました． ([#112631](https://github.com/kubernetes/kubernetes/pull/112631), [@tzneal](https://github.com/tzneal))
- OpenStack の in-tree cloud provider と，Cinder の in-tree volume provider を削除しました．外部のcloud provider と csi driver を [cloud-provider-openstack](https://github.com/kubernetes/cloud-provider-openstack) からインストールしてください． ([#67782](https://github.com/kubernetes/kubernetes/pull/67782), [@dims](https://github.com/dims))
- `GlusterFS` の in-tree storage driver は v1.25 から非推奨になって，v1.26で完全に削除されました． ([#112015](https://github.com/kubernetes/kubernetes/pull/112015), [@humblec](https://github.com/humblec))