はじめに
Kubernetes v1.37 がリリースされました 🎉
引き続き List/Watch 系のパフォーマンス改善が入っています。1.32 から入っていた etcd に保存されているものの、デコードできないオブジェクト処理用の AllowUnsafeMalformedObjectDeletion もベータに昇格し、デフォルト有効になりました。ほかにも、ベータデフォルト有効で追加された Webhook Server へのリクエストの偏りを抑制する WebhookRoundTripLoadBalancing など、運用しやすくなりそうな機能が色々あります。
それでは、API 周りの変更を担当する SIG-API Machinery の変更点を CHANGELOG からピックアップします。(📝 が付いた文章は、CHANGELOG の公式内容ではなく筆者の補足です)
SIG, KEPについてはこちらを参照ください。
✨ Features (機能追加)
List/Watch改善系
-
EtcdRangeStreamFeatureGate をデフォルトで有効にし、ベータに昇格させました。 (#140085)📝 api-serverの再起動時など、大きなクラスタで watch cache を初期化する際に、etcd からページ分割ではなく RangeStream RPC で受け取ることで初期化時間を短縮するための機能です。
詳しくは KEP-5966: etcd RangeStream を参照してください。 -
ConcurrentWatchObjectDecodeFeatureGate をベータに昇格させ、デフォルトで有効にしました。 (#139679)📝 watch オブジェクトのデコードを並列化し、API サーバーの watch が詰まるのを改善するための機能です。元は conversion webhook の遅延が背景にありましたが、こちらでも watch cacheの初期化速度も向上したようです。
-
WatchCacheInitializationPostStartHookを GA に昇格させました。 (#139452)📝 watch cache の初期化が終わるまでapi-server を Ready にしないための機能です。
-
アルファの FeatureGate
ConsistentListFromCacheSkipTimeoutFallbackを追加しました。有効にすると、タイムアウト期間内に watch キャッシュから処理できない consistent な LIST リクエストに対して、kube-apiserverはストレージにフォールバックする代わりに HTTP 429 を返します。 (#138701)📝 1.34でGAした
ConsistentListFromCacheの拡張機能で、今までは consistency が必要な LIST では cache が etcd の最新リビジョンまで追いつくまで待機、間に合わなければetcdへ問い合わせるという挙動でした。
今回のConsistentListFromCacheSkipTimeoutFallbackでは、etcd への不可を下げるため、タイム・アウトした場合でも etcd に直接問い合わせず、 429 を返してクライアント側でリトライさせる挙動になっています。 -
WatchListリクエストに対する圧縮レスポンスのベータサポートを追加しました。クライアントがAccept-Encoding: gzipを送信すると、API サーバーは gzip 圧縮されたレスポンスを返します。この動作はデフォルトで有効であり、WatchListCompressionFeatureGate で無効化できます。通常のwatchリクエストは影響を受けません。 (#140140)📝 1.34 からデフォルト有効な
WatchListの拡張機能で、 この元の方は informer の初期 LIST を watch のストリームとして受けることで apiserver の負荷を抑える機能でした。
今回のWatchListCompressionでは、このストリームを gzip 圧縮することでレイテンシを下げるという機能です。 -
Accept-Encoding: gzipを送信するクライアント向けにWatchListレスポンスを gzip 圧縮するWatchListCompressionFeatureGate(ベータ、デフォルト有効)を追加しました。通常のWatchリクエストは影響を受けません。 (#139308) -
CBORServingAndStorageFeatureGate が有効な場合に、ディスカバリエンドポイントおよび構造化エラーレスポンスにおける CBOR エンコーディングのサポートを追加しました。 (#139632)📝
CBORServingAndStorageは v1.32 から引き続きアルファ・デフォルト無効です。(client-go 側の ClientsAllowCBOR と ClientsPreferCBOR も同様)
Admission
-
⭐
--enable-aggregator-routing=trueを設定したkube-apiserverでは、コネクションキャッシングで同時リクエストが単一のバックエンドエンドポイントにルーティングされるのを防ぐため、admission webhook エンドポイント間でリクエストを均等にロードバランスさせます。クラスタ管理者はWebhookRoundTripLoadBalancingFeatureGate(ベータ、デフォルト有効)でこの動作を一時的にオプトアウトできます。 (#139237)📝 Webhook Server として複数の Pod を使っていた場合、今までは一度 Pod に接続されると、ホスト名をキーにしたプールから残っている接続が使い回されてリクエストが偏っていました。
今回の変更では、リクエストごとに都度ホスト名から Pod IP をランダムに解決するようになりました。 -
宣言的バリデーションタグ
+k8s:dependentRequired("siblingJSONName")を追加しました。タグ付けされたフィールドが設定されている場合、指定された同階層のフィールド(sibling)も設定が必要です。 (#139164) -
ManifestBasedAdmissionControlConfigFeatureGate をベータに昇格し、デフォルトで有効にしました。 (#140559)📝 Admission Webhook や ValidatingAdmissionPolicy / MutatingAdmissionPolicy を、API オブジェクトとしてではなく、kube-apiserver が起動時に読むファイルとして定義できる機能です。
詳しくは KEP-5793: Manifest Based Admission Control Configを参照してください。
-
ValidatingAdmissionPolicy および MutatingAdmissionPolicy で既に除外されている
tokenreviewsやsubjectaccessreviewsなどの auth/authz 仮想リソースを、admission webhook でもスキップするように更新しました。ExcludeAdmissionWebhookVirtualResourcesFeatureGate(ベータ、デフォルト有効)を追加し、以前の動作に戻すオプトアウトオプションを提供しています。 (#140019)
Staleオブジェクトの処理
-
⭐
AllowUnsafeMalformedObjectDeletionFeatureGate をベータに昇格させ、デフォルトで有効にしました。ストレージから読み取れないオブジェクトに対する List エラーに、最初の根本原因が含まれるようになりました。 (#140785)📝 etcd には残っているものの、APIサーバから読めなくなったオブジェクトの検出 & 削除機能
AllowUnsafeMalformedObjectDeletionがデフォルト有で効になりました。1.32 からアルファとして追加されていたものです。以前は 破損オブジェクトは単に 500 エラーが返っていましたが、以下のように分かりやすいエラーが返るようになりました。削除では、
deleteとunsafe-delete-ignore-read-errors権限を持つユーザがignoreStoreReadErrorWithClusterBreakingPotentialオプションを使って実行できます。(1つ下の変更でdry-runも併用できるようになりました)$ kubectl get secret my-secret -n default Error from server (InternalError): Internal error occurred: StorageError: corrupt object, Code: 7, Key: /registry/secrets/default/my-secret, ResourceVersion: 0, AdditionalErrorMsg: data from the storage is not transformable revision=0: no matching prefix found # ignoreStoreReadErrorWithClusterBreakingPotential optionで削除 $ kubectl delete --raw '/api/v1/namespaces/default/secrets/my-secret?ignoreStoreReadErrorWithClusterBreakingPotential=true&dryRun=All' {"kind":"Status","apiVersion":"v1","metadata":{},"status":"Success","details":{"name":"my-secret","kind":"Secret"},"code":200}詳しくは KEP-3926: Handling undecryptable resources を確認してください。
-
安全でない破損オブジェクトの削除に dry-run サポートを追加し、管理者が削除操作を実際に実行する前に安全にテストできます。 (#134037)
-
⭐ StorageVersionMigration の conditions に進捗報告を追加し、マイグレーションで処理されたオブジェクト数を確認できます。 (#138875)
📝 StorageVersionMigration の進捗状況が status.conditions から読めるようになりました。詳細はKEP-4192: Move Storage Version Migrator in-tree を参照してください。
HPA
-
HPAConfigurableToleranceFeatureGate を GA に昇格しました。 (#140107)📝 HPA のスケール判定の許容幅をワークロードごとに調整できる機能が GA しました。v1.35 からベータで、デフォルト有効でした。小さなメトリクス変動による頻繁なスケールを抑えたい場合に使えます。
KEP-4951: Configurable tolerance for Horizontal Pod Autoscalers
-
HorizontalPodAutoscaler の conditions に、条件が記録された時点の
observedGenerationをオプションで含められるようにしました。 (#138653) -
HorizontalPodAutoscaler リソースにおいて
metadata.generationおよびstatus.observedGenerationフィールドを生成します。 (#138228)
🐛 Bug or Regression (バグ修正)
CEL と Admission ポリシー
-
CRD の
metadata.nameおよびmetadata.generateNameに対する CEL コスト見積もりを修正し、それらのメタデータフィールドに追加のバリデーションが定義されていない限り、デフォルトの最大長 253 文字を正しく考慮します。 (#139573)📝 CRD 名の上限は 253 文字ですが、以前は無限長として見積もられていました。
-
⭐
setおよびmapリストに対する CEL の動作を修正しました。等価性比較(==)で重複を含むリストが一致しなくなり、連結(+)で追加された要素に対して set および map のマージセマンティクスが正しく適用されました。 (#140293)📝 CELでは、
setまたはmapのリストを扱うための以下の演算子があります。これらが、今回の変更で定義どおりの動きをするようになりました。-
==: 要素の順序を無視して比較する (集合として比較) -
+: set リストは和集合になる。map リストはキーが同じ要素を右側の値で上書きし、新しいキーの要素は末尾に追加する
たとえば
spec.tags: ["a", "b", "c"]という set リストがあった時、各 CEL 式を評価すると次のようになります。CEL 式 変更前 変更後 self.tags == ['c', 'b', 'a']truetrue(順序は無視)self.tags == ['a', 'a', 'b']truefalse==の修正: 変更前は「要素数が同じ」かつ「右辺の各要素が左辺に含まれる」だけで一致と判定していました。今回右辺が左辺のすべての要素を含んでいるかを確認するようになりました。+の修正: 戻り値自体は正しい動きをしていましたが、左辺のリスト(self.tags)の内部キャッシュまで書き換えていました。そのため、変数で同じリストを使い回すと、後続の演算結果が変わっていました。 -
-
quantity.Addがレシーバーを変更(mutate)してしまう CEL のバグを修正しました。 (#140556) -
audit アクションを持つ複数の ValidatingAdmissionPolicy バインディングに一致するリクエストにおいて、最初のバリデーション失敗のみが audit アノテーションに記録されていた
kube-apiserverのバグを修正しました。すべての audit 失敗が単一のアノテーションに出力されます。 (#140001) -
3つのキーを持つ型付きマップリストに対して CEL 式を評価する際に admission コントローラーがパニックを引き起こす可能性があったバグを修正しました。 (#140386)
-
キャッシュミスによりパラメータオブジェクトが別のパス経由でロードされた際に、ValidatingAdmissionPolicy および MutatingAdmissionPolicy の評価においてオブジェクト表現の微妙な違い(特に quantity フィールドや type meta フィールド周辺)が観測される可能性があったバグを修正しました。CEL 式は params に対して決定論的に動作します。 (#140201)
-
名前空間が削除された後も残存している名前空間付きオブジェクトへの更新が許可されるよう、admission の処理を修正しました。 (#140661)
-
不正な形式のオブジェクト削除が admission や適切に形成されたオブジェクトのグレースフルな削除をバイパスできてしまう可能性があったエッジケースを排除しました。 (#137582)
API サーバーとリソース管理
-
--endpoint-reconciler-typeにmaster-countまたはleaseを使用する場合にkube-apiserverが--advertise-addressの IP を検証するように変更し、指定された IP アドレスが Endpoints API オブジェクトに正常に永続化できることを保証しました。 (#138102) -
ホスト名が 63 バイトを超えているなどの理由で identity Lease を作成できなかった場合に、
kube-apiserverがSIGTERMで無期限にハングする問題を修正しました。 (#140241) -
⭐ create-via-update および created-via-apply リクエストに対して、create リクエストと同様にメタデータフィールドを作成するように
kube-apiserverを修正しました。UIDおよびresourceVersionの前提条件は引き続き尊重されます。 (#138908)📝 SSA など update/apply 経由で作成されたオブジェクトは、以前から create 時と同様に
UIDやcreationTimestampはサーバ側で上書きされていましたが、deletionTimestampなどはクライアントが送った値がそのまま保存されていました。(なので、その場合は作成直後から削除中になる)
この変更により、(作成経由にかかわらず)それらのフィールドもサーバ側で処理されるようになりました。
StorageVersionMigration
- マイグレーションが保留中の間に CRD が削除された場合など、StorageVersionMigration が RESTMapper に存在しないリソースを対象とした場合に
kube-controller-managerでパニックが発生する可能性があった問題を修正しました。 (#140586)
client-go と kubeconfig
-
watch 確立時における 410 Gone(リソース期限切れ)エラーを、ERROR レベルではなくデバッグ詳細度(
V(4))でログ出力するようにclient-goのRetryWatcherを変更しました。 (#138295) -
Windows において
.kube/configディレクトリ外にある認証局(CA)パスが、他の OS の動作と一致せず相対パスに変換されていた処理を修正しました。 (#135735) -
kubeconfigファイルを移行する際(例:~/.kube/.kubeconfigから~/.kube/configへ)、元のファイルのパーミッションを保持するようにclient-goを更新しました。以前は移行先ファイルがより緩いパーミッションで作成され、同一システム上の他のユーザーにクレデンシャルが露出するリスクがありました。 (#138142) -
⭐
client-go: イベントハンドラーを閉じる前に、実行中のイベントハンドラーの完了を待機するサポートを追加しました。 (#139755) -
client-go:v0.36でcache.Storeインターフェースに追加されたメソッドに合わせて、FakeCustomStoreにBookmarkおよびLastStoreSyncResourceVersionメソッドを追加し、再びインターフェースを満たすようにしました。 (#140966)
🔬 Others (その他修正)
- ある型に対して宣言的バリデーション関数が登録されているかどうかを報告する
HasValidationFuncメソッドをruntime.Schemeに追加しました。 (#140120) - etcd 内の MutatingAdmissionPolicy および MutatingAdmissionPolicyBinding のストレージを
admissionregistration.k8s.io/v1バージョンに変更します。 (#137375) - カスタムリソースに対する Server-Side Apply リクエストが、apply パスが完全に同期される前に更新された CustomResourceDefinition を観測してしまい、一貫性のない dry-run 動作を引き起こす可能性があった競合状態を修正しました。 (#140232)
-
k8s.io/apiserver/pkg/server/options.EtcdOptionsの no-op となっていたDefaultWatchCacheSizeフィールドを削除しました。 (#134151) - Service へプロキシする際に、
kube-apiserverのservice/proxyサブリソースが Endpoints ではなく EndpointSlices を使用させます。この変更は、Service に対して手動で Endpoints を作成し、EndpointSlice のミラーリングを無効にしているクラスタにのみ影響します。 (#134860) -
kube-controller-managerの--concurrent-service-syncsフラグ(v1.31 以降 no-op)を削除しました。 (#138002) -
client-goの aggregated discovery 時にv2beta1にフォールバックせず、v2をリクエストさせます。 (#138271) - client-go のリーダー選出 resourcelock パッケージにおいて、
MultiLock、UnknownLeader、ConcatRawRecordを非推奨にしました。 (#138070) -
v1.15で非推奨となっていたkube-apiserverの--enable-logs-handlerフラグの非推奨マークを解除しました。デフォルトでは引き続き無効です。 (#138915) -
kubeadm: サポート対象のコントロールプレーンバージョンv1.34,v1.35,v1.36に対し、サポートする etcd バージョンをv3.6.11に更新しました。 (#138746)