Kubernetes 1.26: SIG-CLI (kubectl) の変更内容

ここでは、Kubernetes 1.26 の CHANGELOG から SIG-CLI (kubectl) の取り組みについてまとめています。:memo: は筆者によるコメントです。

- https://github.com/kubernetes/kubernetes/blob/master/CHANGELOG/CHANGELOG-1.26.md

**新たに追加された主なコマンドとフラグ**

- `kubectl events` コマンド: `kubectl alpha events` からの昇格。既存のコマンドは削除された。
- `kubectl alpha auth whoami` コマンド: ユーザの属性情報の表示。feature gate `APISelfSubjectReview` が有効でないと機能しない。
- `--disable-compression` フラグ: API サーバの API レスポンスを圧縮しない
- `kubectl api-resources --categories` フラグ: API リソースリストをカテゴリでフィルタする
- `kubectl apply --prune-allowlist` フラグ: `--prune-whitelist` フラグのリネーム
- `kubectl create clusterrolebinding --user` フラグ: 同時に複数指定できるようになった
- `kubectl create rolebinding --user` フラグ: 同時に複数指定できるようになった
- `kubectl set subject --user` フラグ: 同時に複数指定できるようになった

**変更があった主なコマンドとフラグ**

- `kubectl api-resources --wide` フラグ: カテゴリが表示されるようになった
- `kubectl config view` コマンド: 秘匿データを含むフィールドが隠されるようになった

**廃止予定のコマンドとフラグ**

- `kubectl run` の次のフラグ
    - `--cascade`, `--filename`, `--force`, `--grace-period`, `--kustomize`, `--recursive`, `--timeout`, `--wait`

**削除されたコマンドとフラグ**

- `kubectl apply --prune-whitelist` フラグ: `--prune-allowlist` フラグが代わりに追加されて削除された
- `kubectl alpha events`: `kubectl events` コマンドに昇格されたことで削除された

そのほか、細かい変更は、 https://github.com/superbrothers/kubectl-docs/compare/v1.25.0...v1.26.0 で参照できます。

## 所感

kubectl プラグインがシェル補完でサポートされ、さらに kubectl プラグインがシェル補完をサポートしている場合に、kubectl からそれが利用できるというさいこうな機能が入りました。アルファですが、新しく追加された `kubectl alpha auth whoami` でユーザ自身の属性が取得できるようになったのも素晴らしいです。

## What's New (Major Themes)（主要な変更）

SIG-CLI に関連する情報はありません。

## Urgent Upgrade Notes（必ず一読してからアップグレードしなければならない事項）

SIG-CLI に関連する情報はありません。

## Changes by Kind（種類別の変更）

### Deprecation（廃止）

SIG-CLI に関連する情報はありません。

### API Change（API の変更）

- 自分自身の属性を取得する auth API が追加（新しい SelfSubjectReviews API が追加）。対応するコマンドとして kubectl に `kubectl auth whoami` が提供されました ([#111333](https://github.com/kubernetes/kubernetes/pull/111333), [nabokihms](https://github.com/nabokihms)) [SIG API Machinery, Auth, CLI and Testing]
    - :memo: これまで TokenAccessReview API を使うことで ServiceAccount トークンでそれが誰なのかの確認はできたが、ユーザの確認はできなかった
    - :memo: kubectl に実際に追加されたのは `kubectl alpha auth whoami` コマンドで、feature gate `APISelfSubjectReview` が有効になっていないと利用できない
- `kubectl wait` コマンドの `jsonpath` フラグで対象のパスをタイムアウトまで待つようになりました ([#109525](https://github.com/kubernetes/kubernetes/pull/109525), [jonyhy96](https://github.com/jonyhy96)) [sig/cli,sig/testing]
    - :memo: `--condition` フラグでは対象のパス（フィールド）が存在しない場合もコマンドが終了せず待ち続ける挙動だったが、`--jsonpath` フラグではフィールドでは存在しないとエラーになってしまっていた。この変更でエラーにならないようになり、2つのフラグで挙動が統一された

### Feature（機能）

- `kubectl` に `--disable-compression` フラグが追加された (デフォルトは false)。true の場合、`apiserver` への全てのリクエストに対してレスポンスの圧縮がされないようになる。これは、クライアントとサーバのネットワーク帯域幅が十分な場合 (>30MB/s) や、サーバの CPU に制約がある場合にリストコールのレイテンシを大幅に改善するのに役立つことがあります。 ([#112580](https://github.com/kubernetes/kubernetes/pull/112580), [shyamjvs](https://github.com/shyamjvs)) [sig/cli,sig/testing]
    - :memo: kubectl の変更とは別に apiserver で API レスポンスで gzip 圧縮レベルが `4` から `1` に変更されている。この変更でネットワーク帯域幅の使用量が増加 (10-50%増加) する代わりに、大きなリスト取得が高速化されるとある。
        - https://github.com/kubernetes/kubernetes/pull/112299
    - :memo: [Gzip compression in k8s API \- Google ドキュメント](https://docs.google.com/document/d/1rMlYKOVyujboAEG2epxSYdx7eyevC7dypkD_kUlBxn4/edit#heading=h.4szsdjv6proq) では K8s API での Gzip 圧縮について扱われていて、長期的には pgzip や zstd といった他のより優れた圧縮アルゴリズムを検討することが好ましいとある
- `remotecommand.Executor` に `StreamWithContext` メソッドを追加して、キャンセル可能な SPDY executor stream がサポートされました ([#103177](https://github.com/kubernetes/kubernetes/pull/103177), [arkbriar](https://github.com/arkbriar)) [sig/node,sig/api-machinery,sig/cli,sig/testing]
    - :memo: `kubectl exec/attach` コマンドではいまだに SPDY が使われていて、多くの SPDY executor stream が作成されると正しくストリームがクローズされずにリークすることがあったそう。context が渡せるようになり正しくキャンセルされるようになったみたい。
- `kubectl api-resources` コマンドの wide アウトプット (`-o wide`) に categories カラムが追加されました。`kubectl api-resources` コマンドに `--categories` フラグが追加され、一つ以上のカテゴリに紐付くリソースのみを出力するように絞り込めるようになりました。 ([#111096](https://github.com/kubernetes/kubernetes/pull/111096), [brianpursley](https://github.com/brianpursley)) [SIG CLI] [sig/cli]
    - :memo: あまり知られていないが、Kubernetes リソースにはカテゴリという属性があり、`kubectl get` コマンドでカテゴリ名を指定してリソースを取得できるが、どのリソースがどのカテゴリに属しているかはこれまで OpenAPI の API 仕様を直接確認しないと分からなかった。例えば `kubectl get all` は、いくつかのリソースが `all` カテゴリに属しているというしくみになっている。
    - :memo: `kubectl get all` のしくみについて [kubectl get all は全リソースの情報を表示しない \| text․superbrothers․dev](https://text.superbrothers.dev/190616-kubectl-get-all-does-not-include-most-resources/) は書いているので興味あれば見てみてください。
- `KUBECTL_EXPLAIN_OPENAPIV3` 環境変数で保護されたアルファの `--output plaintext` が追加されました ([#113146](https://github.com/kubernetes/kubernetes/pull/113146), [alexzielenski](https://github.com/alexzielenski)) [SIG CLI] [sig/cli]
    - :memo: `kubectl explain` コマンドで OpenAPI v3 を使うように変更する KEP があり、そのなかで色々な機能追加が予定されており、この変更ではデフォルトのプレインテキストで出力する機能が追加された。OpenAPI v3 を使った `kubectl explain` は v2 と呼ばれているみたい。今後予定されている機能追加は KEP を参照。
        - KEP: https://github.com/kubernetes/enhancements/tree/master/keps/sig-cli/3515-kubectl-explain-openapiv3
- bash シェルでの kubectl シェル補完に説明文が含まれるようになりました ([#113636](https://github.com/kubernetes/kubernetes/pull/113636), [marckhouzam](https://github.com/marckhouzam)) [sig/cli]
    - :memo: コメント/フラグ名のみが補完されていたが、それらのヘルプ文も表示されるようになったよという変更。他のシェル（zsh など）ではこれまでも表示されていた。
- `kubectl alpha events` が `kubectl events` に昇格しました ([#113819](https://github.com/kubernetes/kubernetes/pull/113819), [soltysh](https://github.com/soltysh)) [sig/cli,sig/testing]
- シェル補完でプラグイン名が表示されるようになりました。加えて、シェル補完は補完サポートを提供するプラグインで機能するようになりました。 ([#105867](https://github.com/kubernetes/kubernetes/pull/105867), [marckhouzam](https://github.com/marckhouzam)) [sig/cli]
    - :memo: kubectl プラグインをインストールしている場合に、シェル補完でプラグインも補完できるようになった。さいこう。加えて、kubectl プラグイン自体がシェル補完サポートを提供している場合に、kubectl からその補完を使えるようになった。すごい。この機能追加については別エントリで詳しく書いているので、詳細はそちらを参照ください。
        - [ついに kubectl plugin のシェル補完がサポートされるぞ \(Kubernetes 1\.26\) \- Qiita](https://qiita.com/superbrothers/items/65a16f5139b52e1b9d56)
- `kubectl config view` は、`datapolicy` タグでマークされている秘匿フィールドを自動的に隠すようになりました ([#109189](https://github.com/kubernetes/kubernetes/pull/109189), [mpuckett159](https://github.com/mpuckett159)) [sig/api-machinery,sig/auth,sig/cli,sig/testing]
    - :memo: `datapolicy` タグはログで秘匿データが出力されないようにサニタイズすることが目的にフィールドに付けられるようになったもの。`kubectl config view` はこれまでいくつかのフィールドを隠すようにハードコードされていたが、この変更でこれまで隠されていなかった OIDC アクセストークン等が隠されるようになった。

### Documentation（ドキュメント）

SIG-CLI に関連する情報はありません。

### Bug or Regression（バグまたはリグレッション）

- 削除されるまでに必要な廃止期間を経ていない `kubectl run` コマンドの使われていないフラグが戻されました ([#112243](https://github.com/kubernetes/kubernetes/pull/112243), [brianpursley](https://github.com/brianpursley)) [sig/cli]
- `kubectl patch` で指定されたパッチタイプでリソースがサポートされていない場合のエラーメッセージが変更されました ([#112556](https://github.com/kubernetes/kubernetes/pull/112556), [ardaguclu](https://github.com/ardaguclu)) [sig/cli]
- `kubectl rollout history` で特定のリビジョンと出力フォーマットをした場合に最新のリビジョンしか表示されないバグが修正されました ([#111093](https://github.com/kubernetes/kubernetes/pull/111093), [brianpursley](https://github.com/brianpursley)) [sig/cli,sig/testing]
- `kubectl label` を `--dry-run` フラグと一緒に実行してもドライランメッセージが出力されないバグが修正されました ([#111571](https://github.com/kubernetes/kubernetes/pull/111571), [brianpursley](https://github.com/brianpursley)) [sig/cli]
- `kubectl` で、`--server-side` が client-side apply が使う全てのフィールドの所有権を指定された `--field-manager` に移行するようになりました。これにより、kubectl を使用して以前に指定されたフィールドが server-side apply の管理外に存在して削除できなくなるのを防がれるようになりました。 ([#112905](https://github.com/kubernetes/kubernetes/pull/112905), [alexzielenski](https://github.com/alexzielenski)) [sig/api-machinery,sig/cli,sig/testing]
    - :memo: client-side apply から server-side apply に移行すると、client-side apply と server-side apply がフィールドの共同所有権になってしまうことで、server-side apply でフィールドを削除しようとしても削除されない事態になってしまっていた
    - :memo: この変更で client-slide apply の所有権がすべて削除されて server-side apply の所有権のみが残るようになった。なお、client-side apply のみが使う `kubectl.kubernetes.io/last-applied-configuration` annotation は、`kubectl-last-applied` field manager が所有するようになっている。
    - :memo: server-side apply やフィールドの所有権について、Kubernetes Meetup Tokyo 48 で詳しく話しているので興味ある方はみてみてください
        - [わかる！metadata\.managedFields \- Speaker Deck](https://speakerdeck.com/superbrothers/wakaru-metadata-dot-managedfields)
        - https://youtu.be/XV_iXPpHnaE?t=2553
- `kubectl` でAPI サーバから返される不正なリクエストエラーの表示が改善されました ([#112150](https://github.com/kubernetes/kubernetes/pull/112150), [liggitt](https://github.com/liggitt)) [sig/cli]
    - :memo: v1.21.0 ではいい感じのメッセージが表示されていたのが、v1.23.5 では `The request is invalid` と表示されるようになってしまっていたみたい
- Kubectl apply: kubectl は、namespace が指定され、allowlint が指定されていない場合に将来のリリースで non-namespaced リソースの `pv & namespace` が無視されるようになるという警告をするようになりました ([#110907](https://github.com/kubernetes/kubernetes/pull/110907), [pacoxu](https://github.com/pacoxu)) [sig/cli]
    - :memo: どうやら namespace を指定して `--prune` フラグ付きで実行しても non-namespaced リソースが取り除かれてしまっていたらしい
    - :memo: この挙動はおかしいので、v1.26 から警告メッセージを表示するようにし、v1.28 で挙動を変更する予定となっている
- Kubectl: `kubectl convert` が正しい API バージョンを選択しないバグが修正されました ([#112700](https://github.com/kubernetes/kubernetes/pull/112700), [SataQiu](https://github.com/SataQiu)) [sig/cli]
    - :memo: `extensions` API グループが先にインポートされていたことが原因のようなので、Ingress や Deployment でうまく変換できてなかったようです
- 同じ値で annotation を設定するとエラーになっていたのをやめてただ無視ようになりました ([#109505](https://github.com/kubernetes/kubernetes/pull/109505), [zigarn](https://github.com/zigarn)) [sig/cli]
    - :memo: `kubectl annotate` コマンドでの変更
- `kubectl` は出力でターミナルの特殊文字をエスケープするようになりました。これは CVE-2021-25743 の修正です。 ([#112553](https://github.com/kubernetes/kubernetes/pull/112553), [dgl](https://github.com/dgl)) [sig/cli,sig/security]
    - :memo: kubectl で `\r` がいくつかのサブコマンドで許可されていて、これは現在の行を置き換えるなどに使えて紛らわしいという問題があったよう。また、ターミナルエミュレータにバグがある場合により深刻な攻撃を付ける可能性があったみたい

### Other (Cleanup or Flake)（そのほか）

- `kubectl apply --prune` で使用できる `--prune-allowlist` フラグが追加されました。このフラグは非推奨の `--prune-whitelist` フラグを置き換えるもので、同じように機能します。 ([#113116](https://github.com/kubernetes/kubernetes/pull/113116), [brianpursley](https://github.com/brianpursley)) [sig/cli]
    - :memo: `--prune-allowlist` は `--prune` の対象となるリソースを明示的に指定するフラグで、指定しない場合はハードコードされたいくつかのリソースが対象になる
- 次の `kubectl run` のフラグを非推奨とし、設定しても無視されるようになりました: `--cascade`, `--filename`, `--force`, `--grace-period`, `--kustomize`, `--recursive`, `--timeout`, `--wait` ([#112261](https://github.com/kubernetes/kubernetes/pull/112261), [brianpursley](https://github.com/brianpursley)) [sig/cli]