1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

OpenShift上のQuakurs APIアプリケーションのパフォーマンス検証手順

1
Posted at

はじめに

これから開発するアプリケーションをKubernetes/OpenShiftにデプロイした際、アプリケーションのPodでどの程度のCPU・メモリが使用されるかを見積もるにはどうすればよいでしょうか。最も確実な方法は、実環境で動作させて検証することだと思います。ただし、アプリケーションはこれから開発するため、実際には何らかのサンプルアプリケーションを作成してパフォーマンス検証を実施することになると思います。

当記事では、IBM CloudのマネージドOpenShift(Red Hat OpenShift on IBM Cloud)に、JavaフレームワークのQuarkusで作成したサンプルAPIアプリケーションをデプロイし、そのアプリケーションのパフォーマンス検証(スループット、PodのCPU・メモリ使用量の確認)を実施したときの手順を示します。

パフォーマンス検証のための負荷ツールはLocustを使用します。

前提環境

  • IBM Cloudが使用可能であること
  • Red Hat OpenShift on IBM Cloud 4.12
  • Quarkus 3.2.4 Final
  • Locust 2.16.1

QuarkusでのサンプルAPIアプリケーションの作成

まず、サンプルのAPIアプリケーションをQuarkusで作成します。

QuarkusのCLIをインストールします。
Quarkus CLIインストール手順

Quarkus CLIでアプリケーションの雛形を作成します。

quarkus create app openshift-performance-sample
cd openshift-performance-sample

src/main/java/org/acme/GreetingResource.javaを以下のように編集します。コードの内容は以下の通りです。

  • /greeting/heavyというエンドポイントを用意(executeHeavyProcessing()メソッド)
  • executeHeavyProcessing()メソッドでは、インスタンス変数processingTimeナノ秒の間、ループを回す(各ループでは10ミリ秒未満のスリープを入れる)
  • かかった処理時間を含むメッセージを戻り値として返す

ループを入れているのは、何も処理が無ければAPIが一瞬で終了してしまうためです。スリープだけさせるとCPU負荷も全くかからないため、指定時間だけループさせています(この部分は改善の余地あり)。

GreetingResource.java
package org.acme;

import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.core.MediaType;
import org.eclipse.microprofile.config.inject.ConfigProperty;

import java.util.Random;

@Path("/greeting")
public class GreetingResource {

    @ConfigProperty(name = "processing.time", defaultValue = "100000000")
    long processingTime;

    @GET
    @Produces(MediaType.TEXT_PLAIN)
    @Path("/heavy")
    public String executeHeavyProcessing() throws Exception {
        long startTime = System.nanoTime();
        Random random = new Random();

        while (System.nanoTime() - startTime < processingTime) { // 100 ms
            Thread.sleep(random.nextInt(10));
        }

        long endTime = System.nanoTime();
        double duration = (endTime - startTime) / 1_000_000.0; // ms

        String message = "処理時間 : " + duration + " ms";
        System.out.println(message);

    	return message;
    }
}

上記のコードのインスタンス変数processingTimeでは、@ConfigPropertyを用いて、値を設定ファイルや環境変数から変更可能にしています。

Quarkusの設定ファイルであるsrc/main/resources/application.propertiesで、値を設定します(デフォルト値と同じなのであまり意味はないですが)。実際には、OpenShift上で環境変数を設定し、値を変更できるようにすることを目的としています。

application.properties
processing.time=100000000

では、アプリケーションの稼働を確認してみます。以下のコマンドで開発モードで起動します。

quarkus dev

標準でポート8080で起動するため、APIのエンドポイントである/greeting/heavyにcurlコマンドでアクセスしてみます。

❯ curl http://localhost:8080/greeting/heavy                                    
処理時間 : 104.354125 ms

正常にアクセスできることが確認できました。

OpenShiftへのデプロイ

次に、作成したAPIアプリケーションをコンテナ化し、OpenShiftにデプロイします。

コンテナイメージを作成するため、QuarkusのExtension container-image-docker を追加します。

quarkus extension add 'container-image-docker'

コンテナイメージをビルドします。

# 通常はこちらのコマンドでOK
./mvnw clean package -Dquarkus.container-image.build=true -DskipTests=true

# M1/M2 Macなど、arm64 CPUを使用している場合は以下のコマンドを実行
# アプリケーションはビルド済みであることが前提
docker image build --platform linux/amd64 -f src/main/docker/Dockerfile.jvm .

作成されたイメージを確認し、イメージの repository, tag を確認します。

❯ docker images                                                                   
REPOSITORY                                                   TAG              IMAGE ID       CREATED        SIZE
imanishi/openshift-performance-sample                        1.0.0-SNAPSHOT   57b1af7ae5a6   24 hours ago   434MB

IBM CloudのコンテナレジストリであるIBM Cloud Container Registryに、作成したイメージをpushします。

# IBM Cloud Container Registryにpushするために、IBM Cloudにログイン
# リージョンは東京、リソースグループはDefaultを指定
ibmcloud login -a https://cloud.ibm.com -r jp-tok -g Default

# IBM Cloud Container Registryのリージョンをap-north(東京)に設定
ibmcloud cr region-set ap-north

# Container Registryにログイン
ibmcloud cr login

# Container Registryに名前空間「openshift-performance-sample」を作成
# この名前空間にイメージをpushする
ibmcloud cr namespace-add openshift-performance-sample

# docker tagコマンドで、作成したQuarkusのコンテナイメージを、Container Registryにpushできるようにタグ付け
# 「jp.icr.io/<名前空間>(先ほど作成したopenshift-performance-sample)/<イメージ名>:<タグ>」
# 「jp.icr.io」は東京リージョンのContainer Registryのホスト名
docker tag <OSユーザ名>/openshift-performance-sample:1.0.0-SNAPSHOT jp.icr.io/openshift-performance-sample/openshift-performance-sample:0.1

# Container Registryにpush
docker push jp.icr.io/openshift-performance-sample/openshift-performance-sample:0.1

# openshift-performance-sample名前空間にpushされていることを確認する
ibmcloud cr image-list --restrict openshift-performance-sample

次はOpenShiftへのデプロイの準備を実施します。OpenShift上に、Quarkusアプリケーションをデプロイするプロジェクト(名前空間)を作成します(ocコマンドが使えるように oc login が実行済みであることが前提)。

# プロジェクトを作成
oc new-project openshift-performance-sample

# 作成したプロジェクトを処理対象プロジェクトとして設定
oc project openshift-performance-sample

作成したプロジェクトでIBM Cloud Container Registryからイメージをpullできるよう、defaultプロジェクトからimagePullSecret(all-icr-io)をコピーします。

oc get secret all-icr-io -n default -o yaml | sed 's/default/openshift-performance-sample/g' | oc create -n openshift-performance-sample -f -

次に、コンテナをデプロイするためのマニフェストファイルを作成します。

Deploymentでは、PodにCPU・メモリの上限を設定するため、resources.limits.cpu500mresources.limits.memory256Miを設定します。また、APIの処理時間を環境変数PROCESSING_TIMEとして与えます。設定値はConfigMapから取得しています。なお、@ConfigPropertyを使用した値の設定については、Quarkus設定リファレンスガイドも適宜参照ください。

deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: openshift-performance-sample
spec:
  selector:
    matchLabels:
      app: openshift-performance-sample
  replicas: 1
  template:
    metadata:
      labels:
        app: openshift-performance-sample
    spec:
      containers:
        - name: openshift-performance-sample
          image: jp.icr.io/openshift-performance-sample/openshift-performance-sample:0.1
          resources:
            limits:
              memory: "256Mi"
              cpu: "500m"
          ports:
            - containerPort: 8080
          env:
            - name: PROCESSING_TIME
              valueFrom:
                configMapKeyRef:
                  name: openshift-performance-sample
                  key: processing-time
      imagePullSecrets:
        - name: all-icr-io

ConfigMapのマニフェストファイルです。環境変数PROCESSING_TIMEに与える値を設定します。

configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: openshift-performance-sample
data:
  processing-time: "500000000"

Serviceのマニフェストファイルです。ポート8080で公開されているQuarkusアプリを、ポート80で公開するようにします。

service.yaml
apiVersion: v1
kind: Service
metadata:
  name: openshift-performance-sample
spec:
  selector:
    app: openshift-performance-sample
  ports:
    - protocol: TCP
      port: 80
      targetPort: 8080
  type: NodePort

各マニフェストファイルをoc applyし、さらにServiceをoc exposeしてRouteを作成し、外部からアクセスできるようにします。

oc apply -f manifest/configmap.yaml
oc apply -f manifest/deployment.yaml
oc apply -f manifest/service.yaml

oc expose svc/openshift-performance-sample

作成したRouteの情報を確認します。openshift-performance-sample-xxxxxxxxx.jp-tok.containers.appdomain.cloud のようなホスト名が取得できます。

oc get route

取得したホスト名に、APIエンドポイント/greeting/heavyを付けてcurlでアクセスします。なお、oc exposeではHTTPのRouteが作成されます。

❯ curl -w "\n" http://openshift-performance-sample-xxxxxxxxx.jp-tok.containers.appdomain.cloud/greeting/heavy
処理時間 : 502.130118 ms

ここまでで、QuarkusのAPIアプリケーションを、処理時間を500ms(0.5秒)に設定してOpenShiftにデプロイすることができました。

Locustによる負荷

ここからはLocustを使って負荷をかけていきます。locustfile.pyというファイルを作成し、以下のシナリオを記述します。単純に/greeting/heavyにアクセスして終了するというものになります。ユーザ数やホスト名はLocustの実行時に設定するため、シナリオ中には含めていません。

locustfile.py
from locust import HttpUser, task

class OpenShiftPerformanceSample(HttpUser):
    @task
    def greeting_heavy(self):
        self.client.get("/greeting/heavy")

Locustをポート3000で起動します。-fオプションで上記のlocustfile.pyを指定しています。

locust --web-port 3000 -f locustfile.py 

http://localhost:3000にブラウザでアクセスすると以下のような画面が表示されます。各項目に以下の値を入力し、「Start swarming」ボタンをクリックすることで実行が開始されます。

  • Number of users:負荷をかけるユーザ数
  • Spawn rate:1秒あたりのユーザ増加数。「Number of users」で設定したユーザ数まで、1秒ごとにここで設定したユーザ数が増えていく
  • Host:負荷をかける対象のホスト名(http://、または、https://を含めて記述)
    2023-08-15 at 23.20.24@2x.png

負荷をかけ始めると、全体のサマリーとして以下のような表形式で状況が表示されます。リクエスト総数、エラー数、レスポンスタイム、スループット(RPS)などが表示されます。
2023-08-15 at 23.21.18@2x.png

「Charts」タブを選択すると、スループットやレスポンスタイムの状況がグラフとして表示されます。
2023-08-15 at 23.22.45@2x.png

OpenShiftでのパフォーマンスモニタリング

それでは最後に、Locustで負荷をかけた状態で、Podがどの程度のCPU・メモリを使用しているかを確認します。

OpenShiftのWebコンソールで、Developer Pespective(以下のスクリーンショットでは「開発者向け表示」)を選択し、「モニタリング」をクリックすると、CPU・メモリなどのリソース状況を確認することができます。

「ダッシュボード」で「Kubernetes / Compute Resources / Workload」を選択し、デプロイしたDeploymentを選択します。
2023-08-18 at 00.16.53@2x.png

以下ではDeploymentと紐づくPodのCPUの使用状況が表示されています。500m(0.5)の上限を設定しましたが、実際に使用されているのは0.034程度で、上限に対して10%未満であることが分かります。
2023-08-18 at 00.17.09@2x.png

メモリの使用状況も同様に表示されています。上限256Miに対して、100MB程度(40%)が使用されていることが分かります。
2023-08-18 at 00.17.21@2x.png

今回は単純なサンプルAPIアプリケーションに対して単純な負荷をかけましたが、サンプルAPIの処理を変えたり、Podのレプリカ数を変えたり、Locustのユーザ数などを変えることで、様々なケースの負荷を試すことができます。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?