クラウドへのデプロイ
Spring Boot の実行可能 jar は、ほとんどの一般的なクラウド PaaS(Platform-as-a-Service)プロバイダー向けに用意されています。これらのプロバイダーは、「独自のコンテナーを持ち込む」ことを要求する傾向があります。アプリケーションプロセス(特に Java アプリケーションではない)を管理するため、実行中のプロセスのクラウドの概念にアプリケーションを適合させる中間層が必要です。
2 つの人気のあるクラウドプロバイダーである Heroku と Cloud Foundry は、"buildpack" アプローチを採用しています。buildpack は、デプロイされたコードを、アプリケーションの起動に必要なものにラップします。これは、JDK と、java
、組み込み Web サーバー、本格的なアプリケーションサーバーへの呼び出しである可能性があります。buildpack はプラグイン可能ですが、理想的には、可能な限り少ないカスタマイズで問題を解決できるはずです。これにより、制御できない機能のフットプリントが削減されます。開発環境と本番環境の間の相違を最小限に抑えます。
理想的には、Spring Boot 実行可能ファイル jar のようなアプリケーションには、実行に必要なものがすべてパッケージ化されています。
このセクションでは、「入門」セクションで開発したアプリケーションをクラウドで稼働させるために必要なことを説明します。
Cloud Foundry
Cloud Foundry は、他の buildpack が指定されていない場合に機能するデフォルトの buildpacks を提供します。Cloud Foundry Java buildpack [GitHub] (英語) は、Spring Boot を含む Spring アプリケーションを優れた方法でサポートします。スタンドアロンの実行可能 jar アプリケーションと、従来の .war
パッケージアプリケーションをデプロイできます。
mvn clean package
などを使用してアプリケーションを構築し、cf
コマンドラインツールをインストールしたら、cf push
コマンド (英語) を使用して、コンパイル済みの .jar
へのパスを置き換えてアプリケーションをデプロイします。アプリケーションをプッシュする前に、cf
コマンドラインクライアントでログインしてください (英語) 。次の行は、cf push
コマンドを使用してアプリケーションをデプロイすることを示しています。
$ cf push acloudyspringtime -p target/demo-0.0.1-SNAPSHOT.jar
前の例では、cf をアプリケーションの名前として指定した値の代わりに acloudyspringtime を使用しています。 |
その他のオプションについては、cf push
ドキュメント (英語) を参照してください。同じディレクトリに Cloud Foundry manifest.yml
(英語) ファイルが存在する場合、それが考慮されます。
この時点で、cf
はアプリケーションのアップロードを開始し、次の例のような出力を生成します。
Uploading acloudyspringtime... OK
Preparing to start acloudyspringtime... OK
-----> Downloaded app package (8.9M)
-----> Java Buildpack Version: v3.12 (offline) | https://github.com/cloudfoundry/java-buildpack.git#6f25b7e
-----> Downloading Open Jdk JRE
Expanding Open Jdk JRE to .java-buildpack/open_jdk_jre (1.6s)
-----> Downloading Open JDK Like Memory Calculator 2.0.2_RELEASE from https://java-buildpack.cloudfoundry.org/memory-calculator/trusty/x86_64/memory-calculator-2.0.2_RELEASE.tar.gz (found in cache)
Memory Settings: -Xss349K -Xmx681574K -XX:MaxMetaspaceSize=104857K -Xms681574K -XX:MetaspaceSize=104857K
-----> Downloading Container Certificate Trust Store 1.0.0_RELEASE from https://java-buildpack.cloudfoundry.org/container-certificate-trust-store/container-certificate-trust-store-1.0.0_RELEASE.jar (found in cache)
Adding certificates to .java-buildpack/container_certificate_trust_store/truststore.jks (0.6s)
-----> Downloading Spring Auto Reconfiguration 1.10.0_RELEASE from https://java-buildpack.cloudfoundry.org/auto-reconfiguration/auto-reconfiguration-1.10.0_RELEASE.jar (found in cache)
Checking status of app 'acloudyspringtime'...
0 of 1 instances running (1 starting)
...
0 of 1 instances running (1 starting)
...
0 of 1 instances running (1 starting)
...
1 of 1 instances running (1 running)
App started
おめでとう! これでアプリケーションが公開されました!
アプリケーションが稼働したら、次の例に示すように、cf apps
コマンドを使用して、デプロイされたアプリケーションのステータスを確認できます。
$ cf apps
Getting applications in ...
OK
name requested state instances memory disk urls
...
acloudyspringtime started 1/1 512M 1G acloudyspringtime.cfapps.io
...
Cloud Foundry がアプリケーションがデプロイされたことを確認すると、指定された URI でアプリケーションを見つけることができるはずです。上記の例では、https://acloudyspringtime.cfapps.io/
で見つけることができます。
サービスへのバインド
デフォルトでは、実行中のアプリケーションに関するメタデータとサービス接続情報は、環境変数($VCAP_SERVICES
など)としてアプリケーションに公開されます。このアーキテクチャの決定は、Cloud Foundry のポリグロット(任意の言語とプラットフォームを buildpack としてサポートできます)の性質によるものです。プロセススコープの環境変数は言語に依存しません。
環境変数は常に最も簡単な API を提供するとは限らないため、Spring Boot は自動的に抽出し、次の例に示すように、Spring の Environment
抽象化を通じてアクセスできるプロパティにデータをフラット化します。
Java
Kotlin
import org.springframework.context.EnvironmentAware;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Component;
@Component
public class MyBean implements EnvironmentAware {
private String instanceId;
@Override
public void setEnvironment(Environment environment) {
this.instanceId = environment.getProperty("vcap.application.instance_id");
}
// ...
}
import org.springframework.context.EnvironmentAware
import org.springframework.core.env.Environment
import org.springframework.stereotype.Component
@Component
class MyBean : EnvironmentAware {
private var instanceId: String? = null
override fun setEnvironment(environment: Environment) {
instanceId = environment.getProperty("vcap.application.instance_id")
}
// ...
}
すべての Cloud Foundry プロパティには、vcap
というプレフィックスが付きます。vcap
プロパティを使用して、アプリケーション情報 (アプリケーションのパブリック URL など) やサービス情報 (データベース資格情報など) にアクセスできます。詳細については、CloudFoundryVcapEnvironmentPostProcessor
(Javadoc) API ドキュメントを参照してください。
Java CFEnv [GitHub] (英語) プロジェクトは、DataSource の構成などのタスクにより適しています。 |
Kubernetes
Spring Boot は、"*_SERVICE_HOST"
および "*_SERVICE_PORT"
変数の環境をチェックすることにより、Kubernetes デプロイ環境を自動検出します。この検出は、spring.main.cloud-platform
構成プロパティでオーバーライドできます。
Spring Boot は、アプリケーションの状態を管理し、アクチュエーターを使用した HTTP Kubernetes プローブでエクスポートできます。
Kubernetes コンテナーライフサイクル
Kubernetes がアプリケーションインスタンスを削除すると、シャットダウンプロセスには複数のサブシステムが同時に関与します。シャットダウンフック、サービスの登録解除、ロードバランサーからのインスタンスの削除…このシャットダウン処理は並行して(分散システムの性質により)行われるため、シャットダウン処理を開始した pod にトラフィックをルーティングできるウィンドウです。
preStop ハンドラーでスリープ実行を構成すると、すでにシャットダウンを開始している pod にリクエストがルーティングされるのを防ぐことができます。このスリープは、新しいリクエストが pod にルーティングされなくなるのに十分な長さである必要があり、その期間は デプロイから デプロイまで異なります。preStop ハンドラーは、次のように pod の構成ファイルで PodSpec を使用して構成できます。
spec:
containers:
- name: "example-container"
image: "example-image"
lifecycle:
preStop:
exec:
command: ["sh", "-c", "sleep 10"]
停止前フックが完了すると、SIGTERM がコンテナーに送信され、正常なシャットダウンが開始され、残りの実行中のリクエストが完了できるようになります。
Kubernetes が SIGTERM シグナルを pod に送信すると、終了猶予期間(デフォルトは 30 秒)と呼ばれる指定された時間待機します。猶予期間後もコンテナーが実行されている場合は、SIGKILL シグナルが送信され、強制的に削除されます。pod のシャットダウンに 30 秒以上かかる場合は、spring.lifecycle.timeout-per-shutdown-phase を増やしたことが原因である可能性があります。必ず、Pod YAML で terminationGracePeriodSeconds オプションを設定して、終了猶予期間を増やしてください。 |
Heroku
Heroku は、もう 1 つの一般的な PaaS プラットフォームです。Heroku ビルドをカスタマイズするには、アプリケーションをデプロイするために必要な呪文を提供する Procfile
を提供します。Heroku は、使用する Java アプリケーションに port
を割り当て、外部 URI へのルーティングが機能することを確認します。
正しいポートでリッスンするようにアプリケーションを構成する必要があります。次の例は、スターター REST アプリケーションの Procfile
を示しています。
web: java -Dserver.port=$PORT -jar target/demo-0.0.1-SNAPSHOT.jar
Spring Boot は、-D
引数を Spring Environment
インスタンスからアクセス可能なプロパティとして使用できるようにします。server.port
構成プロパティは、組み込み Tomcat、Jetty、Undertow インスタンスに供給され、起動時にポートを使用します。$PORT
環境変数は、Heroku PaaS によって割り当てられます。
これが必要なものすべてです。Heroku デプロイの最も一般的なデプロイワークフローは、次の例に示すように、本番環境にコードを git push
することです。
$ git push heroku main
その結果、次のようになります。
Initializing repository, done.
Counting objects: 95, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (78/78), done.
Writing objects: 100% (95/95), 8.66 MiB | 606.00 KiB/s, done.
Total 95 (delta 31), reused 0 (delta 0)
-----> Java app detected
-----> Installing OpenJDK... done
-----> Installing Maven... done
-----> Installing settings.xml... done
-----> Executing: mvn -B -DskipTests=true clean install
[INFO] Scanning for projects...
Downloading: https://repo.spring.io/...
Downloaded: https://repo.spring.io/... (818 B at 1.8 KB/sec)
....
Downloaded: https://s3pository.heroku.com/jvm/... (152 KB at 595.3 KB/sec)
[INFO] Installing /tmp/build_0c35a5d2-a067-4abc-a232-14b1fb7a8229/target/...
[INFO] Installing /tmp/build_0c35a5d2-a067-4abc-a232-14b1fb7a8229/pom.xml ...
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 59.358s
[INFO] Finished at: Fri Mar 07 07:28:25 UTC 2014
[INFO] Final Memory: 20M/493M
[INFO] ------------------------------------------------------------------------
-----> Discovering process types
Procfile declares types -> web
-----> Compressing... done, 70.4MB
-----> Launching... done, v6
https://agile-sierra-1405.herokuapp.com/ deployed to Heroku
To [email protected] (英語) :agile-sierra-1405.git
* [new branch] main -> main
これで、アプリケーションが Heroku で稼働しているはずです。詳細については、Spring Boot アプリケーションを Heroku にデプロイする (英語) を参照してください。
OpenShift
OpenShift (英語) には、Spring Boot アプリケーションをデプロイする方法を説明する多くのリソースがあります。
Amazon Web Services (AWS)
Amazon Web Services は、SpringBoot ベースのアプリケーションを、従来の Web アプリケーション(war)として、または Web サーバーが組み込まれた実行可能 jar ファイルとしてインストールするための複数の方法を提供します。オプションは次のとおりです。
AWS Elastic Beanstalk
AWS Code Deploy
AWS OPS Works
AWS Cloud Formation
AWS Container Registry
それぞれに異なる機能と価格モデルがあります。このドキュメントでは、AWS Elastic Beanstalk を使用したアプローチについて説明します。
AWS Elastic Beanstalk
公式 Elastic Beanstalk Java ガイド [Amazon] に従って、Java アプリケーションをデプロイするには 2 つの主なオプションがあります。「Tomcat プラットフォーム」または「Java SE プラットフォーム」のいずれかを使用できます。
Java SE プラットフォームの使用
このオプションは、jar ファイルを生成し、埋め込み Web コンテナーを実行する Spring Boot プロジェクトに適用されます。Elastic Beanstalk 環境は、ポート 80 で nginx インスタンスを実行し、ポート 5000 で実行されている実際のアプリケーションをプロキシします。設定するには、application.properties
ファイルに次の行を追加します。
プロパティ
YAML
server.port=5000
server:
port: 5000
ソースの代わりにバイナリをアップロードする デフォルトでは、Elastic Beanstalk はソースをアップロードし、AWS でコンパイルします。ただし、代わりにバイナリをアップロードすることをお勧めします。これを行うには、
|
環境型を設定してコストを削減 デフォルトでは、ElasticBeanstalk 環境は負荷分散されています。ロードバランサーにはかなりのコストがかかります。このコストを回避するには、Amazon のドキュメント で説明されているように、環境型を「シングルインスタンス」に設定します。CLI と次のコマンドを使用して、単一インスタンス環境を作成することもできます。
|
要約
これは AWS にアクセスする最も簡単な方法の 1 つですが、Elastic Beanstalk を任意の CI/CD ツールに統合する方法、CLI の代わりに Elastic Beanstalk Maven プラグインを使用する方法など、さらに説明することがあります。これらのトピックをより詳細にカバーするブログ投稿 (英語) があります。
CloudCaptain および Amazon Web Services
CloudCaptain (英語) は、Spring Boot 実行可能ファイル jar または war を、VirtualBox または AWS のいずれかに変更せずにデプロイできる最小の VM イメージに変換することで機能します。CloudCaptain には Spring Boot の緊密な統合が付属しており、Spring Boot 構成ファイルからの情報を使用して、ポートとヘルスチェック URL を自動的に構成します。CloudCaptain は、生成するイメージと、プロビジョニングするすべてのリソース(インスタンス、セキュリティグループ、エラスティックロードバランサーなど)の両方でこの情報を活用します。
CloudCaptain アカウント (英語) を作成し、AWS アカウントに接続し、最新バージョンの CloudCaptain クライアントをインストールし、アプリケーションが Maven または Gradle によってビルドされていることを確認したら(たとえば、mvn clean package
を使用して)、Spring Boot をデプロイできます。次のようなコマンドを使用して AWS に適用します。
$ boxfuse run myapp-1.0.jar -env=prod
その他のオプションについては、boxfuse run
ドキュメント (英語) を参照してください。現在のディレクトリに boxfuse.conf
(英語) ファイルが存在する場合、それが考慮されます。
デフォルトでは、CloudCaptain は起動時に boxfuse という名前の Spring プロファイルをアクティブにします。実行可能 jar または war に application-boxfuse.properties (英語) ファイルが含まれている場合、CloudCaptain は、含まれているプロパティに基づいて構成を行います。 |
この時点で、CloudCaptain はアプリケーションのイメージを作成してアップロードし、AWS で必要なリソースを設定して開始します。その結果、次の例のような出力が得られます。
Fusing Image for myapp-1.0.jar ...
Image fused in 00:06.838s (53937 K) -> axelfontaine/myapp:1.0
Creating axelfontaine/myapp ...
Pushing axelfontaine/myapp:1.0 ...
Verifying axelfontaine/myapp:1.0 ...
Creating Elastic IP ...
Mapping myapp-axelfontaine.boxfuse.io to 52.28.233.167 ...
Waiting for AWS to create an AMI for axelfontaine/myapp:1.0 in eu-central-1 (this may take up to 50 seconds) ...
AMI created in 00:23.557s -> ami-d23f38cf
Creating security group boxfuse-sg_axelfontaine/myapp:1.0 ...
Launching t2.micro instance of axelfontaine/myapp:1.0 (ami-d23f38cf) in eu-central-1 ...
Instance launched in 00:30.306s -> i-92ef9f53
Waiting for AWS to boot Instance i-92ef9f53 and Payload to start at https://52.28.235.61/ ...
Payload started in 00:29.266s -> https://52.28.235.61/
Remapping Elastic IP 52.28.233.167 to i-92ef9f53 ...
Waiting 15s for AWS to complete Elastic IP Zero Downtime transition ...
Deployment completed successfully. axelfontaine/myapp:1.0 is up and running at https://myapp-axelfontaine.boxfuse.io/
これで、アプリケーションが AWS で稼働しているはずです。
EC2 への Spring Boot アプリのデプロイ (英語) に関するブログ投稿と、アプリを実行するための Maven ビルドを開始するための CloudCaptain Spring Boot 統合のドキュメント (英語) を参照してください。
Azure
この入門ガイドは、Spring Boot アプリケーションを Azure Spring Cloud (英語) または Azure アプリサービス のいずれかにデプロイする方法を説明します。
Google クラウド
Google クラウドには、Spring Boot アプリケーションを起動するために使用できるいくつかのオプションがあります。おそらく App Engine を使用するのが最も簡単ですが、Container Engine を使用するコンテナー内で、または Compute Engine を使用する仮想マシン上で Spring Boot を実行する方法を見つけることもできます。
最初のアプリを App Engine スタンダード環境にデプロイするには、このチュートリアル (英語) に従ってください。
または、App Engine Flex では、app.yaml
ファイルを作成して、アプリに必要なリソースを記述する必要があります。通常、このファイルは src/main/appengine
に配置し、次のファイルのようになります。
service: "default"
runtime: "java17"
env: "flex"
handlers:
- url: "/.*"
script: "this field is required, but ignored"
manual_scaling:
instances: 1
health_check:
enable_health_check: false
env_variables:
ENCRYPT_KEY: "your_encryption_key_here"
次の例に示すように、プロジェクト ID をビルド構成に追加することで、アプリを(たとえば、Maven プラグインを使用して)デプロイできます。
<plugin>
<groupId>com.google.cloud.tools</groupId>
<artifactId>appengine-maven-plugin</artifactId>
<version>2.4.4</version>
<configuration>
<project>myproject</project>
</configuration>
</plugin>
次に、mvn appengine:deploy
を使用してデプロイします (最初に認証する必要があります。そうしないと、ビルドは失敗します)。