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

## はじめに

[1.11](https://qiita.com/superbrothers/items/f96229e1590d28206939) に続き、今回も Kubernetes 1.12 における SIG-CLI の取り組みについてまとめています。

- https://github.com/kubernetes/kubernetes/blob/master/CHANGELOG-1.12.md#sig-cli
- https://github.com/kubernetes/kubernetes/blob/master/CHANGELOG-1.12.md#sig-cli-1

**新たに追加されたコマンド**

- なし

**廃止予定のコマンド**

- なし

**廃止されたコマンド**

- なし

その他オプションの追加、削除などの変更は、https://github.com/superbrothers/kubectl-docs/compare/v1.11.0...v1.12.0 で確認できます。

## SIG-CLI の主な取り組み

SIG-CLI は、新しいプラグイン機構の実装とプラグイン作者のための CLI ライブラリの提供に注力し、加えてコードのリファクタリングに取り組みました。

:memo: kubectl 1.8-1.11 で提供されていたプラグイン機構は完全に廃止されました。1.12 から git-style (`kubectl-` から始まる実行ファイルを呼び出す) のプラグイン機能がアルファレベルとして新たに提供されています。`plugin.yaml` など実行ファイル以外に必要なファイルがなくなりとてもシンプルになりました。詳しくは下記ドキュメントを参照してください。

- [Extend kubectl with plugins \- Kubernetes](https://kubernetes.io/docs/tasks/extend-kubectl/kubectl-plugins/)

## SIG-CLI 主な変更点

### kubectl の新しいプラグイン機構に関連する sample-cli-plugin ステージングリポジトリと cli-runtime ステージングリポジトリが追加されました

:memo: cli-runtime リポジトリは、kubectl コマンドとプラグインの作成に利用できる Go のライブラリです。kubectl の共有オプションを簡単に追加したりできます。sample-cli-plugin リポジトリは、そのライブラリを利用したプラグインの実装サンプルです。

- [kubernetes/cli\-runtime: Set of helpers for creating kubectl commands and plugins\.](https://github.com/kubernetes/cli-runtime)
- [kubernetes/sample\-cli\-plugin: Sample kubectl plugin](https://github.com/kubernetes/sample-cli-plugin)

> Added a sample-cli-plugin staging repository and cli-runtime staging repository to help showcase the new kubectl plugins mechanism. ([#67938](https://github.com/kubernetes/kubernetes/pull/67938), [#67658](https://github.com/kubernetes/kubernetes/pull/67658), [@soltysh](https://github.com/soltysh))

## `kubectl patch` コマンドで `--local` オプションを正しく利用されていない問題が修正されました

:memo: `--local` はローカルのファイルのみで処理を完結するオプションですが、1.11までこのオプションを設定していても API サーバから API オブジェクトのスキーマを取得する処理が実行されてしまっていました。1.12からは完全にローカルで処理が完結するようになり、API サーバの接続情報が設定されていない環境でも `kubectl patch` コマンドが正しく利用できるようになりました。

```
$ kubectl patch -f deploy.yaml --patch "$(cat patch.yaml)" --local -o yaml
```

> kubectl patch now respects --local ([#67399](https://github.com/kubernetes/kubernetes/pull/67399), [@deads2k](https://github.com/deads2k))

## `kubectl apply` コマンドは、`--force` オプションによりイミュータブル（不変）フィールドの更新を含むマニフェストの適用でオブジェクトを再作成するようになりました

:memo: 1.11 までは Service オブジェクトの `spec.clusterIP` のようなイミュータブルなフィールドが更新されたマニフェストは、これまで `--force` オプションを付与していても `kubectl apply` コマンドで適用することができず、`kubectl replace` コマンドを `--force` オプションで実行する必要がありました。

> kubectl: When an object can't be updated and must be deleted by force, kubectl will now recreating resources for immutable fields.([#66602](https://github.com/kubernetes/kubernetes/pull/66602), [@dixudx](https://github.com/dixudx))

## `kubectl create {clusterrole,role}` コマンドの `--resources` オプションは、全てのリソースを指定するアスタリクス (`*`) をサポートしました

```
$ kubectl create clusterrole superrole --verb=get  --resource="*"
clusterrole.rbac.authorization.k8s.io/superrole created
```

> `kubectl create {clusterrole,role}`'s `--resources` flag now supports asterisk to specify all resources. ([#62945](https://github.com/kubernetes/kubernetes/pull/62945), [@nak3](https://github.com/nak3))

## `kubectl wait` コマンドは、セレクタに1つのオブジェクトも一致しなかったときに、エラーメッセージの出力と終了ステータス `1` で終了するようになりました

:memo: これまでは、何も出力されず終了ステータスが `0` となっていました。

```
$ kubectl wait deployment -l app=something-that-does-not-exist --for condition=available --timeout=5s
error: no matching resources found
$ echo $?
1
```

>  kubectl: the wait command now prints an error message and exits with the code 1, if there is no resources matching selectors ([#66692](https://github.com/kubernetes/kubernetes/pull/66692), [@m1kola](https://github.com/m1kola))

## `kubectl describe` コマンドで `command`, `args`, `env`, `annotations` で改行が含まれる場合にインデントされるようになりました

:memo: それらのフィールドには一般的に改行が含まれないと思いますが、もし改行が含まれていた場合でも表示上崩れることなくインデントされるようになりました。

> Kubectl now handles newlines for `command`, `args`, `env`, and `annotations` in `kubectl describe` wrapping. ([#66841](https://github.com/kubernetes/kubernetes/pull/66841), [@smarterclayton](https://github.com/smarterclayton))

## `kubectl patch` コマンドは、パッチ適用後に変化がない場合に終了コード `1` で終了しないようになりました

:memo: これまでパッチ適用後にマニフェストに変更がない場合に終了コード `1` でエラー扱いになっていましたが、1.12 から終了コード `0` で正常終了するようになりました。

> The `kubectl patch` command no longer exits with exit code 1 when a redundant patch results in a no-op ([#66725](https://github.com/kubernetes/kubernetes/pull/66725), [@juanvallejo](https://github.com/juanvallejo))

## `kubectl get events` コマンドの出力は、メッセージの表示を優先するように改善され、いくつかのフィールドが `-o wide` オプションに移行されました

:memo: `LAST SEEN`, `TYPE`, `REASON`, `KIND`, `MESSAGE` がデフォルトで表示されるように変更され、`-o wide` オプションを利用した場合のみ `SOURCE`, `SUBOBJECT`, `COUNT`, `FIRST SEEN` が表示されるようになりました。

> The output of `kubectl get events` has been improved to prioritize showing the message, and to move some fields to `-o wide`. ([#66643](https://github.com/kubernetes/kubernetes/pull/66643), [@smarterclayton](https://github.com/smarterclayton))

## `kubectl config set-context` コマンドは、現在のコンテキスト(current-context)の属性を変更する場合に、現在のコンテキスト名を渡す代わりに `--current` オプションを利用できるようになりました

:memo: これまで `kubectl config set-context` コマンドで現在のコンテキストの属性を変更する場合、現在のコンテキスト名を取得してそれを引数としていました。

```
# 現在のコンテキストの名前空間を `production` に変更する
$ kubectl config set-context $(kubectl config current-context) --namespace=production
```

1.12 から現在のコンテキストの属性を変更する場合は、現在のコンテキスト名を引数にする代わりに `--current` オプションを利用できるようになりました。

```
# 地味に便利になりました
$ kubectl config set-context --current --namespace=production
```

>  `kubectl config set-context` can now set attributes of the current context, such as the current namespace, by passing `--current` instead of a specific context name ([#66140](https://github.com/kubernetes/kubernetes/pull/66140), [@liggitt](https://github.com/liggitt))

## `kubectl delete` コマンドは、親オブジェクトを削除する際に子オブジェクトの削除を待つことがなくなりました

:memo: 1.11 までは子オブジェクトがまず削除され、親オブジェクトは最後に削除されるようになっていました。1.12 からは依存オブジェクトはクライアントサイドで削除されず、親オブジェクトのみを削除します。子オブジェクトの削除は、サーバサイドガベージコレクタによって行われるため問題ありません。

この変更は、1.11.1 のパッチリリースにも含まれています。 https://github.com/kubernetes/kubernetes/blob/release-1.11/CHANGELOG-1.11.md#other-notable-changes-2

> "kubectl delete" no longer waits for dependent objects to be deleted when removing parent resources ([#65908](https://github.com/kubernetes/kubernetes/pull/65908), [@juanvallejo](https://github.com/juanvallejo))

## `kubectl proxy` コマンドに Keep-Alive を有効する `--keepalive` オプションが追加されました

:memo: `--keepalive` オプションは、デフォルト `0s` で Keep-Alive が無効です。値は `time.Duration` となっています。 (e.g. 30s, 1m

> A new flag, `--keepalive`, has been introduced, for kubectl proxy to allow setting keep-alive period for long-running request. ([#63793](https://github.com/kubernetes/kubernetes/pull/63793), [@hzxuzhonghu](https://github.com/hzxuzhonghu))

## `--use-openapi-print-columns` オプションでオブジェクトの内容が表示されないバグが修正されました

:memo: `--use-openapi-print-columns` オプション自体はすでに廃止予定です。代わりに `--server-print` オプションを利用しましょう。

> kubectl: fixed a regression with --use-openapi-print-columns that would not print object contents ([#65600](https://github.com/kubernetes/kubernetes/pull/65600), [@liggitt](https://github.com/liggitt))

## Job オブジェクトに対する `kubectl get`、`kubectl describe` コマンドの出力は、進行状況と継続時間を強調するように改善されました

:memo: `kubectl get` コマンドでは、`COMPLETIONS` カラムに Succeeded, Completions, Parallelism の情報が表示されます。また `DURATION` カラムは継続時間 (`job.status.startTime` - `job.status.completionTime`) が表示されます。

```
$ kubectl get job pi
NAME      COMPLETIONS   DURATION   AGE
pi        3/1 of 3      14s        14s
```

`COMPLETIONS` カラムのフォーマットは次のようになっています。

```
COMPLETIONS
0/1        # completions nil or 1, succeeded 0
1/1        # completions nil or 1, succeeded 1
0/3        # completions 3, succeeded 1
1/3        # completions 3, succeeded 1
0/1 of 30  # parallelism of 30, completions is nil
```

:memo: `kubectl describe` コマンドでは、`Completed At` (完了時刻)、`Duration` (継続時間)の表示が追加されました。

```
Start Time:     Thu, 04 Oct 2018 18:53:51 +0900
Completed At:   Thu, 04 Oct 2018 18:54:05 +0900
Duration:       14s
```

> The display of jobs in `kubectl get` and `kubectl describe` has been improved to emphasize progress and duration. ([#65463](https://github.com/kubernetes/kubernetes/pull/65463), [@smarterclayton](https://github.com/smarterclayton))

## `kubectl describe persistentvolume` コマンドに CSI ボリュームの属性が追加されました

:memo: CSI ボリュームの属性は次のフィールドです。

```
$ kubectl explain pv.spec.csi.volumeAttributes
KIND:     PersistentVolume
VERSION:  v1

FIELD:    volumeAttributes <map[string]string>

DESCRIPTION:
     Attributes of the volume to publish.
```

> CSI volume attributes have been added to kubectl describe pv`. ([#65074](https://github.com/kubernetes/kubernetes/pull/65074), [@wgliang](https://github.com/wgliang))

## `kubectl describe persistentvolumeclaim` コマンドは、どの Pod によってマウントされているかを `Mounted By` フィールドで表示するようになりました

:memo: `pvc/task-pv-claim` をみると、`pod/task-pv-pod` によってマウントされていることがわかります。便利ですね。

```
$ kubectl get pv,pvc,po
NAME                              CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                   STORAGECLASS   REASON   AGE
persistentvolume/task-pv-volume   100Mi      RWO            Retain           Bound    default/task-pv-claim   manual                  2m2s

NAME                                  STATUS   VOLUME           CAPACITY   ACCESS MODES   STORAGECLASS   AGE
persistentvolumeclaim/task-pv-claim   Bound    task-pv-volume   100Mi      RWO            manual         85s

NAME              READY   STATUS    RESTARTS   AGE
pod/task-pv-pod   1/1     Running   0          42s
$ kubectl describe pvc task-pv-claim
Name:          task-pv-claim
Namespace:     default
StorageClass:  manual
Status:        Bound
Volume:        task-pv-volume
Labels:        <none>
Annotations:   kubectl.kubernetes.io/last-applied-configuration:
                 {"apiVersion":"v1","kind":"PersistentVolumeClaim","metadata":{"annotations":{},"name":"task-pv-claim","namespace":"default"},"spec":{"acce...
               pv.kubernetes.io/bind-completed: yes
               pv.kubernetes.io/bound-by-controller: yes
Finalizers:    [kubernetes.io/pvc-protection]
Capacity:      100Mi
Access Modes:  RWO
Events:        <none>
Mounted By:    task-pv-pod
```

> Running `kubectl describe pvc` now shows which pods are mounted to the pvc being described with the `Mounted By` field ([#65837](https://github.com/kubernetes/kubernetes/pull/65837), [@clandry94](https://github.com/clandry94))

## `kubectl create secret tls` コマンドは、プロセス置換(process substitution)引数から証明書と鍵ファイルを読み込むことができるようになりました

:memo: 次のような具合に利用できます。この例は単純化されていてこれだけみると意味がないように見えますが、実際には一時ファイルを作成せずに他のリソースから読み込みたいニーズがあるようです。

```
$ kubectl create secret tls test-secret --key <(cat hack/testdata/tls.key) --cert <(cat hack/testdata/tls.crt)
```

> `kubectl create secret tls` can now read certificate and key files from process substitution arguments ([#67713](https://github.com/kubernetes/kubernetes/pull/67713), [@liggitt](https://github.com/liggitt))

## `kubectl rollout status` コマンドは、タイムアウトせずに動作するようになりました

:memo: `kubectl rollout status` コマンドは、最新のロールアウトが完了するまで監視するコマンドですが、1.11 まで API のタイムアウトや LB のタイムアウトなど接続が切れてしまう問題がありました。1.12 では接続断から復旧するようになったことでタイムアウトせずに動作するようになりました。

> `kubectl rollout status` now works for unlimited timeouts. ([#67817](https://github.com/kubernetes/kubernetes/pull/67817), [@tnozicka](https://github.com/tnozicka))