以下の内容はhttps://kakakakakku.hatenablog.com/entry/2020/12/28/013440より取得しました。


Pod に「優先度」を設定できる PriorityClass と Non-preempting 機能を試した

Kubernetes の「PriorityClass」を使うと Pod に優先度(プライオリティ)を設定できる.例えば,通常 Pod を起動するために必要なリソースを確保できない場合は Pending になるけど,そういう場合でも優先的に起動できるようになる.逆に「優先度を低くした待機用 Pod」を使ってノードを多めに起動しておく「オーバープロビジョニング」という活用法にも繋がる.今回は「PriorityClass」を試していく.

kubernetes.io

検証環境

今回は Docker Desktop for MacKubernetes 1.19.3 を使う.検証をシンプルにするために「1 ノード」そして「メモリ 2 GB」にした.

$ kubectl describe nodes | egrep 'Capacity:|Allocatable:|memory:'
Capacity:
  memory:             2035604Ki
Allocatable:
  memory:             1933204Ki

「PriorityClass」設定なし

まず,以下のようなマニフェスト deployment-row.yaml を作る.「メモリ 500 MB」を要求する Pod を3個起動する Deployment とした.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: sandbox-priority-class-row-nginx
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
        - name: nginx
          image: nginx:1.19-alpine
          resources:
            requests:
              memory: "500Mi"
          ports:
            - containerPort: 80

マニフェストを適用すると,期待通りに Pod を起動できた.

$ kubectl apply -f deployment-row.yaml
deployment.apps/sandbox-priority-class-row-nginx created

$ kubectl get pods
NAME                                               READY   STATUS    RESTARTS   AGE
sandbox-priority-class-row-nginx-99fd6b465-9vhsv   1/1     Running   0          10s
sandbox-priority-class-row-nginx-99fd6b465-hg9ch   1/1     Running   0          10s
sandbox-priority-class-row-nginx-99fd6b465-zhv7b   1/1     Running   0          10s

ほぼ同じマニフェスト deployment-high.yaml をもう1個作る.今回は replicas: 1 にした.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: sandbox-priority-class-high-nginx
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
        - name: nginx
          image: nginx:1.19-alpine
          resources:
            requests:
              memory: "500Mi"
          ports:
            - containerPort: 80

同じくマニフェストを適用すると,メモリを確保することができず Pending になった.「PriorityClass」設定なしだと,期待通りの挙動になる.2種類の Deployment を削除しておく.

$ kubectl apply -f deployment-high.yaml
deployment.apps/sandbox-priority-class-high-nginx created

$ kubectl get pods
NAME                                                READY   STATUS    RESTARTS   AGE
sandbox-priority-class-high-nginx-99fd6b465-5rcpm   0/1     Pending   0          10s
sandbox-priority-class-row-nginx-99fd6b465-9vhsv    1/1     Running   0          2m
sandbox-priority-class-row-nginx-99fd6b465-hg9ch    1/1     Running   0          2m
sandbox-priority-class-row-nginx-99fd6b465-zhv7b    1/1     Running   0          2m

$ kubectl delete -f deployment-high.yaml
deployment.apps "sandbox-priority-class-high-nginx" deleted

$ kubectl delete -f deployment-row.yaml
deployment.apps "sandbox-priority-class-row-nginx" deleted

「PriorityClass」設定あり

次に「PriorityClass」を作る.まずは「優先度:高」として使う high-priority.yaml を作る.値は 1000000 にした.値は「10億以下の整数値」を指定できて,大きいほど優先度が高くなる.今回はドキュメントにも載っている数値をそのまま使った.

apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
  name: high-priority
value: 1000000
globalDefault: false

もう1個「優先度 : 低」として使う row-priority.yaml を作る.値は -1 にした.

apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
  name: row-priority
value: -1
globalDefault: false

マニフェストを適用しておく.

$ kubectl apply -f high-priority.yaml
priorityclass.scheduling.k8s.io/high-priority created

$ kubectl apply -f row-priority.yaml
priorityclass.scheduling.k8s.io/row-priority created

次に Deployment に priorityClassName の指定を追加する.deployment-row.yaml「優先度 : 低」の Pod にする.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: sandbox-priority-class-row-nginx
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
        - name: nginx
          image: nginx:1.19-alpine
          resources:
            requests:
              memory: "500Mi"
          ports:
            - containerPort: 80
      priorityClassName: row-priority

deployment-high.yaml「優先度:高」の Pod にする.検証をする準備は整った.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: sandbox-priority-class-high-nginx
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
        - name: nginx
          image: nginx:1.19-alpine
          resources:
            requests:
              memory: "500Mi"
          ports:
            - containerPort: 80
      priorityClassName: high-priority

さっそくマニフェストを適用する.順番はさっきと同じく deployment-row.yamldeployment-high.yaml にする.ポイントは deployment-high.yaml を適用したときに既に起動していた sandbox-priority-class-row-nginx-65dbdbc8f4-bcxk5 が自動的に止まり,代わりに「優先度:高」sandbox-priority-class-high-nginx-868895ff4d-tz7cr が起動した.期待通りに動かせた!

$ kubectl apply -f deployment-row.yaml
deployment.apps/sandbox-priority-class-row-nginx created

$ kubectl get pods
NAME                                                READY   STATUS    RESTARTS   AGE
sandbox-priority-class-row-nginx-65dbdbc8f4-5gzkb   1/1     Running   0          30s
sandbox-priority-class-row-nginx-65dbdbc8f4-bcxk5   1/1     Running   0          30s
sandbox-priority-class-row-nginx-65dbdbc8f4-jnxj9   1/1     Running   0          30s

$ kubectl apply -f deployment-high.yaml
deployment.apps/sandbox-priority-class-high-nginx created

$ kubectl get pods
NAME                                                 READY   STATUS    RESTARTS   AGE
sandbox-priority-class-high-nginx-868895ff4d-tz7cr   1/1     Running   0          20s
sandbox-priority-class-row-nginx-65dbdbc8f4-5gzkb    1/1     Running   0          2m
sandbox-priority-class-row-nginx-65dbdbc8f4-87q8r    0/1     Pending   0          20s
sandbox-priority-class-row-nginx-65dbdbc8f4-jnxj9    1/1     Running   0          2m

また2種類の Deployment を削除しておく.

$ kubectl delete -f deployment-high.yaml
deployment.apps "sandbox-priority-class-high-nginx" deleted

$ kubectl delete -f deployment-row.yaml
deployment.apps "sandbox-priority-class-row-nginx" deleted

Non-preempting 機能 : プリエンプトしない(削除しない)

Feature Gates を確認すると NonPreemptingPriority という機能が Kubernetes 1.19 に Beta としてデフォルトで使えるようになっている.「プリエンプト」とは「Pod を削除すること」を意味していて,簡単に言えば「PriorityClass」を使っても「実行中の Pod は削除せず」スケジューリング待ちの中で優先度を高くする.さっそく試していく.

kubernetes.io

high-priority.yaml をベースに新しく high-priority-nonpreempting.yaml を作る.1箇所 preemptionPolicy: Never を追加した.これで「プリエンプトしない」ことを宣言できる.

apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
  name: high-priority-nonpreempting
value: 1000000
preemptionPolicy: Never
globalDefault: false

次に deployment-high.yamlpriorityClassNamehigh-priority-nonpreempting に変えて,同じように deployment-row.yamldeployment-high.yaml の順番でマニフェストを適用する.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: sandbox-priority-class-high-nginx
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
        - name: nginx
          image: nginx:1.19-alpine
          resources:
            requests:
              memory: "500Mi"
          ports:
            - containerPort: 80
      priorityClassName: high-priority

結果としては「PriorityClass」設定なしと同じになる.他にもスケジューリング待ちの Pod があれば,効果が出てくる.

$ kubectl apply -f deployment-row.yaml
deployment.apps/sandbox-priority-class-row-nginx created

$ kubectl get pods
NAME                                                READY   STATUS    RESTARTS   AGE
sandbox-priority-class-row-nginx-65dbdbc8f4-8vh5d   1/1     Running   0          10s
sandbox-priority-class-row-nginx-65dbdbc8f4-dbgxr   1/1     Running   0          10s
sandbox-priority-class-row-nginx-65dbdbc8f4-srd7c   1/1     Running   0          10s

$ kubectl apply -f deployment-high.yaml
deployment.apps/sandbox-priority-class-high-nginx created

$ kubectl get pods
NAME                                                READY   STATUS    RESTARTS   AGE
sandbox-priority-class-high-nginx-5dbccfd9f-s8trp   0/1     Pending   0          10s
sandbox-priority-class-row-nginx-65dbdbc8f4-8vh5d   1/1     Running   0          40s
sandbox-priority-class-row-nginx-65dbdbc8f4-dbgxr   1/1     Running   0          40s
sandbox-priority-class-row-nginx-65dbdbc8f4-srd7c   1/1     Running   0          40s

ドキュメントを読むと「Non-preempting 機能」のユースケースとして「データサイエンス」の例が載っていた.処理中の計算は無駄にせず継続しながら,その後は優先度を適用していく.良さそう!

An example use case is for data science workloads. A user may submit a job that they want to be prioritized above other workloads, but do not wish to discard existing work by preempting running pods.

まとめ

Kubernetes の「PriorityClass」を使って Pod に優先度(プライオリティ)を設定できることを確認した.また preemptionPolicy を指定して「プリエンプトしない」PriorityClass を宣言できることも確認した.覚えておこう!




以上の内容はhttps://kakakakakku.hatenablog.com/entry/2020/12/28/013440より取得しました。
このページはhttp://font.textar.tv/のウェブフォントを使用してます

不具合報告/要望等はこちらへお願いします。
モバイルやる夫Viewer Ver0.14