はじめに
OKE(Container Engine for Kubernetes)のWorker Nodeとして通常のオンデマンド・インスタンスの他に、プリエンプティブル・インスタンスも利用できるようになりました。
プリエンプティブル・インスタンスは、通常のオンデマンド・インスタンスとできることは同じですが、他のユーザがそのインスタンスのリソースを使用しようとした場合に、インスタンスが停止されてしまいます。
その代わり、オンデマンド・インスタントと比べてコストが半分になります。
AWSだとスポットインスタンスに相当するものですね。
プリエンプティブル・インスタンスの設定
OKEのWorker Nodeにプリエンプティブル・インスタンスを使用する場合、クラスタの新規作成と追加の2通りがあります。
新規作成
新規作成時にプリエンプティブル・インスタンスを使用する場合は、カスタム作成で作る必要があります。
ノードプールの作成画面で配置構成
の拡張オプションを表示させて、容量タイプでプリエンプティブル容量
を選択します。
追加
作成済みのクラスタにノードプールを追加する際に、プリエンプティブル・インスタンスを追加できます。
なお、ノードプール内にオンデマンド・インスタンスとプリエンプティブル・インスタンスを混在できますが、管理のことを考えると、ノードプール内ではインスタンスタイプを統一しておいた方がいいと思います。
また、一つ以上のノードプールはオンデマンド・インスタンスで構成した方が良いでしょう。マニュアルにもベストプラクティスとして書かれています。
今回はオンデマンド・インスタンスのノードプール(pool1)にプリエンプティブル・インスタンスのノードプール(pool2)を追加します。
新規作成と同様に拡張オプションを表示させて、プリエンプティブル容量
を選択します。
追加されたインスタンスをコンソールで確認すると、容量タイプがプリエンプティブル
となっています。
確認
クラスタ上でノードを確認します。
プリエンプティブル・インスタンスにはLabelとTaintが設定されています。
$ k describe nodes 10.0.10.216 |grep preemptible
oci.oraclecloud.com/oke-is-preemptible=true
Taints: oci.oraclecloud.com/oke-is-preemptible:NoSchedule
$ k get node -L oci.oraclecloud.com/oke-is-preemptible
NAME STATUS ROLES AGE VERSION OKE-IS-PREEMPTIBLE
10.0.10.152 Ready node 44h v1.26.2
10.0.10.216 Ready node 7m47s v1.26.2 true
Podのデプロイ
DeploymentでPodをデプロイします。
Taintが設定されているので、オンデマンド・インスタンスの方だけにPodがデプロイされていますね。
$ k create deployment nginx --image nginx --replicas 4
deployment.apps/nginx created
$ k get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-748c667d99-cxgw7 1/1 Running 0 12s 10.244.0.12 10.0.10.152 <none> <none>
nginx-748c667d99-g5qd6 1/1 Running 0 13s 10.244.0.9 10.0.10.152 <none> <none>
nginx-748c667d99-gl5n7 1/1 Running 0 12s 10.244.0.10 10.0.10.152 <none> <none>
nginx-748c667d99-jmjqq 1/1 Running 0 12s 10.244.0.11 10.0.10.152 <none> <none>
一旦削除します。
$ k delete deployments.apps nginx
deployment.apps "nginx" deleted
Tolerationを設定して、プリエンプティブル・インスタンスにもPodがデプロイされるようにします。
apiVersion: apps/v1
kind: Deployment
metadata:
creationTimestamp: null
labels:
app: nginx-tolerations
name: nginx-tolerations
spec:
replicas: 4
selector:
matchLabels:
app: nginx-tolerations
strategy: {}
template:
metadata:
creationTimestamp: null
labels:
app: nginx-tolerations
spec:
containers:
- image: nginx
name: nginx
resources: {}
tolerations:
- key: "oci.oraclecloud.com/oke-is-preemptible"
operator: "Exists"
effect: "NoSchedule"
status: {}
$ k apply -f nginx-tolerations.yaml
deployment.apps/nginx-tolerations created
$ k get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-tolerations-6f5b554fbc-cxwfb 1/1 Running 0 24s 10.244.0.134 10.0.10.216 <none> <none>
nginx-tolerations-6f5b554fbc-dq425 1/1 Running 0 24s 10.244.0.133 10.0.10.216 <none> <none>
nginx-tolerations-6f5b554fbc-mxsvg 1/1 Running 0 24s 10.244.0.14 10.0.10.152 <none> <none>
nginx-tolerations-6f5b554fbc-wwghl 1/1 Running 0 24s 10.244.0.15 10.0.10.152 <none> <none>
今度はオンデマンド・インスタンス、プリエンプティブル・インスタンス両方にデプロイされましたね。
まとめ
プリエンプティブル・インスタンスはいつ落ちるかわかりませんので、インスタンスが落ちても業務が停止しないようにするには、クラスタの設計やDeploymentのreplicasの設定などに注意する必要がありますね。
とはいえ、物理環境に依存することなくコンテナを配置するのはCloud Nativeの基本といえば基本ですので、プリエンプティブル・インスタンスをうまく活用してコストを下げるのはアリかなと思います。
あと、プリエンプティブル・インスタンスがどのくらいの頻度で落ちるか気になるところですが、まだ落ちていないのでわからないですね。落ちたらクラスタやPodがどうなったか更新しようと思います。
(追記)落ちた時の動作
クラスタを作成して約24時間で2回落ちました。
これはリージョン(今回はLondonリージョン)やタイミングにも依存すると思いますので、あくまで一例として捉えていただければと思います。
こちらはプリエンプティブル・インスタンス停止と再作成のログです。
一番下の21:41
の停止は一回で再作成されました。
この場合は以下のように21:38
に停止して、21:41
に再作成が完了していますので、約3分ほど縮退していたことになります。
2回目は3:08
に停止しましたが、何度か再作成が失敗して、約2時間後に再作成が成功しています。失敗するたびに、再作成を開始する間隔が開くようです。
また、1分間隔でNodeとPodの状態を吐き出していました。
これをみると、プリエンプティブル・インスタンスを削除する前にdrainしてPodを逃してから、スケジューリング対象から外して、ノードを削除していることがわかります。
----
Mon Jun 12 03:07:30 GMT 2023
NAME STATUS ROLES AGE VERSION
10.0.10.152 Ready node 2d18h v1.26.2
10.0.10.175 Ready node 5h26m v1.26.2
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-tolerations-6f5b554fbc-4tltw 1/1 Running 0 4h4m 10.244.1.10 10.0.10.175 <none> <none>
nginx-tolerations-6f5b554fbc-5hmvf 1/1 Running 0 4h4m 10.244.1.9 10.0.10.175 <none> <none>
nginx-tolerations-6f5b554fbc-86wrj 1/1 Running 0 4h4m 10.244.0.2 10.0.10.152 <none> <none>
nginx-tolerations-6f5b554fbc-pglxz 1/1 Running 0 4h4m 10.244.0.3 10.0.10.152 <none> <none>
----
Mon Jun 12 03:08:41 GMT 2023
NAME STATUS ROLES AGE VERSION
10.0.10.152 Ready node 2d18h v1.26.2
10.0.10.175 Ready,SchedulingDisabled node 5h27m v1.26.2
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-tolerations-6f5b554fbc-76b28 1/1 Running 0 58s 10.244.0.4 10.0.10.152 <none> <none>
nginx-tolerations-6f5b554fbc-86wrj 1/1 Running 0 4h5m 10.244.0.2 10.0.10.152 <none> <none>
nginx-tolerations-6f5b554fbc-pglxz 1/1 Running 0 4h5m 10.244.0.3 10.0.10.152 <none> <none>
nginx-tolerations-6f5b554fbc-pv26h 1/1 Running 0 58s 10.244.0.5 10.0.10.152 <none> <none>
・・・
----
Mon Jun 12 03:12:12 GMT 2023
NAME STATUS ROLES AGE VERSION
10.0.10.152 Ready node 2d19h v1.26.2
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-tolerations-6f5b554fbc-76b28 1/1 Running 0 4m30s 10.244.0.4 10.0.10.152 <none> <none>
nginx-tolerations-6f5b554fbc-86wrj 1/1 Running 0 4h9m 10.244.0.2 10.0.10.152 <none> <none>
nginx-tolerations-6f5b554fbc-pglxz 1/1 Running 0 4h9m 10.244.0.3 10.0.10.152 <none> <none>
nginx-tolerations-6f5b554fbc-pv26h 1/1 Running 0 4m30s 10.244.0.5 10.0.10.152 <none> <none>