[Kubernetes]PriorityClassの動作を確認する

#はじめに
PriorityClassは、Podに優先度を設定します。PriorityClassの特徴として、デプロイ済みのPodに対しても優先度に応じて退避させることができます。

#PriorityClassの作成
まずはPriorityClassを作成します。今回は以下2つのPriorityClassを作成します。

```priorityClassHigh.yaml
apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
  name: high-priority
value: 100 #10億以下の整数値。大きいほど優先度が高い
globalDefault: false #trueにすると、PriorityClassを指定しないPodのデフォルト値になる
description: "This priority class should be used for XYZ service pods only." #任意の文字列
```

```priorityClassLow.yaml
apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
  name: low-priority
value: 10
globalDefault: false
description: "This priority class should be used for ABC service pods only."
```

このマニフェストをapplyします。

```
$ kubectl apply -f .
priorityclass.scheduling.k8s.io/high-priority created
priorityclass.scheduling.k8s.io/low-priority created
$ kubectl get priorityclasses.scheduling.k8s.io
NAME                      VALUE        GLOBAL-DEFAULT   AGE
high-priority             100          false            56s
low-priority              10           false            56s
system-cluster-critical   2000000000   false            109d
system-node-critical      2000001000   false            109d
```

#Podのデプロイと動作確認
優先度：high/low/設定なし の3つのPodで動作を確認します。

```nginx-high.yaml
apiVersion: v1
kind: Pod
metadata:
  name: nginx-high
spec:
  containers:
  - name: nginx-high
    image: nginx:latest
    resources:
      requests:
        cpu: 1500m
  priorityClassName: high-priority
```
```nginx-low.yaml
apiVersion: v1
kind: Pod
metadata:
  name: nginx-low
spec:
  containers:
  - name: nginx-low
    image: nginx:latest
    resources:
      requests:
        cpu: 1500m
  priorityClassName: low-priority
```
```nginx.yaml
apiVersion: v1
kind: Pod
metadata:
  name: nginx
spec:
  containers:
  - name: nginx
    image: nginx:latest
    resources:
      requests:
        cpu: 1500m
```

CPUのrequests（下限）を1.5コアにしています。workerノードのCPUは2コアですので、各Podは同時に共存できません。

##優先度の低い順
まずは優先度の低い順（設定なし -> low -> hige）でapplyします。その時のPodの状態遷移を別ターミナルで確認します。

```
$ kubectl get pod -w
NAME    READY   STATUS    RESTARTS   AGE
nginx   1/1     Running   0          22s
nginx-low   0/1     Pending   0          0s #kubectl apply -f nginx-low.yaml 実行
nginx-low   0/1     Pending   0          0s
nginx-low   0/1     Pending   0          0s
nginx       1/1     Terminating   0          27s
nginx       0/1     Terminating   0          28s
nginx       0/1     Terminating   0          33s
nginx       0/1     Terminating   0          33s
nginx-low   0/1     Pending       0          6s
nginx-low   0/1     ContainerCreating   0          6s
nginx-low   0/1     ContainerCreating   0          7s
nginx-low   1/1     Running             0          11s
nginx-high   0/1     Pending             0          0s #kubectl apply -f nginx-high.yaml 実行
nginx-high   0/1     Pending             0          0s
nginx-high   0/1     Pending             0          0s
nginx-low    1/1     Terminating         0          45s
nginx-low    0/1     Terminating         0          46s
nginx-low    0/1     Terminating         0          47s
nginx-low    0/1     Terminating         0          47s
nginx-high   0/1     Pending             0          2s
nginx-high   0/1     ContainerCreating   0          2s
nginx-high   0/1     ContainerCreating   0          3s
nginx-high   1/1     Running             0          7s
```

優先度が高いPodがapplyされるたびに、低いPodは退避（停止）してから優先度が高いPodがデプロイされます。
最終的には、一番優先度が高いnginx-highのみになります。

##優先度の高い順
今度は高い順（high -> low）でapplyします。同様に別ターミナルでPodの状態遷移を確認します。

```
$ kubectl get pod -w
NAME         READY   STATUS    RESTARTS   AGE
nginx-high   0/1     Pending   0          0s
nginx-high   0/1     Pending   0          0s
nginx-high   0/1     ContainerCreating   0          0s
nginx-high   0/1     ContainerCreating   0          1s
nginx-high   1/1     Running             0          6s
nginx-low    0/1     Pending             0          0s #kubectl apply -f nginx-low.yaml実行
nginx-low    0/1     Pending             0          0s
nginx-high   1/1     Terminating         0          53s #kubectl delete -f nginx-high.yaml実行
nginx-high   0/1     Terminating         0          54s
nginx-high   0/1     Terminating         0          64s
nginx-high   0/1     Terminating         0          64s
nginx-low    0/1     Pending             0          49s
nginx-low    0/1     ContainerCreating   0          49s
nginx-low    0/1     ContainerCreating   0          50s
nginx-low    1/1     Running             0          55s
```

優先度が高いPodが起動している状態で低いPodをapplyすると、リソースが足らない場合スケジューリングができませんので、Pendingで止まっています。
この状態で優先度が高いPodを停止すると、低いPodがスケジューリングされデプロイされます。

#まとめ
何回かに渡ってKubernetesのスケジューリング制御機能ついて確認してきました。

* [cordon](https://qiita.com/dingtianhongjie/items/b6c2f7e3c940eb3142f2)
    * ノードをスケジューリング対象から外す
* [nodeSelector/Node Affinity/Inter-Pod Affinityなど](https://qiita.com/dingtianhongjie/items/4c95b5564dd5f70d3e34)
    * Podデプロイ時にスケジューリングするノードを決める
* [Taints/Tolerations](https://qiita.com/dingtianhongjie/items/140c0d8025317b42aa36)
    * ノードに設定したTaintsを許容できるPodのみをノードが許可する
* PriorityClass（今回）
    * 優先度に応じてスケジューリングできるPodを決定する

機能が豊富でよくできてるなと思うのですが、動作を確認しただけでユースケースまでまだたどり着いていません。
設計や運用を通じて実際のユースケースも考えたいと思います。