Kubernetes 1.27: SIG-API Machineryの変更内容

# はじめに

Kubernetes v1.27がリリースされました 🎉

ここ最近のSIG-API Machineryのリリースは比較的落ち着いていましたが、v1.27は久々の大型アップデートです! 

v1.22(2021年)のころから開発されていたIn-place Pod vertical Scalingがついに、Alphaとしてリリースされました! イミュータブルだったPodのリソースが再作成なしにリサイズできるようになるので、APIはもちろんスケジューラやNodeのkubeletやruntimeなど広範囲に渡りたって変更が入ってます。デフォルト有効(Beta昇格)になるのは計画どおりだと2バージョン先のv1.29です。その他にも、WatchListがAlphaで入ったり、CELまわりの改善も進んだりと、より便利になっています。

それでは、API周りの変更を担当するSIG-API Machineryの変更点を[CHANGELOG](https://github.com/kubernetes/kubernetes/blob/master/CHANGELOG/CHANGELOG-1.27.md)からピックアックします。(📝がついた文章は、CHANGELOGの公式の内容ではなく筆者の補足です。また、⭐は変更点共有会でとりあげる予定の変更内容です)

> SIG, KEPについては[こちら](https://qiita.com/Ladicle/items/24cff72f5e8f4bd293a6)を参照ください。


# :earth\_asia: API Changes (API周りの変更)

ChangeLogではフラットでしたが、個人的に気になる変更をグルーピングしてます。


## ⭐ In-Place Pod Vertical Scaling

-   In-placeリサイズ機能がPodに導入されました。([#102884](https://github.com/kubernetes/kubernetes/pull/102884))
    -   `PodSpec.Container.Resources` のCPUとメモリのリソースタイプは変更可能になりました。
    -   `PodSpec.Container.ResizePolicy` (新規オブジェクト) コンテナのリサイズ方法をコントロールできます
    -   `PodStatus.Resize` リクエストされたPodのリサイズ状況を説明します。
    -   `PodStatus.ResourcesAllocated` Podに割り当てられたノードのリソースを説明します。
    -   `PodStatus.Resources` CRIによって実行中のコンテナに適用されたノードのリソースについて説明します。
    -   `UpdateContainerResources` CRI APIはLinuxとWindowsをサポートするようになりました。

📝 なぜかWhat's Newに入っていませんでしたが、目玉機能だと思われるPodリソースを垂直スケールさせる機能です。いままでPodを作り直さないとリソース割り当てを変更できませんでしたが、再起動せずにリサイズ要求が出せるようになりました。再起動コストが重いワークロードであってもリソース変更がしやすくなると思います。まだこの機能はAlphaなため、利用するにはFeatureGateの `InPlacePodVerticalScaling` の有効化が必要です。デフォルト有効となるBeta昇格は2バージョン先のv1.29に予定されています。この機能のKEPについてはQiitaの[In-place Pod Vertical Scaling (KEP-2273 & KEP-1287)](https://qiita.com/Ladicle/items/5bb5a9b7fb18bd400682)で解説しているので気になる方は併せて参照してください。また、k8s公式ブロクにもリリース内容についての記事が上がっています。[Kubernetes 1.27: In-place Resource Resize for Kubernetes Pods (alpha) | Kubernetes](https://kubernetes.io/blog/2023/05/12/in-place-pod-resize-alpha/) この記事では、実際のリサイズの様子のデモビデオなども掲載されています。


## ⭐ Watch List

-   reflectorにAPIストリーミングを許可する新しいalpha機能が導入されました。この機能を有効するには、 `ENABLE_CLIENT_GO_WATCH_LIST_ALPHA` 環境変数を設定してください。ただし、サーバはこのストリーミング機能を正式にサポートしている必要があります。もしストリーミングがサーバにサポートされていない場合、reflectorは以前の方法(データをList/Watch経由で取得する方法)にリバートされます。([#110772](https://github.com/kubernetes/kubernetes/pull/110772))
-   `watch-cache` 用のAPIストリーミングが実装されました。 `sendInitialEvents` `ListOption` を `watch=true` と同時に設定すると、watch streamが合成初期化イベントが合成"Bookmark"につづきます。その後、サーバはイベントのストリーミングを継続します。([#110960](https://github.com/kubernetes/kubernetes/pull/110960))
-   ストリーミング用APIが導入されました。 `SendInitialEvents` フィールドが `ListOptions` に追加されました。新しいオプションが `watch=true` と共に設定された時、watch streamが合成初期化イベントが合成"Bookmark"につづきます。その後、サーバはイベントのストリーミングを継続します。([#115402](https://github.com/kubernetes/kubernetes/pull/115402))

📝 個人的に気になっていたWatch Listもv1.27でAlphaリリースされました。元々、List APIはetcdやapi-serverへの負荷によるタイムアウトが問題になっており、v1.8-v1.22にかけてListにChunk機能(continue/limitオプション)が追加されていました。しかし、大規模クラスタでは主にInformerによるキャッシュ構築時のOOMが問題になっていました。これを解決するため、InformerがChunk Listでデータを取得するのではなく、Listでも(watchを利用して)ストリームで取得する設計に変わりました。 これに伴い、主にAPIサーバのcacherやclient-goのreflectorまわりに変更が入っています。設計についてはかなり詳しく解説されているので、気になるかたは以下のKEP-3157を参照してください。[KEP-3157: allow informers for getting a stream of data instead of chunking.](https://github.com/kubernetes/enhancements/tree/master/keps/sig-api-machinery/3157-watch-list)


## ⭐ Common Expression Language(CEL)

-   ValidatingAdmissionPolicyにCEL runtimeのコスト計算が追加されました。評価コストは、CustomResourceDefinitionに既に適用されている制限に対応します。もしルールの評価に制限以上の計算が必要となった場合、APIサーバは評価を打ち切ります。その時の対応は、ValidatingAdmissionPolicyの `failurePolicy` に応じて決定されます。 ([#115747](https://github.com/kubernetes/kubernetes/pull/115747))
-   `auditAnnotations` が `ValidatingAdmissionPolicy` に追加されました。リクエストのauditイベントに対するauditアノテーションの追加にCELが使えるようになりました。 `validationActions` が `ValidatingAdmissionPolicyBinding` に追加されました。バリデーションエラーをwarn, audit, denyの任意の組み合わせで処理できます。 ([#115973](https://github.com/kubernetes/kubernetes/pull/115973))
-   `messageExpression` フィールドが `ValidationRule` に追加されました。([#115969](https://github.com/kubernetes/kubernetes/pull/115969))
-   `messageExpression` が `ValidatingAdmissionPolicy` に追加されました。CEL expressionによるカスタムエラーメッセージを設定できます。([#116397](https://github.com/kubernetes/kubernetes/pull/116397))
-   ValidatingAdmissionPolicyのCEL expressionに認可チェックが追加されました。新しい `authorizer` 変数は `authorizer.group('').resource('pods').check('create').allowed()` といった表現ができるビルダーを提供します。([#116054](https://github.com/kubernetes/kubernetes/pull/116054))
-   `ValidatingAdmissionPolicy` がstatusフィールドを提供するようになりました。このフィールドはバリデーション結果を示します。([#115668](https://github.com/kubernetes/kubernetes/pull/115668))
-   ValidatingAdmissionPolicyに追加されたmatchConditionsフィールドは、CELベースのカスタムマッチをサポートしました。([#116350](https://github.com/kubernetes/kubernetes/pull/116350))
-   `MatchConditions` フィールドが `ValidatingWebhookConfiguration` と `MutatingWebhookConfiguration` のv1betaとv1 APIに追加されました。FeatureGateの `AdmissionWebhookMatchConditions` は現在Alphaです。([#116261](https://github.com/kubernetes/kubernetes/pull/116261))

📝 v1.25で[Common Expression Language(CEL)](https://github.com/google/cel-go)による手軽なCRDのバリデーション機能が追加されてから、v1.26でリリースされた `ValidatingAdmissionPolicy` というk8sの標準リソースのバリデーションもWebhook無しに実施可能とする機能など、CELの使える箇所が増えてきました。本リリースでも `ValidatingAdmissionPolicy` のauditイベントの対応やいくつかのフィールド追加など機能が強化されました。また、新たにCELを使ってwebhookの適用条件を定義できる `AdmissionWebhookMatchConditions` もリリースされました。今後も使える範囲が増えていきそうです。ただし、どちらもまだAlphaなため、利用にはFeature Gateの有効化が必要です。詳しい設計については、 [KEP-3488: CEL for Admission Control](https://github.com/kubernetes/enhancements/tree/master/keps/sig-api-machinery/3488-cel-admission-control)と[KEP-3716: Admission Webhook Match Conditions](https://github.com/kubernetes/enhancements/tree/master/keps/sig-api-machinery/3716-admission-webhook-match-conditions)を参照してください。


## Feature GateのBeta/GA昇格

-   Feature Gateの `GRPCContainerProbe` がGAになりました。常にデフォルトになり、1.29で削除されます。明示的に指定している場合は削除してください。([#116233](https://github.com/kubernetes/kubernetes/pull/116233))
-   Feature Gateの Kubelet `TopologyManager` がGAしました。([#116093](https://github.com/kubernetes/kubernetes/pull/116093))
-   Feature Gateの `CronJobTimeZone` がGAしました。([#115904](https://github.com/kubernetes/kubernetes/pull/115904))
-   Feature Gateの `APISelfSubjectReview` がBetaになりました。([#116274](https://github.com/kubernetes/kubernetes/pull/116274))
-   Feature Gateの `StatefulSetStartOrdinal` がBetaになりました。([#115260](https://github.com/kubernetes/kubernetes/pull/115260))
-   `KVMSv2` がBetaになりました。([#115123](https://github.com/kubernetes/kubernetes/pull/115123))
-   `PodSchedulingRediness` がBetaに昇格しました。([#115815](https://github.com/kubernetes/kubernetes/pull/115815))

## Misc

-   新しくAlpha APIのClusterTrustBundle (`certificates.k8s.io/v1alpha1`)が追加されました。ClusterTrustBundleは、[X.509](https://www.itu.int/rec/T-REC-X.509)トラストアンカーをクラスタ内のワークロードに配布する機能です。([#113218](https://github.com/kubernetes/kubernetes/pull/113218))
-   ワークロードリソース名(Pods, ReplicaSets, Deployments, Jobs, CronJobs, ReplicationControllers)がDNSラベルとして不正な場合にwarningがでるようになりました。([#114412](https://github.com/kubernetes/kubernetes/pull/114412))
-   kubeletのデフォルトAPI QPS limitが変更されました。([#116121](https://github.com/kubernetes/kubernetes/pull/116121))
    -   📝 eventBurst,eventRecordQPS と kubeAPIBurst,kubeAPIQPS がそれぞれ 10,5から10xの100,50に変更されています。
-   K8s.io/client-go/tools/record.EventBroadcaster: Shutdown()が呼ばれた後、broadcasterはsinkへのevent書き込みに失敗した後即座に停止します。以前は、goroutineで12秒間の間複数回リトライしていました。([#115514](https://github.com/kubernetes/kubernetes/pull/115514))
-   Kubelet: "maxParallelImagePulls"フィールドがkubelet設定ファイルで指定できるようになりました。これにより、kubeletが並列にPullするイメージ数を制御できます。([#115220](https://github.com/kubernetes/kubernetes/pull/115220))
    -   📝 [KEP-3673: Kubelet limit of Parallel Image Pulls](https://github.com/kubernetes/enhancements/tree/ea5255ce14f1fd90fa79ce0d73010468c19c93b9/keps/sig-node/3673-kubelet-parallel-image-pull-limit): コンテナのStartupレイテンシを小さくするために並列でPullしたいが、IOやNW帯域への負荷も考えて制限したいということで、並列イメージPull数を制御する機能が導入されました。
-   Kubelet:  `MemoryThrottlingFactor` のデフォルト値が `0.9` に変更されました。 `memory.high` の計算方法も変わりました。([#115371](https://github.com/kubernetes/kubernetes/pull/115371))
    -   📝 [KEP-2570: Support Memory QoS with cgroups v2](https://github.com/kubernetes/enhancements/tree/master/keps/sig-node/2570-memory-qos): v1.22から始まっているcgroups v2によるMemory QoS対応の一貫です。本リリースでは、公式ブログにもMemory QoSの解説がありました。 [Kubernetes 1.27: Quality-of-Service for Memory Resources (alpha) | Kubernetes](https://kubernetes.io/blog/2023/05/05/qos-memory-resources/)
-   KubernetesコンポーネントのLeader Electionにおいて、 `Leases` のみがサポートされるようになりました。([#114055](https://github.com/kubernetes/kubernetes/pull/114055))
-   非推奨となっていたCLIの `--enable-taint-manager` が `--pod-eviction-timeout` 削除されました。([#115840](https://github.com/kubernetes/kubernetes/pull/115840))
-   kmv v2プラグインのkey IDがstableな間は、APIサーバがデータ暗号化キーを再利用するようになりました。データ暗号化キーはサーバ起動時にランダムに生成されますが、atomicカウンターがnonceの衝突を防ぐために利用されます。([#116155](https://github.com/kubernetes/kubernetes/pull/116155))
-   1.26.0でPodに導入されたlist-typeのalpha `resourceClaims` フィールドは `set` から `map` に変更されました。 `CustomResourceDefinitions` 内のこれを利用したスキーマの不整合はserver-side applyによって解決されます。([#114585](https://github.com/kubernetes/kubernetes/pull/114585))
-   `resource.k8s.io/v1alpha1` は `resource.k8s.io/v1alpha2` に置き換えられました。Clusterをアップグレードする前に、全てのresource.k8s.io/v1alpha1に含まれるオブジェクト(ResourceClaim, ResourceClaimTemplate, ResourceClass, PodScheduling) を削除してください。この変更は内部的なもので、新しい `apiVersion` を除き、Podやリソースclaimを生成するYAMLファイルの変更は不要です。 ([#116299](https://github.com/kubernetes/kubernetes/pull/116299))


# :sparkle: Features (機能追加)

-   `applyconfiguration` generatorがcode-generatorスクリプトに追加されました。このスクリプトは、server-side apply configurationとclient APIを生成します。([#114987](https://github.com/kubernetes/kubernetes/pull/114987))
    -   📝 <https://github.com/kubernetes/code-generator/tree/master/cmd/applyconfiguration-gen>
-   cloud controller managerにwebhookをホストする機能が追加されました。([#108838](https://github.com/kubernetes/kubernetes/pull/108838))
    -   📝 一般向けのカスタマイズ機能ではないので使うことはあまりなさそうですが、クラウドプロバイダがクラウドコントローラマネージャ(CCM)を拡張するための機能がフレームワークに追加されました。元々は、sig-storageのPersistent VolumeLabel(PVL) Admissionコントローラが実装されていましたが、いくつかのプロバイダではAdmissionコントローラ経由だと外部のサービスと連携しきれない問題があり、その解決策として追加された機能のようです。詳しくは [KEP-2699: Add webhook hosting capability to CCM framework](https://github.com/kubernetes/enhancements/tree/master/keps/sig-cloud-provider/2699-add-webhook-hosting-to-ccm) を参照してください。
-   feature gateの `LegacyServiceAccountTokenTracking` がBetaに昇格しました。自動生成されたsecret-baseのServiceAccountトークンはデフォルトでワーニングを出すようになりました。関連するSecretは最終利用時間のタイムスタンプがラベルされます。(ラベルキーは `kubernetes.io/legacy-token-last-used`) ([#114523](https://github.com/kubernetes/kubernetes/pull/114523))
-   `apiextensions-apiserver` のバイナリを静的リンクさせます。(debとrpmパッケージにも影響があります) ([#114226](https://github.com/kubernetes/kubernetes/pull/114226))
-   `kube-aggregator` のバイナリを静的リンクさせます。(debとrpmパッケージにも影響があります) ([#114227](https://github.com/kubernetes/kubernetes/pull/114227))
-   `klog` のパフォーマンスが向上しました。([#115277](https://github.com/kubernetes/kubernetes/pull/115277))
-   プロファイリングが `--profiling-path` オプションをつかうことでunix-domainソケットでサーブされるようになりました。(ブロファイリングが有効な時) これはセキュリティ目的です。([#114191](https://github.com/kubernetes/kubernetes/pull/114191))
-   ⭐ Aggregated Discovery Endpointがbetaになり、デフォルト有効になりました。([#116108](https://github.com/kubernetes/kubernetes/pull/116108))
    -   📝 元々, kubectlなどk8s APIのクライアントは有効なAPIを探すためにgroup-versionごとに大量のリクエストを送らなければならず、これによるレイテンシやスロットリングが問題になっていました。負荷を避けるため、kubectlは6時間おきにrefreshしていますが、この方法だとキャッシュの古さが問題になります。これらを解決するために、Discoveryエンドポイントの `/api`, `/apis` に、新しいコンテンツネゴシエーションのタイプとして `APIGroupDiscoveryList` が導入されました。 詳しくは [KEP-3352: Aggregated Discovery](https://github.com/kubernetes/enhancements/blob/master/keps/sig-api-machinery/3352-aggregated-discovery/) を参照してください。
-   `OpenAPIv3` がGAになりました。([#116235](https://github.com/kubernetes/kubernetes/pull/116235))
    -   📝 OpenAPI v3のエンドポイントが生えたのはv1.24のときでした。順調に3バージョンでGAです。めでたい。
-   kubectl explainがOpenAPIV3の情報を使って提供されるようになりました。OpenAPIv2バックエンドは `--output plaintext-openapiv2` フラグを使うとまだ利用できます。([#116390](https://github.com/kubernetes/kubernetes/pull/116390))
-   Feature Gateの `AdvancedAuditing` がv1.27でtrueに固定されるようになりました。また、v1.28で完全に削除されます。([#115163](https://github.com/kubernetes/kubernetes/pull/115163))
-   API Priority and Fairnessの `/debug/api_priority_and_fairness/dump_priority_levels` エンドポイントに2つの変更があります。: ([#112393](https://github.com/kubernetes/kubernetes/pull/112393))
    -   リクエストのディスパッチ、タイムアウト、リジェクト、キャンセルの合計時間が追加されます。
    -   出力は `PriorityLevelName` によってソートされます。
-   `client-go`: `sharedInformerFactory` がmetadatainformerとdynamicinformerのシャットダウン中にgoroutineを待つようになりました。([#114434](https://github.com/kubernetes/kubernetes/pull/114434))


# :bug: Bug or Regression (バグ修正)

-   applyconfiguraton-genが `non-builtin` タイプのマップフィールドも生成できるように修正されました。([#114920](https://github.com/kubernetes/kubernetes/pull/114920))
-   client-go: カスタム `io.Reader` bodyを使ってリトライした際の潜在的なデータ競合を修正しました；この修正により、bodyが存在しない、もしくはbodyに `string` / `[]byte` / `runtime.Object` を持つもののみリトライできるようになりました。([#113933](https://github.com/kubernetes/kubernetes/pull/113933))
-   Discovery documentが正しくAggregated Discoveryを実装していないAggregated APIサーバのリソースを返すようになりました。([#115770](https://github.com/kubernetes/kubernetes/pull/115770))
-   `events/v1` `Events` が似たようなeventタイプを持ち、レポートされるinstanceが `client-go` によって集約されないバグが修正されました。([#112365](https://github.com/kubernetes/kubernetes/pull/112365))
-   同じようなEventを連続して送出した場合にAPIサーバが拒否するバグを修正しました。([#114237](https://github.com/kubernetes/kubernetes/pull/114237))
-   同じようなEventを連続して送出した時のデータ競合を修正しました。([#114236](https://github.com/kubernetes/kubernetes/pull/114236))
-   `kube-apiserver` が内部watchを再初期化するのと同時にwatch APIリクエストが作成された場合に、Eventが欠落する可能性がある `kube-apiserver` の稀な競合状態を修正しました。([#116172](https://github.com/kubernetes/kubernetes/pull/116172))
-   特定の状況下において、CRD Validation Rules(beta)と `ValidatingAdmissionPolicy` (alpha) において、すべてのAdmissionリクエストで `internal error: runtime error: index out of range [3] with length 3 evaluating rule: <rule name>` となるバグを修正しました。([#114857](https://github.com/kubernetes/kubernetes/pull/114857))
-   Beta版Aggregated Discoveryエンドポイントにおいて、同じGroupVersionを持つAggregated APIServiceが削除された場合、CRD discovery情報が一時的に欠落するバグを修正しました(逆のパターンも同様)。([#116770](https://github.com/kubernetes/kubernetes/pull/116770))
-   1.17.0以前のAPIサーバにおいて、reflectorが  `Too large resource version` エラーを解決できないバグが修正されました。([#115093](https://github.com/kubernetes/kubernetes/pull/115093))
-   watchの初期化と同時にwatchキャッシュの再初期化が走ったときの不正なwatch eventを修正しました。([#116436](https://github.com/kubernetes/kubernetes/pull/116436))
-   informerの再リストの削除イベントの欠落を修正しました。全ての削除イベントが正しく発信され、最新のオブジェクトの状態が使用されます。これにより、全てのイベントハンドラとストアが常に実際のapiserverの状態を可能な限り反映するようになります。([#115620](https://github.com/kubernetes/kubernetes/pull/115620))
-   Aggregated Discovery情報の要求時にAggregated APIServiceが `304 Not Modified` を返した場合、APIサーバがスタックする問題が修正されました。([#114459](https://github.com/kubernetes/kubernetes/pull/114459))
-   回帰バグの修正のため、DELETECOLLECTION呼び出しに34秒のタイムアウトが設定されました。([#115341](https://github.com/kubernetes/kubernetes/pull/115341))
-   `PodDisruptionConditions` 機能(1.26よりデフォルト有効)によって発生した2つの回帰バグが修正されました。([#116554](https://github.com/kubernetes/kubernetes/pull/116554))
    -   Pod eviction API呼び出しが不正な前提条件エラーを返し、成功するためには2回のl evict API呼び出しが必要でした。
    -   dry-run eviction API呼び出しは、evictionされるPodのDisruptionTarget条件を永続化していました。
-   HPAコントローラはFeatureGateの `HPAContainerMetrics` が無効の際にContainer Resource Metricsに対してエラーを返すようになりました。Container Resource Metricを持つHPAはscale-downを行わず、他のメトリクスに基づくscal-upのみ実施します。([#116043](https://github.com/kubernetes/kubernetes/pull/116043))
-   kube-apiserver: `--cors-allowed-origins` オプションによって指定された正規表現はバリデーションされるようになりました。 `Origin` リクエストヘッダ内の `hostname` は、先頭に固定する場合は '^' または '//' 接頭辞を、末尾に固定する場合は '$' またはポート区切り文字 ':' を含める必要があります。([#112809](https://github.com/kubernetes/kubernetes/pull/112809))
-   kube-apiserver: N^2となるWebhook Configurationの読み込みの挙動を削除しました。([#114794](https://github.com/kubernetes/kubernetes/pull/114794))
-   `cacher`: `ResourceVersion` が設定されていない場合、ドキュメントにあるように、元となるstorageからwatchが提供されるようになりました。([#115096](https://github.com/kubernetes/kubernetes/pull/115096))
-   `client-go`: Leader Leaseの取得のリトライの待ち時間を修正しました。([#114872](https://github.com/kubernetes/kubernetes/pull/114872))
-   `etcd`: `v3.5.7` にアップデートしました。([#115310](https://github.com/kubernetes/kubernetes/pull/115310))
-   `kube-controller-manager`: `kubecontrollermanager.config.k8s.io` configurationのl `kubeconfig` フィールドが正しく設定されないバグを修正しました。([#116219](https://github.com/kubernetes/kubernetes/pull/116219))
-   `kubectl port-forward` はリモートとの接続が切れた際に、終了コード1を返して終了するようになりました。([#114460](https://github.com/kubernetes/kubernetes/pull/114460))