blog

ソフトウェア開発|KubernetesでJavaサーバーレス関数を最適化する

Knativeでサーバーレス関数を実行する際に、より高速な起動とメモリフットプリントの削減を実現します。...

Oct 21, 2025 · 8 min. read
シェア

Kubernetesでサーバーレスファンクションを実行する際に、より高速なスタートアップとメモリフットプリントの削減を実現します。

使用する場合、何千ものアプリケーションを実行することでリソースを大量に消費するため、ワーカーノードやリソースフットプリントを少なくするほどコストが高くなるため、高速起動とメモリフットプリントの小ささが重要になります。Kubernetesプラットフォーム上でコンテナ化されたマイクロサービスを実行する場合、メモリフットプリントはスループットよりも重要な考慮事項です:

  • 継続的に実行する必要があるため、より多くのリソースを消費します。
  • マイクロサービスは諸経費を増大させます
  • モノリシックなアプリケーションが複数のマイクロサービスになったケース

こうした状況は、サーバーレス機能やJavaのデプロイモデルの開発に大きな影響を与えています。これまで多くの企業開発者は、パフォーマンスのボトルネックに対処するための代替手段としてGo、Python、またはNode.jsを選択してきましたが、kubernetesベースのネイティブJavaスタックである Kubernetes 登場しました。この記事では、Quarkusを使用してサーバーレス機能を実行するkubernetesプラットフォームでパフォーマンスを最適化する方法について説明します。

コンテナ・ファーストの設計思想

Java エコシステム内の従来のフレームワークは、構成ファイルの処理、クラスパスのスキャン、クラスのロード、アノテーションの処理、メタモデルの構築など、フレームワークの初期化を実行する必要があり、これらはすべて不可欠な処理であるため、リソースを多く消費します。複数の異なるフレームワークが使用される場合、消費されるリソースは倍増します。

Quarkusは、すべてのリソース集約的な処理をビルドフェーズに移行することで、このようなJavaのパフォーマンス問題を解決します。コードとフレームワークの解析、バイトコードの変換、動的メタモデルの生成は、ビルドフェーズで、しかも1回だけ実行されます。その結果、実行可能ファイルは高速起動のために高度に最適化され、従来の起動プロセスをすべて実行する必要がなくなります。

さらに、Quarkusは、従来のクラウドネイティブJavaスタックと比較して、高速起動や非常に小さなメモリフットプリント、即時のスケーラビリティ、メモリの高密度利用など、優れたパフォーマンスを備えたネイティブ実行可能ファイルの構築をサポートしています。

Quarkusを使用して Javaサーバーレスプロジェクトを ネイティブ実行ファイルとしてビルドする方法の例を示します。

Quarkusを使用したサーバーレスMavenプロジェクトの作成

次のコマンドは、単純な関数を作成するためのQuarkusプロジェクトを生成します:

  1. $ mvn io.quarkus:quarkus-maven-plugin:1.13.4.Final:create \
  2.        -DprojectGroupId=org.acme \
  3.        -DprojectArtifactId=quarkus-serverless-native \
  4.        -DclassName="org.acme.getting.started.GreetingResource"

以下は、ローカルで実行ファイルをビルドする方法の例です。

Javaプログラムのネイティブ実行ファイルを構築するには、GraalVMを使用する必要があります。 Java サーバーレス 、OpenJDK 11上でのQuarkusネイティブ実行可能ファイルの構築をサポートするように設計された Mandrelなど、GraalVMの任意のディストリビューションを選択できます。

pom.xmlを開くと、ネイティブ設定があります。ネイティブの実行ファイルをビルドするときに使います。

  1. <profiles>
  2.     <profile>
  3.         <id>native</id>
  4.         <properties>
  5.             <quarkus.package.type>native</quarkus.package.type>
  6.         </properties>
  7.     </profile>
  8. </profiles>

注: GraalVM または Mandrel ディストリビューションをローカルにインストールできます。また、Mandrel コンテナイメージをダウンロードしてビルドすることもできますので、ローカルでコンテナエンジンを実行する必要もあります。

コンテナー・ランタイムを開いていると仮定して、この時点でMavenコマンドを実行する必要があります:

コンテナエンジンとして Oracle GraalVM Community Edition 使用します:

  1. $ ./mvnw package -Pnative \
  2. -Dquarkus.native.container-build=true \
  3. -Dquarkus.native.container-runtime=docker

Mandrel コンテナエンジンとして使用します:

  1. $ ./mvnw package -Pnative \
  2. -Dquarkus.native.container-build=true \
  3. -Dquarkus.native.container-runtime=podman

出力メッセージの末尾は BUILD SUCCESSでなければなりません。

JVMなしでネイティブ実行可能ファイルを実行します:

  1. $ target/quarkus-serverless-native-1.0.0-SNAPSHOT-runner

出力メッセージも同様です:

  1. __ ____ __ _____ ___ __ ____ ______
  2. --/ __ \/ / / / _ | / _ \/ //_/ / / / __/
  3. -/ /_/ / /_/ / __ |/ , _/ ,< / /_/ /\ \
  4. --\___\_\____/_/ |_/_/|_/_/|_|\____/___/
  5. INFO [io.quarkus] (main) quarkus-serverless-native 1.0.0-SNAPSHOT native
  6. (powered by Quarkus xx.xx.xx.) Started in 0.019s. Listening on: http://...:80
  7. INFO [io.quarkus] (main) Profile prod activated.
  8. INFO [io.quarkus] (main) Installed features: [cdi, kubernetes, resteasy]

実質的に超音速です!スタートまでわずか19ミリ秒。ランタイムは多少異なる場合があります。

Linuxのpsユーティリティを使用してこれを確認すると、メモリフットプリントはまだ非常に低いです。これを確認するには、別のターミナルを開き、アプリケーションの実行中に以下のコマンドを実行します:

  1. $ ps -o pid,rss,command -p $(pgrep -f runner)

出力は似ています:

  1.   PID    RSS COMMAND
  2.  11360 target/quarkus-serverless-native-1.0.0-SNAPSHOT-runner

このプロセスは、わずか11MBのメモリしか消費しません。とても小さい!

注: さまざまなアプリケーションのレジデント・セットとメモリ・フットプリントのサイズは、オペレーティング環境によって異なり、アプリケーションがロードされるにつれて増加します。

REST APIを使用してこの関数にアクセスすることもできます。出力は Hello RESTEasy.

  1. $ curl localhost:8080/hello
  2. Hello RESTEasy

関数はKnativeサービスにデプロイされます。

まだの場合は、 Docker名前空間を作成し、このローカル実行ファイルをサーバーレス関数としてデプロイします。そして、quarkus-openshiftエクステンションを追加します:

  1. $ ./mvnw -q quarkus:add-extension -Dextensions="openshift"

KnativeとKubernetes関連のリソースを設定するために、 src/main/resources/application.properties ファイルに以下を追加します:

  1. quarkus.container-image.group=quarkus-serverless-native
  2. quarkus.container-image.registry=image-registry.openshift-image-registry.svc:0050
  3. quarkus.native.container-build=true
  4. quarkus.kubernetes-client.trust-certs=true
  5. quarkus.kubernetes.deployment-target=knative
  6. quarkus.kubernetes.deploy=true
  7. quarkus.openshift.build-strategy=docker

ローカル実行ファイルをビルドし、OKDクラスタに直接デプロイします:

  1. $ ./mvnw clean package -Pnative

注意: 事前に oc login コマンドを使って、正しいプロジェクトにログインしていることを確認してください。

ローカルバイナリのビルドを完了し、Knativeサービスとしてデプロイするには数分かかります。サービスの作成に成功したら、kubectl または oc コマンドツールを使って Knative サービスとバージョン情報を表示できます:

  1. $ kubectl get ksvc
  2. NAME URL [...]
  3. quarkus-serverless-native http://--ve-[...].IN True
  4. $ kubectl get rev
  5. NAME CONFIG NAME K8S SERVICE NAME GENERATION READY REASON
  6. quarkus-serverless-native-00001 quarkus-serverless-native quarkus-serverless-native- True

ローカル実行可能関数へのアクセス

kubectl 実行して、サーバー機能のないノードを検索します:

  1. $ kubectl get rt/quarkus-serverless-native

出力メッセージも同様です:

  1. NAME URL READY REASON
  2. quarkus-serverless-native http://-----.IN True

上記のメッセージのURLフィールドにアクセスするには、curlコマンドを使用します:

  1. $ curl http://-----./lo

1秒もかからずに、ローカルで操作しているのと同じ結果が得られます:

  1. Hello RESTEasy

OKDクラスターでQuarkusが実行されているノードのログにアクセスすると、ローカルの実行ファイルがKnativeサービスとして実行されていることがわかります。

次は?

Javaサーバーレス関数をGraalVMディストリビューションで最適化し、Kubernetesを使用してKnativeでサーバーレス関数としてデプロイできます。

Read next