CKAD対策のために、kubectl runコマンドの--restart=~の挙動を調べてみた

# はじめに
認定アプリケーション開発者試験(CKAD)の勉強をするにあたって検索するとよく出てくる以下のサイトなどの演習問題をやっていると、Podを作るときに`--restart=Never`というオプションが結構出てきます。そこでこのオプションを付ける必要はあるのか、またどういうときに付けたほうがいいのかについて調べてみました。

- https://github.com/dgkanatsios/CKAD-exercises
- https://medium.com/bb-tutorials-and-thoughts/practice-enough-with-these-questions-for-the-ckad-exam-2f42d1228552

<!-- 各チャプター -->
# `--restart=~`オプションの挙動
まず[公式ドキュメント](https://kubernetes.io/docs/reference/generated/kubectl/kubectl-commands)の`kubectl run`の部分を確認すると以下のように書いてありました。
![restart1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2472147/0b54432c-2b80-0c4c-85d4-60a09370834a.jpeg)
これから、restartが取れる値は`Always,OnFailure,Never`の3つであることとデフォルト値が`Always`であることが分かります。

公式ドキュメントにはこれ以上の記載はなかったため調べてみると、restartポリシーの値によって作られるものの種類が変わるという記事が出てくるが、これはkubectlのバージョン1.18までの挙動であり1.19以降では何に設定してもPodが作成されます。([kubernetesのrestartPolicyを理解する](https://qiita.com/oguogura/items/2d7df2b645063dc47804)の記事に以前どう記載されていたかも載っていました)

```console
$ kubectl run nginx-always --image=nginx --restart=Always
$ kubectl run nginx-onfailure --image=nginx --restart=OnFailure
$ kubectl run nginx-never --image=nginx --restart=Never

# 全てPodで作成される
$ kubectl get po
NAME              READY   STATUS    RESTARTS   AGE
nginx-always      1/1     Running   0          2m50s
nginx-never       1/1     Running   0          2m16s
nginx-onfailure   1/1     Running   0          2m29s
```

以上から現在の`restart`の値の意味がよく分からなかったですが、もう少しだけ調べてみました。
`ls`で存在するディレクトリと存在しないディレクトリを指定してみます。

```console
# コマンドが成功
$ kubectl run busybox-always-ok --image=busybox --restart=Always -- ls /etc
$ kubectl run busybox-onfailure-ok --image=busybox --restart=OnFailure -- ls /etc
$ kubectl run busybox-never-ok --image=busybox --restart=Never -- ls /etc

# コマンドが失敗
$ kubectl run busybox-always-ng --image=busybox --restart=Always -- ls /notexist;
$ kubectl run busybox-onfailure-ng --image=busybox --restart=OnFailure -- ls /notexist;
$ kubectl run busybox-never-ng --image=busybox --restart=Never -- ls /notexist
```

作られたPodを確認してみます。

```console
$ kubectl get po
NAME                   READY   STATUS             RESTARTS   AGE
busybox-always-ok      0/1     CrashLoopBackOff   2          51s
busybox-always-ng      0/1     CrashLoopBackOff   1          29s
busybox-never-ok       0/1     Completed          0          46s
busybox-never-ng       0/1     Error              0          12s
busybox-onfailure-ok   0/1     Completed          0          51s
busybox-onfailure-ng   0/1     CrashLoopBackOff   1          19s
```

Alwaysはコマンドの成功失敗にかかわらずPodが再起動しています。それに対しOnFailureはコマンドが成功した場合は完了し、失敗した場合は再起動を行っています。Neverはコマンドが成功した場合は完了、失敗した場合もエラーのまま再起動を行わないことが分かります。

|  実行コマンド\\`--restart`  |  Always  |  OnFailure  |  Never  |
| ---- | ---- | ---- | ---- |
|  成功  |  再起動  |  完了  |  完了  |
|  失敗  |  再起動  |  再起動  |  完了(エラー)  |

デフォルトの`--restart=Always`のままにしておくと、正常に実行されていても`CrashLoopBackOff`と表示されてしまうため、多少時間がかかっても`--restart=Never`を付けたほうがyamlファイルの間違いなどにも気づきやすいかもしれないと思いました。

# `--restart=Never`を付けないといけない場合

`--restart=Never`を付けないといけない場合として、作ったnginxPodに別のPodからアクセスできるかを試したい場合などは付ける必要がありました。

```console
$ kubectl run nginx --image=nginx --port=80
$ kubectl get po -o wide
NAME    READY   STATUS    RESTARTS   AGE   IP          NODE             NOMINATED NODE   READINESS GATES
nginx   1/1     Running   0          77s   10.1.3.88   docker-desktop   <none>           <none>

# --restart=Neverを付ける必要がある
$ kubectl run busybox --image=busybox --restart=Never --rm -it -- sh -c "wget -O- 10.1.3.88"
Connecting to 10.1.3.88 (10.1.3.88:80)
writing to stdout
       ・
       ・
       ・
```

これに`--restart=Never(OnFailure)`を付けなかった場合、いくら待っても結果が返ってこなかったです。
おそらくコマンドを実行した後Podの再起動が始まってしまうため、いつまでもPodが完了せず結果が返ってこないのだと思います。

# 結論
`restart`オプションはつけなくていい場合も結構多いのですが`CrashLoopBackOff`の文字は試験中だと結構焦ってしまうため、CKADの試験に当たっては不安なら`--restart=Never`を付けたほうが無難かもしれないと思いました。