GKEでバースト可能なPodを使用する

記事タイトルとURLをコピーする

G-gen の佐々木です。当記事では GKE で新たにサポートされた バースト可能な Pod について解説します。
また、この機能のサポートに伴い、従来よりも小さい容量で Pod のリソースリクエストが可能になったので、こちらもあわせて紹介します。

Pod のバーストをサポートする GKE クラスタ

Pod のバースト

特定の条件(後述)を満たす GKE クラスタでは、ノード上で実行する Pod でバーストを使用することができます。

バースト可能な Pod は、Pod がリクエストするリソース(CPU、メモリなど)容量を超えて、ノード内のリソースを一時的に使用することができます。

小さいサイズの Pod

Pod のバーストをサポートする Autopilot モードのクラスタは、従来の Pod よりも少量のリソースリクエストで Pod を作成することができます。

従来のクラスタと、バースト可能な Pod を利用できるクラスタでリクエスト可能な CPU・メモリの最小容量は以下のようになっています。

リソース バーストをサポートするクラスタ バーストをサポートしていないクラスタ
CPU
(1,000m CPU = 1 vCPU)
50m CPU 250m CPU
メモリ 52MiB 512 MiB

なお、小さいサイズの Pod を使用する条件は「 使用する GKE クラスタでバーストがサポートされている」ことですが、小さいサイズで作成した Pod 自体がバースト可能(QoS が Burstable)である必要はありません。
つまり、バーストしない、小さいサイズの Pod を作成することも可能です。

GKE クラスタでバーストがサポートされる条件

Autopilot モードのクラスタの場合、以下のいずれかの条件を満たした場合にバーストがサポートされます。

  • コンピュートクラスPerformance もしくは Accelerator が設定されている Pod
  • (上記のコンピュートクラスを使用しない場合)現在の GKE クラスタのバージョンが 1.29.2-gke.1060000 以降、かつクラスタ作成時のバージョンが 1.26 以降のクラスタで実行される Pod

クラスタ作成時のバージョンは以下のコマンドで確認することができます。

# クラスタ作成時の GKE のバージョンを確認
$ gcloud container clusters describe {クラスタ名} \
    --location={クラスタのリージョン} \
    --format="value(initialClusterVersion)"

Standard モードのクラスタでは、GKE クラスタのバージョンを問わず、Pod のバーストがサポートされています。

メリット

コスト最適化

Pod のバーストや小さいサイズの Pod を利用するメリットとして、ノードのリソースを効率よく使用することができます。

Autopilot モードのクラスタでは、Pod がリクエストした CPU・メモリの量だけ料金が発生します。つまり、リクエストしたリソースが実際にフルで使用されなくても、フルで使用したぶんの料金が発生するということです。

Pod のバーストを使用することで、ある Pod の負荷が一時的に高まったときに、その Pod のリソースリクエストを増やすことで対処するのではなく、他の Pod がリクエストして使用していないリソースを借りることができます。

パフォーマンスの向上

Pod のバーストにより、予測できないワークロード負荷に対応しやすくなります。また、スケールアウト等で新しい Pod を起動する際に、一時的にリソースを多く使用することで、Pod の起動時間を短縮することができます。

バーストの仕組み

バーストで使用できるリソース容量

Autopilot モードのクラスタ

Autopilot モードのクラスタでは、システム Pod や DaemonSet を含む、同一ノード上のすべての Pod のリソースリクエストの合計から、現在実際に使用されているリソース容量を引いた値がバースト可能な容量となります。

バースト可能容量(Autopilot) = ノード上のすべての Pod のリソースリクエストの合計 - 現在使用されているリソース容量

例えば、以下の図の GKE クラスタで、Node-A 上の Pod(Pod-A-1)がバーストする場合を考えてみます。

Pod-A-1がバーストする場合に追加で使用できるCPUリソース

Node-A には 1~3 までの 3つの Pod があり、CPU リクエストの合計値は 1,200m CPU です。

Pod-A-1 がバーストするタイミングで、リクエストされている CPU のうち、Pod-A-1、Pod-A-2、Pod-A-3 が合計 800m CPU を使用していたとすると、バースト時に使用できる追加の CPU は 1,200 - 800 = 400m CPU となります。

Node-B 上の Pod(Pod-B-1、Pod-B-2、Pod-B-3)では合計 1,800m CPU がリクエストされており、そのうち 1,000m CPU が使用されています。したがって 800m CPU が余っている状態ですが、ノードが異なるため Pod-A-1 のバーストに使用することはできません。

バーストの最適化には、ポッドアフィニティを使用した Pod の配置先の調整や、DaemonSet を使用したリソースの確保などの工夫が必要となります。

Standard モードのクラスタ

Standard モードのクラスタでは、ノードとして実行されている Compute Engine VM の未使用リソースが、バーストで使用できるリソース容量となります。

バースト可能容量(Standard)= ノードの未使用リソース容量

バーストによってノード内のリソースが枯渇した場合

ノードで使用できる CPU リソースがバーストによって枯渇した場合、GKE は一部のコンテナの CPU 使用率を調整することで、すべてのコンテナが元々リクエストしていた CPU を使用できるようにします。

それに対して、ノードで使用できるメモリリソースがバーストによって枯渇した場合、GKE はコンテナを終了してメモリを再利用できるようにします。
Pod に設定された QoS が低く、リソースを大量に使用しているコンテナが優先的に終了されます。

したがって、メモリのバーストには極力依存せず、十分なメモリ容量のリクエストを設定しておくことが推奨されます。

また、バースト可能な Pod は QoS が Burstable に設定されるため、重要なコンテナを含む Pod は、より高い QoS である Guaranteed に設定しておきます。
バーストが使用できるクラスタでは、リソースリクエスト(requests)とリミット(limits)を同一の値にすることで、QoS が Guaranteed の Pod を実行することができます。

バースト可能な Pod を使用する

当記事で使用する GKE クラスタについて

当記事では Autopilot モードの GKE クラスタを使用します。

クラスタのコントロールプレーンとノードのバージョンは以下のようになっています。

MASTER_VERSION: 1.29.2-gke.1521000 
NODE_VERSION: 1.29.2-gke.1521000

使用するマニフェストファイル

burstable-pod.yaml

このマニフェストファイルでは、バースト可能な Pod として、最小の CPU・メモリ容量をリクエストする Pod を作成します。

# burstable-pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: burstable-pod
spec:
  containers:
    - name: burstable-pod
      image: nginx:1.25
      resources:
        requests:
          cpu: 50m
          memory: 52Mi
          ephemeral-storage: 10Mi
  

placeholder-daemon.yaml

このマニフェストファイルでは、ノードのリソースをある程度リクエストしておき、実際には何もしない Pod を作成します。 この Pod の CPU・メモリリクエスト - この Pod が実際に使用している CPU・メモリ ぶんのリソースが、burstable-pod.yaml で作成した Pod のバースト時に使用することができます。

DaemonSet として Pod を作成することで、実行されている全てのノードでバースト用のリソースを確保しておくことができます。
なお、Autopilot モードの場合は、実際にリソースが使用されていなくても、リクエストしたリソースの料金が発生する点は注意が必要です。

# placeholder-daemon.yaml
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: placeholder
  labels:
    app: placeholder
spec:
  selector:
    matchLabels:
      app: placeholder
  template:
    metadata:
      labels:
        app: placeholder
    spec:
      containers:
      - name: placeholder
        image: nginx:1.25
        resources:
          requests:
            cpu: 500m
  

バースト可能な Pod の作成

GKE クラスタにバースト可能な Pod のマニフェストファイルを適用します。

# バースト可能な Pod を作成する
$ kubectl apply -f burstable-pod.yaml
pod/burstable-pod created

Pod の作成後、QuS が Burstable になっていることを確認します。

# Pod の QuS を確認する
$ kubectl describe pod burstable-pod | grep -m 1 "QoS"
QoS Class:                   Burstable

Pod のリソースリクエストの値を確認します。
バースト可能な Pod の最小値が設定できていることがわかります。

# Pod のリソースリクエストを確認する
$ kubectl get pods burstable-pod -o json | jq '.spec.containers[0].resources.requests'
{
  "cpu": "50m",
  "ephemeral-storage": "10Mi",
  "memory": "52Mi"
}

バースト容量を確保する Pod の作成

この DaemonSet で作成される Pod は何も処理を行わず、リソースをほぼ使用しません。したがって、ここでリクエストしたリソースはburstable-pod のバースト時に代わりに使用できます。

# DaemonSet を作成する
$ kubectl apply -f placeholder-daemon.yaml
daemonset.apps/placeholder created
  
# burstable-pod と同じノードに Pod が作成されていることを確認する
$ kubectl get po -o wide
NAME                READY   STATUS    RESTARTS   AGE     IP             NODE                                                  NOMINATED NODE   READINESS GATES
burstable-pod       1/1     Running   0          2m18s   172.17.0.137   gk3-cluster-gke-public-129-aut-pool-2-b4bbb5d3-62bk   <none>           <none>
placeholder-9drqb   1/1     Running   0          12s     172.17.0.138   gk3-cluster-gke-public-129-aut-pool-2-b4bbb5d3-62bk   <none>           <none>
placeholder-bwnx2   1/1     Running   0          12s     172.17.0.202   gk3-cluster-gke-public-129-aut-pool-2-48addb14-h72h   <none>           <none>
placeholder-qm8qj   1/1     Running   0          12s     172.17.1.14    gk3-cluster-gke-public-129-aut-pool-2-af2c9a34-qsbl   <none>           <none>

Pod のバーストを確認

バースト可能な Pod にログインし、yes コマンドで負荷をかけることで、Pod をバーストさせてみます。

# Pod にログインする
$ kubectl exec -it burstable-pod -- /bin/bash
  
# Pod に負荷をかける
root@burstable-pod:/# yes > /dev/null

別ターミナルから、Pod のリソース使用状況を確認します。

CPU リクエスト 50m の Pod がバーストし、966m が使用されていることがわかります。
placeholder-daemon.yaml で作成した Pod の CPU リクエスト(500m)、およびシステム Pod の CPU リクエストのうち、これらの Pod で現在使用されていないぶんのリソースが、バーストした burstable-pod で使用されています。

# 別のターミナルから Pod のリソース使用状況を確認する
$ kubectl top pod burstable-pod
NAME            CPU(cores)   MEMORY(bytes)   
burstable-pod   966m         4Mi 

バーストの上限を設定する

burstable-pod.yaml に limits を追記

バースト可能な Pod のマニフェストファイルで resources.limits を設定することで、バーストの上限を設定することができます。

以下のマニフェストファイルでは、まず 50m CPU の Pod が作成され、バースト時には最大で 300m CPU まで CPU リソースを使用することができます。

# burstable-pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: burstable-pod
spec:
  containers:
    - name: burstable-pod
      image: nginx:1.25
      resources:
        requests:
          cpu: 50m
          memory: 52Mi
          ephemeral-storage: 10Mi
        limits:
          cpu: 300m  # バーストの上限
  

このマニフェストファイルで作成した Pod に負荷をかけてみると、resources.limits で指定した値までしか CPU が使用されていないことがわかります。

# Pod のリソース使用状況を確認する
$ kubectl top pod burstable-pod
NAME            CPU(cores)   MEMORY(bytes)   
burstable-pod   300m         3Mi

バーストが使用できるクラスタで QoS が Guaranteed の Pod を作成する

最後に、バーストが使用できるクラスタで、バーストを使用しない、QoS が Guaranteed に設定された Pod を作成します。
リソースの requestslimits の値を同一にする必要があります。

この Pod は、他の Pod がバーストしたことによってノード上のメモリの枯渇が起きた際に、終了対象として選択される優先度が低くなっています。

# guaranteed-pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: guaranteed-pod
spec:
  containers:
    - name: guaranteed-pod
      image: nginx:1.25
      resources:
        requests:
          cpu: 250m
          memory: 512Mi
        limits:  # requests と同一の値を設定する
          cpu: 250m
          memory: 512Mi
  

マニフェストファイルをクラスタに適用し、Pod の QoS を確認します。

# QoS が Guaranteed の Pod を作成する
$ kubectl apply -f guaranteed-pod.yaml
pod/guaranteed-pod created
  
# Pod の QuS を確認する
$ kubectl describe pod guaranteed-pod | grep -m 1 "QoS"
QoS Class:                   Guaranteed

参考リンク

佐々木 駿太 (記事一覧)

G-gen最北端、北海道在住のクラウドソリューション部エンジニア

2022年6月にG-genにジョイン。Google Cloud Partner Top Engineer 2024に選出。好きなGoogle CloudプロダクトはCloud Run。

趣味はコーヒー、小説(SF、ミステリ)、カラオケなど。