kubernetes [Workloads APIs] のまとめ

# はじめに
[kubernetes 完全ガイド第二版](https://www.amazon.co.jp/Kubernetes%E5%AE%8C%E5%85%A8%E3%82%AC%E3%82%A4%E3%83%89-%E7%AC%AC2%E7%89%88-Top-Gear-%E9%9D%92%E5%B1%B1/dp/4295009792)を読んでいる中で
Workloads APIs(pod とか Deploymentとか)の種類が多くて混乱するのでまとめてみます。

# 対象読者
kubernetes 気になっている初心者エンジニア
※ 自分も実務でガッツリと触っておらず軽く触った程度なので、あくまで基本的な説明に留まります

# kubernetes とは？

https://qiita.com/MahoTakara/items/85096f8b2632c802ab22

kubenetes 自体の説明はこちらの記事に丸投げします。
簡単に言えば、サーバー等のインフラ周りとアプリケーションとの橋渡しをいい感じにしてくれる管理者のようなイメージ。
サーバーを運用する上では、可用性等を考え複数立ち上げるが、その複数をそれぞれ管理するのではなくまとめて操作できる。便利ですね。

# Workloads APIs
早速今回のメインのテーマである Workloads APIs についてまとめていきます。
これらはコンテナの実行に関するリソースの総称を指します。
まずはざっと一覧を。

- Pod
- ReplicaSet
- Deployment
- DaemonSet
- StatefulSet
- Job
- Cronjob

これらについて各自機能を見ていきます。
基本的には pod を単位にそれをどのように管理するか親要素が複数存在する構造です。 
たとえば、 Pod をどう扱うかによって、ReplicaSet, StatefulSet どちらを使用するか変わる、みたいな感じです。

# Pod
リソースの最小単位、この中に docker のコンテナを立てていきます。
1Pod 1コンテナが一般的なのかな。自分はその方が理解しやすいのでそう思っています。
完全ガイドの中ではいくつもデザインパターンが挙げられています。よち詳しく知りたい方は書籍を読んでみてください。

# ReplicaSet
Pod のレプリカを作成し、指定した数の Pod を維持し続けるリソースを指します。
```yaml
replicas: 3 # Pod を三つ維持
```
Pod の数は replicas という項目の設定で変えることができます。上記のように設定すると ReplicaSet は Pod を三つ保ち続けることを責務として稼働します。たとえば突然 Pod の一つが停止したとしても、ReplicaSet がそれを検知し新しく Pod を作成してくれます。

ではどうやってその Pod の種類を検知し監視しているのでしょうか?

```yaml
selector:
  matchLabels:
    app: sample-app
```

答えは ReplicaSet を apply する際に指定したラベルです。
このように定義することで ReplicaSet は `sample-app` というラベルがついた Pod の数を数えそれが指定された replicas の値に合うように維持します。

# Deployment
Deployment は複数の ReplicaSet を管理するリソースです。Pod は ReplicaSet が見てくれているのでさらに親要素は不要じゃないかと思うかもしれませんが、非常に重要なリソースです。

なぜなら、Deployment をデプロイすることによって、ローリングアップデートやロールバックを実現することができるからです。kubernetes の最も推奨されているコンテナの起動方法とされているそうです。

- ローリングアップデートとは
以下のようなフローを取ります。
  
  1. 新しい ReplicaSet を作成
  2. 新しい ReplicaSet 上のレプリカ数(Pod 数) を徐々に減らす
  3. 古い　ReplicaSet 上のレプリカ数(Pod 数) を徐々に増やす
  4. (2, 3) を繰り返す
  5. 古い ReplicaSet はレプリカ数 0 で保持する   

つまり、 Pod 数を 0 にならないようにうまく少しづつアップデートしてくれます。一瞬でもサービス断が起きてしまったら嫌ですよね。特に商用環境において。

### Deployment のアップデート戦略
spec.stratery.type の値を変えることでアップデート戦略を変えることができます。

- Recreate
一度全ての Pod を削除してから再度 Pod を作成します。そのためダウンタイムが発生します。メリットは余分なリソースを使わない点、切り替え完了が早い点が挙げられます。

- RollingUpdate
defalut はこちら。先ほど記載したローリングアップデートを実施してくれます。option で不足　Pod 数と超過 Pod 数を設定することができます。
 

# DaemonSet
ReplicaSet の特殊な形とも言える DeamonSet は各ノードに一つずつ pod を配置するリソースです。ノードを増やした際にも自動的にそのノードに Pod を作成してくれます。

linux 等の os でもユーザーが意識することがないような裏の部分で動いているものをデーモンと呼びますね。この際のデーモンの意味は悪魔ではなく守護神という意味です。

kubernetes では全ノードでかならず動作させたいプロセスのために使うことが有用だと言われています。

### DaemonSet のアップデート戦略
こちらも2種類から選択可能です。

- OnDelete
DaemonSet のマニフェストを変更してイメージ等を差し替えたとしても既存の Pod のアップデートは行いません。任意のタイミングでしかアップデートされないような仕組みです。

- RollingUpdate
こちらが defaultです。Deployment と同様なローリングアップデートを行うことができます。ただ、 DaemonSet は1ノードに複数の同一 Pod を作成することはできないため、超過 Pod 数は設定することはできません。一度に停止可能な Pod 数のみを設定してローリングアップデートを行います。 

# StatefulSet
これも ReplicaSet の亜種のようなものです。データベースのデータなど、絶対に消えたら困るデータを state として保持してくれるリソースです。(永続化領域を確保)

StatefulSet が以下のリソースを作って永続化領域を確保している
persistentVolumeClaim (PersistentVolume 要求)
persistentVolume (永続化領域)

### StatefulSet のライフサイクル
複数の pod を並行して作成することはせず、一つずつ pod を作成します。しかし、設定で並列作成も可能です。

### StatefulSet のアップデート戦略
こちらも2種類から選択可能です。
  - OnDelete
DaemonSet の onDelete 時と同様に pod の update は勝手には行いません。
  - RolingUpdate
こちらが default です。一つずつ Pod ごとにアップデートします。
particiton を設定することで全体の Pod のうちどの Pod まで更新するか指定できる。これによって全体に影響を与えることなく試しに一部分だけアップデートすることができます。

# Job
コンテナを利用して一回限りの処理を実行させるリソースです。 Pod の停止が正常終了と期待される用途に向いています。Job も Replicaset と同様に Pod を作成するリソースの一種です。なので Job も Pod の親のような立ち位置になります。

### restartPolicy による挙動の違い
Pod 内のプロセスが停止した後の挙動を設定によって変更できます。
こちらで`never`、 `onFailure` という2種類の設定ができます。
- never
pod 内のプロセスが停止すると、新規の pod が立ち上がり、　Job を続行しようとします。

-  onFailure
pod 内のプロセスが停止すると、同一の pod が再起動し、 Job を続行しようとします。永続化していない場合はデータも消失します。

### タスク型とワークキュー型の並列実行
Job を利用する際に用いるいくつかのパターンを紹介します。
completions / parallelism のデフォルトは 1 になります。

#### One Shot Task
```yaml
completions: 1 # 成功回数
parallelism: 1 # 並列で処理する個数
backoffLimit: 0 # 失敗許容回数
```
一回だけ実行するタスクになります。上記のように設定すると成功の有無にかかわらず、必ず一回だけ実行されます。

#### Multi Task
```yaml
completions: 5　 # 成功回数
parallelism: 3　 # 並列で処理する個数
backoffLimit: 5　 # 失敗許容回数
```
最初に3個 pod が作られ、その後全部成功した場合2つ作られます。確率が低い場合でもそのあと Pod は3つ作られないことに注意しましょう。

#### Multi WorkQueue
```yaml
# completions: 1　# 成功回数 (指定しない)
parallelism: 3　 # 並列で処理する個数
backoffLimit: 1 # 失敗許容回数
```
複数pod を作成し、そのうちどれか一つでも作成したら、それ以降 pod は作成しないようになります。

#### Single WorkQueue
```yaml
# completions: 1　# 成功回数 (指定しない)
parallelism: 1　 # 並列で処理する個数
backoffLimit: 1 # 失敗許容回数
```
一度正常終了するまで一個ずつ実行するワークキューになります。

# Cron Job
スケジュールされた時間に job を作成します。 Deployment と ReplicaSet との関係に似て Job を管理する親のような立ち位置になります。

# まとめ
- 以上 Workloads APIs まとめでした。書籍をもとにした情報なので、古くなっている部分あれば教えてください。今後また別の API カテゴリもまとめていきたいと思います。
- 書籍ではこの情報にさらに yaml を実際に `kubectl apply` することができるのでやってみるとより理解に繋がると思います。

# 引用
- [kubernetes 完全ガイド第二版](https://www.amazon.co.jp/Kubernetes%E5%AE%8C%E5%85%A8%E3%82%AC%E3%82%A4%E3%83%89-%E7%AC%AC2%E7%89%88-Top-Gear-%E9%9D%92%E5%B1%B1/dp/4295009792)